-
Notifications
You must be signed in to change notification settings - Fork 0
/
gaussian_gr.qs
89 lines (75 loc) · 2.78 KB
/
gaussian_gr.qs
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
87
88
89
/// This Q# program sets a qubit register in a Gaussian superposition
/// using the [Grover-Rudolph algorithm](arXiv:quant-ph/0208112)
/// implemented by [Klco et. al.](arXiv:1904.10440)
namespace Gaussian {
open Microsoft.Quantum.ResourceEstimation;
open Microsoft.Quantum.Diagnostics;
open Microsoft.Quantum.Arrays;
open Microsoft.Quantum.Convert;
open Microsoft.Quantum.Math;
open Microsoft.Quantum.Measurement;
@EntryPoint()
operation GaussianStatePrepGR() : Int {
// Set number of qubits
let n = 4;
use reg = Qubit[n];
GroverRudolphStatePrep(reg);
DumpMachine();
// Measure the qubits.
let m = MeasureInteger(reg);
BoolArrayAsInt(Reversed(IntAsBoolArray(m, n)))
}
operation GroverRudolphStatePrep(reg : Qubit[]) : Unit is Adj + Ctl {
let angles = GenAngles(Length(reg));
Ry(angles[0][0], reg[0]);
for l in 1..Length(reg) - 1 {
for i in 0..(1 <<< l) - 1 {
let bitArray = Reversed(IntAsBoolArray(i, l));
ApplyControlledOnBitString(bitArray, Ry, reg[0..l-1], (angles[l][i], reg[l]));
}
}
}
internal function GenAngles(n : Int) : Double[][] {
mutable angles : Double[][] = [[], size = n];
for l in 0..n - 1 {
mutable anglesInner : Double[] = [];
for k in 0..2 ^ l - 1 {
set anglesInner += [Theta(n, l, k)];
}
set angles w/= l <- anglesInner;
}
angles
}
internal function Theta(n : Int, l : Int, k : Int) : Double {
let xMin = (1 <<< (n - l - 1)) * (2 * k + 1);
let xMax = (1 <<< (n - l)) * (k + 1) - 1;
let yMin = k * (1 <<< (n - l));
let yMax = xMin - 1;
mutable ns : Double[] = [];
for x in xMin..xMax {
set ns += [Psi(n, x) ^ 2.0];
}
mutable ds : Double[] = [];
for y in yMin..yMax {
set ds += [Psi(n, y) ^ 2.0];
}
let sumN = Fold((x, y) -> x + y, 0.0, ns);
let sumD = Fold((x, y) -> x + y, 0.0, ds);
2.0 * ArcTan(Sqrt(sumN / sumD))
}
internal function Psi(n : Int, x : Int) : Double {
let N = 2 ^ n;
let muC = 1.0 - (1.0 / IntAsDouble(N));
let mu = IntAsDouble(2 ^ (n - 1)) * muC;
let sigmaC = 0.5;
let sigma = IntAsDouble(2 ^ (n - 1)) * sigmaC;
let sigmaSq = sigma ^ 2.0;
let xTerm = E() ^ (-((IntAsDouble(x) - mu) ^ 2.0) / (2.0 * sigmaSq));
mutable allTerms : Double[] = [];
for i in 0..N - 1 {
set allTerms += [E() ^ (-((IntAsDouble(i) - mu) ^ 2.0) / (2.0 * sigmaSq))];
}
let norm = Sqrt(Fold((x, y) -> x + y, 0.0, allTerms));
xTerm / norm
}
}