microsoft/qdk

Public

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

CodeCommitsIssuesPull requestsActionsInsightsSecurity
fedimser/memory-re

Branches

Tags

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

Clone

HTTPS

Download ZIP

samples/algorithms/Grover.qs

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