-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathrandom_walk_qpe.py
100 lines (84 loc) · 2.79 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
"""
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.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()