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_circuit.py DELETED
@@ -1,1699 +0,0 @@
1
- # pylint: disable=invalid-name
2
-
3
- import os
4
- import sys
5
- from functools import partial
6
-
7
- import numpy as np
8
- import opt_einsum as oem
9
- import pytest
10
- from pytest_lazyfixture import lazy_fixture as lf
11
-
12
- # see https://stackoverflow.com/questions/56307329/how-can-i-parametrize-tests-to-run-with-different-fixtures-in-pytest
13
-
14
- thisfile = os.path.abspath(__file__)
15
- modulepath = os.path.dirname(os.path.dirname(thisfile))
16
-
17
- sys.path.insert(0, modulepath)
18
- import tensorcircuit as tc
19
-
20
-
21
- @pytest.mark.parametrize("backend", [lf("npb"), lf("cpb")])
22
- def test_wavefunction(backend):
23
- qc = tc.Circuit(2)
24
- qc.unitary(
25
- 0,
26
- 1,
27
- unitary=tc.gates.Gate(np.arange(16).reshape(2, 2, 2, 2).astype(np.complex64)),
28
- )
29
- assert np.real(qc.wavefunction()[2]) == 8
30
- qc = tc.Circuit(2)
31
- qc.unitary(
32
- 1,
33
- 0,
34
- unitary=tc.gates.Gate(np.arange(16).reshape(2, 2, 2, 2).astype(np.complex64)),
35
- )
36
- qc.wavefunction()
37
- assert np.real(qc.wavefunction()[2]) == 4
38
- qc = tc.Circuit(2)
39
- qc.unitary(
40
- 0, unitary=tc.gates.Gate(np.arange(4).reshape(2, 2).astype(np.complex64))
41
- )
42
- qc.wavefunction()
43
- assert np.real(qc.wavefunction()[2]) == 2
44
-
45
-
46
- @pytest.mark.parametrize("backend", [lf("npb"), lf("cpb")])
47
- def test_basics(backend):
48
- c = tc.Circuit(2)
49
- c.x(0)
50
- np.testing.assert_allclose(tc.backend.numpy(c.amplitude("10")), np.array(1.0))
51
- c.CNOT(0, 1)
52
- np.testing.assert_allclose(tc.backend.numpy(c.amplitude("11")), np.array(1.0))
53
-
54
-
55
- @pytest.mark.parametrize("backend", [lf("npb"), lf("cpb")])
56
- def test_measure(backend):
57
- c = tc.Circuit(3)
58
- c.H(0)
59
- c.h(1)
60
- c.toffoli(0, 1, 2)
61
- assert c.measure(2)[0] in [0, 1]
62
-
63
-
64
- def test_gates_in_circuit():
65
- c = tc.Circuit(2, inputs=np.eye(2**2))
66
- c.iswap(0, 1)
67
- ans = tc.gates.iswap_gate().tensor.reshape([4, 4])
68
- np.testing.assert_allclose(c.state().reshape([4, 4]), ans, atol=1e-5)
69
-
70
-
71
- def test_control_vgate():
72
- c = tc.Circuit(2)
73
- c.x(1)
74
- c.crx(1, 0, theta=0.3)
75
- np.testing.assert_allclose(
76
- c.expectation([tc.gates._z_matrix, 0]), 0.95533645, atol=1e-5
77
- )
78
-
79
-
80
- def test_adjoint_gate_circuit():
81
- c = tc.Circuit(1)
82
- c.X(0)
83
- c.SD(0)
84
- np.testing.assert_allclose(c.state(), np.array([0.0, -1.0j]))
85
-
86
-
87
- @pytest.mark.parametrize("backend", [lf("tfb"), lf("jaxb")])
88
- def test_jittable_measure(backend):
89
- @partial(tc.backend.jit, static_argnums=(2, 3))
90
- def f(param, key, n=6, nlayers=3):
91
- if key is not None:
92
- tc.backend.set_random_state(key)
93
- c = tc.Circuit(n)
94
- for i in range(n):
95
- c.H(i)
96
- for j in range(nlayers):
97
- for i in range(n - 1):
98
- c.exp1(i, i + 1, theta=param[2 * j, i], hamiltonian=tc.gates._zz_matrix)
99
- for i in range(n):
100
- c.rx(i, theta=param[2 * j + 1, i])
101
- return c.measure_jit(0, 1, 2, with_prob=True)
102
-
103
- if tc.backend.name == "tensorflow":
104
- import tensorflow as tf
105
-
106
- print(f(tc.backend.ones([6, 6]), None))
107
- print(f(tc.backend.ones([6, 6]), None))
108
- print(f(tc.backend.ones([6, 6]), tf.random.Generator.from_seed(23)))
109
- print(f(tc.backend.ones([6, 6]), tf.random.Generator.from_seed(24)))
110
- elif tc.backend.name == "jax":
111
- import jax
112
-
113
- print(f(tc.backend.ones([6, 6]), jax.random.PRNGKey(23)))
114
- print(f(tc.backend.ones([6, 6]), jax.random.PRNGKey(24)))
115
-
116
- # As seen here, though I have tried the best, the random API is still not that consistent under jit
117
-
118
-
119
- @pytest.mark.parametrize("backend", [lf("tfb"), lf("jaxb")])
120
- def test_jittable_depolarizing(backend):
121
- @tc.backend.jit
122
- def f1(key):
123
- n = 5
124
- if key is not None:
125
- tc.backend.set_random_state(key)
126
- c = tc.Circuit(n)
127
- for i in range(n):
128
- c.H(i)
129
- for i in range(n):
130
- c.cnot(i, (i + 1) % n)
131
- for i in range(n):
132
- c.unitary_kraus(
133
- [
134
- tc.gates._x_matrix,
135
- tc.gates._y_matrix,
136
- tc.gates._z_matrix,
137
- tc.gates._i_matrix,
138
- ],
139
- i,
140
- prob=[0.2, 0.2, 0.2, 0.4],
141
- )
142
- for i in range(n):
143
- c.cz(i, (i + 1) % n)
144
- return c.wavefunction()
145
-
146
- @tc.backend.jit
147
- def f2(key):
148
- n = 5
149
- if key is not None:
150
- tc.backend.set_random_state(key)
151
- c = tc.Circuit(n)
152
- for i in range(n):
153
- c.H(i)
154
- for i in range(n):
155
- c.cnot(i, (i + 1) % n)
156
- for i in range(n):
157
- c.unitary_kraus(
158
- tc.channels.depolarizingchannel(0.2, 0.2, 0.2),
159
- i,
160
- )
161
- for i in range(n):
162
- c.X(i)
163
- return c.wavefunction()
164
-
165
- @tc.backend.jit
166
- def f3(key):
167
- n = 5
168
- if key is not None:
169
- tc.backend.set_random_state(key)
170
- c = tc.Circuit(n)
171
- for i in range(n):
172
- c.H(i)
173
- for i in range(n):
174
- c.cnot(i, (i + 1) % n)
175
- for i in range(n):
176
- c.depolarizing(i, px=0.2, py=0.2, pz=0.2)
177
- for i in range(n):
178
- c.X(i)
179
- return c.wavefunction()
180
-
181
- @tc.backend.jit
182
- def f4(key):
183
- n = 5
184
- if key is not None:
185
- tc.backend.set_random_state(key)
186
- c = tc.Circuit(n)
187
- for i in range(n):
188
- c.H(i)
189
- for i in range(n):
190
- c.cnot(i, (i + 1) % n)
191
- for i in range(n):
192
- c.depolarizing2(i, px=0.2, py=0.2, pz=0.2)
193
- for i in range(n):
194
- c.X(i)
195
- return c.wavefunction()
196
-
197
- @tc.backend.jit
198
- def f5(key):
199
- n = 5
200
- if key is not None:
201
- tc.backend.set_random_state(key)
202
- c = tc.Circuit(n)
203
- for i in range(n):
204
- c.H(i)
205
- for i in range(n):
206
- c.cnot(i, (i + 1) % n)
207
- for i in range(n):
208
- c.unitary_kraus2(
209
- tc.channels.depolarizingchannel(0.2, 0.2, 0.2),
210
- i,
211
- )
212
- for i in range(n):
213
- c.X(i)
214
- return c.wavefunction()
215
-
216
- for f in [f1, f2, f3, f4, f5]:
217
- if tc.backend.name == "tensorflow":
218
- import tensorflow as tf
219
-
220
- np.testing.assert_allclose(tc.backend.norm(f(None)), 1.0, atol=1e-4)
221
- np.testing.assert_allclose(
222
- tc.backend.norm(f(tf.random.Generator.from_seed(23))), 1.0, atol=1e-4
223
- )
224
- np.testing.assert_allclose(
225
- tc.backend.norm(f(tf.random.Generator.from_seed(24))), 1.0, atol=1e-4
226
- )
227
-
228
- elif tc.backend.name == "jax":
229
- import jax
230
-
231
- np.testing.assert_allclose(
232
- tc.backend.norm(f(jax.random.PRNGKey(23))), 1.0, atol=1e-4
233
- )
234
- np.testing.assert_allclose(
235
- tc.backend.norm(f(jax.random.PRNGKey(24))), 1.0, atol=1e-4
236
- )
237
-
238
-
239
- @pytest.mark.parametrize("backend", [lf("jaxb")]) # too slow for np
240
- def test_large_scale_sample(backend):
241
- L = 30
242
- c = tc.Circuit(L)
243
- c.h(0)
244
- c.cnot([i for i in range(L - 1)], [i + 1 for i in range(L - 1)])
245
- results = c.sample(
246
- allow_state=False, batch=1024, format="count_dict_bin", jittable=False
247
- )
248
- assert (
249
- results["0" * L] / results["1" * L] < 1.2
250
- and results["0" * L] / results["1" * L] > 0.8
251
- )
252
-
253
-
254
- @pytest.mark.parametrize("backend", [lf("npb"), lf("cpb")])
255
- def test_expectation(backend):
256
- c = tc.Circuit(2)
257
- c.H(0)
258
- np.testing.assert_allclose(
259
- tc.backend.numpy(c.expectation((tc.gates.z(), [0]))), 0, atol=1e-7
260
- )
261
-
262
-
263
- @pytest.mark.parametrize("backend", [lf("npb"), lf("tfb"), lf("jaxb"), lf("cpb")])
264
- def test_exp1(backend):
265
- @partial(tc.backend.jit, jit_compile=True)
266
- def sf():
267
- c = tc.Circuit(2)
268
- xx = np.array(
269
- [[0, 0, 0, 1], [0, 0, 1, 0], [0, 1, 0, 0], [1, 0, 0, 0]], dtype=np.complex64
270
- )
271
- c.exp1(0, 1, unitary=xx, theta=tc.num_to_tensor(0.2))
272
- s = c.state()
273
- return s
274
-
275
- @tc.backend.jit
276
- def s1f():
277
- c = tc.Circuit(2)
278
- xx = np.array(
279
- [[0, 0, 0, 1], [0, 0, 1, 0], [0, 1, 0, 0], [1, 0, 0, 0]], dtype=np.complex64
280
- )
281
- c.exp(0, 1, unitary=xx, theta=tc.num_to_tensor(0.2))
282
- s1 = c.state()
283
- return s1
284
-
285
- s = tc.backend.numpy(sf())
286
- s1 = tc.backend.numpy(s1f())
287
- np.testing.assert_allclose(s, s1, atol=1e-4)
288
-
289
-
290
- def test_complex128(highp, tfb):
291
- c = tc.Circuit(2)
292
- c.H(1)
293
- c.rx(0, theta=tc.gates.num_to_tensor(1j))
294
- c.wavefunction()
295
- np.testing.assert_allclose(c.expectation((tc.gates.z(), [1])), 0)
296
-
297
-
298
- # def test_qcode():
299
- # qcode = """
300
- # 4
301
- # x 0
302
- # cnot 0 1
303
- # r 2 theta 1.0 alpha 1.57
304
- # """
305
- # c = tc.Circuit.from_qcode(qcode)
306
- # assert c.measure(1)[0] == "1"
307
- # assert c.to_qcode() == qcode[1:]
308
-
309
-
310
- def universal_ad():
311
- @tc.backend.jit
312
- def forward(theta):
313
- c = tc.Circuit(2)
314
- c.R(0, theta=theta, alpha=0.5, phi=0.8)
315
- return tc.backend.real(c.expectation((tc.gates.z(), [0])))
316
-
317
- gg = tc.backend.grad(forward)
318
- vg = tc.backend.value_and_grad(forward)
319
- gg = tc.backend.jit(gg)
320
- vg = tc.backend.jit(vg)
321
- theta = tc.gates.num_to_tensor(1.0)
322
- grad1 = gg(theta)
323
- v2, grad2 = vg(theta)
324
- assert grad1 == grad2
325
- return v2, grad2
326
-
327
-
328
- @pytest.mark.parametrize("backend", [lf("tfb"), lf("jaxb")])
329
- def test_ad(backend):
330
- # this amazingly shows how to code once and run in very different AD-ML engines
331
- print(universal_ad())
332
-
333
-
334
- def test_single_qubit():
335
- c = tc.Circuit(1)
336
- c.H(0)
337
- w = c.state()[0]
338
- np.testing.assert_allclose(w, np.array([1, 1]) / np.sqrt(2), atol=1e-4)
339
-
340
-
341
- @pytest.mark.parametrize("backend", [lf("npb"), lf("cpb")])
342
- def test_expectation_between_two_states(backend):
343
- zp = np.array([1.0, 0.0])
344
- zd = np.array([0.0, 1.0])
345
- assert tc.expectation((tc.gates.y(), [0]), ket=zp, bra=zd) == 1j
346
-
347
- c = tc.Circuit(3)
348
- c.H(0)
349
- c.ry(1, theta=tc.num_to_tensor(0.8))
350
- c.cnot(1, 2)
351
-
352
- state = c.wavefunction()
353
- x1z2 = [(tc.gates.x(), [0]), (tc.gates.z(), [1])]
354
- e1 = c.expectation(*x1z2)
355
- e2 = tc.expectation(*x1z2, ket=state, bra=state, normalization=True)
356
- np.testing.assert_allclose(tc.backend.numpy(e2), tc.backend.numpy(e1))
357
-
358
- c = tc.Circuit(3)
359
- c.H(0)
360
- c.ry(1, theta=tc.num_to_tensor(0.8 + 0.7j))
361
- c.cnot(1, 2)
362
-
363
- state = c.wavefunction()
364
- x1z2 = [(tc.gates.x(), [0]), (tc.gates.z(), [1])]
365
- e1 = c.expectation(*x1z2) / tc.backend.norm(state) ** 2
366
- e2 = tc.expectation(*x1z2, ket=state, normalization=True)
367
- np.testing.assert_allclose(tc.backend.numpy(e2), tc.backend.numpy(e1))
368
-
369
- c = tc.Circuit(2)
370
- c.X(1)
371
- s1 = c.state()
372
- c2 = tc.Circuit(2)
373
- c2.X(0)
374
- s2 = c2.state()
375
- c3 = tc.Circuit(2)
376
- c3.H(1)
377
- s3 = c3.state()
378
- x1x2 = [(tc.gates.x(), [0]), (tc.gates.x(), [1])]
379
- e = tc.expectation(*x1x2, ket=s1, bra=s2)
380
- np.testing.assert_allclose(tc.backend.numpy(e), 1.0)
381
- e2 = tc.expectation(*x1x2, ket=s3, bra=s2)
382
- np.testing.assert_allclose(tc.backend.numpy(e2), 1.0 / np.sqrt(2))
383
-
384
-
385
- @pytest.mark.parametrize("backend", [lf("npb"), lf("tfb"), lf("jaxb"), lf("cpb")])
386
- def test_any_inputs_state(backend):
387
- c = tc.Circuit(2, inputs=tc.array_to_tensor(np.array([0.0, 0.0, 0.0, 1.0])))
388
- c.X(0)
389
- z0 = c.expectation((tc.gates.z(), [0]))
390
- assert z0 == 1.0
391
- c = tc.Circuit(2, inputs=tc.array_to_tensor(np.array([0.0, 0.0, 1.0, 0.0])))
392
- c.X(0)
393
- z0 = c.expectation((tc.gates.z(), [0]))
394
- assert z0 == 1.0
395
- c = tc.Circuit(2, inputs=tc.array_to_tensor(np.array([1.0, 0.0, 0.0, 0.0])))
396
- c.X(0)
397
- z0 = c.expectation((tc.gates.z(), [0]))
398
- assert z0 == -1.0
399
- c = tc.Circuit(
400
- 2,
401
- inputs=tc.array_to_tensor(np.array([1 / np.sqrt(2), 0.0, 1 / np.sqrt(2), 0.0])),
402
- )
403
- c.X(0)
404
- z0 = c.expectation((tc.gates.z(), [0]))
405
- np.testing.assert_allclose(tc.backend.numpy(z0), 0.0, rtol=1e-4, atol=1e-4)
406
-
407
-
408
- @pytest.mark.parametrize("backend", [lf("npb"), lf("tfb"), lf("cpb")])
409
- def test_postselection(backend):
410
- c = tc.Circuit(3)
411
- c.H(1)
412
- c.H(2)
413
- c.mid_measurement(1, 1)
414
- c.mid_measurement(2, 1)
415
- s = c.wavefunction()
416
- np.testing.assert_allclose(tc.backend.numpy(s[3]).real, 0.5)
417
-
418
-
419
- @pytest.mark.parametrize("backend", [lf("npb"), lf("cpb")])
420
- def test_unitary(backend):
421
- c = tc.Circuit(2, inputs=np.eye(4))
422
- c.X(0)
423
- c.Y(1)
424
- answer = tc.backend.numpy(np.kron(tc.gates.x().tensor, tc.gates.y().tensor))
425
- np.testing.assert_allclose(
426
- tc.backend.numpy(c.wavefunction().reshape([4, 4])), answer, atol=1e-4
427
- )
428
-
429
-
430
- @pytest.mark.parametrize("backend", [lf("npb"), lf("cpb")])
431
- def test_expectation_ps(backend):
432
- c = tc.Circuit(2)
433
- c.X(0)
434
- r = c.expectation_ps(z=[0, 1])
435
- np.testing.assert_allclose(tc.backend.numpy(r), -1, atol=1e-5)
436
-
437
- c = tc.Circuit(2)
438
- c.H(0)
439
- r = c.expectation_ps(z=[1], x=[0])
440
- np.testing.assert_allclose(tc.backend.numpy(r), 1, atol=1e-5)
441
- r1 = c.expectation_ps(ps=[1, 3])
442
- np.testing.assert_allclose(tc.backend.numpy(r1), 1, atol=1e-5)
443
- r1 = c.expectation_ps(z=[1, 2], ps=[1, 3])
444
- np.testing.assert_allclose(tc.backend.numpy(r1), 1, atol=1e-5)
445
-
446
-
447
- def test_probability():
448
- for c_cls in [tc.Circuit, tc.DMCircuit]:
449
- c = c_cls(2)
450
- c.h(0)
451
- c.h(1)
452
- np.testing.assert_allclose(
453
- c.probability(), np.array([1, 1, 1, 1]) / 4, atol=1e-5
454
- )
455
-
456
-
457
- @pytest.mark.parametrize("backend", [lf("tfb"), lf("jaxb")])
458
- def test_dqas_type_circuit(backend):
459
- eye = tc.gates.i().tensor
460
- x = tc.gates.x().tensor
461
- y = tc.gates.y().tensor
462
- z = tc.gates.z().tensor
463
-
464
- def f(params, structures):
465
- paramsc = tc.backend.cast(params, dtype="complex64")
466
- structuresc = tc.backend.softmax(structures, axis=-1)
467
- structuresc = tc.backend.cast(structuresc, dtype="complex64")
468
- c = tc.Circuit(5)
469
- for i in range(5):
470
- c.H(i)
471
- for j in range(2):
472
- for i in range(4):
473
- c.cz(i, i + 1)
474
- for i in range(5):
475
- c.any(
476
- i,
477
- unitary=structuresc[i, j, 0]
478
- * (
479
- tc.backend.cos(paramsc[i, j, 0]) * eye
480
- + tc.backend.sin(paramsc[i, j, 0]) * x
481
- )
482
- + structuresc[i, j, 1]
483
- * (
484
- tc.backend.cos(paramsc[i, j, 1]) * eye
485
- + tc.backend.sin(paramsc[i, j, 1]) * y
486
- )
487
- + structuresc[i, j, 2]
488
- * (
489
- tc.backend.cos(paramsc[i, j, 2]) * eye
490
- + tc.backend.sin(paramsc[i, j, 2]) * z
491
- ),
492
- )
493
- return tc.backend.real(c.expectation([tc.gates.z(), (2,)]))
494
-
495
- structures = tc.array_to_tensor(
496
- np.random.normal(size=[16, 5, 2, 3]), dtype="float32"
497
- )
498
- params = tc.array_to_tensor(np.random.normal(size=[5, 2, 3]), dtype="float32")
499
-
500
- vf = tc.backend.vmap(f, vectorized_argnums=(1,))
501
-
502
- np.testing.assert_allclose(vf(params, structures).shape, [16])
503
-
504
- vvag = tc.backend.vvag(f, argnums=0, vectorized_argnums=1)
505
-
506
- vvag = tc.backend.jit(vvag)
507
-
508
- value, grad = vvag(params, structures)
509
-
510
- np.testing.assert_allclose(value.shape, [16])
511
- np.testing.assert_allclose(grad.shape, [5, 2, 3])
512
-
513
-
514
- @pytest.mark.parametrize("backend", [lf("tfb"), lf("jaxb")])
515
- def test_mixed_measurement_circuit(backend):
516
- n = 4
517
-
518
- def f(params, structures):
519
- structuresc = tc.backend.cast(structures, dtype="complex64")
520
- c = tc.Circuit(n)
521
- for i in range(n):
522
- c.H(i)
523
- for j in range(2):
524
- for i in range(n):
525
- c.cnot(i, (i + 1) % n)
526
- for i in range(n):
527
- c.rz(i, theta=params[j, i])
528
- obs = []
529
- for i in range(n):
530
- obs.append(
531
- [
532
- tc.gates.Gate(
533
- sum(
534
- [
535
- structuresc[i, k] * g.tensor
536
- for k, g in enumerate(tc.gates.pauli_gates)
537
- ]
538
- )
539
- ),
540
- (i,),
541
- ]
542
- )
543
- loss = c.expectation(*obs, reuse=False)
544
- return tc.backend.real(loss)
545
-
546
- # measure X0 to X3
547
-
548
- structures = tc.backend.cast(tc.backend.eye(n), "int32")
549
- structures = tc.backend.onehot(structures, num=4)
550
-
551
- f_vvag = tc.backend.jit(tc.backend.vvag(f, vectorized_argnums=1, argnums=0))
552
- v, g = f_vvag(tc.backend.ones([2, n], dtype="float32"), structures)
553
- np.testing.assert_allclose(
554
- v,
555
- np.array(
556
- [
557
- 0.157729,
558
- 0.157729,
559
- 0.157728,
560
- 0.085221,
561
- ]
562
- ),
563
- atol=1e-5,
564
- )
565
- np.testing.assert_allclose(
566
- g[0],
567
- np.array([-0.378372, -0.624019, -0.491295, -0.378372]),
568
- atol=1e-5,
569
- )
570
-
571
-
572
- def test_circuit_add_demo():
573
- # to be refactored for better API
574
- c = tc.Circuit(2)
575
- c.x(0)
576
- c2 = tc.Circuit(2, mps_inputs=c.quvector())
577
- c2.X(0)
578
- answer = np.array([1.0, 0, 0, 0])
579
- np.testing.assert_allclose(c2.wavefunction(), answer, atol=1e-4)
580
- c3 = tc.Circuit(2)
581
- c3.X(0)
582
- c3.replace_mps_inputs(c.quvector())
583
- np.testing.assert_allclose(c3.wavefunction(), answer, atol=1e-4)
584
-
585
-
586
- def test_circuit_replace_inputs():
587
- n = 3
588
- c = tc.Circuit(n, inputs=np.zeros([2**n]))
589
- for i in range(n):
590
- c.H(i)
591
- evenstate = np.ones([2**n])
592
- evenstate /= np.linalg.norm(evenstate)
593
- c.replace_inputs(evenstate)
594
- for i in range(n):
595
- np.testing.assert_allclose(c.expectation_ps(z=[i]), 1.0, atol=1e-5)
596
-
597
-
598
- @pytest.mark.parametrize("backend", [lf("npb"), lf("tfb"), lf("jaxb")])
599
- def test_circuit_matrix(backend):
600
- c = tc.Circuit(2)
601
- c.x(1)
602
- c.cnot(0, 1)
603
- np.testing.assert_allclose(c.matrix()[3], np.array([0.0, 0.0, 0.0, 1.0]), atol=1e-5)
604
- np.testing.assert_allclose(c.state(), np.array([0, 1.0, 0, 0]), atol=1e-5)
605
-
606
-
607
- @pytest.mark.parametrize("backend", [lf("tfb"), lf("jaxb")])
608
- def test_circuit_split(backend):
609
- n = 4
610
-
611
- def f(param, max_singular_values=None, max_truncation_err=None, fixed_choice=None):
612
- if (max_singular_values is None) and (max_truncation_err is None):
613
- split = None
614
- else:
615
- split = {
616
- "max_singular_values": max_singular_values,
617
- "max_truncation_err": max_truncation_err,
618
- "fixed_choice": fixed_choice,
619
- }
620
- c = tc.Circuit(
621
- n,
622
- split=split,
623
- )
624
- for i in range(n):
625
- c.H(i)
626
- for j in range(2):
627
- for i in range(n - 1):
628
- c.exp1(i, i + 1, theta=param[2 * j, i], hermitian=tc.gates._zz_matrix)
629
- for i in range(n):
630
- c.rx(i, theta=param[2 * j + 1, i])
631
- loss = c.expectation(
632
- (
633
- tc.gates.z(),
634
- [1],
635
- ),
636
- (
637
- tc.gates.z(),
638
- [2],
639
- ),
640
- )
641
- return tc.backend.real(loss)
642
-
643
- s1 = f(tc.backend.ones([4, n]))
644
- s2 = f(tc.backend.ones([4, n]), max_truncation_err=1e-5)
645
- s3 = f(tc.backend.ones([4, n]), max_singular_values=2, fixed_choice=1)
646
-
647
- np.testing.assert_allclose(s1, s2, atol=1e-5)
648
- np.testing.assert_allclose(s1, s3, atol=1e-5)
649
-
650
- f_jit = tc.backend.jit(f, static_argnums=(1, 2, 3))
651
-
652
- s1 = f_jit(tc.backend.ones([4, n]))
653
- # s2 = f_jit(tc.backend.ones([4, n]), max_truncation_err=1e-5) # doesn't work now
654
- # this cannot be done anyway, since variable size tensor network will fail opt einsum
655
- s3 = f_jit(tc.backend.ones([4, n]), max_singular_values=2, fixed_choice=1)
656
-
657
- # np.testing.assert_allclose(s1, s2, atol=1e-5)
658
- np.testing.assert_allclose(s1, s3, atol=1e-5)
659
-
660
- f_vg = tc.backend.jit(
661
- tc.backend.value_and_grad(f, argnums=0), static_argnums=(1, 2, 3)
662
- )
663
-
664
- s1, g1 = f_vg(tc.backend.ones([4, n]))
665
- s3, g3 = f_vg(tc.backend.ones([4, n]), max_singular_values=2, fixed_choice=1)
666
-
667
- np.testing.assert_allclose(s1, s3, atol=1e-5)
668
- # DONE(@refraction-ray): nan on jax backend?
669
- # i see, complex value SVD is not supported on jax for now :)
670
- # I shall further customize complex SVD, finally it has applications
671
-
672
- # tf 2.6.2 also doesn't support complex valued SVD AD, weird...
673
- # if tc.backend.name == "tensorflow":
674
- np.testing.assert_allclose(g1, g3, atol=1e-5)
675
-
676
-
677
- @pytest.mark.parametrize("backend", [lf("npb"), lf("tfb"), lf("jaxb")])
678
- def test_gate_split(backend):
679
- n = 4
680
-
681
- def f(param, max_singular_values=None, max_truncation_err=None, fixed_choice=None):
682
- if (max_singular_values is None) and (max_truncation_err is None):
683
- split = None
684
- else:
685
- split = {
686
- "max_singular_values": max_singular_values,
687
- "max_truncation_err": max_truncation_err,
688
- "fixed_choice": fixed_choice,
689
- }
690
- c = tc.Circuit(
691
- n,
692
- )
693
- for i in range(n):
694
- c.H(i)
695
- for j in range(2):
696
- for i in range(n - 1):
697
- c.exp1(
698
- i,
699
- i + 1,
700
- theta=param[2 * j, i],
701
- unitary=tc.gates._zz_matrix,
702
- split=split,
703
- )
704
- for i in range(n):
705
- c.rx(i, theta=param[2 * j + 1, i])
706
- loss = c.expectation(
707
- (
708
- tc.gates.x(),
709
- [1],
710
- ),
711
- )
712
- return tc.backend.real(loss)
713
-
714
- s1 = f(tc.backend.ones([4, n]))
715
- s2 = f(tc.backend.ones([4, n]), max_truncation_err=1e-5)
716
- s3 = f(tc.backend.ones([4, n]), max_singular_values=2, fixed_choice=1)
717
-
718
- np.testing.assert_allclose(s1, s2, atol=1e-5)
719
- np.testing.assert_allclose(s1, s3, atol=1e-5)
720
-
721
-
722
- def test_toqir():
723
- split = {
724
- "max_singular_values": 2,
725
- "fixed_choice": 1,
726
- }
727
- c = tc.Circuit(3)
728
- c.H(0)
729
- c.rx(1, theta=tc.array_to_tensor(0.7))
730
- c.exp1(
731
- 0, 1, unitary=tc.gates._zz_matrix, theta=tc.array_to_tensor(-0.2), split=split
732
- )
733
- z1 = c.expectation((tc.gates.z(), [1]))
734
- qirs = c.to_qir()
735
- c = tc.Circuit.from_qir(qirs, circuit_params={"nqubits": 3})
736
- assert len(c._nodes) == 7
737
- z2 = c.expectation((tc.gates.z(), [1]))
738
- np.testing.assert_allclose(z1, z2, atol=1e-5)
739
- c.append_from_qir(qirs)
740
- z3 = c.expectation((tc.gates.z(), [1]))
741
- assert len(c._nodes) == 11
742
- np.testing.assert_allclose(z3, 0.202728, atol=1e-5)
743
-
744
-
745
- def test_vis_tex():
746
- c = tc.Circuit(3)
747
- for i in range(3):
748
- c.H(i)
749
- for i in range(3):
750
- c.any(i, (i + 1) % 3, unitary=tc.backend.ones([4, 4]), name="hihi")
751
- c.any(2, unitary=tc.backend.ones([2, 2]), name="invisible")
752
- c.cz(1, 2)
753
- c.any(1, 0, 2, unitary=tc.backend.ones([8, 8]), name="ccha")
754
- c.z(2)
755
- c.cnot(0, 1)
756
- c.cz(2, 1)
757
-
758
- print(c.vis_tex(init=["0", "1", ""], measure=["x", "y", "z"]))
759
-
760
-
761
- def test_debug_contract():
762
- n = 10
763
- d = 4
764
- try:
765
- import cotengra # pylint: disable=unused-import
766
-
767
- except ImportError:
768
- pytest.skip("cotengra is not installed")
769
-
770
- @tc.set_function_contractor(
771
- "custom_stateful",
772
- optimizer=oem.RandomGreedy,
773
- max_time=10,
774
- max_repeats=64,
775
- minimize="size",
776
- debug_level=2,
777
- contraction_info=True,
778
- )
779
- def small_tn():
780
- param = tc.backend.ones([2 * d, n])
781
- c = tc.Circuit(n)
782
- c = tc.templates.blocks.example_block(c, param, nlayers=d)
783
- return c.state()
784
-
785
- np.testing.assert_allclose(small_tn(), np.zeros([2**n]), atol=1e-5)
786
-
787
-
788
- @pytest.mark.parametrize("backend", [lf("npb"), lf("tfb"), lf("jaxb")])
789
- def test_teleportation(backend):
790
- key = tc.backend.get_random_state(42)
791
-
792
- @tc.backend.jit
793
- def f(key):
794
- tc.backend.set_random_state(key)
795
- c = tc.Circuit(2)
796
- c.H(0)
797
- r = c.cond_measurement(0)
798
- c.conditional_gate(r, [tc.gates.i(), tc.gates.x()], 1)
799
- return r, c.expectation([tc.gates.z(), [1]])
800
-
801
- keys = []
802
- for _ in range(6):
803
- key, subkey = tc.backend.random_split(key)
804
- keys.append(subkey)
805
- rs = [f(k) for k in keys]
806
- for r, e in rs:
807
- if tc.backend.numpy(r) > 0.5:
808
- np.testing.assert_allclose(e, -1, atol=1e-5)
809
- else:
810
- np.testing.assert_allclose(e, 1, atol=1e-5)
811
-
812
-
813
- @pytest.mark.parametrize("backend", [lf("npb"), lf("tfb"), lf("jaxb")])
814
- def test_append_circuit(backend):
815
- c = tc.Circuit(2)
816
- c.cnot(0, 1)
817
- c1 = tc.Circuit(2)
818
- c1.x(0)
819
- c.append(c1)
820
- np.testing.assert_allclose(c.expectation_ps(z=[1]), 1.0)
821
-
822
- c = tc.Circuit(2)
823
- c.cnot(0, 1)
824
- c1 = tc.Circuit(2)
825
- c1.x(0)
826
- c.prepend(c1)
827
- np.testing.assert_allclose(c.expectation_ps(z=[1]), -1.0)
828
-
829
- c = tc.Circuit(2)
830
- c1 = tc.Circuit(1)
831
- c1.x(0)
832
- c.append(c1, [1])
833
- np.testing.assert_allclose(c.state(), [0, 1, 0, 0])
834
-
835
-
836
- @pytest.mark.parametrize("backend", [lf("npb"), lf("tfb"), lf("jaxb")])
837
- def test_apply_mpo_gate(backend):
838
- gate = tc.gates.multicontrol_gate(tc.gates._x_matrix, ctrl=[1, 0])
839
- ans = np.array(
840
- [
841
- [1.0, 0, 0, 0, 0, 0, 0, 0],
842
- [0, 1.0, 0, 0, 0, 0, 0, 0],
843
- [0, 0, 1.0, 0, 0, 0, 0, 0],
844
- [0, 0, 0, 1.0, 0, 0, 0, 0],
845
- [0, 0, 0, 0, 0, 1.0, 0, 0],
846
- [0, 0, 0, 0, 1.0, 0, 0, 0],
847
- [0, 0, 0, 0, 0, 0, 1.0, 0],
848
- [0, 0, 0, 0, 0, 0, 0, 1.0],
849
- ]
850
- )
851
- c = tc.Circuit(3)
852
- c.X(0)
853
- c.mpo(0, 1, 2, mpo=gate.copy())
854
- np.testing.assert_allclose(c.expectation([tc.gates.z(), [2]]), -1, atol=1e-5)
855
- c = tc.Circuit(3)
856
- c.X(1)
857
- c.mpo(0, 1, 2, mpo=gate.copy())
858
- np.testing.assert_allclose(c.expectation([tc.gates.z(), [2]]), 1, atol=1e-5)
859
- np.testing.assert_allclose(gate.eval_matrix(), ans, atol=1e-5)
860
-
861
-
862
- def test_apply_multicontrol_gate():
863
- c = tc.Circuit(3)
864
- c.X(2)
865
- c.multicontrol(0, 2, 1, ctrl=[0, 1], unitary=tc.gates._x_matrix)
866
- np.testing.assert_allclose(c.expectation([tc.gates.z(), [1]]), -1, atol=1e-5)
867
- c = tc.Circuit(3)
868
- c.X(0)
869
- c.multicontrol(0, 2, 1, ctrl=[0, 1], unitary=tc.gates._x_matrix)
870
- np.testing.assert_allclose(c.expectation([tc.gates.z(), [1]]), 1, atol=1e-5)
871
- c = tc.Circuit(4)
872
- c.X(0)
873
- c.X(2)
874
- c.multicontrol(0, 1, 2, 3, ctrl=[1, 0], unitary=tc.gates.swap())
875
- np.testing.assert_allclose(c.expectation([tc.gates.z(), [3]]), -1, atol=1e-5)
876
-
877
-
878
- @pytest.mark.parametrize("backend", [lf("npb"), lf("tfb"), lf("jaxb")])
879
- def test_circuit_quoperator(backend):
880
- c = tc.Circuit(3)
881
- c.x(0)
882
- c.cnot(0, 1)
883
- c.cz(1, 2)
884
- c.y(2)
885
- c.exp1(0, 2, theta=1.0, unitary=tc.gates._xx_matrix)
886
- c.H(1)
887
- c.multicontrol(0, 2, 1, ctrl=[1, 0], unitary=tc.gates.z())
888
- qo = c.quoperator()
889
- np.testing.assert_allclose(qo.eval_matrix(), c.matrix(), atol=1e-5)
890
-
891
-
892
- @pytest.mark.parametrize("backend", [lf("npb"), lf("tfb"), lf("jaxb")])
893
- def test_qir2cirq(backend):
894
- try:
895
- import cirq
896
- except ImportError:
897
- pytest.skip("cirq is not installed")
898
- n = 6
899
- c = tc.Circuit(n)
900
- for i in range(n):
901
- c.H(i)
902
- zz = np.array([[1, 0, 0, 0], [0, -1, 0, 0], [0, 0, -1, 0], [0, 0, 0, 1]])
903
- for i in range(n):
904
- c.exp(
905
- i,
906
- (i + 1) % n,
907
- theta=tc.array_to_tensor(np.random.uniform()),
908
- unitary=tc.array_to_tensor(zz),
909
- name="zz",
910
- )
911
- c.exp1(
912
- 1, 3, theta=tc.array_to_tensor(0.0j), unitary=tc.array_to_tensor(zz), name="zz"
913
- )
914
- c.fredkin(0, 1, 2)
915
- c.cswap(1, 2, 3)
916
- c.ccnot(1, 2, 3)
917
- c.cx(2, 3)
918
- c.swap(0, 1)
919
- c.iswap(0, 1)
920
- c.iswap(1, 3, theta=-1.9)
921
- c.toffoli(0, 1, 2)
922
- c.s(1)
923
- c.t(1)
924
- c.sd(1)
925
- c.td(1)
926
- c.x(2)
927
- c.y(2)
928
- c.z(2)
929
- c.wroot(3)
930
- c.cnot(0, 1)
931
- c.cy(0, 1)
932
- c.cz(0, 1)
933
- c.oy(4, 3)
934
- c.oz(4, 3)
935
- c.ox(4, 3)
936
- c.oy(4, 3)
937
- c.oz(4, 3)
938
- c.ox(3, 4)
939
- c.phase(2, theta=0.3)
940
- c.cphase(1, 0, theta=-1.2)
941
- c.rxx(0, 2, theta=0.9)
942
- c.ryy(1, 4, theta=-2.0)
943
- c.rzz(1, 3, theta=0.5)
944
- c.u(2, theta=0, lbd=4.6, phi=-0.3)
945
- c.cu(4, 1, theta=1.2)
946
- c.rx(1, theta=tc.array_to_tensor(np.random.uniform()))
947
- c.r(5, theta=tc.array_to_tensor(np.random.uniform()))
948
- c.cr(
949
- 1,
950
- 2,
951
- theta=tc.array_to_tensor(np.random.uniform()),
952
- alpha=tc.array_to_tensor(np.random.uniform()),
953
- phi=tc.array_to_tensor(np.random.uniform()),
954
- )
955
- c.ry(1, theta=tc.array_to_tensor(np.random.uniform()))
956
- c.rz(1, theta=tc.array_to_tensor(np.random.uniform()))
957
- c.crz(2, 3, theta=tc.array_to_tensor(np.random.uniform()))
958
- c.crx(5, 3, theta=tc.array_to_tensor(np.random.uniform()))
959
- c.cry(1, 3, theta=tc.array_to_tensor(np.random.uniform()))
960
- c.orx(5, 3, theta=tc.array_to_tensor(np.random.uniform()))
961
- c.ory(5, 3, theta=tc.array_to_tensor(np.random.uniform()))
962
- c.orz(5, 3, theta=tc.array_to_tensor(np.random.uniform()))
963
-
964
- c.any(1, 3, unitary=tc.array_to_tensor(np.reshape(zz, [2, 2, 2, 2])))
965
-
966
- gate = tc.gates.multicontrol_gate(
967
- tc.array_to_tensor(tc.gates._x_matrix), ctrl=[1, 0]
968
- )
969
- c.mpo(0, 1, 2, mpo=gate.copy())
970
- c.multicontrol(
971
- 0,
972
- 2,
973
- 4,
974
- 1,
975
- 5,
976
- ctrl=[0, 1, 0],
977
- unitary=tc.array_to_tensor(tc.gates._zz_matrix),
978
- name="zz",
979
- )
980
- tc_unitary = c.matrix()
981
- tc_unitary = np.reshape(tc_unitary, [2**n, 2**n])
982
-
983
- cirq = c.to_cirq()
984
- cirq_unitary = cirq.unitary()
985
- cirq_unitary = np.reshape(cirq_unitary, [2**n, 2**n])
986
-
987
- np.testing.assert_allclose(tc_unitary, cirq_unitary, atol=1e-5)
988
-
989
-
990
- @pytest.mark.parametrize("backend", [lf("npb"), lf("tfb"), lf("jaxb")])
991
- def test_qir2qiskit(backend):
992
- try:
993
- import qiskit.quantum_info as qi
994
-
995
- from tensorcircuit.translation import perm_matrix
996
- except ImportError:
997
- pytest.skip("qiskit is not installed")
998
-
999
- n = 6
1000
- c = tc.Circuit(n, inputs=tc.array_to_tensor(np.eye(2**n)))
1001
-
1002
- for i in range(n):
1003
- c.H(i)
1004
- zz = np.array([[1, 0, 0, 0], [0, -1, 0, 0], [0, 0, -1, 0], [0, 0, 0, 1]])
1005
- for i in range(n):
1006
- c.exp(
1007
- i,
1008
- (i + 1) % n,
1009
- theta=tc.array_to_tensor(np.random.uniform()),
1010
- unitary=tc.array_to_tensor(zz),
1011
- name="zz",
1012
- )
1013
- c.exp1(
1014
- 1, 3, theta=tc.array_to_tensor(0.0j), unitary=tc.array_to_tensor(zz), name="zz"
1015
- )
1016
- c.fredkin(1, 2, 3)
1017
- c.cswap(1, 2, 3)
1018
- c.ccnot(1, 2, 3)
1019
- c.cx(2, 3)
1020
- c.swap(0, 1)
1021
- c.iswap(0, 1)
1022
- c.iswap(1, 3, theta=-1.9)
1023
- c.toffoli(0, 1, 2)
1024
- c.s(1)
1025
- c.t(1)
1026
- c.sd(1)
1027
- c.td(1)
1028
- c.x(2)
1029
- c.y(2)
1030
- c.z(2)
1031
- c.wroot(3)
1032
- c.cnot(0, 1)
1033
- c.cy(0, 1)
1034
- c.cz(0, 1)
1035
- c.oy(4, 3)
1036
- c.oz(4, 3)
1037
- c.ox(4, 3)
1038
- c.oy(4, 3)
1039
- c.oz(4, 3)
1040
- c.ox(3, 4)
1041
- c.phase(2, theta=0.3)
1042
- c.cphase(1, 0, theta=-1.2)
1043
- c.rxx(0, 2, theta=0.9)
1044
- c.ryy(1, 4, theta=-2.0)
1045
- c.rzz(1, 3, theta=0.5)
1046
- c.u(2, theta=0, lbd=4.6, phi=-0.3)
1047
- c.cu(4, 1, theta=1.2)
1048
- c.rx(1, theta=tc.array_to_tensor(np.random.uniform()))
1049
- c.r(5, theta=tc.array_to_tensor(np.random.uniform()))
1050
- c.cr(
1051
- 1,
1052
- 2,
1053
- theta=tc.array_to_tensor(np.random.uniform()),
1054
- alpha=tc.array_to_tensor(np.random.uniform()),
1055
- phi=tc.array_to_tensor(np.random.uniform()),
1056
- )
1057
- c.ry(1, theta=tc.array_to_tensor(np.random.uniform()))
1058
- c.rz(1, theta=tc.array_to_tensor(np.random.uniform()))
1059
- c.crz(2, 3, theta=tc.array_to_tensor(np.random.uniform()))
1060
- c.crx(5, 3, theta=tc.array_to_tensor(np.random.uniform()))
1061
- c.cry(1, 3, theta=tc.array_to_tensor(np.random.uniform()))
1062
- c.orx(5, 3, theta=tc.array_to_tensor(np.random.uniform()))
1063
- c.ory(5, 3, theta=tc.array_to_tensor(np.random.uniform()))
1064
- c.orz(5, 3, theta=tc.array_to_tensor(np.random.uniform()))
1065
-
1066
- c.any(1, 3, unitary=tc.array_to_tensor(np.reshape(zz, [2, 2, 2, 2])))
1067
- gate = tc.gates.multicontrol_gate(
1068
- tc.array_to_tensor(tc.gates._x_matrix), ctrl=[1, 0]
1069
- )
1070
- c.mpo(0, 1, 2, mpo=gate.copy())
1071
- c.multicontrol(
1072
- 0,
1073
- 2,
1074
- 4,
1075
- 1,
1076
- 5,
1077
- ctrl=[0, 1, 0],
1078
- unitary=tc.array_to_tensor(tc.gates._zz_matrix),
1079
- name="zz",
1080
- )
1081
- tc_unitary = c.wavefunction()
1082
- tc_unitary = np.reshape(tc_unitary, [2**n, 2**n])
1083
-
1084
- qisc = c.to_qiskit()
1085
- qis_unitary = qi.Operator(qisc)
1086
- qis_unitary = np.reshape(qis_unitary, [2**n, 2**n])
1087
-
1088
- p_mat = perm_matrix(n)
1089
- np.testing.assert_allclose(p_mat @ tc_unitary @ p_mat, qis_unitary, atol=1e-5)
1090
-
1091
-
1092
- def test_qiskit2tc():
1093
- try:
1094
- import qiskit.quantum_info as qi
1095
- from qiskit import QuantumCircuit
1096
- from qiskit.circuit.library import HamiltonianGate
1097
- from qiskit.circuit.library.standard_gates import MCXGate, SwapGate
1098
-
1099
- from tensorcircuit.translation import perm_matrix
1100
- except ImportError:
1101
- pytest.skip("qiskit is not installed")
1102
- n = 6
1103
- qisc = QuantumCircuit(n)
1104
- for i in range(n):
1105
- qisc.h(i)
1106
- zz = np.array([[1, 0, 0, 0], [0, -1, 0, 0], [0, 0, -1, 0], [0, 0, 0, 1]])
1107
- exp_op = qi.Operator(zz)
1108
- for i in range(n):
1109
- gate = HamiltonianGate(exp_op, time=np.random.uniform())
1110
- qisc.append(gate, [i, (i + 1) % n])
1111
- qisc.fredkin(1, 2, 3)
1112
- qisc.cswap(1, 2, 3)
1113
- qisc.swap(0, 1)
1114
- qisc.iswap(0, 1)
1115
- qisc.toffoli(0, 1, 2)
1116
- # test Instructions
1117
- qisc2 = QuantumCircuit(1)
1118
- qisc2.h(0)
1119
- qisc.compose(qisc2, qubits=[1], inplace=True, wrap=True)
1120
- qisc.barrier(0, 1, 2)
1121
- qisc.s(1)
1122
- qisc.t(1)
1123
- qisc.sdg(2)
1124
- qisc.tdg(2)
1125
- qisc.x(3)
1126
- qisc.y(3)
1127
- qisc.z(3)
1128
- qisc.cu(
1129
- 5.868768495722669, 2.24809352294186, 3.59102783505607, 2.0223650288392, 1, 3
1130
- )
1131
- qisc.cnot(0, 1)
1132
- qisc.cy(0, 1)
1133
- qisc.cz(0, 1, ctrl_state=0)
1134
- qisc.cy(0, 1, ctrl_state=0)
1135
- qisc.cx(0, 1, ctrl_state=0)
1136
- qisc.rxx(0.3, 1, 2)
1137
- qisc.rzz(-0.8, 2, 0)
1138
- qisc.u(0.3, 0.9, -1.2, 2)
1139
- qisc.rx(np.random.uniform(), 1)
1140
- qisc.ry(np.random.uniform(), 2)
1141
- qisc.rz(np.random.uniform(), 3)
1142
- qisc.crz(np.random.uniform(), 2, 3)
1143
- qisc.crz(np.random.uniform(), 2, 3)
1144
- qisc.crz(np.random.uniform(), 2, 3)
1145
- qisc.crz(np.random.uniform(), 2, 3, ctrl_state=0)
1146
- qisc.crz(np.random.uniform(), 2, 3, ctrl_state=0)
1147
- qisc.crz(np.random.uniform(), 2, 3, ctrl_state=0)
1148
- qisc.r(np.random.uniform(), np.random.uniform(), 1)
1149
- qisc.unitary(exp_op, [1, 3])
1150
- mcx_g = MCXGate(3, ctrl_state="010")
1151
- qisc.append(mcx_g, [0, 1, 2, 3])
1152
- qisc.ccx(0, 1, 2, ctrl_state="01")
1153
- CCCRX = SwapGate().control(2, ctrl_state="01")
1154
- qisc.append(CCCRX, [0, 1, 2, 3])
1155
-
1156
- c = tc.Circuit.from_qiskit(qisc, n, np.eye(2**n))
1157
- tc_unitary = c.wavefunction()
1158
- tc_unitary = np.reshape(tc_unitary, [2**n, 2**n])
1159
- qis_unitary = qi.Operator(qisc)
1160
- qis_unitary = np.reshape(qis_unitary, [2**n, 2**n])
1161
- p_mat = perm_matrix(n)
1162
- np.testing.assert_allclose(p_mat @ tc_unitary @ p_mat, qis_unitary, atol=1e-5)
1163
- qisc_from_tc = c.to_qiskit(enable_instruction=True)
1164
- qis_unitary2 = qi.Operator(qisc_from_tc)
1165
- qis_unitary2 = np.reshape(qis_unitary2, [2**n, 2**n])
1166
- np.testing.assert_allclose(qis_unitary2, qis_unitary, atol=1e-5)
1167
-
1168
-
1169
- @pytest.mark.parametrize("backend", [lf("tfb"), lf("jaxb"), lf("torchb")])
1170
- def test_qiskit2tc_parameterized(backend):
1171
- try:
1172
- from qiskit.circuit import Parameter, ParameterVector, QuantumCircuit
1173
- from qiskit.circuit.library import TwoLocal
1174
- from qiskit.quantum_info import Operator
1175
- from qiskit_nature.second_q.circuit.library import UCCSD
1176
- from qiskit_nature.second_q.mappers import ParityMapper
1177
- except ImportError:
1178
- pytest.skip("qiskit or qiskit-nature is not installed")
1179
- from tensorcircuit.translation import perm_matrix
1180
-
1181
- mapper = ParityMapper()
1182
- ansatz1 = UCCSD(2, [1, 1], mapper)
1183
- ansatz2 = TwoLocal(2, rotation_blocks="ry", entanglement_blocks="cz")
1184
- ansatz3 = QuantumCircuit(1)
1185
- ansatz3_param = Parameter("θ")
1186
- ansatz3.rx(ansatz3_param, 0)
1187
- ansatz4 = QuantumCircuit(1)
1188
- ansatz4_param = ParameterVector("φ", 3)
1189
- ansatz4.rx(2.0 * ansatz4_param[0] + 5.0, 0)
1190
- ansatz4.ry(ansatz4_param[0] * ansatz4_param[1] + ansatz4_param[2], 0)
1191
- ansatz4.rz(
1192
- np.exp(np.sin(ansatz4_param[0]))
1193
- + np.abs(ansatz4_param[1]) / np.arctan(ansatz4_param[2]),
1194
- 0,
1195
- )
1196
- ansatz_list = [ansatz1, ansatz2, ansatz3, ansatz4]
1197
- for ansatz in ansatz_list:
1198
- n = ansatz.num_qubits
1199
- if ansatz in [ansatz1, ansatz2, ansatz4]:
1200
- params = np.random.rand(ansatz.num_parameters)
1201
- else:
1202
- params = {ansatz3_param: 0.618}
1203
- qisc = ansatz.assign_parameters(params)
1204
- qiskit_unitary = Operator(qisc)
1205
- qiskit_unitary = np.reshape(qiskit_unitary, [2**n, 2**n])
1206
-
1207
- # test jit
1208
- @tc.backend.jit
1209
- def get_unitary(params):
1210
- return tc.Circuit.from_qiskit(
1211
- ansatz, inputs=np.eye(2**n), binding_params=params
1212
- ).state()
1213
-
1214
- tc_unitary = get_unitary(params)
1215
- tc_unitary = np.reshape(tc_unitary, [2**n, 2**n])
1216
- p_mat = tc.array_to_tensor(perm_matrix(n))
1217
- np.testing.assert_allclose(
1218
- p_mat @ tc_unitary @ p_mat, qiskit_unitary, atol=1e-5
1219
- )
1220
-
1221
- # test grad
1222
- def cost_fn(params):
1223
- return tc.backend.real(tc.backend.sum(get_unitary(params)))
1224
-
1225
- if ansatz in [ansatz1, ansatz2, ansatz4]:
1226
- grad = tc.backend.grad(cost_fn)(tc.backend.convert_to_tensor(params))
1227
- assert tc.backend.sum(tc.num_to_tensor(np.isnan(grad))) == 0
1228
- else:
1229
- # tf only supports tf tensor as input
1230
- grad = tc.backend.grad(cost_fn)(
1231
- {ansatz3_param: tc.backend.convert_to_tensor(0.618)}
1232
- )
1233
- assert not np.isnan(grad[ansatz3_param])
1234
-
1235
-
1236
- @pytest.mark.parametrize("backend", [lf("npb"), lf("tfb"), lf("jaxb")])
1237
- def test_qiskit_vs_tc_intialization(backend):
1238
- try:
1239
- import qiskit.quantum_info as qi
1240
- from qiskit import QuantumCircuit
1241
- except ImportError:
1242
- pytest.skip("qiskit is not installed")
1243
-
1244
- n = 3
1245
-
1246
- qis_c = QuantumCircuit(n)
1247
- qis_c.h(0)
1248
- qis_c.cnot(0, 1)
1249
- qis_c.y(2)
1250
- state = qi.Statevector(qis_c)
1251
- qis_c = QuantumCircuit(n)
1252
- qis_c.initialize(state)
1253
- qis_c.cnot(1, 2)
1254
- c = tc.Circuit.from_qiskit(qis_c)
1255
- c2 = tc.Circuit(n)
1256
- c2.h(0)
1257
- c2.cnot(0, 1)
1258
- c2.y(2)
1259
- c2.cnot(1, 2)
1260
- np.testing.assert_allclose(c.state(), c2.state(), atol=1e-8)
1261
- np.testing.assert_allclose(
1262
- qi.Statevector(c.to_qiskit(enable_inputs=True)),
1263
- qi.Statevector(qis_c),
1264
- atol=1e-8,
1265
- )
1266
-
1267
-
1268
- @pytest.mark.parametrize("backend", [lf("npb"), lf("tfb"), lf("jaxb")])
1269
- def test_batch_sample(backend):
1270
- c = tc.Circuit(3)
1271
- c.H(0)
1272
- c.cnot(0, 1)
1273
- print(c.sample())
1274
- print(c.sample(batch=8))
1275
- print(c.sample(random_generator=tc.backend.get_random_state(42)))
1276
- print(c.sample(allow_state=True))
1277
- print(c.sample(batch=8, allow_state=True))
1278
- print(
1279
- c.sample(
1280
- batch=8, allow_state=True, random_generator=tc.backend.get_random_state(42)
1281
- )
1282
- )
1283
- print(
1284
- c.sample(
1285
- batch=8,
1286
- allow_state=True,
1287
- status=np.random.uniform(size=[8]),
1288
- format="sample_bin",
1289
- )
1290
- )
1291
-
1292
-
1293
- def test_expectation_y_bug():
1294
- c = tc.Circuit(1, inputs=1 / np.sqrt(2) * np.array([-1, 1.0j]))
1295
- m = c.expectation_ps(y=[0])
1296
- np.testing.assert_allclose(m, -1, atol=1e-5)
1297
-
1298
-
1299
- def test_lightcone_expectation():
1300
- def construct_c(pbc=True):
1301
- n = 4
1302
- ns = n
1303
- if pbc is False:
1304
- ns -= 1
1305
- c = tc.Circuit(n)
1306
- for j in range(2):
1307
- for i in range(n):
1308
- c.rx(i, theta=0.2, name="rx" + str(j) + "-" + str(i))
1309
- for i in range(ns):
1310
- c.cnot(i, (i + 1) % n, name="cnot" + str(j) + "-" + str(i))
1311
- return c
1312
-
1313
- for b in [True, False]:
1314
- c = construct_c(b)
1315
- m1 = c.expectation_ps(z=[0], enable_lightcone=True)
1316
- m2 = c.expectation_ps(z=[0])
1317
- np.testing.assert_allclose(m1, m2, atol=1e-5)
1318
- nodes = c.expectation_before([tc.gates.z(), 0], reuse=False)
1319
- l1 = len(nodes)
1320
- nodes = tc.simplify._full_light_cone_cancel(nodes)
1321
- l2 = len(nodes)
1322
- if b is False:
1323
- assert l1 == 37 and l2 == 25
1324
- else:
1325
- assert l1 == 41 and l2 == 41
1326
-
1327
-
1328
- @pytest.mark.parametrize("backend", [lf("npb"), lf("tfb"), lf("jaxb")])
1329
- def test_circuit_inverse(backend):
1330
- inputs = np.random.uniform(size=[8])
1331
- inputs /= np.linalg.norm(inputs)
1332
- c = tc.Circuit(3, inputs=inputs)
1333
- c.H(1)
1334
- c.rx(0, theta=0.5)
1335
- c.cnot(1, 2)
1336
- c.rzz(0, 2, theta=-0.8)
1337
- c1 = c.inverse()
1338
- c.append(c1)
1339
- np.testing.assert_allclose(c.state(), inputs, atol=1e-5)
1340
-
1341
-
1342
- @pytest.mark.parametrize("backend", [lf("npb"), lf("tfb"), lf("jaxb")])
1343
- def test_circuit_inverse_2(backend):
1344
- inputs = np.random.uniform(size=[8])
1345
- inputs /= np.linalg.norm(inputs)
1346
- c = tc.Circuit(3, inputs=inputs)
1347
- c.iswap(0, 1)
1348
- c.iswap(1, 0, theta=0.6)
1349
- c.rxx(1, 2, theta=-0.2)
1350
- c.cu(0, 1, lbd=2.0, theta=-0.7)
1351
- c.r(2, alpha=0.3)
1352
- c.sd(2)
1353
- c.cx(1, 2)
1354
- c.unitary(0, unitary=tc.gates._x_matrix)
1355
- c1 = c.inverse()
1356
- c.append(c1)
1357
- print(c.draw())
1358
- np.testing.assert_allclose(c.state(), inputs, atol=1e-5)
1359
-
1360
-
1361
- @pytest.mark.parametrize("backend", [lf("tfb"), lf("jaxb")])
1362
- def test_jittable_amplitude(backend):
1363
- # @tc.backend.jit
1364
- def amp(s):
1365
- c = tc.Circuit(3)
1366
- c.H(0)
1367
- c.cnot(0, 1)
1368
- c.swap(1, 2)
1369
- return c.amplitude(s)
1370
-
1371
- np.testing.assert_allclose(
1372
- amp(tc.array_to_tensor([0, 1, 1], dtype="float32")), 0, atol=1e-5
1373
- )
1374
- np.testing.assert_allclose(
1375
- amp(tc.array_to_tensor([0, 0, 0], dtype="float32")), 1 / np.sqrt(2), atol=1e-5
1376
- )
1377
-
1378
-
1379
- def test_draw_cond_measure():
1380
- c = tc.Circuit(2)
1381
- c.H(0)
1382
- c.cond_measure(0)
1383
- c.cnot(0, 1)
1384
- print("")
1385
- print(c.draw())
1386
-
1387
-
1388
- def test_minus_index():
1389
- c = tc.Circuit(3)
1390
- c.H(-2)
1391
- c.H(0)
1392
- np.testing.assert_allclose(tc.backend.real(c.expectation_ps(x=[0])), 1, atol=1e-5)
1393
- np.testing.assert_allclose(tc.backend.real(c.expectation_ps(x=[1])), 1, atol=1e-5)
1394
- np.testing.assert_allclose(tc.backend.real(c.expectation_ps(x=[-1])), 0, atol=1e-5)
1395
- np.testing.assert_allclose(tc.backend.real(c.expectation_ps(z=[-2])), 0, atol=1e-5)
1396
-
1397
-
1398
- @pytest.mark.parametrize("backend", [lf("npb"), lf("tfb"), lf("jaxb")])
1399
- def test_sexpps(backend):
1400
- c = tc.Circuit(1, inputs=1 / np.sqrt(2) * np.array([1.0, 1.0j]))
1401
- y = c.sample_expectation_ps(y=[0])
1402
- ye = c.expectation_ps(y=[0])
1403
- np.testing.assert_allclose(y, 1.0, atol=1e-5)
1404
- np.testing.assert_allclose(ye, 1.0, atol=1e-5)
1405
-
1406
- c = tc.Circuit(4)
1407
- c.H(0)
1408
- c.cnot(0, 1)
1409
- c.rx(1, theta=0.3)
1410
- c.rz(2, theta=-1.2)
1411
- c.ccnot(2, 3, 1)
1412
- c.rzz(0, 3, theta=0.5)
1413
- c.ry(3, theta=2.2)
1414
- c.s(1)
1415
- c.td(2)
1416
- y = c.sample_expectation_ps(x=[1], y=[0], z=[2, 3])
1417
- ye = c.expectation_ps(x=[1], y=[0], z=[2, 3])
1418
- np.testing.assert_allclose(ye, y, atol=1e-5)
1419
- y2 = c.sample_expectation_ps(x=[1], y=[0], z=[2, 3], shots=81920)
1420
- assert np.abs(y2 - y) < 0.01
1421
-
1422
-
1423
- @pytest.mark.parametrize("backend", [lf("npb"), lf("tfb"), lf("jaxb")])
1424
- def test_sample_format(backend):
1425
- c = tc.Circuit(2)
1426
- c.H(0)
1427
- c.cnot(0, 1)
1428
- key = tc.backend.get_random_state(42)
1429
- for allow_state in [False, True]:
1430
- print("allow_state: ", allow_state)
1431
- for batch in [None, 1, 3]:
1432
- print(" batch: ", batch)
1433
- for format_ in [
1434
- None,
1435
- "sample_int",
1436
- "sample_bin",
1437
- "count_vector",
1438
- "count_tuple",
1439
- "count_dict_bin",
1440
- "count_dict_int",
1441
- ]:
1442
- print(" format: ", format_)
1443
- print(
1444
- " ",
1445
- c.sample(
1446
- batch=batch,
1447
- allow_state=allow_state,
1448
- format_=format_,
1449
- random_generator=key,
1450
- ),
1451
- )
1452
-
1453
-
1454
- @pytest.mark.parametrize("backend", [lf("npb"), lf("tfb"), lf("jaxb")])
1455
- def test_channel_auto_register(backend, highp):
1456
- c = tc.Circuit(2)
1457
- c.H(0)
1458
- c.reset(0, status=0.8)
1459
- s = c.state()
1460
- np.testing.assert_allclose(s[0], 1.0, atol=1e-9)
1461
-
1462
-
1463
- @pytest.mark.parametrize("backend", [lf("npb"), lf("tfb"), lf("jaxb")])
1464
- def test_circuit_to_json(backend):
1465
- c = tc.Circuit(3)
1466
- c.h(0)
1467
- c.CNOT(1, 2)
1468
- c.rxx(0, 2, theta=0.3)
1469
- c.crx(0, 1, theta=-0.8)
1470
- c.r(1, theta=tc.backend.ones([]), alpha=0.2)
1471
- c.toffoli(0, 2, 1)
1472
- c.ccnot(0, 1, 2)
1473
- c.multicontrol(1, 2, 0, ctrl=[0, 1], unitary=tc.gates._x_matrix)
1474
- s = c.to_json()
1475
- c2 = tc.Circuit.from_json(s)
1476
- print(c2.draw())
1477
- np.testing.assert_allclose(c.state(), c2.state(), atol=1e-5)
1478
-
1479
-
1480
- def test_gate_count():
1481
- c = tc.Circuit(3)
1482
- c.x(0)
1483
- c.h(0)
1484
- c.rx(1, theta=-0.2)
1485
- c.h(2)
1486
- c.multicontrol(0, 1, 2, ctrl=[0, 1], unitary=tc.gates._x_matrix)
1487
- c.toffoli(0, 2, 1)
1488
- c.ccnot(1, 2, 0)
1489
- c.ccx(1, 2, 0)
1490
- assert c.gate_count() == 8
1491
- assert c.gate_count("h") == 2
1492
- assert c.gate_count(["ccnot"]) == 3
1493
- assert c.gate_count(["rx", "multicontrol"]) == 2
1494
- assert c.gate_count_by_condition(lambda qir: qir["index"] == (0,)) == 2
1495
- assert c.gate_count_by_condition(lambda qir: qir["mpo"]) == 1
1496
- print(c.gate_summary())
1497
- # {'x': 1, 'h': 2, 'rx': 1, 'multicontrol': 1, 'toffoli': 3}
1498
-
1499
-
1500
- def test_to_openqasm(tmp_path):
1501
- c = tc.Circuit(3)
1502
- c.H(0)
1503
- c.rz(2, theta=0.2)
1504
- c.cnot(2, 1)
1505
- c.rzz(0, 1, theta=-1.0)
1506
- c.ccx(1, 2, 0)
1507
- c.u(2, theta=0.5, lbd=1.3)
1508
- c.measure_instruction(1)
1509
- print(c.to_openqasm(formatted=True))
1510
- s = c.to_openqasm()
1511
- c1 = tc.Circuit.from_openqasm(s)
1512
- print(c1.draw())
1513
- np.testing.assert_allclose(c.state(), c1.state())
1514
- c.to_openqasm_file(os.path.join(tmp_path, "test.qasm"))
1515
- c2 = tc.Circuit.from_openqasm_file(os.path.join(tmp_path, "test.qasm"))
1516
- np.testing.assert_allclose(c.state(), c2.state())
1517
-
1518
-
1519
- def test_from_qasm_keep_measure_order():
1520
- qasm_str = """OPENQASM 2.0;
1521
- include "qelib1.inc";
1522
- qreg q[2];
1523
- creg c[2];
1524
- h q[0];
1525
- measure q[1] -> c[1];
1526
- measure q[0] -> c[0];"""
1527
- c = tc.Circuit.from_openqasm(qasm_str)
1528
- c.to_openqasm().split("\n")[-2][-3] == "1"
1529
- c = tc.Circuit.from_openqasm(qasm_str, keep_measure_order=True)
1530
- c.to_openqasm().split("\n")[-2][-3] == "0"
1531
-
1532
-
1533
- def test_initial_mapping():
1534
- c = tc.Circuit(3)
1535
- c.cnot(0, 1)
1536
- c.h(1)
1537
- c.rx(1, theta=0.5)
1538
- c.cz(2, 1)
1539
- c.measure_instruction(2)
1540
-
1541
- c1 = c.initial_mapping({0: 1, 1: 2, 2: 0})
1542
- print(c1.draw())
1543
-
1544
- np.testing.assert_allclose(
1545
- c.expectation_ps(z=[1]), c1.expectation_ps(z=[2]), atol=1e-5
1546
- )
1547
- assert c1._extra_qir[0]["index"][0] == 0
1548
-
1549
- c2 = c1.initial_mapping({1: 0, 2: 1, 0: 2})
1550
- np.testing.assert_allclose(
1551
- c.expectation_ps(z=[1]), c2.expectation_ps(z=[1]), atol=1e-5
1552
- )
1553
-
1554
- c3 = c.initial_mapping({0: 2, 1: 7, 2: 0}, n=9)
1555
- np.testing.assert_allclose(
1556
- c.expectation_ps(z=[1]), c3.expectation_ps(z=[7]), atol=1e-5
1557
- )
1558
- print(c3.draw())
1559
-
1560
-
1561
- def test_get_positional_logical_mapping():
1562
- c = tc.Circuit(3)
1563
- c.cx(0, 1)
1564
- c.cz(1, 2)
1565
- c.h(1)
1566
- assert c.get_positional_logical_mapping() == {0: 0, 1: 1, 2: 2}
1567
- c = tc.Circuit(3)
1568
- c.cx(0, 1)
1569
- c.h(1)
1570
- c.measure_instruction(2)
1571
- c.measure_instruction(0)
1572
- assert c.get_positional_logical_mapping() == {0: 2, 1: 0}
1573
-
1574
-
1575
- @pytest.mark.parametrize("backend", [lf("tfb"), lf("jaxb")])
1576
- def test_inverse_jit(backend):
1577
- K = tc.backend
1578
-
1579
- def simple_ansatz(param):
1580
- c = tc.Circuit(3)
1581
- for i in range(3):
1582
- c.cx(i, (i + 1) % 3)
1583
- c.rzz(i, (i + 1) % 3, theta=param[i])
1584
- c1 = c.inverse()
1585
- c2 = tc.Circuit(3)
1586
- c2.x(1)
1587
- c1.append(c2)
1588
- return tc.backend.real(c1.expectation_ps(z=[1]))
1589
-
1590
- v_ansatz = K.jit(K.vvag(simple_ansatz))
1591
- vs, gs = v_ansatz(K.ones([2, 3], dtype="float32"))
1592
- assert K.shape_tuple(gs) == (2, 3)
1593
- np.testing.assert_allclose(K.numpy(vs), -1.0 * K.ones([2]), atol=1e-5)
1594
-
1595
-
1596
- @pytest.mark.parametrize("backend", [lf("tfb"), lf("jaxb"), lf("npb")])
1597
- def test_fancy_circuit_indexing(backend):
1598
- c = tc.Circuit(4)
1599
- c.cx([0, 1], [-1, -2])
1600
- c.h(range(c._nqubits))
1601
- c.rz([0], theta=0.2)
1602
- c.rx([1, 2], theta=[0.3, 0.5])
1603
- c.rzz([2, 3], [0, 1], theta=tc.backend.ones([2]))
1604
- c.rxx([2, 0, 1], [0, 1, 2], theta=tc.backend.ones([1]))
1605
- assert c.gate_count("h") == 4
1606
- assert c.gate_count("rzz") == 2
1607
- assert c.gate_count("rxx") == 3
1608
-
1609
-
1610
- @pytest.mark.parametrize("backend", [lf("tfb"), lf("jaxb"), lf("npb")])
1611
- def test_general_kraus(backend):
1612
- c = tc.Circuit(2)
1613
- c.h([0, 1])
1614
- p = 0.5
1615
- status = [0.3, 0.8]
1616
- rs = []
1617
- for i in range(2):
1618
- rs.append(
1619
- c.general_kraus(
1620
- [
1621
- np.sqrt(p) * np.array([[1.0, 0], [0, 0]]),
1622
- np.sqrt(p) * np.array([[0, 0], [0, 1.0]]),
1623
- np.sqrt(1 - p) * np.eye(2),
1624
- ],
1625
- i,
1626
- status=status[i],
1627
- )
1628
- )
1629
- np.testing.assert_allclose(rs[0], 1)
1630
- np.testing.assert_allclose(rs[1], 2)
1631
- np.testing.assert_allclose(c.expectation_ps(z=[0]), -1, atol=1e-5)
1632
- np.testing.assert_allclose(c.expectation_ps(z=[1]), 0, atol=1e-5)
1633
-
1634
-
1635
- @pytest.mark.parametrize("backend", [lf("tfb"), lf("jaxb"), lf("npb")])
1636
- def test_general_kraus_with_prob(backend):
1637
- c = tc.Circuit(2)
1638
- c.h([0, 1])
1639
- p = 0.5
1640
- status = [0.3, 0.8]
1641
- rs = []
1642
- for i in range(2):
1643
- rs.append(
1644
- c.general_kraus(
1645
- [
1646
- np.sqrt(p) * np.array([[1.0, 0], [0, 0]]),
1647
- np.sqrt(p) * np.array([[0, 0], [0, 1.0]]),
1648
- np.sqrt(1 - p) * np.eye(2),
1649
- ],
1650
- i,
1651
- status=status[i],
1652
- with_prob=True,
1653
- )
1654
- )
1655
- np.testing.assert_allclose(rs[0][0], 1)
1656
- np.testing.assert_allclose(rs[1][0], 2)
1657
- np.testing.assert_allclose(c.expectation_ps(z=[0]), -1, atol=1e-5)
1658
- np.testing.assert_allclose(c.expectation_ps(z=[1]), 0, atol=1e-5)
1659
- np.testing.assert_allclose(rs[0][1], [0.25, 0.25, 0.5], atol=1e-5)
1660
- np.testing.assert_allclose(rs[1][1], [0.25, 0.25, 0.5], atol=1e-5)
1661
- np.testing.assert_allclose(tc.backend.norm(c.state()), 1, atol=1e-5)
1662
-
1663
-
1664
- @pytest.mark.parametrize("backend", [lf("tfb"), lf("jaxb"), lf("npb")])
1665
- def test_circuit_copy(backend):
1666
- c = tc.Circuit(2)
1667
- c.h(0)
1668
- c1 = c.copy()
1669
- c.rz(0, theta=0.1)
1670
- assert c1.gate_count() == 1
1671
-
1672
-
1673
- @pytest.mark.parametrize("backend", [lf("tfb"), lf("jaxb"), lf("npb")])
1674
- def test_projected_subsystem(backend):
1675
- c = tc.Circuit(3)
1676
- c.h(0)
1677
- c.cnot(0, 1)
1678
- c.rx(1, theta=0.9)
1679
- c.cy(1, 2)
1680
- s = c.projected_subsystem(tc.backend.convert_to_tensor(np.array([1, 1, 1.0])), (0,))
1681
- np.testing.assert_allclose(s, np.array([0.43496, 0.900447j]), atol=1e-5)
1682
- s = c.projected_subsystem(
1683
- tc.backend.convert_to_tensor(np.array([0, 0, 0.0])), (0, 2)
1684
- )
1685
- np.testing.assert_allclose(s[0], 0.900447, atol=1e-5)
1686
-
1687
- c = tc.DMCircuit(3)
1688
- c.h(0)
1689
- c.cnot(0, 1)
1690
- c.rx(1, theta=0.9)
1691
- c.cy(1, 2)
1692
- s = c.projected_subsystem(tc.backend.convert_to_tensor(np.array([1, 1, 1.0])), (0,))
1693
- assert tc.backend.shape_tuple(s) == (2, 2)
1694
- np.testing.assert_allclose(s[1, 1], 0.8108051, atol=1e-5)
1695
- s = c.projected_subsystem(
1696
- tc.backend.convert_to_tensor(np.array([1, 1, 1.0])), (1, 2)
1697
- )
1698
- assert tc.backend.shape_tuple(s) == (4, 4)
1699
- np.testing.assert_allclose(s[3, 3], 0.8108051, atol=1e-5)