-
Notifications
You must be signed in to change notification settings - Fork 3
/
random_walk_qpe.py
102 lines (85 loc) · 2.83 KB
/
random_walk_qpe.py
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
90
91
92
93
94
95
96
97
98
99
100
101
102
"""
Implementation of the adaptive random walk phase estimation algorithm from
https://arxiv.org/abs/2208.04526.
The example Hamiltonian and numbers are taken from https://arxiv.org/abs/2206.12950.
"""
import math
from collections.abc import Callable
from guppylang.decorator import guppy
from guppylang.module import GuppyModule
from guppylang.std.angles import angle
from guppylang.std.builtins import owned, py, result
from guppylang.std.quantum import discard, measure, qubit
from guppylang.std.quantum_functional import cx, h, rz, x
sqrt_e = math.sqrt(math.e)
sqrt_e_div = math.sqrt((math.e - 1) / math.e)
@guppy
def random_walk_phase_estimation(
eigenstate: Callable[[], qubit],
controlled_oracle: Callable[[qubit @owned, qubit @owned, float], tuple[qubit, qubit]],
num_iters: int,
reset_rate: int,
mu: float,
sigma: float,
) -> float:
"""Performs the random walk phase estimation algorithm on a single qubit for
some Hamiltonian H.
Arguments:
eigenstate: Function preparing the eigenstate of e^itH
controlled_oracle: The oracle circuit for a controlled e^itH
num_iters: Number of iterations to run the algorithm for
reset_rate: Reset the eigenstate every x iterations
mu: Initial mean for the eigenvalue estimate
sigma: Initial standard deviation for the eigenvalue estimate
"""
tgt = eigenstate()
i = 0
while i < num_iters:
aux = h(qubit())
t = 1 / sigma
aux = rz(h(aux), angle((sigma - mu) * t))
aux, tgt = controlled_oracle(aux, tgt, t)
if measure(h(aux)):
mu += sigma / py(sqrt_e)
else:
mu -= sigma / py(sqrt_e)
sigma *= py(sqrt_e_div)
# Reset the eigenstate every few iterations to increase the fidelity of
# the algorithm
if i % reset_rate == 0:
discard(tgt)
tgt = eigenstate()
i += 1
discard(tgt)
return mu
@guppy
def example_controlled_oracle(q1: qubit @owned, q2: qubit @owned, t: float) -> tuple[qubit, qubit]:
"""A controlled e^itH gate for the example Hamiltonian H = -0.5 * Z"""
# This is just a controlled rz gate
a = angle(-0.5 * t)
q2 = rz(q2, a / 2)
q1, q2 = cx(q1, q2)
q2 = rz(q2, -a / 2)
return cx(q1, q2)
@guppy
def example_eigenstate() -> qubit:
"""The eigenstate of e^itH for the example Hamiltonian H = -0.5 * Z"""
# This is just |1>
return x(qubit())
@guppy
def main() -> int:
num_iters = 24 # To avoid underflows
reset_rate = 8
mu = py(sqrt_e)
sigma = py(sqrt_e_div)
eigenvalue = random_walk_phase_estimation(
example_eigenstate,
example_controlled_oracle,
num_iters,
reset_rate,
mu,
sigma,
)
result("eigenvalue", eigenvalue) # Expected outcome is 0.5
return 0
hugr = guppy.compile_module()