tensorcircuit-nightly 1.0.2.dev20250108__py3-none-any.whl → 1.4.0.dev20251103__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.

Files changed (76) hide show
  1. tensorcircuit/__init__.py +18 -2
  2. tensorcircuit/about.py +46 -0
  3. tensorcircuit/abstractcircuit.py +4 -0
  4. tensorcircuit/analogcircuit.py +413 -0
  5. tensorcircuit/applications/layers.py +1 -1
  6. tensorcircuit/applications/van.py +1 -1
  7. tensorcircuit/backends/abstract_backend.py +320 -7
  8. tensorcircuit/backends/cupy_backend.py +3 -1
  9. tensorcircuit/backends/jax_backend.py +102 -4
  10. tensorcircuit/backends/jax_ops.py +110 -1
  11. tensorcircuit/backends/numpy_backend.py +49 -3
  12. tensorcircuit/backends/pytorch_backend.py +92 -3
  13. tensorcircuit/backends/tensorflow_backend.py +102 -3
  14. tensorcircuit/basecircuit.py +157 -98
  15. tensorcircuit/circuit.py +115 -57
  16. tensorcircuit/cloud/local.py +1 -1
  17. tensorcircuit/cloud/quafu_provider.py +1 -1
  18. tensorcircuit/cloud/tencent.py +1 -1
  19. tensorcircuit/compiler/simple_compiler.py +2 -2
  20. tensorcircuit/cons.py +142 -21
  21. tensorcircuit/densitymatrix.py +43 -14
  22. tensorcircuit/experimental.py +387 -129
  23. tensorcircuit/fgs.py +282 -81
  24. tensorcircuit/gates.py +66 -22
  25. tensorcircuit/interfaces/__init__.py +1 -3
  26. tensorcircuit/interfaces/jax.py +189 -0
  27. tensorcircuit/keras.py +3 -3
  28. tensorcircuit/mpscircuit.py +154 -65
  29. tensorcircuit/quantum.py +868 -152
  30. tensorcircuit/quditcircuit.py +733 -0
  31. tensorcircuit/quditgates.py +618 -0
  32. tensorcircuit/results/counts.py +147 -20
  33. tensorcircuit/results/readout_mitigation.py +4 -1
  34. tensorcircuit/shadows.py +1 -1
  35. tensorcircuit/simplify.py +3 -1
  36. tensorcircuit/stabilizercircuit.py +479 -0
  37. tensorcircuit/templates/__init__.py +2 -0
  38. tensorcircuit/templates/blocks.py +2 -2
  39. tensorcircuit/templates/hamiltonians.py +174 -0
  40. tensorcircuit/templates/lattice.py +1789 -0
  41. tensorcircuit/timeevol.py +896 -0
  42. tensorcircuit/translation.py +10 -3
  43. tensorcircuit/utils.py +7 -0
  44. {tensorcircuit_nightly-1.0.2.dev20250108.dist-info → tensorcircuit_nightly-1.4.0.dev20251103.dist-info}/METADATA +73 -23
  45. tensorcircuit_nightly-1.4.0.dev20251103.dist-info/RECORD +96 -0
  46. {tensorcircuit_nightly-1.0.2.dev20250108.dist-info → tensorcircuit_nightly-1.4.0.dev20251103.dist-info}/WHEEL +1 -1
  47. {tensorcircuit_nightly-1.0.2.dev20250108.dist-info → tensorcircuit_nightly-1.4.0.dev20251103.dist-info}/top_level.txt +0 -1
  48. tensorcircuit_nightly-1.0.2.dev20250108.dist-info/RECORD +0 -115
  49. tests/__init__.py +0 -0
  50. tests/conftest.py +0 -67
  51. tests/test_backends.py +0 -1031
  52. tests/test_calibrating.py +0 -149
  53. tests/test_channels.py +0 -365
  54. tests/test_circuit.py +0 -1699
  55. tests/test_cloud.py +0 -219
  56. tests/test_compiler.py +0 -147
  57. tests/test_dmcircuit.py +0 -555
  58. tests/test_ensemble.py +0 -72
  59. tests/test_fgs.py +0 -310
  60. tests/test_gates.py +0 -156
  61. tests/test_interfaces.py +0 -429
  62. tests/test_keras.py +0 -160
  63. tests/test_miscs.py +0 -277
  64. tests/test_mpscircuit.py +0 -341
  65. tests/test_noisemodel.py +0 -156
  66. tests/test_qaoa.py +0 -86
  67. tests/test_qem.py +0 -152
  68. tests/test_quantum.py +0 -526
  69. tests/test_quantum_attr.py +0 -42
  70. tests/test_results.py +0 -347
  71. tests/test_shadows.py +0 -160
  72. tests/test_simplify.py +0 -46
  73. tests/test_templates.py +0 -218
  74. tests/test_torchnn.py +0 -99
  75. tests/test_van.py +0 -102
  76. {tensorcircuit_nightly-1.0.2.dev20250108.dist-info → tensorcircuit_nightly-1.4.0.dev20251103.dist-info/licenses}/LICENSE +0 -0
tests/test_miscs.py DELETED
@@ -1,277 +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_ps2coo(tfb):
40
- for l, a in check_pairs:
41
- r1 = PauliString2COO(tf.constant(l, dtype=tf.int64))
42
- np.testing.assert_allclose(tc.backend.to_dense(r1), a, atol=1e-5)
43
-
44
-
45
- def test_pss2coo(tfb):
46
- l = [t[0] for t in check_pairs[:4]]
47
- a = sum([t[1] for t in check_pairs[:4]])
48
- r1 = PauliStringSum2COO(tf.constant(l, dtype=tf.int64))
49
- np.testing.assert_allclose(tc.backend.to_dense(r1), a, atol=1e-5)
50
- l = [t[0] for t in check_pairs[4:]]
51
- a = sum([t[1] for t in check_pairs[4:]])
52
- r1 = PauliStringSum2COO(tf.constant(l, dtype=tf.int64), weight=[0.5, 1])
53
- a = check_pairs[4][1] * 0.5 + check_pairs[5][1] * 1.0
54
- np.testing.assert_allclose(tc.backend.to_dense(r1), a, atol=1e-5)
55
-
56
-
57
- def test_sparse(benchmark, tfb):
58
- def sparse(h):
59
- return PauliStringSum2COO(h)
60
-
61
- h = [[1 for _ in range(12)], [2 for _ in range(12)]]
62
- h = tf.constant(h, dtype=tf.int64)
63
- sparse(h)
64
- benchmark(sparse, h)
65
-
66
-
67
- def test_dense(benchmark, tfb):
68
- def dense(h):
69
- return construct_matrix_v2(h, dtype=tf.complex64)
70
-
71
- h = [[1 for _ in range(12)], [2 for _ in range(12)]]
72
- h = [[1.0] + hi for hi in h]
73
- dense(h)
74
- benchmark(dense, h)
75
-
76
-
77
- @pytest.mark.parametrize("backend", [lf("tfb"), lf("jaxb")])
78
- def test_adaptive_vmap(backend):
79
- def f(x):
80
- return x**2
81
-
82
- x = tc.backend.ones([30, 2])
83
-
84
- vf = experimental.adaptive_vmap(f, chunk_size=6)
85
- np.testing.assert_allclose(vf(x), tc.backend.ones([30, 2]), atol=1e-5)
86
-
87
- vf2 = experimental.adaptive_vmap(f, chunk_size=7)
88
- np.testing.assert_allclose(vf2(x), tc.backend.ones([30, 2]), atol=1e-5)
89
-
90
- def f2(x):
91
- return tc.backend.sum(x)
92
-
93
- vf3 = experimental.adaptive_vmap(f2, chunk_size=7)
94
- np.testing.assert_allclose(vf3(x), 2 * tc.backend.ones([30]), atol=1e-5)
95
-
96
- vf3_jit = tc.backend.jit(vf3)
97
- np.testing.assert_allclose(vf3_jit(x), 2 * tc.backend.ones([30]), atol=1e-5)
98
-
99
-
100
- @pytest.mark.parametrize("backend", [lf("tfb"), lf("jaxb")])
101
- def test_adaptive_vmap_mul_io(backend):
102
- def f(x, y, a):
103
- return x + y + a
104
-
105
- vf = experimental.adaptive_vmap(f, chunk_size=6, vectorized_argnums=(0, 1))
106
- x = tc.backend.ones([30, 2])
107
- a = tc.backend.ones([2])
108
- # jax vmap has some weird behavior in terms of keyword arguments...
109
- # TODO(@refraction-ray): further investigate jax vmap behavior with kwargs
110
- np.testing.assert_allclose(vf(x, x, a), 3 * tc.backend.ones([30, 2]), atol=1e-5)
111
-
112
-
113
- @pytest.mark.parametrize("backend", [lf("tfb"), lf("jaxb")])
114
- def test_qng(backend):
115
- n = 6
116
-
117
- def f(params):
118
- params = tc.backend.reshape(params, [4, n])
119
- c = tc.Circuit(n)
120
- c = tc.templates.blocks.example_block(c, params)
121
- return c.state()
122
-
123
- params = tc.backend.ones([4 * n])
124
- fim = experimental.qng(f)(params)
125
- assert tc.backend.shape_tuple(fim) == (4 * n, 4 * n)
126
- print(experimental.dynamics_matrix(f)(params))
127
-
128
-
129
- @pytest.mark.parametrize("backend", [lf("tfb"), lf("jaxb")])
130
- def test_dynamic_rhs(backend):
131
- h1 = tc.array_to_tensor(tc.gates._z_matrix)
132
-
133
- def f(param):
134
- c = tc.Circuit(1)
135
- c.rx(0, theta=param)
136
- return c.state()
137
-
138
- rhsf = experimental.dynamics_rhs(f, h1)
139
- np.testing.assert_allclose(rhsf(tc.backend.ones([])), -np.sin(1.0) / 2, atol=1e-5)
140
-
141
- h2 = tc.backend.coo_sparse_matrix(
142
- indices=tc.array_to_tensor(np.array([[0, 0], [1, 1]]), dtype="int64"),
143
- values=tc.array_to_tensor(np.array([1, -1])),
144
- shape=[2, 2],
145
- )
146
-
147
- rhsf = experimental.dynamics_rhs(f, h2)
148
- np.testing.assert_allclose(rhsf(tc.backend.ones([])), -np.sin(1.0) / 2, atol=1e-5)
149
-
150
-
151
- @pytest.mark.parametrize("backend", ["tensorflow", "jax"])
152
- def test_two_qng_approaches(backend):
153
- n = 6
154
- nlayers = 2
155
- with tc.runtime_backend(backend) as K:
156
- with tc.runtime_dtype("complex128"):
157
-
158
- def state(params):
159
- params = K.reshape(params, [2 * nlayers, n])
160
- c = tc.Circuit(n)
161
- c = tc.templates.blocks.example_block(c, params, nlayers=nlayers)
162
- return c.state()
163
-
164
- params = K.ones([2 * nlayers * n])
165
- params = K.cast(params, "float32")
166
- n1 = experimental.qng(state)(params)
167
- n2 = experimental.qng2(state)(params)
168
- np.testing.assert_allclose(n1, n2, atol=1e-7)
169
-
170
-
171
- def test_arg_alias():
172
- @partial(tc.utils.arg_alias, alias_dict={"theta": ["alpha", "gamma"]})
173
- def f(theta: float, beta: float) -> float:
174
- """
175
- f doc
176
-
177
- :param theta: theta angle
178
- :type theta: float
179
- :param beta: beta angle
180
- :type beta: float
181
- :return: sum angle
182
- :rtype: float
183
- """
184
- return theta + beta
185
-
186
- np.testing.assert_allclose(f(beta=0.2, alpha=0.1), 0.3, atol=1e-5)
187
- print(f.__doc__)
188
- assert len(f.__doc__.strip().split("\n")) == 12
189
-
190
-
191
- def test_finite_difference_tf(tfb):
192
- def f(param1, param2):
193
- n = 4
194
- c = tc.Circuit(n)
195
- for i in range(n):
196
- c.rx(i, theta=param1[i])
197
- for i in range(n - 1):
198
- c.cx(i, i + 1)
199
- for i in range(n - 1):
200
- c.rzz(i, i + 1, theta=param2[i])
201
- r = [c.expectation_ps(z=[i]) for i in range(n)]
202
- return tc.backend.stack(r)
203
-
204
- def fsum(param1, param2):
205
- return tc.backend.mean(f(param1, param2))
206
-
207
- p1 = tf.ones([4])
208
- p2 = tf.ones([3])
209
- g1, g2 = tc.backend.value_and_grad(fsum)(p1, p2)
210
-
211
- f1 = experimental.finite_difference_differentiator(
212
- f, argnums=(0, 1), shifts=(np.pi / 2, 2)
213
- )
214
-
215
- def fsum1(param1, param2):
216
- return tc.backend.mean(f1(param1, param2))
217
-
218
- g3, g4 = tc.backend.value_and_grad(fsum1)(p1, p2)
219
-
220
- np.testing.assert_allclose(g1, g3, atol=1e-5)
221
- np.testing.assert_allclose(g2, g4, atol=1e-5)
222
-
223
-
224
- def test_evol(jaxb):
225
- def h_square(t, b):
226
- return (tc.backend.sign(t - 1.0) + 1) / 2 * b * tc.gates.x().tensor
227
-
228
- c = tc.Circuit(3)
229
- c.x(0)
230
- c.cx(0, 1)
231
- c.h(2)
232
- c = experimental.evol_local(
233
- c, [1], h_square, 2.0, tc.backend.convert_to_tensor(0.2)
234
- )
235
- c.rx(1, theta=np.pi - 0.4)
236
- np.testing.assert_allclose(c.expectation_ps(z=[1]), 1.0, atol=1e-5)
237
-
238
- ixi = tc.quantum.PauliStringSum2COO([[0, 1, 0]])
239
-
240
- def h_square_sparse(t, b):
241
- return (tc.backend.sign(t - 1.0) + 1) / 2 * b * ixi
242
-
243
- c = tc.Circuit(3)
244
- c.x(0)
245
- c.cx(0, 1)
246
- c.h(2)
247
- c = experimental.evol_global(
248
- c, h_square_sparse, 2.0, tc.backend.convert_to_tensor(0.2)
249
- )
250
- c.rx(1, theta=np.pi - 0.4)
251
- np.testing.assert_allclose(c.expectation_ps(z=[1]), 1.0, atol=1e-5)
252
-
253
-
254
- def test_energy_baseline():
255
- print(TFIM1Denergy(10))
256
- print(Heisenberg1Denergy(10))
257
-
258
-
259
- def test_jax_function_load(jaxb, tmp_path):
260
- K = tc.backend
261
-
262
- @K.jit
263
- def f(weights):
264
- c = tc.Circuit(3)
265
- c.rx(range(3), theta=weights)
266
- return K.real(c.expectation_ps(z=[0]))
267
-
268
- print(f(K.ones([3])))
269
-
270
- experimental.jax_jitted_function_save(
271
- os.path.join(tmp_path, "temp.bin"), f, K.ones([3])
272
- )
273
-
274
- f_load = tc.experimental.jax_jitted_function_load(
275
- os.path.join(tmp_path, "temp.bin")
276
- )
277
- 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
- )