Skip to content

Commit

Permalink
Added first figure to document
Browse files Browse the repository at this point in the history
  • Loading branch information
jamieparkinson committed May 2, 2016
1 parent 3f933b8 commit 44e58a9
Show file tree
Hide file tree
Showing 5 changed files with 191 additions and 15 deletions.
22 changes: 18 additions & 4 deletions css/grover-figures.css
Original file line number Diff line number Diff line change
@@ -1,13 +1,27 @@
body {
font-family: "Computer Modern Serif";
div.svg-fig {
width: 55%;
padding: 5px 0 20px 0;
}

.circ-label {
div.svg-fig .fig-caption {
padding: 0 20px;
font-size: 14px;
}

div.svg-fig svg#fig1 {
font-family: "Roboto";
font-size: 11px;
display: block;
margin-left: 25px;
}

div.svg-fig svg#fig1 .circ-label {
fill: white;
pointer-events: none;
}

#tooltip text {
div.svg-fig svg#fig1 #tooltip text {
font-family: "Inconsolata", sans-serif;
font-weight: bold;
font-size: 13.5px;
}
34 changes: 28 additions & 6 deletions groverSearch.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@
<title>Grover's Search Algorithm</title>
<link rel="stylesheet" href="css/Serif/cmun-serif.css"/>
<link rel="stylesheet" href="css/tufte.css"/>
<link rel="stylesheet" href="css/grover-figures.css"/>
<link href='https://fonts.googleapis.com/css?family=Inconsolata' rel='stylesheet' type='text/css'>
<link href='https://fonts.googleapis.com/css?family=Roboto' rel='stylesheet' type='text/css'>

<script type="text/x-mathjax-config">
MathJax.Hub.Config({
Expand All @@ -21,6 +24,14 @@
});
</script>
<script type="text/javascript" async src="https://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS_HTML"></script>

<script src="https://d3js.org/d3.v3.min.js" charset="utf-8"></script>

<!-- Global D3 variables etc -->
<script type="text/javascript">
var n_bits = 4; // Number of qubits
</script>

<body>

<div id = "tufte_container"><h1 id="grovers-search-algorithm">Grover’s Search Algorithm</h1>
Expand All @@ -33,7 +44,18 @@ <h2 id="constructing-the-algorithm">Constructing the Algorithm</h2>
1 &amp; x = x_0 \\
0 &amp; x \neq x_0
\end{cases}\]</span></p>
<p>And so the search problem is to apply the oracle to successive values of <span class="math">\(x\)</span> until it returns 1 (the needle is found). As this is a quantum algorithm, we need to make the oracle work on quantum states and so we define an <em>oracle operator</em> <span class="math">\(O\)</span>:</p>
<p>And so the search problem is to apply the oracle to successive values of <span class="math">\(x\)</span> until it returns 1 (the needle is found).</p>

<!-- Figure 1 -->
<div class="svg-fig">
<svg id="fig1"></svg>
<div class="fig-caption">
<strong>Figure 1.</strong> We will illustrate the Grover search for the case of <span class="math">\(N=16\)</span> (ie with 4 qubits). Select the needle that we will find by clicking on the respective circle above. You can see the binary representation of its index by hovering over the circle.
</div>
</div>
<script type="text/javascript" src="js/fig1.js"></script>

<p>As this is a quantum algorithm, we need to make the oracle work on quantum states and so we define an <em>oracle operator</em> <span class="math">\(O\)</span>:</p>
<p><span class="math">\[O( \ket{x} \ket{b} ) = \ket{x} \ket{b \oplus f(x)}\]</span></p>
<p>Where <span class="math">\(\ket{b}\)</span> is the <em>oracle qubit</em> and <span class="math">\(\oplus\)</span> denotes binary modular addition<sup>2</sup><span class="marginnote">2. Modular addition is like normal addition except the number line is periodic - when we reach a certain value we go back to the beginning. For example, on a 12-hour clock if we add 6 hours to 11 then rather than getting 17, we get <span class="math">\(11 + 6 \pmod {12} = 5\)</span>. Our oracle operator, as with most of information theory, uses addition modulo 2 - the only numbers we’re allowed are 0 and 1! For example, <span class="math">\(1 \oplus 0 = 1 \pmod 2 = 1\)</span>, but <span class="math">\(1 \oplus 1 = 2 \pmod 2 = 0\)</span>.</span>.</p>
<p>Now we perform the first “quantum” step: say that we put the oracle qubit <span class="math">\(\ket{b}\)</span> in the <span class="math">\(\ket{-}\)</span> state, equal to <span class="math">\((\ket{0} - \ket{1})/\sqrt{2}\)</span>. Now the action of the oracle operator is:</p>
Expand Down Expand Up @@ -76,9 +98,9 @@ <h2 id="performing-the-search">Performing the search</h2>
<li>After our repeated application of step 3, we should have <span class="math">\[\ket{\psi_4} \approx \ket{x_0}\ket{-}\]</span> And so we measure the <span class="math">\(n\)</span> haystack qubits (ignoring the oracle qubit as its work is done) and obtain the needle <span class="math">\(x_0\)</span> with high probability.</li>
</ol></div>
<p>The repeated sign changes of the needle state combined with the flips about the mean increase the needle state’s amplitude compared to the rest of the haystack. When this is sufficiently high, a measurement on the haystack qubits will return the needle state with high probability (<span class="math">\(\propto [\text{needle amplitude}]^2\)</span>).</p>
<h3 id="how-many-iterations">How many iterations?</h3>
<h2 id="how-many-iterations">How many iterations?</h2>
<p>We said that it is necessary to apply step 3 some number <span class="math">\(R\)</span> of times in order to obtain the needle state with sufficiently high probability. We’ll now look at what value <span class="math">\(R\)</span> might take.</p>
<p>First, write our initial state as: <span class="math">\[\ket{\psi} = \nu_0 \ket{x_0} + \sum_{x \neq x_0} \eta_0 \ket{x}\]</span> Where the subscripts on <span class="math">\(\nu\)</span> and <span class="math">\(\eta\)</span> denote the number of grover iterations performed. Referring to Step 2 of the above, note that <span class="math">\(\nu_0 = \eta_0 = 1/\sqrt{N}\)</span>. Now consider the action of the grover iteration on the <span class="math">\(\nu_j\)</span> and <span class="math">\(\eta_j\)</span>:</p>
<p>First, write our initial state as: <span class="math">\[\ket{\psi} = \nu_0 \ket{x_0} + \sum_{x \neq x_0} \eta_0 \ket{x}\]</span> Where the subscripts on <span class="math">\(\nu\)</span> and <span class="math">\(\eta\)</span> denote the number of Grover iterations performed. Referring to Step 2 of the above, note that <span class="math">\(\nu_0 = \eta_0 = 1/\sqrt{N}\)</span>. Now consider the action of the Grover iteration on the <span class="math">\(\nu_j\)</span> and <span class="math">\(\eta_j\)</span>:</p>
<div class="list-container"><ol style="list-style-type: lower-roman">
<li>Action of the oracle is denoted by a prime: <span class="math">\[\nu_j^\prime = -\nu_j\]</span></li>
<li>Inversion about the mean. Call the mean <span class="math">\(\mu\)</span>: <span class="math">\[\mu_i = \frac{1}{N}(\nu_i + (N-1)\eta_i) = \frac{\nu_i - \eta_i}{N} + \eta_i\]</span> And so we can see that <span class="math">\[\begin{align}
Expand All @@ -90,7 +112,7 @@ <h3 id="how-many-iterations">How many iterations?</h3>
&amp; = -\frac{2}{N} \nu_j + \frac{N-2}{N} \eta_j
\end{align}\]</span></li>
</ol></div>
<p>It is rather difficult to solve these recurrence relations, but their solutions are given in Ref [<span class="citation">3</span>]. The solutions are: <span class="math">\[\begin{align} \nu_j &amp; = \sin([2j+1]\theta) \\ \eta_j &amp; = \frac{1}{\sqrt{N-1}}\cos([2j+1]\theta) \end{align}\]</span> Where <span class="math">\(\sin^2 \theta = 1/N\)</span>. That these are the correct solutions can be proved by induction<sup>6</sup><span class="marginnote">6. We prove as follows.<br/> <strong>Basis case</strong>. Set <span class="math">\(j=0\)</span>. Now insert into the solution: <span class="math">\[\begin{align} \nu_0 &amp; = \sin(\theta) \\
<p>It is rather difficult to solve these recurrence relations, but their solutions are given in Ref [<span class="citation">3</span>]. The solutions are: <span class="math">\[\begin{align} \nu_j &amp; = \sin([2j+1]\theta) \\ \eta_j &amp; = \frac{1}{\sqrt{N-1}}\cos([2j+1]\theta) \end{align}\]</span> Where <span class="math">\(\sin^2 \theta = 1/N\)</span>. The validity of these solutions can be proven by induction<sup>6</sup><span class="marginnote">6. We prove as follows.<br/> <strong>Basis case</strong>. Set <span class="math">\(j=0\)</span>. Now insert into the solution: <span class="math">\[\begin{align} \nu_0 &amp; = \sin(\theta) \\
&amp; = \sin(\arcsin(\frac{1}{\sqrt{N}})) \\
&amp; = \frac{1}{\sqrt{N}} \\
\eta_0 &amp; = \frac{1}{\sqrt{N-1}}\cos(\theta) \\
Expand All @@ -101,14 +123,14 @@ <h3 id="how-many-iterations">How many iterations?</h3>
&amp; = \sin([2j + 1]\theta + 2\theta) \\
&amp; = \sin([2j + 1]\theta) \cos(2\theta) + \cos([2j + 1]\theta) \sin(2 \theta) \\
&amp; = \nu_j (\cos^2\theta - \sin^2\theta) + \sqrt{N-1} \eta_j (2 \cos\theta \sin\theta) \\
&amp; = \nu_j (\frac{N-1}{N} - \frac{1}{N}) + \sqrt{N-1} \eta_j (2 \sqrt{\frac{N-1}{N}} \sqrt{1}{N}) \\
&amp; = \nu_j (\frac{N-1}{N} - \frac{1}{N}) + \sqrt{N-1} \eta_j (2 \sqrt{\frac{N-1}{N}} \frac{1}{\sqrt{N}}) \\
&amp; = \frac{N-2}{N} \nu_j + \frac{2(N-1)}{N} \eta_j \\
\eta_{j+1} &amp; = \frac{1}{\sqrt{N-1}} \cos([2(j+1) + 1]\theta) \\
&amp; = \frac{1}{\sqrt{N-1}} \cos([2j + 1]\theta + 2 \theta) \\
&amp; = \frac{1}{\sqrt{N-1}} \big( \cos([2j+1]\theta) \cos(2\theta) - \sin([2j+1]\theta) \sin(2\theta) \big) \\
&amp; = \frac{1}{\sqrt{N-1}} ( \sqrt{N-1} \eta_j \frac{N-2}{N} - 2 \nu_j \frac{\sqrt{N-1}}{N} ) \\
&amp; = -\frac{2}{N} \nu_j + \frac{N-2}{N} \eta_j
\end{align}\]</span> Q.E.D.</span>. As we want to maximise the probability of measuring the needle, we clearly want to maximise <span class="math">\(\nu_j\)</span>. The maximum of <span class="math">\(\sin(x)\)</span> is at <span class="math">\(x = \pi/2\)</span> and so we want <span class="math">\((2j + 1)\theta = \pi/2\)</span>. Considering that <span class="math">\(j\)</span> must be an integer, we want: <span class="math">\[j = \left \lfloor \frac{\pi - 2\theta}{4\theta} \right \rfloor\]</span> Now see that since <span class="math">\(\sin\theta \approx \theta\)</span> for small <span class="math">\(\theta\)</span> and recalling that <span class="math">\(\sin\theta = 1/\sqrt{N}\)</span>: <span class="math">\[j \approx \left \lfloor \frac{\pi - 2/\sqrt{N}}{4/\sqrt{N}} \right \rfloor \approx \frac{\pi}{4}\sqrt{N}\]</span> And thus we choose <span class="math">\(R\)</span> to be the above value. Note an interesting - and characteristically quantum - implication of the sinusoidal form for <span class="math">\(\nu_j\)</span>: we can perform too many iterations of the algorithm! In the classical world we’d expect our extra work to reap us some reward (or at least not to make things <em>worse</em>) but here the performance of the algorithm is periodic in <span class="math">\(R\)</span> so we need to stop at exactly the right point.</p>
\end{align}\]</span> Q.E.D.</span>. As we want to maximise the probability of measuring the needle, we clearly want to maximise <span class="math">\(\nu_j\)</span>. The maximum of <span class="math">\(\sin(x)\)</span> is at <span class="math">\(x = \pi/2\)</span> and so we want <span class="math">\((2j + 1)\theta = \pi/2\)</span>. Considering that <span class="math">\(j\)</span> must be an integer, we want: <span class="math">\[j = \left \lfloor \frac{\pi - 2\theta}{4\theta} \right \rfloor\]</span> Now see that since <span class="math">\(\sin\theta \approx \theta\)</span> for small <span class="math">\(\theta\)</span> and recalling that <span class="math">\(\sin\theta = 1/\sqrt{N}\)</span>: <span class="math">\[j \approx \left \lfloor \frac{\pi - 2/\sqrt{N}}{4/\sqrt{N}} \right \rfloor \approx \left \lfloor \frac{\pi}{4}\sqrt{N} \right \rfloor\]</span> And thus we choose <span class="math">\(R\)</span> to be the above value. Note an interesting - and characteristically quantum - implication of the sinusoidal form for <span class="math">\(\nu_j\)</span>: we can perform too many iterations of the algorithm! In the classical world we’d expect our extra work to reap us some reward (or at least not to make things <em>worse</em>) but here the performance of the algorithm is periodic in <span class="math">\(R\)</span> so we need to stop at exactly the right point in order to find our needle.</p>
<div class="references">
<h2>References</h2>
<p>[1]L. K. Grover, “Quantum Mechanics Helps in Searching for a Needle in a Haystack,” <em>Phys. Rev. Lett.</em>, vol. 79, no. 2, pp. 325–328, Jul. 1997.</p>
Expand Down
131 changes: 131 additions & 0 deletions js/fig1.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
var h_stack = 90; // SVG canvas size
var w_stack = 580;
var y_origin = 40; // What we will use as the origin for the y-axis

var w_tip = 35; // Tooltip dimensions
var h_tip = 17;

var n_circs = Math.pow(2, n_bits); // N
var circ_dat = new Array(n_circs).fill(0);
var chosen = -1; // Haven't picked a circle yet
var circ_r = 13;

// Helper for drawing straight lines
function myLine(svgHandle, startCoord, endCoord) {
svgHandle.append("line").style("stroke", "gray")
.attr("x1", startCoord[0]).attr("y1", startCoord[1])
.attr("x2", endCoord[0]).attr("y2", endCoord[1])
.attr("opacity", 0.25);
}

// Helper for translating groups
function gpos(x, y) {
return "translate(" + x + "," + y + ")";
}

// Create canvas
var svg = d3.select("#fig1").attr("width", w_stack).attr("height", h_stack);

// Draw some "axis" lines
myLine(svg, [0.5, y_origin], [w_stack - 0.5, y_origin]);
myLine(svg, [0.5, y_origin + 4], [0.5, y_origin - 4]);
myLine(svg, [w_stack - 0.5, y_origin + 4], [w_stack - 0.5, y_origin - 4]);

/// Create our 3 main components: the circes, their text, and the tooltip
var circs = svg.append("g").attr("id", "circs").selectAll("circle").data(circ_dat).enter().append("circle");
var labels = svg.append("g").attr("id", "circ-labels").selectAll("text")
.data(circ_dat).enter().append("text").attr("class", "circ-label");
var tooltip = svg.append("g").attr("id", "tooltip")
.style("opacity", 0)
.attr("transform", gpos(-w_tip - 1, y_origin + h_tip));
tooltip.append("rect")
.attr("width", w_tip)
.attr("height", h_tip)
.attr("rx", 3)
.attr("ry", 3)
.style("fill", "lightgrey")
tooltip.append("text")
.text("000")
.attr("text-anchor", "middle")
.attr("x", (w_tip / 2.0) - 0.5)
.attr("y", h_tip - 4);

// Given a base-10 number, returns a string of the binary representation
function dec2bin(dec) {
var bitstring = "";
var pad = new Array(n_bits).fill(0).join('');
while (dec > 0) {
var bit = dec % 2;
var quot = Math.floor(dec / 2);
bitstring = bit.toString() + bitstring;
dec = quot;
}
return pad.substring(0, n_bits - bitstring.length) + bitstring;
}

// Calculates the coordinate of the centre of a circle (evenly spaced)
function circX(i) {
var spacing = (w_stack - 3*circ_r) / (n_circs - 1);
return i*spacing + 1.5*circ_r;
}

// Set up circles
circs.attr("cx", function(val, i) { return circX(i); })
.attr("cy", y_origin)
.attr("r", circ_r)
.attr("fill", "black")
.attr("opacity", 0.85)
.on("mouseover", function(val, i) {
d3.select(this)
.transition()
.duration(100)
.attr("cy", y_origin - 8) // Move up
.attr("r", circ_r + 3); // Grow slightly
d3.select(labels[0][i])
.transition()
.duration(100)
.attr("y", y_origin - 3); // Move label as well

d3.select("#tooltip text").html(dec2bin(i)); // Change tooltip text to binary representation of this bit

d3.select("#tooltip")
.attr("transform", gpos(circX(i) - 0.5*w_tip, y_origin + h_tip)) // Move tooltip
.transition()
.duration(100)
.style("opacity", 1); // Show tooltip
})
.on("mouseout", function(val, i) { // Note that these transitions are slower than their inverse (mouseover)
d3.select(this)
.transition()
.duration(200)
.attr("cy", y_origin) // Move back down
.attr("r", function() { return i == chosen ? circ_r + 3 : circ_r; }); // Return to original size
d3.select(labels[0][i])
.transition()
.duration(200)
.attr("y", y_origin + 5); // Move back down

d3.select("#tooltip")
.transition()
.duration(200)
.style("opacity", 0); // Hide tooltip again
})
.on("click", function(val, i) { // Make the clicked circle grey
chosen = i;
d3.select(".chosen-circ") // Un-grey any previously clicked circle
.transition()
.duration(100)
.attr("class", "")
.style("fill", "black")
.attr("r", circ_r);
d3.select(this)
.transition()
.duration(100)
.attr("class", "chosen-circ")
.style("fill", "gray");
});

labels.text(function(val, i) { return i; }) // Put the labels in the right place
.attr("text-anchor", "middle")
.attr("x", function(val, i) { return circX(i); })
.attr("y", y_origin + 4);
Loading

0 comments on commit 44e58a9

Please sign in to comment.