Website/slides/cse4562sp2018/2018-02-07-RA-Equivs.html

542 lines
24 KiB
HTML
Raw Normal View History

2018-02-06 22:44:57 -05:00
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>CSE 4/562 - Spring 2018</title>
<meta name="description" content="CSE 4/562 - Spring 2018">
<meta name="author" content="Oliver Kennedy">
<meta name="apple-mobile-web-app-capable" content="yes" />
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no, minimal-ui">
<link rel="stylesheet" href="../reveal.js-3.6.0/css/reveal.css">
<link rel="stylesheet" href="ubodin.css" id="theme">
<!-- Code syntax highlighting -->
<link rel="stylesheet" href="../reveal.js-3.6.0/lib/css/zenburn.css">
<!-- Printing and PDF exports -->
<script>
var link = document.createElement( 'link' );
link.rel = 'stylesheet';
link.type = 'text/css';
link.href = window.location.search.match( /print-pdf/gi ) ? '../reveal.js-3.6.0/css/print/pdf.css' : '../reveal.js-3.6.0/css/print/paper.css';
document.getElementsByTagName( 'head' )[0].appendChild( link );
</script>
<script src="../reveal.js-3.6.0/lib/js/head.min.js"></script>
<!--[if lt IE 9]>
<script src="../reveal.js-3.6.0/lib/js/html5shiv.js"></script>
<![endif]-->
</head>
<body>
<div class="reveal">
<!-- Any section element inside of this container is displayed as a slide -->
<div class="header">
<!-- Any Talk-Specific Header Content Goes Here -->
CSE 4/562 - Database Systems
</div>
<div class="slides">
<section>
<h1>Relational Algebra Equivalences</h1>
<h3>CSE 4/562 Database Systems</h3>
<h5>February 7, 2018</h5>
</section>
<section>
<section>
<h3>Recap: Relational Algebra</h3>
<table style="font-size: 70%">
<tr><th>Operation</th><th>Sym</th><th>Meaning</th></tr>
<tr><td>Selection</td><td>$\sigma$</td><td>Select a subset of the input rows</td></tr>
<tr><td>Projection</td><td>$\pi$</td><td>Delete unwanted columns</td></tr>
<tr><td>Cross-product</td><td>$\times$</td><td>Combine two relations</td></tr>
<tr><td>Set-difference</td><td>$-$</td><td>Tuples in Rel 1, but not Rel 2</td></tr>
<tr><td>Union</td><td>$\cup$</td><td>Tuples either in Rel 1 or in Rel 2</td></tr>
<tr><td>Intersection</td><td>$\cap$</td><td>Tuples in both Rel 1 and Rel 2</td></tr>
<tr><td>Join</td><td>$\bowtie$</td><td>Pairs of tuples matching a specified condition</td></tr>
<tr style="color: grey;"><td>Division</td><td>$/$</td><td>"Inverse" of cross-product</td></tr>
</table>
</section>
<section>
<h3>Division ($/$)</h3>
<p>Not typically supported as a primitive operator,<br/>but useful for expressing queries like:</p>
<p style="font-size: 70%; font-weight: bold">Find species that appear in all boroughs</p>
<div style="font-size: 70%" class="fragment">
$$\pi_{BORONAME,\ SPC\_COMMON}(\textbf{Trees}) \;\;/\;\;\pi_{SPC\_COMMON}(\textbf{Trees})$$
(using set relational algebra)
</div>
<p class="fragment">
$$R / S \equiv \{\; \left<\vec t\right> \;|\; \forall \left<\vec s\right> \in S, \left< \vec t \vec s \right> \in R \;\}$$
</p>
</section>
<section>
<h3>Division ($/$)</h3>
<table style="font-size: 60%; margin-top: 30px; display: inline-block; vertical-align: middle;">
<tr><th>BORO</th> <th>SPC_COMMON</th></tr>
<tr class="fragment highlight-blue" data-fragment-index="1"><td>Brooklyn</td> <td>honeylocust</td></tr>
<tr class="fragment highlight-red" data-fragment-index="3"><td>Brooklyn</td> <td>American linden</td></tr>
<tr><td>Brooklyn</td> <td>London planetree</td></tr>
<tr class="fragment highlight-blue" data-fragment-index="1"><td>Manhattan</td> <td>honeylocust</td></tr>
<tr class="fragment highlight-red" data-fragment-index="3"><td>Manhattan</td> <td>American linden</td></tr>
<tr class="fragment highlight-green" data-fragment-index="5"><td>Manhattan</td> <td>pin oak</td></tr>
<tr class="fragment highlight-blue" data-fragment-index="1"><td>Queens</td> <td>honeylocust</td></tr>
<tr class="fragment highlight-red" data-fragment-index="3"><td>Queens</td> <td>American linden</td></tr>
<tr class="fragment highlight-blue" data-fragment-index="1"><td>Bronx</td> <td>honeylocust</td></tr>
</table>
<table style="font-size: 40%; margin-left: 30px; display: inline-block; vertical-align: middle;">
<tr class="fragment" data-fragment-index="1"><td>
<span style="font-size: 200%">/</span>
<table style="display: inline-block; vertical-align: middle; margin-left: 10px; border: 1px solid black;"><tr><th>SPC_COMMON</th></tr><tr><td class="fragment highlight-current-blue" data-fragment-index="1">honeylocust</td></tr></table>
<span class="fragment" data-fragment-index="2">
<span style="font-size: 200%; margin-left: 10px;">=</span>
<table style="display: inline-block; vertical-align: middle; margin-left: 10px; border: 1px solid black;"><tr><th>BORO</th></tr><tr><td>Brooklyn</td></tr><tr><td>Manhattan</td></tr><tr><td>Queens</td></tr><tr><td>Bronx</td></tr></table>
</span>
</td></tr>
<tr class="fragment" data-fragment-index="3"><td>
<span style="font-size: 200%">/</span>
<table style="display: inline-block; vertical-align: middle; margin-left: 10px; border: 1px solid black;"><tr><th>SPC_COMMON</th></tr><tr><td class="fragment highlight-current-blue" data-fragment-index="3">honeylocust</td></tr><tr><td class="fragment highlight-current-red" data-fragment-index="3">American linden</td></tr></table>
<span class="fragment" data-fragment-index="4">
<span style="font-size: 200%; margin-left: 10px;">=</span>
<table style="display: inline-block; vertical-align: middle; margin-left: 10px; border: 1px solid black;"><tr><th>BORO</th></tr><tr><td>Brooklyn</td></tr><tr><td>Manhattan</td></tr><tr><td>Queens</td></tr></table>
</span>
</td></tr>
<tr class="fragment" data-fragment-index="5"><td>
<span style="font-size: 200%">/</span>
<table style="display: inline-block; vertical-align: middle; margin-left: 10px; border: 1px solid black;"><tr><th>SPC_COMMON</th></tr><tr><td class="fragment highlight-current-blue" data-fragment-index="5">honeylocust</td></tr><tr><td class="fragment highlight-current-red" data-fragment-index="5">American linden</td></tr><tr><td class="fragment highlight-current-green" data-fragment-index="5">pin oak</td></tr></table>
<span class="fragment" data-fragment-index="6">
<span style="font-size: 200%; margin-left: 10px;">=</span>
<table style="display: inline-block; vertical-align: middle; margin-left: 10px; border: 1px solid black;"><tr><th>BORO</th></tr><tr><td>Manhattan</td></tr></table>
</span>
</td></tr>
</table>
</section>
</section>
<section>
<section>
<h3>The running theme</h3>
<p>
<span class="fragment highlight-grey" data-fragment-index="1">If X and Y are </span><u>equivalent</u><span class="fragment highlight-grey" data-fragment-index="1"> and Y is <u>better</u>,<br/>
then replace all Xs with Ys</span>
</p>
<p class="fragment" data-fragment-index="1" style="font-size: 70%;"><b>Today's focus</b>: Provable Equivalence for RA Expressions</p>
</section>
<section>
<h3>Equivalence</h3>
$$Q_1 = \pi_{A}\left( \sigma_{c}( R ) \right)$$
$$Q_2 = \sigma_{c}\left( \pi_{A}( R ) \right)$$
<div class="fragment">
$$Q_1 \stackrel{?}{\equiv} Q_2$$
</div>
</section>
<section>
<h3>Ground Rules</h3>
<dl>
<dt class="fragment" data-fragment-index="1">Only Relational Values Matter</dt>
<dd class="fragment" data-fragment-index="1">Obviously $Q_1 \neq Q_2$. What we care about is whether $Q_1(R) = Q_2(R)$...</dd>
<dt class="fragment" data-fragment-index="2">Data Independent</dt>
<dd class="fragment" data-fragment-index="2">... for <i>all</i> valid input data $R$.</dd>
<dd class="fragment" data-fragment-index="3" style="font-size: 70%">However, it's fair to talk about equivalence when we know the data has some properties. (more on this later)</dd>
<dt class="fragment" data-fragment-index="4">Data-Model Dependent</dt>
<dd class="fragment" data-fragment-index="4">It's important to be clear whether we're talking about sets, <span class="fragment highlight-blue">bags</span>, or lists.</dd>
</dl>
</section>
<section>
<h3>In summary...</h3>
<p style="font-size: 80%;">
We say that $Q_1 \equiv Q_2$ if and only if<br/>
we can guarantee that the <i>bag</i> of tuples produced by $Q_1(R, S, T, \ldots)$ <br/>
is the same as the <i>bag</i> of tuples produced by $Q_2(R, S, T, \ldots)$ <br/>
for any combination of valid inputs $R, S, T, \ldots$.
</p>
<p style="font-size: 70%;" class="fragment">
... that satisfy any necessary properties.
</p>
</section>
<section>
<h3>Starting Rules</h3>
<table style="font-size: 80%">
<tr><th colspan="2" style="padding-top: 20px;">Selection</th></tr>
<tr>
<td>$\sigma_{c_1 \wedge c_2}(R) \equiv \sigma_{c_1}(\sigma_{c_2}(R))$</td>
<td>(Decomposability)</td>
</tr>
<tr><th colspan="2" style="padding-top: 20px;">Projection</th></tr>
<tr>
<td>$\pi_{A}(R) \equiv \pi_{A}(\pi_{A \cup B}(R))$</td>
<td>(Idempotence)</td>
</tr>
<tr><th colspan="2" style="padding-top: 20px;">Cross Product</th></tr>
<tr>
<td>$R \times (S \times T) \equiv (R \times S) \times T$</td>
<td>(Associativity)</td>
</tr>
<tr>
<td>$R \times S \equiv S \times R$</td>
<td>(Commutativity)</td>
</tr>
<tr><th colspan="2" style="padding-top: 20px;">Union</th></tr>
<tr>
<td>$R \cup (S \cup T) \equiv (R \cup S) \cup T$</td>
<td>(Associativity)</td>
</tr>
<tr>
<td>$R \cup S \equiv S \cup R$</td>
<td>(Commutativity)</td>
</tr>
</table>
</section>
<section>
<h3>Try it!</h3>
<p class="fragment highlight-grey" data-fragment-index="1">
Show that
$$R \times (S \times T) \equiv T \times (S \times R)$$
</p>
<div class="fragment highlight-grey" data-fragment-index="2">
<p class="fragment" data-fragment-index="1">
Show that
$$\sigma_{c_1}(\sigma_{c_2}(R)) \equiv \sigma_{c_2}(\sigma_{c_1}(R))$$
</p>
</div>
<div class="fragment highlight-grey" data-fragment-index="3">
<p class="fragment" data-fragment-index="2">
Show that
$$R \bowtie_{c} S \equiv S \bowtie_{c} R$$
</p>
</div>
<p class="fragment" data-fragment-index="3">
Show that
$$\sigma_{R.B = S.B \wedge R.A > 3}(R \times S) \equiv \sigma_{R.A > 3}(R \bowtie_{B} S)$$
</p>
</section>
</section>
<section>
<section>
<h3>Rules for Multiple Operators</h3>
</section>
<section>
<table style="font-size: 90%; margin-bottom: 50px;">
<tr><th colspan="2" style="padding-top: 20px;">Selection + Projection</th></tr>
<tr>
<td>$\pi_{A}(\sigma_{c}(R)) \equiv \sigma_{c}(\pi_{A}(R))$</td>
<td>(Commutativity)</td>
</tr>
</table>
<p style="font-size: 80%;" class="fragment">... but only if $A$ and $c$ are <u>compatible</u></p>
<p style="font-size: 80%;" class="fragment">$A$ must include all columns referenced by $c$ ($cols(c)$)</p>
<div class="fragment" style="margin-top: 50px;">
<h3>Try it!</h3>
<p>
Show that
$$\pi_A(\sigma_c(R)) \equiv \pi_A(\sigma_c(\pi_{(A \cup cols(c))}(R)))$$
</p>
</div>
</section>
<section>
<table style="font-size: 90%; margin-bottom: 50px;">
<tr><th colspan="2" style="padding-top: 20px;">Selection + Cross Product</th></tr>
<tr>
<td>$\sigma_c(R \times S) \equiv (\sigma_{c}(R)) \times S$</td>
<td>(Commutativity)</td>
</tr>
</table>
<p style="font-size: 80%;" class="fragment">... but only if $c$ references only columns of $R$</p>
<p style="font-size: 60%;" class="fragment">$cols(c) \subseteq cols(R)$</p>
<div class="fragment" style="margin-top: 50px;">
<h3>Try it!</h3>
<p>
Show that
$$\sigma_{R.B = S.B \wedge R.A > 3}(R \times S) \equiv (\sigma_{R.A > 3}(R)) \bowtie_{B} S$$
<div style="font-size: 70%;" class="fragment">When is this rewrite a good idea?</div>
</p>
</div>
</section>
<section>
<table style="font-size: 90%; margin-bottom: 50px;">
<tr><th colspan="2" style="padding-top: 20px;">Projection + Cross Product</th></tr>
<tr>
<td>$\pi_A(R \times S) \equiv (\pi_{A_R}(R)) \times (\pi_{A_S}(S))$</td>
<td>(Commutativity)</td>
</tr>
</table>
<p style="font-size: 80%;">... where $A_R$ and $A_S$ are the columns of $A$ from $R$ and $S$ respectively.</p>
<p style="font-size: 60%;">$A_R = A \cap cols(R)$&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$A_S = A \cap cols(S)$</p>
<div class="fragment" style="margin-top: 50px;">
<h3>Try it!</h3>
<p>
Show that
$$\pi_{A}(R \bowtie_c S) \equiv (\pi_{A_R}(R)) \bowtie_c (\pi_{A_S}(S))$$
<div style="font-size: 70%;" class="fragment">When does this condition hold?</div>
</p>
</div>
</section>
<section>
2018-02-07 11:14:04 -05:00
<table style="font-size: 80%; margin-bottom: 50px;">
2018-02-06 22:44:57 -05:00
<tr><th colspan="2" style="padding-top: 20px;">Intersection</th></tr>
<tr>
<td>$R \cap (S \cap T) \equiv (R \cap S) \cap T$</td>
<td>(Associativity)</td>
</tr>
<tr>
<td>$R \cap S \equiv S \cap R$</td>
<td>(Commutativity)</td>
</tr>
2018-02-07 11:14:04 -05:00
<tr><th colspan="2" style="padding-top: 20px;">Selection + <u>&nbsp;&nbsp;&nbsp;&nbsp;</u></th></tr>
2018-02-06 22:44:57 -05:00
<tr>
<td>$\sigma_c(R \cup S) \equiv (\sigma_c(R)) \cup (\sigma_c(R))$</td>
<td>(Commutativity)</td>
</tr>
<tr>
<td>$\sigma_c(R \cap S) \equiv (\sigma_c(R)) \cap (\sigma_c(R))$</td>
<td>(Commutativity)</td>
</tr>
2018-02-07 11:14:04 -05:00
<tr><th colspan="2" style="padding-top: 20px;">Projection + <u>&nbsp;&nbsp;&nbsp;&nbsp;</u></th></tr>
2018-02-06 22:44:57 -05:00
<tr>
<td>$\pi_A(R \cup S) \equiv (\pi_A(R)) \cup (\pi_A(R))$</td>
<td>(Commutativity)</td>
</tr>
<tr>
<td>$\pi_A(R \cap S) \equiv (\pi_A(R)) \cap (\pi_A(R))$</td>
<td>(Commutativity)</td>
</tr>
<tr><th colspan="2" style="padding-top: 20px;">Cross Product + Union</th></tr>
<tr>
<td>$R \times (S \cup T) \equiv (R \times S) \cup (R \times T)$</td>
<td>(Distributivity)</td>
</tr>
</table>
</section>
</section>
<section>
<section>
<h3>Example</h3>
<pre style="display: inline-block; width: 300px; vertical-align: middle;"><code class="sql">
SELECT R.A, T.E
FROM R, S, T
WHERE R.B = S.B
AND S.C < 5
AND S.D = T.D
</code></pre>
<span style="vertical-align: middle; margin: 50px; font-size: 300%"></span>
<img src="graphics/2018-02-07-RA-Opt-1.svg" style="vertical-align: middle;"/>
</section>
2018-02-07 11:15:08 -05:00
<section>
2018-02-06 22:44:57 -05:00
<img src="graphics/2018-02-07-RA-Opt-1.svg" style="vertical-align: middle;" />
<span style="vertical-align: middle; margin: 50px; font-size: 300%"></span>
<img src="graphics/2018-02-07-RA-Opt-2.svg" style="vertical-align: middle;"/>
</section>
2018-02-07 11:15:08 -05:00
<section>
2018-02-06 22:44:57 -05:00
<img src="graphics/2018-02-07-RA-Opt-2.svg" style="vertical-align: middle;" />
<span style="vertical-align: middle; margin: 50px; font-size: 300%"></span>
<img src="graphics/2018-02-07-RA-Opt-3.svg" style="vertical-align: middle;" />
</section>
2018-02-07 11:15:08 -05:00
<section>
2018-02-06 22:44:57 -05:00
<img src="graphics/2018-02-07-RA-Opt-3.svg" style="vertical-align: middle;" />
<span style="vertical-align: middle; margin: 50px; font-size: 300%"></span>
<img src="graphics/2018-02-07-RA-Opt-4.svg" style="vertical-align: middle;" />
</section>
2018-02-07 11:15:08 -05:00
<section>
2018-02-06 22:44:57 -05:00
<img src="graphics/2018-02-07-RA-Opt-4.svg" style="vertical-align: middle;" />
<span style="vertical-align: middle; margin: 50px; font-size: 300%"></span>
<img src="graphics/2018-02-07-RA-Opt-5.svg" style="vertical-align: middle;" />
</section>
2018-02-07 11:15:08 -05:00
<section>
2018-02-06 22:44:57 -05:00
<img src="graphics/2018-02-07-RA-Opt-5.svg" style="vertical-align: middle;" />
<span style="vertical-align: middle; margin: 50px; font-size: 300%"></span>
<img src="graphics/2018-02-07-RA-Opt-6.svg" style="vertical-align: middle;" />
</section>
2018-02-07 11:15:08 -05:00
<section>
2018-02-06 22:44:57 -05:00
<img src="graphics/2018-02-07-RA-Opt-6.svg" style="vertical-align: middle;" />
<span style="vertical-align: middle; margin: 50px; font-size: 300%"></span>
<img src="graphics/2018-02-07-RA-Opt-7.svg" style="vertical-align: middle;" />
</section>
</section>
<section>
<section>
<h3>General Query Optimizers</h3>
<p><b>Input:</b> Dumb translation of SQL to RA</p>
<p>⬇︎</p>
2018-02-07 11:16:26 -05:00
<p>Apply rewrites</p>
<p>⬇︎</p>
2018-02-06 22:44:57 -05:00
<p><b>Output:</b> Better, but equivalent query</p>
</section>
<section>
<p>Which rewrite rules should we apply?</p>
</section>
<section>
<dl style="font-size: 75%">
<dt class="fragment highlight-grey" data-fragment-index="1">Selection Pushdown</dt>
<dd class="fragment highlight-grey" data-fragment-index="1"><b>Always</b> commute Selections as close to the leaves as possible.</dd>
<dt class="fragment highlight-grey" data-fragment-index="1">Join Construction</dt>
<dd class="fragment highlight-grey" data-fragment-index="1">Joins are <b>always</b> better than cross-products.</dd>
<dt class="fragment highlight-grey" data-fragment-index="1">(Optional) Projection Pushdown</dt>
<dd class="fragment highlight-grey" data-fragment-index="1">Commuting Projections down to the leaves removes redundant columns, and <b>may</b> be beneficial for some systems.</dd>
<dt>Join Algorithm Selection</dt>
<dd>Joins can be implemented differently, depending on the join predicate.</dd>
<dt>Join/Union Ordering</dt>
<dd>The order in which joins are evaluated <b>may</b> affect query runtimes.</dd>
<dt>Access Paths</dt>
<dd>$(\sigma_c(R))$ and $(Q(\ldots) \bowtie_c R)$ are special cases that we can make fast!</dd>
</dl>
<p class="fragment" data-fragment-index="1" style="font-size: 60%">Some rewrites are situational... we need more information to decide when to apply them.</p>
</section>
2018-02-07 11:21:58 -05:00
<section>
<h3>General Query Optimizers</h3>
2018-02-07 11:27:47 -05:00
<ol style="font-size: 60%">
2018-02-07 11:35:27 -05:00
<li class="fragment" data-fragment-index="1">Apply blind heuristics (e.g., push down selections)</li>
<li class="fragment" data-fragment-index="2">Enumerate all possible <i>execution plans</i> by varying <span class="fragment" data-fragment-index="6" style="font-size: 80%;">(or for a reasonable subset)</span>
2018-02-07 11:26:38 -05:00
<ul>
2018-02-07 11:35:27 -05:00
<li>Join/Union Evaluation Order (commutativity, associativity, distributivity)</li>
<li class="fragment" data-fragment-index="3"><span class="fragment highlight-blue" data-fragment-index="8">Algorithms</span> for Joins, <span class="fragment highlight-blue" data-fragment-index="7">Aggregates, Sort, Distinct</span>, and others</span></li>
<li class="fragment" data-fragment-index="3">Data <span class="fragment highlight-blue" data-fragment-index="9">Access Paths</span></li>
2018-02-07 11:26:38 -05:00
</ul>
2018-02-07 11:21:58 -05:00
</li>
2018-02-07 11:35:27 -05:00
<li class="fragment" data-fragment-index="4"><span class="fragment highlight-blue" data-fragment-index="10">Estimate</span> the cost of each execution plan</li>
<li class="fragment" data-fragment-index="5">Pick the execution plan with the lowest cost</li>
2018-02-07 11:21:58 -05:00
</ol>
</section>
2018-02-06 22:44:57 -05:00
<section>
<b>Next Class:</b> Extended Relational Algebra and Basic Join Algorithms
</section>
</section>
</div></div>
<script src="../reveal.js-3.6.0/js/reveal.js"></script>
<script>
// Full list of configuration options available at:
// https://github.com/hakimel/../reveal.js#configuration
Reveal.initialize({
controls: false,
progress: true,
history: true,
center: true,
slideNumber: true,
transition: 'fade', // none/fade/slide/convex/concave/zoom
chart: {
defaults: {
global: {
title: { fontColor: "#333", fontSize: 24 },
legend: {
labels: { fontColor: "#333", fontSize: 20 },
},
responsiveness: true
},
scale: {
scaleLabel: { fontColor: "#333", fontSize: 20 },
gridLines: { color: "#333", zeroLineColor: "#333" },
ticks: { fontColor: "#333", fontSize: 16 },
}
},
line: { borderColor: [ "rgba(20,220,220,.8)" , "rgba(220,120,120,.8)", "rgba(20,120,220,.8)" ], "borderDash": [ [5,10], [0,0] ]},
bar: { backgroundColor: [
"rgba(220,220,220,0.8)",
"rgba(151,187,205,0.8)",
"rgba(205,151,187,0.8)",
"rgba(187,205,151,0.8)"
]
},
pie: { backgroundColor: [ ["rgba(0,0,0,.8)" , "rgba(220,20,20,.8)", "rgba(20,220,20,.8)", "rgba(220,220,20,.8)", "rgba(20,20,220,.8)"] ]},
radar: { borderColor: [ "rgba(20,220,220,.8)" , "rgba(220,120,120,.8)", "rgba(20,120,220,.8)" ]},
},
// Optional ../reveal.js plugins
dependencies: [
{ src: '../reveal.js-3.6.0/lib/js/classList.js', condition: function() { return !document.body.classList; } },
{ src: '../reveal.js-3.6.0/plugin/math/math.js',
condition: function() { return true; },
mathjax: '../reveal.js-3.6.0/js/MathJax.js'
},
{ src: '../reveal.js-3.6.0/plugin/markdown/marked.js', condition: function() { return !!document.querySelector( '[data-markdown]' ); } },
{ src: '../reveal.js-3.6.0/plugin/markdown/markdown.js', condition: function() { return !!document.querySelector( '[data-markdown]' ); } },
{ src: '../reveal.js-3.6.0/plugin/highlight/highlight.js', async: true, condition: function() { return !!document.querySelector( 'pre code' ); }, callback: function() { hljs.initHighlightingOnLoad(); } },
{ src: '../reveal.js-3.6.0/plugin/zoom-js/zoom.js', async: true },
{ src: '../reveal.js-3.6.0/plugin/notes/notes.js', async: true },
// Chart.min.js
{ src: '../reveal.js-3.6.0/plugin/chart/Chart.min.js'},
// the plugin
{ src: '../reveal.js-3.6.0/plugin/chart/csv2chart.js'},
{ src: '../reveal.js-3.6.0/plugin/svginline/es6-promise.auto.js', async: false },
{ src: '../reveal.js-3.6.0/plugin/svginline/data-src-svg.js', async: false }
]
});
</script>
</body>
</html>