microsoft/qdk

Public

mirrored fromhttps://github.com/microsoft/qdkAvailable

CodeCommitsIssuesPull requestsActionsInsightsSecurity
v1.1.1

Branches

Tags

  • No tags available.
0Branches0Tags
Go to file
Add file
Code

Clone

HTTPS

Download ZIP

samples/algorithms/Grover.qs

125lines · modecode

1/// # Sample
2/// Grover's search algorithm
3///
4/// # Description
5/// Grover's search algorithm is a quantum algorithm that finds with high
6/// probability the unique input to a black box function that produces a
7/// particular output value.
8///
9/// This Q# program implements the Grover's search algorithm.
10namespace Sample {
11 open Microsoft.Quantum.Convert;
12 open Microsoft.Quantum.Math;
13 open Microsoft.Quantum.Arrays;
14 open Microsoft.Quantum.Measurement;
15 open Microsoft.Quantum.Diagnostics;
16
17 @EntryPoint()
18 operation Main() : Result[] {
19 let nQubits = 5;
20
21 // Grover's algorithm relies on performing a "Grover iteration" an
22 // optimal number of times to maximize the probability of finding the
23 // value we are searching for.
24 // You can set the number iterations to a value lower than optimal to
25 // intentionally reduce precision.
26 let iterations = CalculateOptimalIterations(nQubits);
27 Message($"Number of iterations: {iterations}");
28
29 // Use Grover's algorithm to find a particular marked state.
30 let results = GroverSearch(nQubits, iterations, ReflectAboutMarked);
31 return results;
32 }
33
34 /// # Summary
35 /// Implements Grover's algorithm, which searches all possible inputs to an
36 /// operation to find a particular marked state.
37 operation GroverSearch(
38 nQubits : Int,
39 iterations : Int,
40 phaseOracle : Qubit[] => Unit) : Result[] {
41
42 use qubits = Qubit[nQubits];
43
44 // Initialize a uniform superposition over all possible inputs.
45 PrepareUniform(qubits);
46
47 // The search itself consists of repeatedly reflecting about the marked
48 // state and our start state, which we can write out in Q# as a for loop.
49 for _ in 1..iterations {
50 phaseOracle(qubits);
51 ReflectAboutUniform(qubits);
52 }
53
54 // Measure and return the answer.
55 return MResetEachZ(qubits);
56 }
57
58 /// # Summary
59 /// Returns the optimal number of Grover iterations needed to find a marked
60 /// item, given the number of qubits in a register.
61 function CalculateOptimalIterations(nQubits : Int) : Int {
62 if nQubits > 63 {
63 fail "This sample supports at most 63 qubits.";
64 }
65 let nItems = 1 <<< nQubits; // 2^nQubits
66 let angle = ArcSin(1. / Sqrt(IntAsDouble(nItems)));
67 let iterations = Round(0.25 * PI() / angle - 0.5);
68 return iterations;
69 }
70
71 /// # Summary
72 /// Reflects about the basis state marked by alternating zeros and ones.
73 /// This operation defines what input we are trying to find in the search.
74 operation ReflectAboutMarked(inputQubits : Qubit[]) : Unit {
75 Message("Reflecting about marked state...");
76 use outputQubit = Qubit();
77 within {
78 // We initialize the outputQubit to (|0⟩ - |1⟩) / √2, so that
79 // toggling it results in a (-1) phase.
80 X(outputQubit);
81 H(outputQubit);
82 // Flip the outputQubit for marked states.
83 // Here, we get the state with alternating 0s and 1s by using the X
84 // operation on every other qubit.
85 for q in inputQubits[...2...] {
86 X(q);
87 }
88 } apply {
89 Controlled X(inputQubits, outputQubit);
90 }
91 }
92
93 /// # Summary
94 /// Given a register in the all-zeros state, prepares a uniform
95 /// superposition over all basis states.
96 operation PrepareUniform(inputQubits : Qubit[]) : Unit is Adj + Ctl {
97 for q in inputQubits {
98 H(q);
99 }
100 }
101
102 /// # Summary
103 /// Reflects about the all-ones state.
104 operation ReflectAboutAllOnes(inputQubits : Qubit[]) : Unit {
105 Controlled Z(Most(inputQubits), Tail(inputQubits));
106 }
107
108 /// # Summary
109 /// Reflects about the uniform superposition state.
110 operation ReflectAboutUniform(inputQubits : Qubit[]) : Unit {
111 within {
112 // Transform the uniform superposition to all-zero.
113 Adjoint PrepareUniform(inputQubits);
114 // Transform the all-zero state to all-ones
115 for q in inputQubits {
116 X(q);
117 }
118 } apply {
119 // Now that we've transformed the uniform superposition to the
120 // all-ones state, reflect about the all-ones state, then let the
121 // within/apply block transform us back.
122 ReflectAboutAllOnes(inputQubits);
123 }
124 }
125}
126