tensorcircuit-nightly 1.2.1.dev20250725__py3-none-any.whl → 1.3.0.dev20250727__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.

@@ -0,0 +1,159 @@
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)
tests/test_miscs.py CHANGED
@@ -312,3 +312,23 @@ def test_distrubuted_contractor(jaxb):
312
312
  return c.expectation_ps(z=[-1])
313
313
 
314
314
  np.testing.assert_allclose(value, baseline(params), atol=1e-6)
315
+
316
+
317
+ @pytest.mark.parametrize("backend", [lf("npb"), lf("tfb"), lf("jaxb")])
318
+ def test_runtime_nodes_capture(backend):
319
+ with tc.cons.runtime_nodes_capture() as captured:
320
+ c = tc.Circuit(3)
321
+ c.h(0)
322
+ c.amplitude("010")
323
+ len(captured["nodes"]) == 7
324
+
325
+
326
+ @pytest.mark.parametrize("backend", [lf("npb"), lf("tfb"), lf("jaxb")])
327
+ def test_function_nodes_capture(backend):
328
+ @tc.cons.function_nodes_capture
329
+ def exp(theta):
330
+ c = tc.Circuit(3)
331
+ c.h(0)
332
+ return c.expectation_ps(z=[-3], reuse=False)
333
+
334
+ assert len(exp(0.3)) == 9
tests/test_stabilizer.py CHANGED
@@ -215,3 +215,12 @@ def test_mipt():
215
215
  return c.entanglement_entropy(list(range(n // 2)))
216
216
 
217
217
  print(ruc(50, 10, 0.1))
218
+
219
+
220
+ def test_measure_with_prob():
221
+ c = tc.StabilizerCircuit(3)
222
+ c.h(0)
223
+ c.cnot(0, 1)
224
+ m, p = c.measure(0, 2, with_prob=True)
225
+ np.testing.assert_allclose(p, 0.5, atol=1e-6)
226
+ print(m)