-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathGrover with multiple solutions.slq
86 lines (72 loc) · 2.15 KB
/
Grover with multiple solutions.slq
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
// Grover's algorithm for a known number (M) of solutions
// - Returns one of the x for which f(x) = 1
//
// - More detailed description: https://arxiv.org/ftp/arxiv/papers/0705/0705.4171.pdf
// Grover Diffusion Operator
def groverDiffusion[n:!ℕ](cand:uint[n])mfree: uint[n]{
for k in [0..n) { cand[k] := H(cand[k]); }
if cand!=0{ phase(π); }
for k in [0..n) { cand[k] := H(cand[k]); }
return cand;
}
// Random number generators
def uniformInt(range:!ℕ){
// returns x~{0,...range-1}
n:=ceil(log(range)/log(2)) coerce !ℕ;
r:=range;
while (r>range-1) {
// rerolls r if it is greater than range
r=0;
for k in [0..n){
// rolls each bit of r
r+=2^k*rand();
}
}
return r;
}
def rand(){
// quantum number generator
return measure(H(false));
}
def grover_multiple[n:!ℕ](f: const uint[n] !→ lifted 𝔹, M:!ℕ):!ℕ{
nIterations:= round((π/4) * sqrt(2^n/M));
cand:=0:uint[n];
for k in [0..n) { cand[k] := H(cand[k]); }
for k in [0..nIterations){
if f(cand){
phase(π);
}
cand:=groverDiffusion(cand);
}
return measure(cand) as !ℕ;
}
/* EXAMPLE CALL */
def main(){
f := λ(x:uint[6])lifted:𝔹{ return x==4 || x==5 || x==6; };
// creates an oracle which outputs one only when x is in {4,5,6}
x := grover_multiple(f, 3);
assert(x==4 || x==5 || x==6);
// verifies that grover_multiple finds one of the right solutions
return x;
}
/* TEST */
// This function defines tests for Grover with respectively 2, 3 and 4 solutions
def test_grover_multiple() {
n := 6;
def f2(x:uint[n])lifted:𝔹{
return x==2 || x==3;
}
def f3(x:uint[n])lifted:𝔹{
return x==4 || x==5 || x==6;
}
def f4(x:uint[n])lifted:𝔹{
return x==7 || x==8 || x==9 || x==10;
} // creates oracles with respectively 2, 3 and 4 solutions
x := grover_multiple(f2, 2);
y := grover_multiple(f3, 3);
z := grover_multiple(f4, 4);
// verifies that grover_multiple finds one of the right solutions
assert(x==2 || x==3);
assert(y==4 || y==5 || y==6);
assert(z==7 || z==8 || z==9 || z==10);
}