tensorcircuit-nightly 1.3.0.dev20250728__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 (72) hide show
  1. tensorcircuit/__init__.py +5 -1
  2. tensorcircuit/abstractcircuit.py +4 -0
  3. tensorcircuit/analogcircuit.py +413 -0
  4. tensorcircuit/applications/layers.py +1 -1
  5. tensorcircuit/applications/van.py +1 -1
  6. tensorcircuit/backends/abstract_backend.py +312 -5
  7. tensorcircuit/backends/cupy_backend.py +3 -1
  8. tensorcircuit/backends/jax_backend.py +92 -3
  9. tensorcircuit/backends/jax_ops.py +108 -0
  10. tensorcircuit/backends/numpy_backend.py +49 -3
  11. tensorcircuit/backends/pytorch_backend.py +92 -3
  12. tensorcircuit/backends/tensorflow_backend.py +102 -3
  13. tensorcircuit/basecircuit.py +123 -82
  14. tensorcircuit/circuit.py +67 -57
  15. tensorcircuit/cloud/local.py +1 -1
  16. tensorcircuit/cloud/quafu_provider.py +1 -1
  17. tensorcircuit/cloud/tencent.py +1 -1
  18. tensorcircuit/compiler/simple_compiler.py +2 -2
  19. tensorcircuit/cons.py +1 -0
  20. tensorcircuit/densitymatrix.py +16 -11
  21. tensorcircuit/experimental.py +7 -152
  22. tensorcircuit/fgs.py +5 -6
  23. tensorcircuit/gates.py +66 -22
  24. tensorcircuit/keras.py +3 -3
  25. tensorcircuit/mpscircuit.py +109 -61
  26. tensorcircuit/quantum.py +697 -133
  27. tensorcircuit/quditcircuit.py +733 -0
  28. tensorcircuit/quditgates.py +618 -0
  29. tensorcircuit/results/counts.py +45 -31
  30. tensorcircuit/shadows.py +1 -1
  31. tensorcircuit/simplify.py +3 -1
  32. tensorcircuit/stabilizercircuit.py +4 -2
  33. tensorcircuit/templates/blocks.py +2 -2
  34. tensorcircuit/templates/hamiltonians.py +29 -8
  35. tensorcircuit/templates/lattice.py +676 -335
  36. tensorcircuit/timeevol.py +896 -0
  37. {tensorcircuit_nightly-1.3.0.dev20250728.dist-info → tensorcircuit_nightly-1.4.0.dev20251103.dist-info}/METADATA +50 -25
  38. tensorcircuit_nightly-1.4.0.dev20251103.dist-info/RECORD +96 -0
  39. {tensorcircuit_nightly-1.3.0.dev20250728.dist-info → tensorcircuit_nightly-1.4.0.dev20251103.dist-info}/top_level.txt +0 -1
  40. tensorcircuit_nightly-1.3.0.dev20250728.dist-info/RECORD +0 -122
  41. tests/__init__.py +0 -0
  42. tests/conftest.py +0 -67
  43. tests/test_backends.py +0 -1035
  44. tests/test_calibrating.py +0 -149
  45. tests/test_channels.py +0 -409
  46. tests/test_circuit.py +0 -1713
  47. tests/test_cloud.py +0 -219
  48. tests/test_compiler.py +0 -147
  49. tests/test_dmcircuit.py +0 -555
  50. tests/test_ensemble.py +0 -72
  51. tests/test_fgs.py +0 -318
  52. tests/test_gates.py +0 -156
  53. tests/test_hamiltonians.py +0 -159
  54. tests/test_interfaces.py +0 -557
  55. tests/test_keras.py +0 -160
  56. tests/test_lattice.py +0 -1666
  57. tests/test_miscs.py +0 -334
  58. tests/test_mpscircuit.py +0 -341
  59. tests/test_noisemodel.py +0 -156
  60. tests/test_qaoa.py +0 -86
  61. tests/test_qem.py +0 -152
  62. tests/test_quantum.py +0 -549
  63. tests/test_quantum_attr.py +0 -42
  64. tests/test_results.py +0 -379
  65. tests/test_shadows.py +0 -160
  66. tests/test_simplify.py +0 -46
  67. tests/test_stabilizer.py +0 -226
  68. tests/test_templates.py +0 -218
  69. tests/test_torchnn.py +0 -99
  70. tests/test_van.py +0 -102
  71. {tensorcircuit_nightly-1.3.0.dev20250728.dist-info → tensorcircuit_nightly-1.4.0.dev20251103.dist-info}/WHEEL +0 -0
  72. {tensorcircuit_nightly-1.3.0.dev20250728.dist-info → tensorcircuit_nightly-1.4.0.dev20251103.dist-info}/licenses/LICENSE +0 -0
tests/test_fgs.py DELETED
@@ -1,318 +0,0 @@
1
- import numpy as np
2
- import pytest
3
- from pytest_lazyfixture import lazy_fixture as lf
4
- import tensorflow as tf
5
-
6
- try:
7
- import openfermion as _
8
- except ModuleNotFoundError:
9
- pytestmark = pytest.mark.skip("skip fgs test due to missing openfermion module")
10
-
11
- import tensorcircuit as tc
12
-
13
- F = tc.fgs.FGSSimulator
14
- FT = tc.fgs.FGSTestSimulator
15
-
16
-
17
- @pytest.mark.parametrize("backend", [lf("npb"), lf("tfb"), lf("jaxb")])
18
- def test_cmatrix(backend, highp):
19
- import openfermion
20
-
21
- def asymmetric_hopping(J, gamma, i, j, L):
22
- m0 = tc.fgs.onehot_matrix(i, j, 2 * L) - tc.fgs.onehot_matrix(
23
- j + L, i + L, 2 * L
24
- )
25
- m = (J + gamma) * m0 + (J - gamma) * tc.backend.adjoint(m0)
26
- return m / 2
27
-
28
- def asymmetric_hopping_jw(J, gamma, i, j, L):
29
- op = (J + gamma) * openfermion.FermionOperator(f"{str(i)}^ {str(j)}") + np.conj(
30
- J - gamma
31
- ) * openfermion.FermionOperator(f"{str(j)}^ {str(i)}")
32
- sop = openfermion.transforms.jordan_wigner(op)
33
- m = openfermion.get_sparse_operator(sop, n_qubits=L).todense()
34
- return m
35
-
36
- c = tc.fgs.FGSSimulator(4, [0])
37
- c1 = tc.fgs.FGSTestSimulator(4, [0])
38
- c.evol_hp(0, 1, 1.2)
39
- c1.evol_hp(0, 1, 1.2)
40
- c.evol_icp(2, 0.5)
41
- c1.evol_icp(2, 0.5)
42
- c.evol_cp(0, -0.8)
43
- c1.evol_cp(0, -0.8)
44
- c.evol_sp(1, 0, 0.5)
45
- c1.evol_sp(1, 0, 0.5)
46
- c.evol_ghamiltonian(asymmetric_hopping(1, 0.5, 0, 2, 4))
47
- c1.evol_ghamiltonian(np.array(asymmetric_hopping_jw(1, 0.5, 0, 2, 4)))
48
- c.evol_sp(1, 2, 1.5)
49
- c1.evol_sp(1, 2, 1.5)
50
- c.evol_ihamiltonian(c.chemical_potential(1.0, 1, 4))
51
- c1.evol_ihamiltonian(c1.chemical_potential_jw(1.0, 1, 4))
52
- np.testing.assert_allclose(
53
- c1.get_cmatrix_majorana(), c.get_cmatrix_majorana(), atol=1e-5
54
- )
55
- np.testing.assert_allclose(c1.get_cmatrix(), c.get_cmatrix(), atol=1e-5)
56
- np.testing.assert_allclose(c1.entropy([0, 2]), c.entropy([0, 2]), atol=1e-5)
57
- np.testing.assert_allclose(
58
- c1.renyi_entropy(2, [1]), c.renyi_entropy(2, [1]), atol=1e-5
59
- )
60
-
61
-
62
- def test_full_trace():
63
- c = tc.FGSSimulator(4)
64
- with pytest.raises(ValueError):
65
- c.entropy([0, 1, 2, 3])
66
-
67
-
68
- @pytest.mark.parametrize("backend", [lf("npb"), lf("tfb"), lf("jaxb")])
69
- def test_otoc(backend, highp):
70
- c = tc.FGSSimulator(4, [0, 1])
71
- c1 = tc.fgs.FGSTestSimulator(4, [0, 1])
72
- h = c.hopping(0.6, 1, 2, 4)
73
- h += c.hopping(-0.8, 3, 2, 4)
74
- h += c.chemical_potential(0.3, 2, 4)
75
- h1 = c1.hopping_jw(0.6, 1, 2, 4)
76
- h1 += c1.hopping_jw(-0.8, 3, 2, 4)
77
- h1 += c1.chemical_potential_jw(0.3, 2, 4)
78
- c.evol_hamiltonian(h)
79
- m = c.get_cmatrix(now_i=True, now_j=False)
80
- m0 = c1.get_ot_cmatrix(h1)
81
- np.testing.assert_allclose(m, m0, atol=1e-5)
82
- m = c.get_cmatrix(now_i=False, now_j=True)
83
- m0 = c1.get_ot_cmatrix(h1, now_i=False)
84
- np.testing.assert_allclose(m, m0, atol=1e-5)
85
-
86
-
87
- @pytest.mark.parametrize("backend", [lf("tfb"), lf("jaxb")])
88
- def test_fgs_ad(backend, highp):
89
- import optax
90
-
91
- N = 18
92
-
93
- def f(chi):
94
- c = tc.fgs.FGSSimulator(N, [0])
95
- for i in range(N - 1):
96
- c.evol_hp(i, i + 1, chi[i])
97
- cm = c.get_cmatrix()
98
- return -tc.backend.real(1 - cm[N, N])
99
-
100
- chi_vg = tc.backend.jit(tc.backend.value_and_grad(f))
101
-
102
- if tc.backend.name == "tensorflow":
103
- opt = tc.backend.optimizer(tf.keras.optimizers.Adam(1e-2))
104
- else:
105
- opt = tc.backend.optimizer(optax.adam(1e-2))
106
-
107
- param = tc.backend.ones([N - 1], dtype="float64")
108
- for _ in range(300):
109
- vs, gs = chi_vg(param)
110
- param = opt.update(gs, param)
111
-
112
- np.testing.assert_allclose(vs, -0.9986, atol=1e-2)
113
-
114
-
115
- @pytest.mark.parametrize("backend", [lf("npb"), lf("tfb"), lf("jaxb")])
116
- def test_hamiltonian_generation(backend):
117
- hc = F.chemical_potential(0.8, 0, 3)
118
- h1 = FT.get_hmatrix(hc, 3) + 0.4 * tc.backend.eye(2**3)
119
- # constant shift
120
- h2 = FT.chemical_potential_jw(0.8, 0, 3)
121
- np.testing.assert_allclose(h1, h2, atol=1e-5)
122
-
123
- hc = F.hopping(0.8j, 0, 1, 3)
124
- h1 = FT.get_hmatrix(hc, 3)
125
- h2 = FT.hopping_jw(0.8j, 0, 1, 3)
126
- np.testing.assert_allclose(h1, h2, atol=1e-5)
127
-
128
- hc = F.sc_pairing(0.8, 1, 0, 3)
129
- h1 = FT.get_hmatrix(hc, 3)
130
- h2 = FT.sc_pairing_jw(0.8, 1, 0, 3)
131
- np.testing.assert_allclose(h1, h2, atol=1e-5)
132
-
133
-
134
- @pytest.mark.parametrize("backend", [lf("npb"), lf("tfb"), lf("jaxb")])
135
- def test_ground_state(backend, highp):
136
- N = 3
137
- hc = (
138
- F.hopping(1.0, 0, 1, N)
139
- + F.hopping(1.0, 1, 2, N)
140
- + F.chemical_potential(0.4, 0, N)
141
- - F.chemical_potential(0.4, 1, N)
142
- + F.sc_pairing(0.8, 0, 1, N)
143
- )
144
-
145
- c = F(N, hc=hc)
146
- c1 = FT(N, hc=hc)
147
-
148
- np.testing.assert_allclose(c.get_cmatrix(), c1.get_cmatrix(), atol=1e-6)
149
- np.testing.assert_allclose(c1.entropy([0]), c.entropy([0]), atol=1e-5)
150
-
151
-
152
- @pytest.mark.parametrize("backend", [lf("npb"), lf("tfb"), lf("jaxb")])
153
- def test_post_select(backend, highp):
154
- for ind in [0, 1, 2]:
155
- for keep in [0, 1]:
156
- c = F(3, filled=[0, 2])
157
- c.evol_hp(0, 1, 0.2)
158
- c.evol_cp(0, 0.5)
159
- c.evol_hp(1, 2, 0.3j)
160
- c.evol_cp(1, -0.8)
161
- c.evol_sp(0, 2, 0.3)
162
- c.post_select(ind, keep)
163
- c1 = FT(3, filled=[0, 2])
164
- c1.evol_hp(0, 1, 0.2)
165
- c1.evol_cp(0, 0.5)
166
- c1.evol_hp(1, 2, 0.3j)
167
- c1.evol_cp(1, -0.8)
168
- c1.evol_sp(0, 2, 0.3)
169
- c1.post_select(ind, keep)
170
- np.testing.assert_allclose(c.get_cmatrix(), c1.get_cmatrix(), atol=1e-5)
171
-
172
-
173
- @pytest.mark.parametrize("backend", [lf("npb"), lf("tfb"), lf("jaxb")])
174
- def test_post_select_cmatrix_refresh(backend, highp):
175
- sim_post = tc.FGSSimulator(L=2, filled=[0])
176
- sim_post.evol_hp(0, 1, np.pi / 4)
177
- sim_post.post_select(0, keep=1)
178
- np.testing.assert_allclose(1 - sim_post.get_cmatrix()[0, 0], 1, atol=1e-6)
179
-
180
-
181
- @pytest.mark.parametrize("backend", [lf("tfb"), lf("jaxb")])
182
- def test_jittable_measure(backend):
183
- @tc.backend.jit
184
- def get_cmatrix(status):
185
- r = []
186
- c = F(3, filled=[0])
187
- c.evol_hp(0, 1, 0.2)
188
- c.evol_cp(0, 0.5)
189
- c.evol_hp(1, 2, 0.3j)
190
- r.append(c.cond_measure(1, status[0]))
191
- c.evol_cp(1, -0.8)
192
- r.append(c.cond_measure(2, status[1]))
193
- r.append(c.cond_measure(1, status[3]))
194
- c.evol_sp(0, 2, 0.3)
195
- c.evol_hp(2, 1, 0.2)
196
- c.evol_hp(0, 1, 0.8)
197
- return c.get_cmatrix(), tc.backend.stack(r)
198
-
199
- def get_cmatrix_baseline(status):
200
- r = []
201
- c = FT(3, filled=[0])
202
- c.evol_hp(0, 1, 0.2)
203
- c.evol_cp(0, 0.5)
204
- c.evol_hp(1, 2, 0.3j)
205
- r.append(c.cond_measure(1, status[0]))
206
- c.evol_cp(1, -0.8)
207
- r.append(c.cond_measure(2, status[1]))
208
- r.append(c.cond_measure(1, status[3]))
209
- c.evol_sp(0, 2, 0.3)
210
- c.evol_hp(2, 1, 0.2)
211
- c.evol_hp(0, 1, 0.8)
212
- return c.get_cmatrix(), np.array(r)
213
-
214
- status = np.array([0.2, 0.83, 0.61, 0.07])
215
- m, his = get_cmatrix(tc.backend.convert_to_tensor(status))
216
- m1, his1 = get_cmatrix_baseline(status)
217
- np.testing.assert_allclose(m, m1, atol=1e-5)
218
- np.testing.assert_allclose(his, his1, atol=1e-5)
219
-
220
-
221
- @pytest.mark.parametrize("backend", [lf("npb"), lf("tfb"), lf("jaxb")])
222
- def test_exp_2body(backend):
223
- c = F(3, filled=[1])
224
- np.testing.assert_allclose(c.expectation_2body(4, 1), 1.0, atol=1e-5)
225
- np.testing.assert_allclose(c.expectation_2body(5, 2), 0.0, atol=1e-5)
226
- np.testing.assert_allclose(c.expectation_2body(1, 4), 0.0, atol=1e-5)
227
-
228
-
229
- @pytest.mark.parametrize("backend", [lf("npb"), lf("tfb"), lf("jaxb")])
230
- def test_exp_4body(backend):
231
- c = F(4, filled=[0, 2])
232
- c.evol_hp(0, 1, 0.3)
233
- c.evol_hp(2, 3, 0.3)
234
- c.evol_sp(0, 3, 0.5)
235
- c.evol_sp(0, 2, 0.9)
236
- c.evol_cp(0, -0.4)
237
-
238
- c1 = FT(4, filled=[0, 2])
239
- c1.evol_hp(0, 1, 0.3)
240
- c1.evol_hp(2, 3, 0.3)
241
- c1.evol_sp(0, 3, 0.5)
242
- c1.evol_sp(0, 2, 0.9)
243
- c1.evol_cp(0, -0.4)
244
-
245
- np.testing.assert_allclose(
246
- c.expectation_4body(0, 4, 1, 5), c.expectation_4body(0, 4, 1, 5), atol=1e-5
247
- )
248
- np.testing.assert_allclose(
249
- c.expectation_4body(0, 1, 4, 5), c.expectation_4body(0, 1, 4, 5), atol=1e-5
250
- )
251
- np.testing.assert_allclose(
252
- c.expectation_4body(0, 4, 2, 6), c.expectation_4body(0, 4, 2, 6), atol=1e-5
253
- )
254
- np.testing.assert_allclose(
255
- c.expectation_4body(0, 2, 3, 1), c.expectation_4body(0, 2, 3, 1), atol=1e-5
256
- )
257
- np.testing.assert_allclose(
258
- c.expectation_4body(0, 1, 4, 6), c.expectation_4body(0, 1, 4, 6), atol=1e-5
259
- )
260
- np.testing.assert_allclose(
261
- c.expectation_4body(1, 0, 6, 7), c.expectation_4body(1, 0, 6, 7), atol=1e-5
262
- )
263
-
264
-
265
- @pytest.mark.parametrize("backend", [lf("npb"), lf("tfb"), lf("jaxb")])
266
- def test_overlap(backend):
267
- def compute_overlap(FGScls):
268
- c = FGScls(3, filled=[0, 2])
269
- c.evol_hp(0, 1, 1.2)
270
- c.evol_hp(1, 2, 0.3)
271
- c.evol_cp(0, 0.5)
272
- c.evol_sp(0, 2, 0.3)
273
- c1 = FGScls(3, filled=[0, 2])
274
- c1.evol_hp(0, 1, 0.2)
275
- c1.evol_hp(1, 2, 0.6)
276
- c1.evol_sp(1, 0, -1.1)
277
- return tc.backend.abs(c.overlap(c1))
278
-
279
- np.testing.assert_allclose(
280
- compute_overlap(tc.FGSSimulator), compute_overlap(tc.fgs.FGSTestSimulator), 1e-5
281
- )
282
-
283
-
284
- @pytest.mark.parametrize("backend", [lf("npb"), lf("tfb"), lf("jaxb")])
285
- def test_entanglement_asymmetry(backend, highp):
286
- def discrete_c(c):
287
- c.evol_sp(0, 1, 0.3)
288
- c.evol_sp(1, 3, 1.1)
289
- c.evol_hp(0, 1, -0.2)
290
- c.evol_hp(2, 3, 1.4)
291
- c.evol_hp(3, 4, -0.6)
292
- c.evol_hp(4, 5, -0.8)
293
- c.evol_sp(2, 6, 2.1)
294
- return c
295
-
296
- c = discrete_c(tc.fgs.FGSSimulator(7, filled=[0, 2, 4, 6]))
297
- c1 = discrete_c(tc.fgs.FGSTestSimulator(7, filled=[0, 2, 4, 6]))
298
- for k in [2, 3, 4]:
299
- for traceout in [[1, 2, 4, 5], [2, 3, 5], [0, 3, 4, 5, 6]]:
300
- print(k, traceout)
301
- sa_ans = c1.renyi_entropy(k, traceout)
302
- saq_ans = c1.renyi_entanglement_asymmetry(k, traceout)
303
- np.testing.assert_allclose(
304
- np.log(c.charge_moment([0 for _ in range(k)], k, traceout))
305
- * 1
306
- / (1 - k),
307
- sa_ans,
308
- atol=2e-4,
309
- )
310
- saq, std = c.renyi_entanglement_asymmetry(
311
- k, traceout, batch=400, with_std=True
312
- )
313
- np.testing.assert_allclose(
314
- saq,
315
- saq_ans,
316
- atol=6 * std,
317
- )
318
- print(std)
tests/test_gates.py DELETED
@@ -1,156 +0,0 @@
1
- import sys
2
- import os
3
- import numpy as np
4
-
5
- thisfile = os.path.abspath(__file__)
6
- modulepath = os.path.dirname(os.path.dirname(thisfile))
7
-
8
- sys.path.insert(0, modulepath)
9
- import tensorcircuit as tc
10
-
11
-
12
- def test_rgate(highp):
13
- np.testing.assert_almost_equal(
14
- tc.gates.r_gate(1, 2, 3).tensor, tc.gates.rgate_theoretical(1, 2, 3).tensor
15
- )
16
-
17
-
18
- def test_phase_gate():
19
- c = tc.Circuit(1)
20
- c.h(0)
21
- c.phase(0, theta=np.pi / 2)
22
- np.testing.assert_allclose(c.state()[1], 0.7071j, atol=1e-4)
23
-
24
-
25
- def test_cu_gate():
26
- c = tc.Circuit(2)
27
- c.cu(0, 1, theta=np.pi / 2, phi=-np.pi / 4, lbd=np.pi / 4)
28
- m = c.matrix()
29
- print(m)
30
- np.testing.assert_allclose(m[2:, 2:], tc.gates._wroot_matrix, atol=1e-5)
31
- np.testing.assert_allclose(m[:2, :2], np.eye(2), atol=1e-5)
32
-
33
-
34
- def test_get_u_parameter(highp):
35
- for _ in range(6):
36
- hermitian = np.random.uniform(size=[2, 2])
37
- hermitian += np.conj(np.transpose(hermitian))
38
- unitary = tc.backend.expm(hermitian * 1.0j)
39
- params = tc.gates.get_u_parameter(unitary)
40
- unitary2 = tc.gates.u_gate(theta=params[0], phi=params[1], lbd=params[2])
41
- ans = unitary2.tensor
42
- unitary = unitary / np.exp(1j * np.angle(unitary[0, 0]))
43
- np.testing.assert_allclose(unitary, ans, atol=1e-3)
44
-
45
-
46
- def test_ided_gate():
47
- g = tc.gates.rx.ided()
48
- np.testing.assert_allclose(
49
- tc.backend.reshapem(g(theta=0.3).tensor),
50
- np.kron(np.eye(2), tc.gates.rx(theta=0.3).tensor),
51
- atol=1e-5,
52
- )
53
- g1 = tc.gates.rx.ided(before=False)
54
- np.testing.assert_allclose(
55
- tc.backend.reshapem(g1(theta=0.3).tensor),
56
- np.kron(tc.gates.rx(theta=0.3).tensor, np.eye(2)),
57
- atol=1e-5,
58
- )
59
-
60
-
61
- def test_fsim_gate():
62
- theta = 0.2
63
- phi = 0.3
64
- c = tc.Circuit(2)
65
- c.iswap(0, 1, theta=-theta)
66
- c.cphase(0, 1, theta=-phi)
67
- m = c.matrix()
68
- ans = np.array(
69
- [
70
- [1.0 + 0.0j, 0.0 + 0.0j, 0.0 + 0.0j, 0.0 + 0.0j],
71
- [0.0 + 0.0j, 0.95105654 + 0.0j, 0.0 - 0.309017j, 0.0 + 0.0j],
72
- [0.0 + 0.0j, 0.0 - 0.309017j, 0.95105654 + 0.0j, 0.0 + 0.0j],
73
- [0.0 + 0.0j, 0.0 + 0.0j, 0.0 + 0.0j, 0.9553365 - 0.29552022j],
74
- ]
75
- )
76
- np.testing.assert_allclose(m, ans, atol=1e-5)
77
- print(m)
78
-
79
-
80
- def test_exp_gate():
81
- c = tc.Circuit(2)
82
- c.exp(
83
- 0,
84
- 1,
85
- unitary=tc.gates.array_to_tensor(
86
- np.array([[1.0, 0, 0, 0], [0, -1.0, 0, 0], [0, 0, -1, 0], [0, 0, 0, 1]])
87
- ),
88
- theta=tc.gates.num_to_tensor(np.pi / 2),
89
- )
90
- np.testing.assert_allclose(c.wavefunction()[0], -1j)
91
-
92
-
93
- def test_any_gate():
94
- c = tc.Circuit(2)
95
- c.any(0, unitary=np.eye(2))
96
- np.testing.assert_allclose(c.expectation((tc.gates.z(), [0])), 1.0)
97
-
98
-
99
- def test_iswap_gate():
100
- t = tc.gates.iswap_gate().tensor
101
- ans = np.array([[1.0, 0, 0, 0], [0, 0, 1j, 0], [0, 1j, 0, 0], [0, 0, 0, 1.0]])
102
- np.testing.assert_allclose(t, ans.reshape([2, 2, 2, 2]), atol=1e-5)
103
- t = tc.gates.iswap_gate(theta=0).tensor
104
- np.testing.assert_allclose(t, np.eye(4).reshape([2, 2, 2, 2]), atol=1e-5)
105
-
106
-
107
- def test_gate_list():
108
- assert tc.Circuit.sgates == tc.abstractcircuit.sgates
109
-
110
-
111
- def test_controlled():
112
- xgate = tc.gates.x
113
- cxgate = xgate.controlled()
114
- ccxgate = cxgate.controlled()
115
- assert ccxgate.n == "ccx"
116
- assert ccxgate.ctrl == [1, 1]
117
- np.testing.assert_allclose(
118
- ccxgate().tensor, tc.backend.reshape2(tc.gates._toffoli_matrix)
119
- )
120
- ocxgate = cxgate.ocontrolled()
121
- c = tc.Circuit(3)
122
- c.x(0)
123
- c.any(1, 0, 2, unitary=ocxgate())
124
- np.testing.assert_allclose(c.expectation([tc.gates.z(), [2]]), -1, atol=1e-5)
125
- print(c.to_qir()[1])
126
-
127
-
128
- def test_variable_controlled():
129
- crxgate = tc.gates.rx.controlled()
130
- c = tc.Circuit(2)
131
- c.x(0)
132
- tc.Circuit.crx_my = tc.Circuit.apply_general_variable_gate_delayed(crxgate)
133
- c.crx_my(0, 1, theta=0.3)
134
- np.testing.assert_allclose(
135
- c.expectation([tc.gates.z(), [1]]), 0.95533645, atol=1e-5
136
- )
137
- assert c.to_qir()[1]["name"] == "crx"
138
-
139
-
140
- def test_adjoint_gate():
141
- np.testing.assert_allclose(
142
- tc.gates.sd().tensor, tc.backend.adjoint(tc.gates._s_matrix)
143
- )
144
- assert tc.gates.td.n == "td"
145
-
146
-
147
- def test_rxx_gate():
148
- c1 = tc.Circuit(3)
149
- c1.rxx(0, 1, theta=1.0)
150
- c1.ryy(0, 2, theta=0.5)
151
- c1.rzz(0, 1, theta=-0.5)
152
- c2 = tc.Circuit(3)
153
- c2.exp1(0, 1, theta=1.0 / 2, unitary=tc.gates._xx_matrix)
154
- c2.exp1(0, 2, theta=0.5 / 2, unitary=tc.gates._yy_matrix)
155
- c2.exp1(0, 1, theta=-0.5 / 2, unitary=tc.gates._zz_matrix)
156
- np.testing.assert_allclose(c1.state(), c2.state(), atol=1e-5)
@@ -1,159 +0,0 @@
1
- import pytest
2
- import numpy as np
3
- from pytest_lazyfixture import lazy_fixture as lf
4
-
5
- import tensorcircuit as tc
6
-
7
- from tensorcircuit.templates.lattice import (
8
- ChainLattice,
9
- SquareLattice,
10
- CustomizeLattice,
11
- )
12
- from tensorcircuit.templates.hamiltonians import (
13
- heisenberg_hamiltonian,
14
- rydberg_hamiltonian,
15
- )
16
-
17
- PAULI_X = np.array([[0, 1], [1, 0]], dtype=complex)
18
- PAULI_Y = np.array([[0, -1j], [1j, 0]], dtype=complex)
19
- PAULI_Z = np.array([[1, 0], [0, -1]], dtype=complex)
20
- PAULI_I = np.eye(2, dtype=complex)
21
-
22
-
23
- class TestHeisenbergHamiltonian:
24
- """
25
- Test suite for the heisenberg_hamiltonian function.
26
- """
27
-
28
- def test_empty_lattice(self):
29
- """
30
- Test that an empty lattice produces a 0x0 matrix.
31
- """
32
- empty_lattice = CustomizeLattice(
33
- dimensionality=2, identifiers=[], coordinates=[]
34
- )
35
- h = heisenberg_hamiltonian(empty_lattice)
36
- assert h.shape == (1, 1)
37
- assert h.nnz == 0
38
-
39
- def test_single_site(self):
40
- """
41
- Test that a single-site lattice (no bonds) produces a 2x2 zero matrix.
42
- """
43
- single_site_lattice = ChainLattice(size=(1,), pbc=False)
44
- h = heisenberg_hamiltonian(single_site_lattice)
45
- assert h.shape == (2, 2)
46
- assert h.nnz == 0
47
-
48
- @pytest.mark.parametrize("backend", [lf("npb"), lf("tfb"), lf("jaxb")])
49
- def test_two_sites_chain(self, backend):
50
- """
51
- Test a two-site chain against a manually calculated Hamiltonian.
52
- This is the most critical test for scientific correctness.
53
- """
54
- lattice = ChainLattice(size=(2,), pbc=False)
55
- j_coupling = -1.5 # Test with a non-trivial coupling constant
56
- h_generated = heisenberg_hamiltonian(lattice, j_coupling=j_coupling)
57
-
58
- # Manually construct the expected Hamiltonian: H = J * (X_0X_1 + Y_0Y_1 + Z_0Z_1)
59
- xx = np.kron(PAULI_X, PAULI_X)
60
- yy = np.kron(PAULI_Y, PAULI_Y)
61
- zz = np.kron(PAULI_Z, PAULI_Z)
62
- h_expected = j_coupling * (xx + yy + zz)
63
-
64
- assert h_generated.shape == (4, 4)
65
- print(tc.backend.to_dense(h_generated))
66
- assert np.allclose(tc.backend.to_dense(h_generated), h_expected, atol=1e-5)
67
-
68
- def test_square_lattice_properties(self):
69
- """
70
- Test properties of a larger lattice (2x2 square) without full matrix comparison.
71
- """
72
- lattice = SquareLattice(size=(2, 2), pbc=True) # 4 sites, 8 bonds with PBC
73
- h = heisenberg_hamiltonian(lattice, j_coupling=1.0)
74
-
75
- assert h.shape == (16, 16)
76
- assert h.nnz > 0
77
- h_dense = tc.backend.to_dense(h)
78
- assert np.allclose(h_dense, h_dense.conj().T)
79
-
80
-
81
- class TestRydbergHamiltonian:
82
- """
83
- Test suite for the rydberg_hamiltonian function.
84
- """
85
-
86
- def test_single_site_rydberg(self):
87
- """
88
- Test a single atom, which should only have driving and detuning terms.
89
- """
90
- lattice = ChainLattice(size=(1,), pbc=False)
91
- omega, delta, c6 = 2.0, 0.5, 100.0
92
- h_generated = rydberg_hamiltonian(lattice, omega, delta, c6)
93
-
94
- h_expected = (omega / 2.0) * PAULI_X + (delta / 2.0) * PAULI_Z
95
-
96
- assert h_generated.shape == (2, 2)
97
- assert np.allclose(tc.backend.to_dense(h_generated), h_expected)
98
-
99
- def test_two_sites_rydberg(self):
100
- """
101
- Test a two-site chain for Rydberg Hamiltonian, including interaction.
102
- """
103
- lattice = ChainLattice(size=(2,), pbc=False, lattice_constant=1.5)
104
- omega, delta, c6 = 1.0, -0.5, 10.0
105
- h_generated = rydberg_hamiltonian(lattice, omega, delta, c6)
106
-
107
- v_ij = c6 / (1.5**6)
108
-
109
- h1 = (omega / 2.0) * (np.kron(PAULI_X, PAULI_I) + np.kron(PAULI_I, PAULI_X))
110
- z0_coeff = delta / 2.0 - v_ij / 4.0
111
- z1_coeff = delta / 2.0 - v_ij / 4.0
112
- h2 = z0_coeff * np.kron(PAULI_Z, PAULI_I) + z1_coeff * np.kron(PAULI_I, PAULI_Z)
113
- h3 = (v_ij / 4.0) * np.kron(PAULI_Z, PAULI_Z)
114
-
115
- h_expected = h1 + h2 + h3
116
-
117
- assert h_generated.shape == (4, 4)
118
- h_generated_dense = tc.backend.to_dense(h_generated)
119
-
120
- assert np.allclose(h_generated_dense, h_expected)
121
-
122
- def test_zero_distance_robustness(self):
123
- """
124
- Test that the function does not crash when two atoms have zero distance.
125
- """
126
- lattice = CustomizeLattice(
127
- dimensionality=2,
128
- identifiers=[0, 1],
129
- coordinates=[[0.0, 0.0], [0.0, 0.0]],
130
- )
131
-
132
- try:
133
- h = rydberg_hamiltonian(lattice, omega=1.0, delta=1.0, c6=1.0)
134
- # The X terms contribute 8 non-zero elements.
135
- # The Z terms (Z0+Z1) have diagonal elements that cancel out,
136
- # resulting in only 2 non-zero elements. Total nnz = 8 + 2 = 10.
137
- assert h.nnz == 10
138
- except ZeroDivisionError:
139
- pytest.fail("The function failed to handle zero distance between sites.")
140
-
141
- @pytest.mark.parametrize("backend", [lf("npb"), lf("tfb"), lf("jaxb")])
142
- def test_anisotropic_heisenberg(self, backend):
143
- """
144
- Test the anisotropic Heisenberg model with different Jx, Jy, Jz.
145
- """
146
- lattice = ChainLattice(size=(2,), pbc=False)
147
- j_coupling = [-1.0, 0.5, 2.0] # Jx, Jy, Jz
148
- h_generated = heisenberg_hamiltonian(lattice, j_coupling=j_coupling)
149
-
150
- # Manually construct the expected Hamiltonian
151
- jx, jy, jz = j_coupling
152
- xx = np.kron(PAULI_X, PAULI_X)
153
- yy = np.kron(PAULI_Y, PAULI_Y)
154
- zz = np.kron(PAULI_Z, PAULI_Z)
155
- h_expected = jx * xx + jy * yy + jz * zz
156
-
157
- h_generated_dense = tc.backend.to_dense(h_generated)
158
- assert h_generated_dense.shape == (4, 4)
159
- assert np.allclose(h_generated_dense, h_expected)