-
Notifications
You must be signed in to change notification settings - Fork 0
/
fquite_realtime.py
132 lines (113 loc) · 4.42 KB
/
fquite_realtime.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
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
import numpy as np
def gamma_opt(beta, AA=False):
coeff = 2
if AA:
coeff = 4
return beta / 2 * (np.sqrt(1 + coeff / beta) - 1)
def Qu(beta, gamma, eps=1e-3):
return 2.0 * (beta/gamma + 1.0) * np.log(4.0/eps)
def alpha_beta(beta):
return np.exp(-gamma_opt(beta))
class FragmentedQuITE:
def __init__(self, nqubits, energy, eps=1e-3):
"""Test function for optimization."""
self.n = nqubits
self.E = energy
self.Emin = np.min(self.E)
self.query = Qu
self.eps = eps
def compute_query(self, params, schedule, r, b, query_depth=False):
"""Compute query optimization."""
beta = np.array([ b * schedule(step/r, params) for step in range(1, r+1)])
alphab = alpha_beta(b)
DeltaBeta = np.diff(beta)
# k == 0
PsucBr = self.Psuc(beta[r-1], gamma_opt(beta[r-1]))
prod = alpha_beta(beta[0])
prod2 = alpha_beta(beta[0])**2
for k in range(r-1):
prod *= alpha_beta(DeltaBeta[k])
prod2 *= alpha_beta(DeltaBeta[k])**2
eps_prime = self.eps / (2 * 4.0**(r-1)) * np.sqrt(PsucBr) * prod / alphab
Sigma = self.query(beta[0]-0, gamma_opt(beta[0]-0), eps=eps_prime)
if not query_depth:
Sigma = Sigma / prod2
# k > 0
for k in range(r-1):
PsucBk = 1
if not query_depth:
PsucBk = self.Psuc(beta[k], gamma_opt(beta[k]))
prod = 1
prod2 = 1
for j in range(k, r-1):
prod *= alpha_beta(DeltaBeta[j])
prod2 *= alpha_beta(DeltaBeta[j])**2
eps_prime = self.eps / 4.0**(r-(k+1)) * np.sqrt(PsucBr/PsucBk) * prod * alpha_beta(beta[k]) / alphab
if query_depth:
Sigma += PsucBk * self.query(DeltaBeta[k], gamma_opt(DeltaBeta[k]), eps=eps_prime)
else:
Sigma += PsucBk * self.query(DeltaBeta[k], gamma_opt(DeltaBeta[k]), eps=eps_prime) / alpha_beta(beta[k])**2 / prod2
Psbeta = self.Psuc(beta[r-1], gamma_opt(beta[r-1]))
if query_depth:
Psbeta = 1
alphab = 1
return 1/Psbeta * Sigma * alphab**2
def Psuc(self, beta, gamma):
Zt = np.sum(np.exp(-beta * (self.E - self.Emin)))
N = 2**self.n
return Zt / N * np.exp(-2.0 * gamma)
def F(self, r, beta, gamma):
"""Return linear query prediction."""
return self.compute_query(params=None, schedule=lambda t, _: t, r=r, b=beta)
def C(self, beta, Psbeta, gamma, alpha=1):
bquery = self.query(beta=beta**alpha, gamma=gamma, eps=self.eps / 2 * np.sqrt(Psbeta))
return 1/Psbeta * bquery
def AA(self, beta, Psbeta, gamma, alpha=1):
return 1/np.sqrt(Psbeta) * self.query(beta=beta**alpha, gamma=gamma, eps=self.eps / 2 * np.sqrt(Psbeta))
def rF(self, beta, gamma):
values = []
r_range = []
r = 2
tol = 0
while True:
val = self.F(r, beta, gamma)
if len(values) > 0:
if values[-1] < val:
tol += 1
if tol > 2:
break
values.append(val)
r_range.append(r)
r += 1
f = np.min(values)
f_r_best = r_range[np.argmin(values)]
f_depth = self.compute_query(params=None, schedule=lambda t,_: t,
r=f_r_best, b=beta, query_depth=True)
return f, f_r_best, f_depth
def rFfit(self, beta, gamma):
from scipy.optimize import minimize
def schedule(t, params):
return t**params[0]
values = []
params = []
r_range = []
r = 2
tol = 0
while True:
m = minimize(lambda p, _: self.compute_query(p, schedule, r, beta),
[1.0], 'BFGS')
if len(values) > 0:
if values[-1] < m.fun:
tol += 1
if tol > 2:
break
values.append(m.fun)
params.append(m.x)
r_range.append(r)
r += 1
f = np.min(values)
f_r_best = r_range[np.argmin(values)]
f_depth = self.compute_query(params=params[np.argmin(values)],
schedule=schedule,
r=f_r_best, b=beta, query_depth=True)
return f, f_r_best, f_depth, params[np.argmin(values)]