tensorcircuit-nightly 1.2.0.dev20250326__py3-none-any.whl → 1.4.0.dev20251128__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of tensorcircuit-nightly might be problematic. Click here for more details.
- tensorcircuit/__init__.py +5 -1
- tensorcircuit/abstractcircuit.py +4 -0
- tensorcircuit/analogcircuit.py +413 -0
- tensorcircuit/applications/layers.py +1 -1
- tensorcircuit/applications/van.py +1 -1
- tensorcircuit/backends/abstract_backend.py +312 -5
- tensorcircuit/backends/cupy_backend.py +3 -1
- tensorcircuit/backends/jax_backend.py +100 -4
- tensorcircuit/backends/jax_ops.py +108 -0
- tensorcircuit/backends/numpy_backend.py +49 -3
- tensorcircuit/backends/pytorch_backend.py +92 -3
- tensorcircuit/backends/tensorflow_backend.py +102 -3
- tensorcircuit/basecircuit.py +157 -98
- tensorcircuit/circuit.py +115 -57
- tensorcircuit/cloud/local.py +1 -1
- tensorcircuit/cloud/quafu_provider.py +1 -1
- tensorcircuit/cloud/tencent.py +1 -1
- tensorcircuit/compiler/simple_compiler.py +2 -2
- tensorcircuit/cons.py +105 -23
- tensorcircuit/densitymatrix.py +16 -11
- tensorcircuit/experimental.py +733 -153
- tensorcircuit/fgs.py +254 -73
- tensorcircuit/gates.py +66 -22
- tensorcircuit/interfaces/jax.py +5 -3
- tensorcircuit/interfaces/tensortrans.py +6 -2
- tensorcircuit/interfaces/torch.py +14 -4
- tensorcircuit/keras.py +3 -3
- tensorcircuit/mpscircuit.py +154 -65
- tensorcircuit/quantum.py +698 -134
- tensorcircuit/quditcircuit.py +733 -0
- tensorcircuit/quditgates.py +618 -0
- tensorcircuit/results/counts.py +131 -18
- tensorcircuit/results/readout_mitigation.py +4 -1
- tensorcircuit/shadows.py +1 -1
- tensorcircuit/simplify.py +3 -1
- tensorcircuit/stabilizercircuit.py +29 -17
- tensorcircuit/templates/__init__.py +2 -0
- tensorcircuit/templates/blocks.py +2 -2
- tensorcircuit/templates/hamiltonians.py +174 -0
- tensorcircuit/templates/lattice.py +1789 -0
- tensorcircuit/timeevol.py +896 -0
- tensorcircuit/translation.py +10 -3
- tensorcircuit/utils.py +7 -0
- {tensorcircuit_nightly-1.2.0.dev20250326.dist-info → tensorcircuit_nightly-1.4.0.dev20251128.dist-info}/METADATA +66 -29
- tensorcircuit_nightly-1.4.0.dev20251128.dist-info/RECORD +96 -0
- {tensorcircuit_nightly-1.2.0.dev20250326.dist-info → tensorcircuit_nightly-1.4.0.dev20251128.dist-info}/WHEEL +1 -1
- {tensorcircuit_nightly-1.2.0.dev20250326.dist-info → tensorcircuit_nightly-1.4.0.dev20251128.dist-info}/top_level.txt +0 -1
- tensorcircuit_nightly-1.2.0.dev20250326.dist-info/RECORD +0 -118
- tests/__init__.py +0 -0
- tests/conftest.py +0 -67
- tests/test_backends.py +0 -1035
- tests/test_calibrating.py +0 -149
- tests/test_channels.py +0 -409
- tests/test_circuit.py +0 -1699
- tests/test_cloud.py +0 -219
- tests/test_compiler.py +0 -147
- tests/test_dmcircuit.py +0 -555
- tests/test_ensemble.py +0 -72
- tests/test_fgs.py +0 -310
- tests/test_gates.py +0 -156
- tests/test_interfaces.py +0 -562
- tests/test_keras.py +0 -160
- tests/test_miscs.py +0 -282
- tests/test_mpscircuit.py +0 -341
- tests/test_noisemodel.py +0 -156
- tests/test_qaoa.py +0 -86
- tests/test_qem.py +0 -152
- tests/test_quantum.py +0 -549
- tests/test_quantum_attr.py +0 -42
- tests/test_results.py +0 -380
- tests/test_shadows.py +0 -160
- tests/test_simplify.py +0 -46
- tests/test_stabilizer.py +0 -217
- tests/test_templates.py +0 -218
- tests/test_torchnn.py +0 -99
- tests/test_van.py +0 -102
- {tensorcircuit_nightly-1.2.0.dev20250326.dist-info → tensorcircuit_nightly-1.4.0.dev20251128.dist-info}/licenses/LICENSE +0 -0
tests/test_miscs.py
DELETED
|
@@ -1,282 +0,0 @@
|
|
|
1
|
-
# pylint: disable=invalid-name
|
|
2
|
-
|
|
3
|
-
import sys
|
|
4
|
-
import os
|
|
5
|
-
from functools import partial
|
|
6
|
-
import numpy as np
|
|
7
|
-
import tensorflow as tf
|
|
8
|
-
import pytest
|
|
9
|
-
from pytest_lazyfixture import lazy_fixture as lf
|
|
10
|
-
|
|
11
|
-
thisfile = os.path.abspath(__file__)
|
|
12
|
-
modulepath = os.path.dirname(os.path.dirname(thisfile))
|
|
13
|
-
|
|
14
|
-
sys.path.insert(0, modulepath)
|
|
15
|
-
import tensorcircuit as tc
|
|
16
|
-
from tensorcircuit import experimental
|
|
17
|
-
from tensorcircuit.quantum import PauliString2COO, PauliStringSum2COO
|
|
18
|
-
from tensorcircuit.applications.vqes import construct_matrix_v2
|
|
19
|
-
from tensorcircuit.applications.physics.baseline import TFIM1Denergy, Heisenberg1Denergy
|
|
20
|
-
|
|
21
|
-
i, x, y, z = [t.tensor for t in tc.gates.pauli_gates]
|
|
22
|
-
|
|
23
|
-
# note i is in use!
|
|
24
|
-
|
|
25
|
-
check_pairs = [
|
|
26
|
-
([0, 0], np.eye(4)),
|
|
27
|
-
([0, 1], np.kron(i, x)),
|
|
28
|
-
([2, 1], np.kron(y, x)),
|
|
29
|
-
([3, 1], np.kron(z, x)),
|
|
30
|
-
([3, 2, 2, 0], np.kron(np.kron(np.kron(z, y), y), i)),
|
|
31
|
-
([0, 1, 1, 1], np.kron(np.kron(np.kron(i, x), x), x)),
|
|
32
|
-
]
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
def test_about():
|
|
36
|
-
print(tc.about())
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
def test_cite():
|
|
40
|
-
print(tc.cite())
|
|
41
|
-
print(tc.cite("aps"))
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
def test_ps2coo(tfb):
|
|
45
|
-
for l, a in check_pairs:
|
|
46
|
-
r1 = PauliString2COO(tf.constant(l, dtype=tf.int64))
|
|
47
|
-
np.testing.assert_allclose(tc.backend.to_dense(r1), a, atol=1e-5)
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
def test_pss2coo(tfb):
|
|
51
|
-
l = [t[0] for t in check_pairs[:4]]
|
|
52
|
-
a = sum([t[1] for t in check_pairs[:4]])
|
|
53
|
-
r1 = PauliStringSum2COO(tf.constant(l, dtype=tf.int64))
|
|
54
|
-
np.testing.assert_allclose(tc.backend.to_dense(r1), a, atol=1e-5)
|
|
55
|
-
l = [t[0] for t in check_pairs[4:]]
|
|
56
|
-
a = sum([t[1] for t in check_pairs[4:]])
|
|
57
|
-
r1 = PauliStringSum2COO(tf.constant(l, dtype=tf.int64), weight=[0.5, 1])
|
|
58
|
-
a = check_pairs[4][1] * 0.5 + check_pairs[5][1] * 1.0
|
|
59
|
-
np.testing.assert_allclose(tc.backend.to_dense(r1), a, atol=1e-5)
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
def test_sparse(benchmark, tfb):
|
|
63
|
-
def sparse(h):
|
|
64
|
-
return PauliStringSum2COO(h)
|
|
65
|
-
|
|
66
|
-
h = [[1 for _ in range(12)], [2 for _ in range(12)]]
|
|
67
|
-
h = tf.constant(h, dtype=tf.int64)
|
|
68
|
-
sparse(h)
|
|
69
|
-
benchmark(sparse, h)
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
def test_dense(benchmark, tfb):
|
|
73
|
-
def dense(h):
|
|
74
|
-
return construct_matrix_v2(h, dtype=tf.complex64)
|
|
75
|
-
|
|
76
|
-
h = [[1 for _ in range(12)], [2 for _ in range(12)]]
|
|
77
|
-
h = [[1.0] + hi for hi in h]
|
|
78
|
-
dense(h)
|
|
79
|
-
benchmark(dense, h)
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
@pytest.mark.parametrize("backend", [lf("tfb"), lf("jaxb")])
|
|
83
|
-
def test_adaptive_vmap(backend):
|
|
84
|
-
def f(x):
|
|
85
|
-
return x**2
|
|
86
|
-
|
|
87
|
-
x = tc.backend.ones([30, 2])
|
|
88
|
-
|
|
89
|
-
vf = experimental.adaptive_vmap(f, chunk_size=6)
|
|
90
|
-
np.testing.assert_allclose(vf(x), tc.backend.ones([30, 2]), atol=1e-5)
|
|
91
|
-
|
|
92
|
-
vf2 = experimental.adaptive_vmap(f, chunk_size=7)
|
|
93
|
-
np.testing.assert_allclose(vf2(x), tc.backend.ones([30, 2]), atol=1e-5)
|
|
94
|
-
|
|
95
|
-
def f2(x):
|
|
96
|
-
return tc.backend.sum(x)
|
|
97
|
-
|
|
98
|
-
vf3 = experimental.adaptive_vmap(f2, chunk_size=7)
|
|
99
|
-
np.testing.assert_allclose(vf3(x), 2 * tc.backend.ones([30]), atol=1e-5)
|
|
100
|
-
|
|
101
|
-
vf3_jit = tc.backend.jit(vf3)
|
|
102
|
-
np.testing.assert_allclose(vf3_jit(x), 2 * tc.backend.ones([30]), atol=1e-5)
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
@pytest.mark.parametrize("backend", [lf("tfb"), lf("jaxb")])
|
|
106
|
-
def test_adaptive_vmap_mul_io(backend):
|
|
107
|
-
def f(x, y, a):
|
|
108
|
-
return x + y + a
|
|
109
|
-
|
|
110
|
-
vf = experimental.adaptive_vmap(f, chunk_size=6, vectorized_argnums=(0, 1))
|
|
111
|
-
x = tc.backend.ones([30, 2])
|
|
112
|
-
a = tc.backend.ones([2])
|
|
113
|
-
# jax vmap has some weird behavior in terms of keyword arguments...
|
|
114
|
-
# TODO(@refraction-ray): further investigate jax vmap behavior with kwargs
|
|
115
|
-
np.testing.assert_allclose(vf(x, x, a), 3 * tc.backend.ones([30, 2]), atol=1e-5)
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
@pytest.mark.parametrize("backend", [lf("tfb"), lf("jaxb")])
|
|
119
|
-
def test_qng(backend):
|
|
120
|
-
n = 6
|
|
121
|
-
|
|
122
|
-
def f(params):
|
|
123
|
-
params = tc.backend.reshape(params, [4, n])
|
|
124
|
-
c = tc.Circuit(n)
|
|
125
|
-
c = tc.templates.blocks.example_block(c, params)
|
|
126
|
-
return c.state()
|
|
127
|
-
|
|
128
|
-
params = tc.backend.ones([4 * n])
|
|
129
|
-
fim = experimental.qng(f)(params)
|
|
130
|
-
assert tc.backend.shape_tuple(fim) == (4 * n, 4 * n)
|
|
131
|
-
print(experimental.dynamics_matrix(f)(params))
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
@pytest.mark.parametrize("backend", [lf("tfb"), lf("jaxb")])
|
|
135
|
-
def test_dynamic_rhs(backend):
|
|
136
|
-
h1 = tc.array_to_tensor(tc.gates._z_matrix)
|
|
137
|
-
|
|
138
|
-
def f(param):
|
|
139
|
-
c = tc.Circuit(1)
|
|
140
|
-
c.rx(0, theta=param)
|
|
141
|
-
return c.state()
|
|
142
|
-
|
|
143
|
-
rhsf = experimental.dynamics_rhs(f, h1)
|
|
144
|
-
np.testing.assert_allclose(rhsf(tc.backend.ones([])), -np.sin(1.0) / 2, atol=1e-5)
|
|
145
|
-
|
|
146
|
-
h2 = tc.backend.coo_sparse_matrix(
|
|
147
|
-
indices=tc.array_to_tensor(np.array([[0, 0], [1, 1]]), dtype="int64"),
|
|
148
|
-
values=tc.array_to_tensor(np.array([1, -1])),
|
|
149
|
-
shape=[2, 2],
|
|
150
|
-
)
|
|
151
|
-
|
|
152
|
-
rhsf = experimental.dynamics_rhs(f, h2)
|
|
153
|
-
np.testing.assert_allclose(rhsf(tc.backend.ones([])), -np.sin(1.0) / 2, atol=1e-5)
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
@pytest.mark.parametrize("backend", ["tensorflow", "jax"])
|
|
157
|
-
def test_two_qng_approaches(backend):
|
|
158
|
-
n = 6
|
|
159
|
-
nlayers = 2
|
|
160
|
-
with tc.runtime_backend(backend) as K:
|
|
161
|
-
with tc.runtime_dtype("complex128"):
|
|
162
|
-
|
|
163
|
-
def state(params):
|
|
164
|
-
params = K.reshape(params, [2 * nlayers, n])
|
|
165
|
-
c = tc.Circuit(n)
|
|
166
|
-
c = tc.templates.blocks.example_block(c, params, nlayers=nlayers)
|
|
167
|
-
return c.state()
|
|
168
|
-
|
|
169
|
-
params = K.ones([2 * nlayers * n])
|
|
170
|
-
params = K.cast(params, "float32")
|
|
171
|
-
n1 = experimental.qng(state)(params)
|
|
172
|
-
n2 = experimental.qng2(state)(params)
|
|
173
|
-
np.testing.assert_allclose(n1, n2, atol=1e-7)
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
def test_arg_alias():
|
|
177
|
-
@partial(tc.utils.arg_alias, alias_dict={"theta": ["alpha", "gamma"]})
|
|
178
|
-
def f(theta: float, beta: float) -> float:
|
|
179
|
-
"""
|
|
180
|
-
f doc
|
|
181
|
-
|
|
182
|
-
:param theta: theta angle
|
|
183
|
-
:type theta: float
|
|
184
|
-
:param beta: beta angle
|
|
185
|
-
:type beta: float
|
|
186
|
-
:return: sum angle
|
|
187
|
-
:rtype: float
|
|
188
|
-
"""
|
|
189
|
-
return theta + beta
|
|
190
|
-
|
|
191
|
-
np.testing.assert_allclose(f(beta=0.2, alpha=0.1), 0.3, atol=1e-5)
|
|
192
|
-
print(f.__doc__)
|
|
193
|
-
assert len(f.__doc__.strip().split("\n")) == 12
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
def test_finite_difference_tf(tfb):
|
|
197
|
-
def f(param1, param2):
|
|
198
|
-
n = 4
|
|
199
|
-
c = tc.Circuit(n)
|
|
200
|
-
for i in range(n):
|
|
201
|
-
c.rx(i, theta=param1[i])
|
|
202
|
-
for i in range(n - 1):
|
|
203
|
-
c.cx(i, i + 1)
|
|
204
|
-
for i in range(n - 1):
|
|
205
|
-
c.rzz(i, i + 1, theta=param2[i])
|
|
206
|
-
r = [c.expectation_ps(z=[i]) for i in range(n)]
|
|
207
|
-
return tc.backend.stack(r)
|
|
208
|
-
|
|
209
|
-
def fsum(param1, param2):
|
|
210
|
-
return tc.backend.mean(f(param1, param2))
|
|
211
|
-
|
|
212
|
-
p1 = tf.ones([4])
|
|
213
|
-
p2 = tf.ones([3])
|
|
214
|
-
g1, g2 = tc.backend.value_and_grad(fsum)(p1, p2)
|
|
215
|
-
|
|
216
|
-
f1 = experimental.finite_difference_differentiator(
|
|
217
|
-
f, argnums=(0, 1), shifts=(np.pi / 2, 2)
|
|
218
|
-
)
|
|
219
|
-
|
|
220
|
-
def fsum1(param1, param2):
|
|
221
|
-
return tc.backend.mean(f1(param1, param2))
|
|
222
|
-
|
|
223
|
-
g3, g4 = tc.backend.value_and_grad(fsum1)(p1, p2)
|
|
224
|
-
|
|
225
|
-
np.testing.assert_allclose(g1, g3, atol=1e-5)
|
|
226
|
-
np.testing.assert_allclose(g2, g4, atol=1e-5)
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
def test_evol(jaxb):
|
|
230
|
-
def h_square(t, b):
|
|
231
|
-
return (tc.backend.sign(t - 1.0) + 1) / 2 * b * tc.gates.x().tensor
|
|
232
|
-
|
|
233
|
-
c = tc.Circuit(3)
|
|
234
|
-
c.x(0)
|
|
235
|
-
c.cx(0, 1)
|
|
236
|
-
c.h(2)
|
|
237
|
-
c = experimental.evol_local(
|
|
238
|
-
c, [1], h_square, 2.0, tc.backend.convert_to_tensor(0.2)
|
|
239
|
-
)
|
|
240
|
-
c.rx(1, theta=np.pi - 0.4)
|
|
241
|
-
np.testing.assert_allclose(c.expectation_ps(z=[1]), 1.0, atol=1e-5)
|
|
242
|
-
|
|
243
|
-
ixi = tc.quantum.PauliStringSum2COO([[0, 1, 0]])
|
|
244
|
-
|
|
245
|
-
def h_square_sparse(t, b):
|
|
246
|
-
return (tc.backend.sign(t - 1.0) + 1) / 2 * b * ixi
|
|
247
|
-
|
|
248
|
-
c = tc.Circuit(3)
|
|
249
|
-
c.x(0)
|
|
250
|
-
c.cx(0, 1)
|
|
251
|
-
c.h(2)
|
|
252
|
-
c = experimental.evol_global(
|
|
253
|
-
c, h_square_sparse, 2.0, tc.backend.convert_to_tensor(0.2)
|
|
254
|
-
)
|
|
255
|
-
c.rx(1, theta=np.pi - 0.4)
|
|
256
|
-
np.testing.assert_allclose(c.expectation_ps(z=[1]), 1.0, atol=1e-5)
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
def test_energy_baseline():
|
|
260
|
-
print(TFIM1Denergy(10))
|
|
261
|
-
print(Heisenberg1Denergy(10))
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
def test_jax_function_load(jaxb, tmp_path):
|
|
265
|
-
K = tc.backend
|
|
266
|
-
|
|
267
|
-
@K.jit
|
|
268
|
-
def f(weights):
|
|
269
|
-
c = tc.Circuit(3)
|
|
270
|
-
c.rx(range(3), theta=weights)
|
|
271
|
-
return K.real(c.expectation_ps(z=[0]))
|
|
272
|
-
|
|
273
|
-
print(f(K.ones([3])))
|
|
274
|
-
|
|
275
|
-
experimental.jax_jitted_function_save(
|
|
276
|
-
os.path.join(tmp_path, "temp.bin"), f, K.ones([3])
|
|
277
|
-
)
|
|
278
|
-
|
|
279
|
-
f_load = tc.experimental.jax_jitted_function_load(
|
|
280
|
-
os.path.join(tmp_path, "temp.bin")
|
|
281
|
-
)
|
|
282
|
-
np.testing.assert_allclose(f_load(K.ones([3])), 0.5403, atol=1e-4)
|
tests/test_mpscircuit.py
DELETED
|
@@ -1,341 +0,0 @@
|
|
|
1
|
-
# pylint: disable=unused-variable
|
|
2
|
-
# pylint: disable=invalid-name
|
|
3
|
-
|
|
4
|
-
from typing import Tuple, Any
|
|
5
|
-
import sys
|
|
6
|
-
import os
|
|
7
|
-
import numpy as np
|
|
8
|
-
import pytest
|
|
9
|
-
from pytest_lazyfixture import lazy_fixture as lf
|
|
10
|
-
|
|
11
|
-
Tensor = Any
|
|
12
|
-
|
|
13
|
-
thisfile = os.path.abspath(__file__)
|
|
14
|
-
modulepath = os.path.dirname(os.path.dirname(thisfile))
|
|
15
|
-
|
|
16
|
-
sys.path.insert(0, modulepath)
|
|
17
|
-
import tensorcircuit as tc
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
N = 8
|
|
21
|
-
D = 6
|
|
22
|
-
split = tc.cons.split_rules(max_singular_values=D)
|
|
23
|
-
type_test_circuits = Tuple[
|
|
24
|
-
tc.Circuit, Tensor, tc.MPSCircuit, Tensor, tc.MPSCircuit, Tensor
|
|
25
|
-
]
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
def reproducible_unitary(n, param):
|
|
29
|
-
exp2n = 2**n
|
|
30
|
-
A = tc.backend.cast(
|
|
31
|
-
tc.backend.reshape(tc.backend.arange(exp2n**2), (exp2n, exp2n)), tc.dtypestr
|
|
32
|
-
)
|
|
33
|
-
A = A + tc.backend.sin(A) * param * 1j
|
|
34
|
-
A = A - tc.backend.conj(tc.backend.transpose(A))
|
|
35
|
-
return tc.backend.reshape(tc.backend.expm(A), (2,) * n * 2)
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
def simulate(c, check=True, params=None):
|
|
39
|
-
if params is None:
|
|
40
|
-
params = tc.backend.ones((3,), dtype=tc.dtypestr)
|
|
41
|
-
O1 = tc.gates.any(reproducible_unitary(1, params[0]))
|
|
42
|
-
O2 = tc.gates.any(reproducible_unitary(2, params[1]))
|
|
43
|
-
O3 = tc.gates.any(reproducible_unitary(3, params[2]))
|
|
44
|
-
|
|
45
|
-
# Construct a complicated circuit by Circuit and MPSCircuit and compare
|
|
46
|
-
|
|
47
|
-
c.H(0)
|
|
48
|
-
# create as much correlation as possible
|
|
49
|
-
for i in range(0, N - 1, 2):
|
|
50
|
-
c.apply(O2.copy(), i, i + 1)
|
|
51
|
-
c.apply(O1.copy(), i)
|
|
52
|
-
c.apply(O3.copy(), int(N * 0.1), int(N * 0.5), int(N * 0.9))
|
|
53
|
-
c.apply(O2.copy(), 1, N - 2)
|
|
54
|
-
if check and isinstance(c, tc.MPSCircuit):
|
|
55
|
-
np.testing.assert_allclose(np.abs(c._mps.check_canonical()), 0, atol=1e-12)
|
|
56
|
-
c.cz(2, 3)
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
def get_test_circuits() -> type_test_circuits:
|
|
60
|
-
c = tc.Circuit(N)
|
|
61
|
-
simulate(c)
|
|
62
|
-
w_c = c.wavefunction()
|
|
63
|
-
|
|
64
|
-
mps = tc.MPSCircuit(N, split=split)
|
|
65
|
-
simulate(mps)
|
|
66
|
-
do_test_norm(mps)
|
|
67
|
-
mps.normalize()
|
|
68
|
-
w_mps = mps.wavefunction()
|
|
69
|
-
|
|
70
|
-
mps_exact = tc.MPSCircuit(N)
|
|
71
|
-
simulate(mps_exact)
|
|
72
|
-
w_mps_exact = mps_exact.wavefunction()
|
|
73
|
-
|
|
74
|
-
return [c, w_c, mps, w_mps, mps_exact, w_mps_exact]
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
def do_test_norm(mps: tc.MPSCircuit):
|
|
78
|
-
norm1 = mps.get_norm()
|
|
79
|
-
norm2 = tc.backend.norm(mps.wavefunction())
|
|
80
|
-
np.testing.assert_allclose(norm1, norm2, atol=1e-12)
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
def do_test_canonical(test_circuits: type_test_circuits):
|
|
84
|
-
(
|
|
85
|
-
c,
|
|
86
|
-
w_c,
|
|
87
|
-
mps,
|
|
88
|
-
w_mps,
|
|
89
|
-
mps_exact,
|
|
90
|
-
w_mps_exact,
|
|
91
|
-
) = test_circuits
|
|
92
|
-
np.testing.assert_allclose(np.abs(mps._mps.check_canonical()), 0, atol=1e-12)
|
|
93
|
-
np.testing.assert_allclose(np.abs(mps_exact._mps.check_canonical()), 0, atol=1e-12)
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
def do_test_wavefunction(test_circuits: type_test_circuits):
|
|
97
|
-
(
|
|
98
|
-
c,
|
|
99
|
-
w_c,
|
|
100
|
-
mps,
|
|
101
|
-
w_mps,
|
|
102
|
-
mps_exact,
|
|
103
|
-
w_mps_exact,
|
|
104
|
-
) = test_circuits
|
|
105
|
-
# the wavefuntion is exact if there's no truncation
|
|
106
|
-
np.testing.assert_allclose(tc.backend.numpy(w_mps_exact), tc.backend.numpy(w_c))
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
def do_test_truncation(
|
|
110
|
-
test_circuits: type_test_circuits, real_fedility_ref, estimated_fedility_ref
|
|
111
|
-
):
|
|
112
|
-
(
|
|
113
|
-
c,
|
|
114
|
-
w_c,
|
|
115
|
-
mps,
|
|
116
|
-
w_mps,
|
|
117
|
-
mps_exact,
|
|
118
|
-
w_mps_exact,
|
|
119
|
-
) = test_circuits
|
|
120
|
-
# compare with a precalculated value
|
|
121
|
-
real_fedility = (
|
|
122
|
-
np.abs(tc.backend.numpy(w_mps).conj().dot(tc.backend.numpy(w_c))) ** 2
|
|
123
|
-
)
|
|
124
|
-
estimated_fedility = tc.backend.numpy(mps._fidelity)
|
|
125
|
-
print(real_fedility, estimated_fedility)
|
|
126
|
-
if real_fedility_ref is not None:
|
|
127
|
-
np.testing.assert_allclose(real_fedility, real_fedility_ref, atol=1e-5)
|
|
128
|
-
if estimated_fedility_ref is not None:
|
|
129
|
-
np.testing.assert_allclose(
|
|
130
|
-
estimated_fedility, estimated_fedility_ref, atol=1e-5
|
|
131
|
-
)
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
def do_test_amplitude(test_circuits: type_test_circuits):
|
|
135
|
-
(
|
|
136
|
-
c,
|
|
137
|
-
w_c,
|
|
138
|
-
mps,
|
|
139
|
-
w_mps,
|
|
140
|
-
mps_exact,
|
|
141
|
-
w_mps_exact,
|
|
142
|
-
) = test_circuits
|
|
143
|
-
# compare with wavefunction
|
|
144
|
-
s = "01" * (N // 2)
|
|
145
|
-
sint = int(s, 2) # binary to decimal
|
|
146
|
-
err_amplitude = tc.backend.abs(mps.amplitude(s) - w_mps[sint])
|
|
147
|
-
np.testing.assert_allclose(err_amplitude, 0, atol=1e-12)
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
def do_test_expectation(test_circuits: type_test_circuits):
|
|
151
|
-
(
|
|
152
|
-
c,
|
|
153
|
-
w_c,
|
|
154
|
-
mps,
|
|
155
|
-
w_mps,
|
|
156
|
-
mps_exact,
|
|
157
|
-
w_mps_exact,
|
|
158
|
-
) = test_circuits
|
|
159
|
-
|
|
160
|
-
single_gate = (tc.gates.z(), [3])
|
|
161
|
-
tensor = (np.sin(np.arange(16)) + np.cos(np.arange(16)) * 1j).reshape((2, 2, 2, 2))
|
|
162
|
-
double_gate_nonunitary = (
|
|
163
|
-
tc.gates.Gate(tc.backend.convert_to_tensor(tensor)),
|
|
164
|
-
[2, 6],
|
|
165
|
-
)
|
|
166
|
-
double_gate = (tc.gates.cnot(), [2, 6])
|
|
167
|
-
triple_gate = (tc.gates.toffoli(), [7, 1, 5])
|
|
168
|
-
gates = [single_gate, double_gate_nonunitary, triple_gate]
|
|
169
|
-
|
|
170
|
-
exp_mps = mps_exact.expectation(*gates)
|
|
171
|
-
exp_c = c.expectation(*gates, reuse=False)
|
|
172
|
-
np.testing.assert_allclose(exp_mps, exp_c, atol=1e-7)
|
|
173
|
-
|
|
174
|
-
# ps
|
|
175
|
-
x = [0, 2]
|
|
176
|
-
y = [5, 3, 1]
|
|
177
|
-
z = [6, 4]
|
|
178
|
-
exp_mps = mps_exact.expectation_ps(x=x, y=y, z=z)
|
|
179
|
-
exp_c = c.expectation_ps(x=x, y=y, z=z)
|
|
180
|
-
np.testing.assert_allclose(exp_mps, exp_c, atol=1e-7)
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
def external_wavefunction():
|
|
184
|
-
# create a fixed wavefunction and create the corresponding MPS
|
|
185
|
-
w_external = np.abs(np.sin(np.arange(2**N) % np.exp(1))).astype(
|
|
186
|
-
tc.dtypestr
|
|
187
|
-
) # Just want to find a function that is so strange that the correlation is strong enough
|
|
188
|
-
w_external /= np.linalg.norm(w_external)
|
|
189
|
-
w_external = tc.backend.convert_to_tensor(w_external)
|
|
190
|
-
mps_external = tc.MPSCircuit(N, wavefunction=w_external, split=split)
|
|
191
|
-
mps_external_exact = tc.MPSCircuit(N, wavefunction=w_external)
|
|
192
|
-
return w_external, mps_external, mps_external_exact
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
def do_test_fromwavefunction(external_wavefunction, relative_err_ref):
|
|
196
|
-
(
|
|
197
|
-
w_external,
|
|
198
|
-
mps_external,
|
|
199
|
-
mps_external_exact,
|
|
200
|
-
) = external_wavefunction
|
|
201
|
-
np.testing.assert_allclose(mps_external_exact.wavefunction(), w_external, atol=1e-7)
|
|
202
|
-
# compare fidelity of truncation with theoretical limit obtained by SVD
|
|
203
|
-
w_external = tc.backend.numpy(w_external)
|
|
204
|
-
real_fedility = (
|
|
205
|
-
np.abs(tc.backend.numpy(mps_external.wavefunction()).conj().dot(w_external))
|
|
206
|
-
** 2
|
|
207
|
-
)
|
|
208
|
-
s = np.linalg.svd(w_external.reshape((2 ** (N // 2), 2 ** (N // 2))))[1]
|
|
209
|
-
theoretical_upper_limit = np.sum(s[0:D] ** 2)
|
|
210
|
-
relative_err = np.log((1 - real_fedility) / (1 - theoretical_upper_limit))
|
|
211
|
-
if relative_err_ref is not None:
|
|
212
|
-
np.testing.assert_allclose(relative_err, relative_err_ref, atol=1e-4)
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
def do_test_proj(test_circuits: type_test_circuits, external_wavefunction):
|
|
216
|
-
(
|
|
217
|
-
c,
|
|
218
|
-
w_c,
|
|
219
|
-
mps,
|
|
220
|
-
w_mps,
|
|
221
|
-
mps_exact,
|
|
222
|
-
w_mps_exact,
|
|
223
|
-
) = test_circuits
|
|
224
|
-
(
|
|
225
|
-
w_external,
|
|
226
|
-
mps_external,
|
|
227
|
-
mps_external_exact,
|
|
228
|
-
) = external_wavefunction
|
|
229
|
-
# compare projection value with wavefunction calculated results
|
|
230
|
-
proj = mps.proj_with_mps(mps_external)
|
|
231
|
-
proj_ref = (
|
|
232
|
-
tc.backend.numpy(mps_external.wavefunction())
|
|
233
|
-
.conj()
|
|
234
|
-
.dot(tc.backend.numpy(w_mps))
|
|
235
|
-
)
|
|
236
|
-
np.testing.assert_allclose(proj, proj_ref, atol=1e-12)
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
def do_test_tensor_input(test_circuits: type_test_circuits):
|
|
240
|
-
(
|
|
241
|
-
c,
|
|
242
|
-
w_c,
|
|
243
|
-
mps,
|
|
244
|
-
w_mps,
|
|
245
|
-
mps_exact,
|
|
246
|
-
w_mps_exact,
|
|
247
|
-
) = test_circuits
|
|
248
|
-
newmps = tc.MPSCircuit(
|
|
249
|
-
mps._nqubits,
|
|
250
|
-
tensors=mps.get_tensors(),
|
|
251
|
-
center_position=mps.get_center_position(),
|
|
252
|
-
)
|
|
253
|
-
for t1, t2 in zip(newmps.get_tensors(), mps.get_tensors()):
|
|
254
|
-
np.testing.assert_allclose(
|
|
255
|
-
tc.backend.numpy(t1), tc.backend.numpy(t2), atol=1e-12
|
|
256
|
-
)
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
def do_test_measure(test_circuits: type_test_circuits):
|
|
260
|
-
(
|
|
261
|
-
c,
|
|
262
|
-
w_c,
|
|
263
|
-
mps,
|
|
264
|
-
w_mps,
|
|
265
|
-
mps_exact,
|
|
266
|
-
w_mps_exact,
|
|
267
|
-
) = test_circuits
|
|
268
|
-
index = [6, 5, 2, 1]
|
|
269
|
-
status = tc.backend.convert_to_tensor([0.1, 0.3, 0.7, 0.9])
|
|
270
|
-
result_c = c.measure(*index, with_prob=True, status=status)
|
|
271
|
-
result_mps_exact = mps_exact.measure(*index, with_prob=True, status=status)
|
|
272
|
-
np.testing.assert_allclose(result_mps_exact[0], result_c[0], atol=1e-8)
|
|
273
|
-
np.testing.assert_allclose(result_mps_exact[1], result_c[1], atol=1e-8)
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
def test_MPO_conversion(highp, tfb):
|
|
277
|
-
O3 = reproducible_unitary(3, 1.0)
|
|
278
|
-
I = tc.backend.eye(2, dtype=tc.dtypestr)
|
|
279
|
-
gate = tc.gates.Gate(O3)
|
|
280
|
-
|
|
281
|
-
MPO3, _ = tc.MPSCircuit.gate_to_MPO(gate, 2, 3, 4)
|
|
282
|
-
tensor3 = tc.MPSCircuit.MPO_to_gate(MPO3).tensor
|
|
283
|
-
tensor3 = tc.backend.numpy(tensor3)
|
|
284
|
-
tensor3_ref = tc.backend.numpy(O3)
|
|
285
|
-
np.testing.assert_allclose(tensor3, tensor3_ref, atol=1e-12)
|
|
286
|
-
|
|
287
|
-
MPO4, _ = tc.MPSCircuit.gate_to_MPO(gate, 1, 3, 4)
|
|
288
|
-
tensor4 = tc.MPSCircuit.MPO_to_gate(MPO4).tensor
|
|
289
|
-
tensor4_ref = tc.backend.einsum("ijkabc,pq->ipjkaqbc", O3, I)
|
|
290
|
-
tensor4 = tc.backend.numpy(tensor4)
|
|
291
|
-
tensor4_ref = tc.backend.numpy(tensor4_ref)
|
|
292
|
-
np.testing.assert_allclose(tensor4, tensor4_ref, atol=1e-12)
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
@pytest.mark.parametrize(
|
|
296
|
-
"backend, dtype", [(lf("tfb"), lf("highp")), (lf("jaxb"), lf("highp"))]
|
|
297
|
-
)
|
|
298
|
-
def test_circuits(backend, dtype):
|
|
299
|
-
circuits = get_test_circuits()
|
|
300
|
-
do_test_canonical(circuits)
|
|
301
|
-
do_test_wavefunction(circuits)
|
|
302
|
-
do_test_truncation(circuits, 0.902663090851, 0.910305380327)
|
|
303
|
-
do_test_amplitude(circuits)
|
|
304
|
-
do_test_expectation(circuits)
|
|
305
|
-
external = external_wavefunction()
|
|
306
|
-
do_test_fromwavefunction(external, 0.276089)
|
|
307
|
-
do_test_proj(circuits, external)
|
|
308
|
-
do_test_tensor_input(circuits)
|
|
309
|
-
do_test_measure(circuits)
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
@pytest.mark.parametrize("backend, dtype", [(lf("tfb"), lf("highp"))])
|
|
313
|
-
def test_circuits_jit(backend, dtype):
|
|
314
|
-
def expec(params):
|
|
315
|
-
mps = tc.MPSCircuit(N, split=split)
|
|
316
|
-
simulate(mps, check=False, params=params)
|
|
317
|
-
x = [0, 2]
|
|
318
|
-
y = [5, 3, 1]
|
|
319
|
-
z = [6, 4]
|
|
320
|
-
exp = mps.expectation_ps(x=x, y=y, z=z)
|
|
321
|
-
return tc.backend.real(exp)
|
|
322
|
-
|
|
323
|
-
params = tc.backend.ones((3,), dtype=tc.dtypestr)
|
|
324
|
-
expec_vg = tc.backend.value_and_grad(expec)
|
|
325
|
-
expec_vg_jit = tc.backend.jit(expec_vg)
|
|
326
|
-
exp = expec(params)
|
|
327
|
-
exp_jit, exp_grad_jit = expec_vg_jit(params)
|
|
328
|
-
dir = tc.backend.convert_to_tensor(np.array([1.0, 2.0, 3.0], dtype=tc.dtypestr))
|
|
329
|
-
epsilon = 1e-6
|
|
330
|
-
exp_p = expec(params + dir * epsilon)
|
|
331
|
-
exp_m = expec(params - dir * epsilon)
|
|
332
|
-
exp_grad_dir_numerical = (exp_p - exp_m) / (epsilon * 2)
|
|
333
|
-
exp_grad_dir_jit = tc.backend.real(tc.backend.sum(exp_grad_jit * dir))
|
|
334
|
-
np.testing.assert_allclose(
|
|
335
|
-
tc.backend.numpy(exp), tc.backend.numpy(exp_jit), atol=1e-10
|
|
336
|
-
)
|
|
337
|
-
np.testing.assert_allclose(
|
|
338
|
-
tc.backend.numpy(exp_grad_dir_numerical),
|
|
339
|
-
tc.backend.numpy(exp_grad_dir_jit),
|
|
340
|
-
atol=1e-6,
|
|
341
|
-
)
|