Skip to content
This repository was archived by the owner on Aug 21, 2024. It is now read-only.

Commit d5d5daf

Browse files
committed
first draft of Counting Kata
1 parent 397be16 commit d5d5daf

File tree

3 files changed

+39
-152
lines changed

3 files changed

+39
-152
lines changed

Counting/ReferenceImplementation.qs

Lines changed: 33 additions & 124 deletions
Original file line numberDiff line numberDiff line change
@@ -24,54 +24,20 @@ namespace Quantum.Kata.Counting {
2424
// Part I. Oracle for Counting
2525
//////////////////////////////////////////////////////////////////
2626

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+
}
7033

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 {
7541
using (target = Qubit()) {
7642
// Put the target into the |-⟩ state
7743
X(target);
@@ -87,111 +53,54 @@ namespace Quantum.Kata.Counting {
8753
}
8854
}
8955

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-
13556
// 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
13758
{
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);
14768
}
14869

14970

15071
//////////////////////////////////////////////////////////////////
15172
// Part III. Putting it all together: Quantum Counting
15273
//////////////////////////////////////////////////////////////////
15374

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-
}
16475

165-
operation Counting_Reference() : Double {
76+
operation Counting_Reference(n_bit : Int, n_sol: Int, precision: Int) : Double {
16677
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));
17278

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)));
17482

17583

17684
// Allocate qubits to hold the eigenstate of U and the phase in a big endian register
17785

17886
let phaseRegisterBE = BigEndian(phaseRegister);
17987
// Prepare the eigenstate of U
180-
HadamardTransform(reg);
181-
//should return 0.5
88+
ApplyToEach(H, reg);
18289
// Call library
18390
QuantumPhaseEstimation(oracle, reg, phaseRegisterBE);
18491
// 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));
18693

18794
ResetAll(reg);
18895
ResetAll(phaseRegister);
18996
}
19097
let angle = PI()*phase;
19198
let res = (PowD(Sin(angle),2.0));
19299

193-
return 8.0*res;
100+
return PowD(2.0,IntAsDouble(n_bit))*res;
194101
}
195102

196-
103+
operation CR(): Double {
104+
return Counting_Reference(4, 4, 3);
105+
}
197106
}

Counting/TestSuiteRunner.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
using Xunit.Abstractions;
1313
using System.Diagnostics;
1414

15-
namespace Quantum.Kata.GroversAlgorithm
15+
namespace Quantum.Kata.Counting
1616
{
1717
public class TestSuiteRunner
1818
{
@@ -25,7 +25,7 @@ public TestSuiteRunner(ITestOutputHelper output)
2525

2626
/// <summary>
2727
/// This driver will run all Q# tests (operations named "...Test")
28-
/// that belong to namespace Quantum.Kata.GroversAlgorithm.
28+
/// that belong to namespace Quantum.Kata.Counting.
2929
/// </summary>
3030
[OperationDriver(TestNamespace = "Quantum.Kata.Counting")]
3131
public void TestTarget(TestOperation op)

Counting/Tests.qs

Lines changed: 4 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -14,39 +14,17 @@ namespace Quantum.Kata.Counting {
1414
open Microsoft.Quantum.Diagnostics;
1515
open Microsoft.Quantum.Convert;
1616
open Microsoft.Quantum.Math;
17+
open Microsoft.Quantum.Intrinsic;
1718

1819

19-
// ------------------------------------------------------
20-
// helper wrapper to represent oracle operation on input and output registers as an operation on an array of qubits
21-
operation QubitArrayWrapperOperation (op : ((Qubit[], Qubit, Qubit[]) => Unit is Adj), qs : Qubit[]) : Unit
22-
is Adj {
23-
let reg= Partitioned([3,1],qs);
24-
op(reg[0], reg[1][0], reg[2]);
25-
}
26-
27-
28-
// ------------------------------------------------------
29-
// helper wrapper to test for operation equality on various register sizes
30-
operation AssertRegisterOperationsEqual (testOp : (Qubit[] => Unit), refOp : (Qubit[] => Unit is Adj)) : Unit {
31-
AssertOperationsEqualReferenced(7, testOp, refOp);
3220

33-
}
34-
35-
36-
// ------------------------------------------------------
37-
38-
operation T11_Oracle_Sprinkler_Test () : Unit {
39-
let testOp = QubitArrayWrapperOperation(Oracle_Sprinkler, _);
40-
let refOp = QubitArrayWrapperOperation(Oracle_Sprinkler_Reference, _);
41-
AssertRegisterOperationsEqual(testOp, refOp);
42-
}
43-
4421

4522

4623

4724
// ------------------------------------------------------
48-
operation T21_Counting_Test () : Unit {
49-
let reference=Counting();
25+
operation T11_Counting_Test () : Unit {
26+
let reference=Counting_Reference(4,4,3);
27+
// Message(DoubleAsString(reference));
5028
let actual=4.0;
5129
EqualityWithinToleranceFact(reference,actual,3.0);
5230
}

0 commit comments

Comments
 (0)