Skip to content

Commit d0c6ab8

Browse files
committed
update2 noisemodel
1 parent f70eb30 commit d0c6ab8

29 files changed

+910
-148
lines changed

.github/workflows/ci.yml

+2
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,8 @@ jobs:
4848
python mcnoise_boost.py
4949
python quantumng.py
5050
python universal_lr.py
51+
python parameter_shift.py
52+
python mpsvsexact.py
5153
- name: setup build
5254
run: |
5355
python3 setup.py build

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
data
12
.prettierignore
23
.idea/
34
dataset

CHANGELOG.md

+18
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,24 @@
22

33
## Unreleased
44

5+
### Added
6+
7+
- Add native support for `rxx`, `ryy` and `rzz` gates for translation from qiskit
8+
9+
- Add `from_openqasm` and `from_openqasm_file` methods for `Circuit`
10+
11+
- Add `circuit_params` argument for translation from qiskit to make the interface universal and consistent with other `from_` methods
12+
13+
- Add `shifts` tuple parameter for `experimental.parameter_shift_grad` API so that we can also customize finite difference gradient from this method
14+
15+
### Changed
16+
17+
- Improve the efficiency of `sample_expectation_ps` method by using cached state.
18+
19+
### Fixed
20+
21+
- Fixed `unitary_kraus` of Circuit class support for multi-qubit kraus channels, previous implementation fails to reshape the kraus tensor as matrix
22+
523
## 0.5.0
624

725
### Added

README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ We also have [Docker support](/docker).
109109

110110
- Efficiency
111111

112-
- Time: 10 to 10^6 times acceleration compared to tfq or qiskit
112+
- Time: 10 to 10^6+ times acceleration compared to TensorFlow Quantum, Pennylane or Qiskit
113113

114114
- Space: 600+ qubits 1D VQE workflow (converged energy inaccuracy: < 1%)
115115

README_cn.md

+1-5
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ pip install tensorcircuit-nightly
105105

106106
- 效率
107107

108-
- 时间:与 TFQ 或 Qiskit 相比,加速 10 到 10^6 倍
108+
- 时间:与 TFQ, Pennylane, 或 Qiskit 相比,加速 10 到 10^6+
109109

110110
- 空间:600+ qubits 1D VQE 工作流(收敛能量误差:< 1%)
111111

@@ -145,7 +145,3 @@ pip install tensorcircuit-nightly
145145

146146
VQEX 在 MBL 相位识别上的应用见 [教程](/docs/source/tutorials/vqex_mbl.ipynb)
147147
参考论文: https://arxiv.org/pdf/2111.13719.pdf
148-
149-
```
150-
151-
```

benchmarks/README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
`cd scripts`
44

5-
`python benchmark.py -n [# of Qubits] -nlayer [# of QC layers] -nitrs [# of max iterations] -t [time limitation] -gpu [0 for no gpu and 1 for gpu enabled] -tcbackend [jax or tensorflow]`
5+
`python benchmark.py -n [# of Qubits] -nlayer [# of QC layers] -nitrs [# of max iterations] -nbatch [# of batch for QML task] -t [time limitation] -gpu [0 for no gpu and 1 for gpu enabled] -tcbackend [jax or tensorflow]`
66

77
then a `.json` file will be created in data folder which contains the information of benchmarking parameters and results.
88

benchmarks/scripts/qml_pennylane.py

+47-3
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,6 @@
1010
import tensorcircuit as tc
1111
import utils
1212

13-
tc.set_backend("tensorflow")
14-
1513

1614
def pennylane_benchmark(
1715
uuid,
@@ -60,6 +58,52 @@ def pennylane_benchmark(
6058
)
6159
meta["Results"] = {}
6260

61+
dev = qml.device("lightning.qubit", wires=nwires)
62+
63+
K = tc.get_backend("tensorflow")
64+
65+
@qml.qnode(dev, diff_method="adjoint", interface="tf")
66+
def lt_expval(img, params):
67+
for i in range(nwires - 1):
68+
qml.RX(img[i] * np.pi, wires=i)
69+
for j in range(nlayer):
70+
for i in range(nwires - 1):
71+
qml.IsingZZ(params[i + j * 2 * nwires], wires=[i, nwires - 1])
72+
for i in range(nwires):
73+
qml.RX(params[nwires + i + j * 2 * nwires], wires=i)
74+
return qml.expval(qml.Hamiltonian([1.0], [qml.PauliZ(nwires - 1)], True))
75+
76+
def loss(imgs, lbls, param):
77+
params = K.stack([param for _ in range(lbls.shape[0])])
78+
params = K.transpose(params, [1, 0])
79+
return K.mean(
80+
(lbls - K.cast(lt_expval(imgs, params), "float32") * 0.5 - 0.5) ** 2
81+
)
82+
83+
vag = K.value_and_grad(loss, argnums=2)
84+
param = K.convert_to_tensor((np.random.normal(size=[nlayer * 2 * nwires])))
85+
86+
def f(train_imgs, train_lbls):
87+
e, grad = vag(
88+
K.transpose(
89+
K.convert_to_tensor(np.array(train_imgs).astype(np.float32)), (1, 0)
90+
),
91+
K.reshape(
92+
K.convert_to_tensor(np.array(train_lbls).astype(np.float32)), (-1)
93+
),
94+
param,
95+
)
96+
return e
97+
98+
ct, it, Nitrs = utils.qml_timing(f, nbatch, nitrs, timeLimit)
99+
meta["Results"]["lightning"] = {
100+
"Construction time": ct,
101+
"Iteration time": it,
102+
"# of actual iterations": Nitrs,
103+
}
104+
105+
print(meta["Results"]["lightning"])
106+
63107
dev = qml.device("default.qubit.jax", wires=nwires)
64108

65109
@qml.qnode(dev, interface="jax")
@@ -196,7 +240,7 @@ def tf_loss(img, lbl, params):
196240
return loss
197241

198242
tf_vvag = tf.function(
199-
tc.backend.vvag(tf_loss, vectorized_argnums=(0, 1), argnums=2)
243+
tc.get_backend("tensorflow").vvag(tf_loss, vectorized_argnums=(0, 1), argnums=2)
200244
)
201245

202246
def f(train_imgs, train_lbls):

benchmarks/scripts/utils.py

+26-12
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
import numpy as np
77
import tensorflow as tf
88
from pathlib import Path
9+
import optax
10+
import tensorcircuit as tc
911

1012

1113
qml_data = {}
@@ -218,18 +220,16 @@ def save(data, _uuid, path):
218220

219221
def timing(f, nitrs, timeLimit):
220222
t0 = time.time()
221-
print(f())
223+
a = f()
222224
t1 = time.time()
223225
Nitrs = 1e-8
224226
for i in range(nitrs):
225227
a = f()
226-
print(a)
227228
# if a != None:
228229
# print(a)
230+
Nitrs += 1
229231
if time.time() - t1 > timeLimit:
230232
break
231-
else:
232-
Nitrs += 1
233233
t2 = time.time()
234234
return t1 - t0, (t2 - t1) / Nitrs, int(Nitrs)
235235

@@ -254,24 +254,38 @@ def qml_timing(f, nbatch, nitrs, timeLimit, tfq=False):
254254
)
255255
if a is not None:
256256
print(a)
257+
Nitrs += 1
257258
if time.time() - t1 > timeLimit:
258259
break
259-
else:
260-
Nitrs += 1
261260
t2 = time.time()
262261
return t1 - t0, (t2 - t1) / Nitrs, int(Nitrs)
263262

264263

265264
class Opt:
266-
def __init__(self, f, params, lr=0.01, tuning=True):
265+
def __init__(self, f, params, lr=0.002, tuning=True, backend="tensorflow"):
267266
self.f = f
268267
self.params = params
269-
self.adam = tf.keras.optimizers.Adam(lr)
268+
if backend == "tensorflow":
269+
self.adam = tc.backend.optimizer(tf.keras.optimizers.Adam(lr))
270+
elif backend == "jax":
271+
self.adam = tc.backend.optimizer(optax.adam(lr))
272+
elif backend == "numpy":
273+
self.adam = tc.get_backend("tensorflow").optimizer(
274+
tf.keras.optimizers.Adam(lr)
275+
)
270276
self.tuning = tuning
277+
self.backend = backend
271278

272279
def step(self):
273-
e, grad = self.f(*self.params)
280+
if getattr(self.params, "shape", False):
281+
e, grad = self.f(self.params)
282+
else:
283+
e, grad = self.f(*self.params)
274284
if self.tuning:
275-
grad = [tf.convert_to_tensor(g) for g in grad]
276-
self.adam.apply_gradients(zip(grad, self.params))
277-
return e[()]
285+
if self.backend == "numpy":
286+
self.params = tf.constant(self.params)
287+
self.params = self.adam.update(grad, self.params)
288+
if self.backend == "numpy":
289+
self.params = self.params.numpy()
290+
print(e)
291+
return e

benchmarks/scripts/vqe_pennylane.py

+26
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,32 @@ def f():
129129
"# of actual iterations": Nitrs,
130130
}
131131

132+
print("begin testing lightning")
133+
dev = qml.device("lightning.qubit", wires=nwires)
134+
135+
@qml.qnode(dev, diff_method="adjoint")
136+
def lt_expval(params):
137+
for i in range(nwires):
138+
qml.Hadamard(wires=i)
139+
for j in range(nlayer):
140+
for i in range(nwires - minus):
141+
qml.IsingZZ(params[i + j * 2 * nwires], wires=[i, (i + 1) % nwires])
142+
for i in range(nwires):
143+
qml.RX(params[nwires + i + j * 2 * nwires], wires=i)
144+
return qml.expval(Htfim)
145+
146+
vag = qml.grad(lt_expval, argnum=0)
147+
params = np.random.normal(size=[nlayer * 2 * nwires])
148+
149+
def f():
150+
return vag(params)
151+
152+
ct, it, Nitrs = utils.timing(f, nitrs, timeLimit)
153+
meta["Results"]["lightning.cpu"] = {
154+
"Construction time": ct,
155+
"Iteration time": it,
156+
"# of actual iterations": Nitrs,
157+
}
132158
# using tf interface and expvalcost
133159
# params.assign(np.random.normal(size=[nlayer * 2 * nwires]))
134160
# cost_fn_tf = qml.ExpvalCost(circuit, Htfim, dev, interface="tf")

benchmarks/scripts/vqe_qibo.py

+109
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
import datetime
2+
import sys
3+
import uuid
4+
import cpuinfo
5+
6+
import tensorcircuit as tc
7+
8+
tc.set_backend("tensorflow")
9+
import tensorflow as tf
10+
from functools import reduce
11+
from operator import mul
12+
import qibo
13+
14+
qibo.set_backend("tensorflow")
15+
from qibo import gates, models, hamiltonians
16+
from qibo.symbols import I, X, Z
17+
import utils
18+
19+
20+
def qibo_benchmark(uuid, n, nlayer, nitrs, timeLimit, minus=1):
21+
@tf.function
22+
def geth(s, n):
23+
ctc = tc.Circuit(n, inputs=s)
24+
loss = 0.0
25+
for i in range(n - 1):
26+
loss += ctc.expectation_ps(z=[i, i + 1])
27+
for i in range(n):
28+
loss -= ctc.expectation_ps(x=[i])
29+
return loss
30+
31+
@tf.function # jit will raise error
32+
def optimize(params):
33+
with tf.GradientTape() as tape:
34+
c = models.Circuit(n)
35+
for i in range(n):
36+
c.add(gates.H(i))
37+
for j in range(nlayer):
38+
for i in range(n - minus):
39+
c.add(gates.CNOT(i, i + 1))
40+
c.add(gates.RZ(i + 1, theta=params[j, i, 0]))
41+
c.add(gates.CNOT(i, i + 1))
42+
for i in range(n):
43+
c.add(gates.RX(0, theta=params[j, i, 1]))
44+
s = c().state()
45+
# h = hamiltonians.TFIM(n, h=-1)
46+
# loss = h.expectation(s)
47+
# failed in jit
48+
# qibo lacks the API for local expectation, using tc as assistance
49+
# we must ensure the observable is computed term by term
50+
# instead of the expectation for the Hamiltonian as a whole
51+
# to ensure the comparison is fair
52+
53+
loss = geth(s, n)
54+
55+
grads = tape.gradient(loss, params)
56+
return loss, grads
57+
58+
meta = {}
59+
meta["Software"] = "qibo"
60+
meta["minus"] = minus
61+
meta["Cpuinfo"] = cpuinfo.get_cpu_info()["brand_raw"]
62+
meta["Version"] = {
63+
"sys": sys.version,
64+
"qibo": qibo.__version__,
65+
}
66+
meta["VQE test parameters"] = {
67+
"nQubits": n,
68+
"nlayer": nlayer,
69+
"nitrs": nitrs,
70+
"timeLimit": timeLimit,
71+
}
72+
meta["UUID"] = uuid
73+
meta["Benchmark Time"] = (
74+
datetime.datetime.now().astimezone().strftime("%Y-%m-%d %H:%M %Z")
75+
)
76+
meta["Results"] = {}
77+
params = tf.Variable(tf.random.normal((nlayer, n, 2), dtype=tf.float64))
78+
opt = utils.Opt(optimize, params, tuning=True, backend="tensorflow")
79+
ct, it, Nitrs = utils.timing(opt.step, nitrs, timeLimit)
80+
meta["Results"]["with jit"] = {
81+
"Construction time": ct,
82+
"Iteration time": it,
83+
"# of actual iterations": Nitrs,
84+
}
85+
print(meta)
86+
return meta
87+
88+
89+
if __name__ == "__main__":
90+
_uuid = str(uuid.uuid4())
91+
(
92+
n,
93+
nlayer,
94+
nitrs,
95+
timeLimit,
96+
isgpu,
97+
minus,
98+
path,
99+
) = utils.arg()
100+
101+
r = qibo_benchmark(
102+
_uuid,
103+
n,
104+
nlayer,
105+
nitrs,
106+
timeLimit,
107+
minus=minus,
108+
)
109+
utils.save(r, _uuid, path)

0 commit comments

Comments
 (0)