@@ -24,54 +24,20 @@ namespace Quantum.Kata.Counting {
24
24
// Part I. Oracle for Counting
25
25
//////////////////////////////////////////////////////////////////
26
26
27
- // Task 1.1. The Sprinkler oracle
28
- // Let us consider an example inspired by the sprinkler problem of (Pearl 1988):
29
- // we have three Boolean variable, s, r, w representing respectively propositions
30
- // “the sprinkler was on”, "ıt rained last night” and “the grass is wet”.
31
- // We know that if the sprinkler was on the grass is wet (s → w),
32
- // if it rained last night the grass is wet (r → w)
33
- //and that the the sprinkler being on and rain last night cannot be true at the same time (s, r →).
34
- // Transformed in conjunctive normal formal we obtain formula (¬s ∨ w) ∧ (¬r ∨ w) ∧ (¬s ∨ ¬r)
35
- // Let s,r,w=queryRegister[0],queryRegister[1],queryRegister[2]
36
- operation Oracle_Sprinkler_Reference (queryRegister : Qubit [], target : Qubit , ancilla : Qubit []) : Unit
37
- {
38
- body (... ) {
39
- X (queryRegister [2 ]);
40
- X (ancilla [0 ]);
41
- X (ancilla [1 ]);
42
- X (ancilla [2 ]);
43
-
44
- CCNOT (queryRegister [0 ],queryRegister [1 ],ancilla [0 ]);
45
- CCNOT (queryRegister [1 ],queryRegister [2 ],ancilla [1 ]);
46
- CCNOT (queryRegister [0 ],queryRegister [2 ],ancilla [2 ]);
47
- (Controlled X )([ancilla [0 ],ancilla [1 ],ancilla [2 ]],target );
48
- CCNOT (queryRegister [0 ],queryRegister [2 ],ancilla [2 ]);
49
- CCNOT (queryRegister [1 ],queryRegister [2 ],ancilla [1 ]);
50
- CCNOT (queryRegister [0 ],queryRegister [1 ],ancilla [0 ]);
51
-
52
- X (ancilla [2 ]);
53
- X (ancilla [1 ]);
54
- X (ancilla [0 ]);
55
- }
56
- adjoint invert ;
57
- controlled auto ;
58
- controlled adjoint auto ;
59
- }
60
-
61
-
62
-
63
-
64
- // Arbitrary bit pattern oracle
65
- operation Oracle_ArbitraryPattern_Reference (queryRegister : Qubit [], target : Qubit , pattern : Bool []) : Unit
66
- is Adj + Ctl {
67
- (ControlledOnBitString (pattern , X ))(queryRegister , target );
68
- }
69
-
27
+ operation Oracle_SolutionCount_Reference (queryRegister : Qubit [], target : Qubit , nSol : Int ) : Unit is Ctl + Adj {
28
+ // Designate first nSol integers solutions (since we don't really care which ones are solutions)
29
+ for (i in 0 .. nSol - 1 ) {
30
+ (ControlledOnInt (i , X ))(queryRegister , target );
31
+ }
32
+ }
70
33
71
- // Oracle converter
72
- operation OracleConverterImpl (markingOracle : ((Qubit [], Qubit ) => Unit is Adj + Ctl ), register : Qubit []) : Unit
73
- is Adj + Ctl {
74
-
34
+ //////////////////////////////////////////////////////////////////
35
+ // Part II. The Grover iteration
36
+ //////////////////////////////////////////////////////////////////
37
+
38
+
39
+ // Helper operation which converts marking oracle into phase oracle using an extra qubit
40
+ operation ApplyMarkingOracleAsPhaseOracle (markingOracle : ((Qubit [], Qubit ) => Unit is Ctl + Adj ), register : Qubit []) : Unit is Adj + Ctl {
75
41
using (target = Qubit ()) {
76
42
// Put the target into the |-⟩ state
77
43
X (target );
@@ -87,111 +53,54 @@ namespace Quantum.Kata.Counting {
87
53
}
88
54
}
89
55
90
-
91
- function OracleConverter (markingOracle : ((Qubit [], Qubit ) => Unit is Adj + Ctl )) : (Qubit [] => Unit is Adj + Ctl ) {
92
- return OracleConverterImpl (markingOracle , _ );
93
- }
94
-
95
-
96
- //////////////////////////////////////////////////////////////////
97
- // Part II. The Grover iteration
98
- //////////////////////////////////////////////////////////////////
99
-
100
- // The Hadamard transform
101
- operation HadamardTransform (register : Qubit []) : Unit
102
- is Adj + Ctl {
103
-
104
- // ApplyToEachA(H, register);
105
-
106
- // ApplyToEach is a library routine that is equivalent to the following code:
107
- let nQubits = Length (register );
108
- for (idxQubit in 0 .. nQubits - 1 ) {
109
- H (register [idxQubit ]);
110
- }
111
- }
112
-
113
-
114
- // Conditional phase flip
115
- operation ConditionalPhaseFlip (register : Qubit []) : Unit {
116
-
117
- body (... ) {
118
- // Define a marking oracle which detects an all zero state
119
- let allZerosOracle = Oracle_ArbitraryPattern_Reference (_ , _ , new Bool [Length (register )]);
120
-
121
- // Convert it into a phase-flip oracle and apply it
122
- let flipOracle = OracleConverter (allZerosOracle );
123
- flipOracle (register );
124
- R (PauliI , 2.0 * PI (), register [0 ]);
125
- }
126
-
127
- adjoint self ;
128
- controlled auto ;
129
- controlled adjoint auto ;
130
- }
131
-
132
-
133
-
134
-
135
56
// The Grover iteration
136
- operation GroverIteration (register : Qubit [], oracle : (Qubit [] => Unit is Adj + Ctl )) : Unit
57
+ operation GroverIteration (register : Qubit [], oracle : (( Qubit [], Qubit ) => Unit is Ctl + Adj )) : Unit is Ctl + Adj
137
58
{
138
- body ( ... ) {
139
- oracle ( register );
140
- HadamardTransform ( register );
141
- ConditionalPhaseFlip ( register );
142
- HadamardTransform ( register );
143
- }
144
- adjoint auto ;
145
- controlled auto ;
146
- controlled adjoint auto ;
59
+
60
+ // apply oracle
61
+ ApplyMarkingOracleAsPhaseOracle ( oracle , register );
62
+ // apply inversion about the mean
63
+ ApplyToEachCA ( H , register );
64
+ ApplyToEachCA ( X , register );
65
+ Controlled Z ( Most ( register ), Tail ( register )) ;
66
+ ApplyToEachCA ( X , register ) ;
67
+ ApplyToEachCA ( H , register ) ;
147
68
}
148
69
149
70
150
71
//////////////////////////////////////////////////////////////////
151
72
// Part III. Putting it all together: Quantum Counting
152
73
//////////////////////////////////////////////////////////////////
153
74
154
- operation UnitaryPowerImpl (U : (Qubit [] => Unit is Adj + Ctl ), power : Int , q : Qubit []) : Unit {
155
- body (... ) {
156
- for (i in 1 .. power ) {
157
- U (q );
158
- }
159
- }
160
- adjoint auto ;
161
- controlled auto ;
162
- controlled adjoint auto ;
163
- }
164
75
165
- operation Counting_Reference () : Double {
76
+ operation Counting_Reference (n_bit : Int , n_sol : Int , precision : Int ) : Double {
166
77
mutable phase = - 1.0 ;
167
- let n = 4 ;
168
- using ((reg ,phaseRegister ,ancilla )= (Qubit [3 ],Qubit [n ],Qubit [3 ]))
169
- {
170
- // Construct a phase estimation oracle from the unitary
171
- let phaseOracle = OracleConverter (Oracle_Sprinkler_Reference (_ ,_ ,ancilla ));
172
78
173
- let oracle = DiscreteOracle (UnitaryPowerImpl (GroverIteration (_ , phaseOracle ), _ , _ ));
79
+ using ((reg ,phaseRegister )= (Qubit [n_bit ],Qubit [precision ]))
80
+ {
81
+ let oracle = OracleToDiscrete (GroverIteration (_ , Oracle_SolutionCount_Reference (_ ,_ ,n_sol )));
174
82
175
83
176
84
// Allocate qubits to hold the eigenstate of U and the phase in a big endian register
177
85
178
86
let phaseRegisterBE = BigEndian (phaseRegister );
179
87
// Prepare the eigenstate of U
180
- HadamardTransform (reg );
181
- //should return 0.5
88
+ ApplyToEach (H , reg );
182
89
// Call library
183
90
QuantumPhaseEstimation (oracle , reg , phaseRegisterBE );
184
91
// Read out the phase
185
- set phase = IntAsDouble (MeasureInteger (BigEndianAsLittleEndian (phaseRegisterBE ))) / IntAsDouble (1 <<< (n ));
92
+ set phase = IntAsDouble (MeasureInteger (BigEndianAsLittleEndian (phaseRegisterBE ))) / IntAsDouble (1 <<< (n_bit ));
186
93
187
94
ResetAll (reg );
188
95
ResetAll (phaseRegister );
189
96
}
190
97
let angle = PI ()* phase ;
191
98
let res = (PowD (Sin (angle ),2.0 ));
192
99
193
- return 8.0 * res ;
100
+ return PowD ( 2.0 , IntAsDouble ( n_bit )) * res ;
194
101
}
195
102
196
-
103
+ operation CR (): Double {
104
+ return Counting_Reference (4 , 4 , 3 );
105
+ }
197
106
}
0 commit comments