tensorcircuit-nightly 1.3.0.dev20250729__py3-none-any.whl → 1.3.0.dev20250731__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of tensorcircuit-nightly might be problematic. Click here for more details.
- tensorcircuit/__init__.py +1 -1
- tensorcircuit/backends/abstract_backend.py +76 -2
- tensorcircuit/backends/jax_backend.py +20 -1
- tensorcircuit/backends/jax_ops.py +108 -0
- tensorcircuit/backends/numpy_backend.py +8 -1
- tensorcircuit/backends/tensorflow_backend.py +38 -1
- tensorcircuit/fgs.py +5 -6
- tensorcircuit/quantum.py +1 -1
- tensorcircuit/stabilizercircuit.py +4 -2
- tensorcircuit/timeevol.py +495 -30
- {tensorcircuit_nightly-1.3.0.dev20250729.dist-info → tensorcircuit_nightly-1.3.0.dev20250731.dist-info}/METADATA +2 -2
- {tensorcircuit_nightly-1.3.0.dev20250729.dist-info → tensorcircuit_nightly-1.3.0.dev20250731.dist-info}/RECORD +17 -17
- tests/test_backends.py +121 -0
- tests/test_timeevol.py +412 -9
- {tensorcircuit_nightly-1.3.0.dev20250729.dist-info → tensorcircuit_nightly-1.3.0.dev20250731.dist-info}/WHEEL +0 -0
- {tensorcircuit_nightly-1.3.0.dev20250729.dist-info → tensorcircuit_nightly-1.3.0.dev20250731.dist-info}/licenses/LICENSE +0 -0
- {tensorcircuit_nightly-1.3.0.dev20250729.dist-info → tensorcircuit_nightly-1.3.0.dev20250731.dist-info}/top_level.txt +0 -0
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
tensorcircuit/__init__.py,sha256=
|
|
1
|
+
tensorcircuit/__init__.py,sha256=3yUehn2Xo7YNGDZZMC3I-Pz8sbvVzWsuXV0XDFWkGoQ,2055
|
|
2
2
|
tensorcircuit/about.py,sha256=DazTswU2nAwOmASTaDII3L04PVtaQ7oiWPty5YMI3Wk,5267
|
|
3
3
|
tensorcircuit/abstractcircuit.py,sha256=0osacPqq7B1EJki-cI1aLYoVRmjFaG9q3XevWMs7SsA,44125
|
|
4
4
|
tensorcircuit/asciiart.py,sha256=neY1OWFwtoW5cHPNwkQHgRPktDniQvdlP9QKHkk52fM,8236
|
|
@@ -8,17 +8,17 @@ tensorcircuit/circuit.py,sha256=mE4b_9xRu3ydoB8iDffdx35V9GZLhAQD_tkjZDLnLjg,3910
|
|
|
8
8
|
tensorcircuit/cons.py,sha256=uYKBeYKkDoJEqJTNrOZPRM31tBtkqe5aAg8GtVidJ1Y,33014
|
|
9
9
|
tensorcircuit/densitymatrix.py,sha256=VqMBnWCxO5-OsOp6LOdc5RS2AzmB3U4-w40Vn_lqygo,14865
|
|
10
10
|
tensorcircuit/experimental.py,sha256=TGK4FaS6TS_ZhtjcIZgYVuAkGdRW50LN0DdXp-h4bos,29906
|
|
11
|
-
tensorcircuit/fgs.py,sha256=
|
|
11
|
+
tensorcircuit/fgs.py,sha256=J1TjAiiqZk9KO1xYX_V0xsgKlYZaUQ7Enm4s5zkRM50,49514
|
|
12
12
|
tensorcircuit/gates.py,sha256=x-wA7adVpP7o0AQLt_xYUScFKj8tU_wUOV2mR1GyrPc,29322
|
|
13
13
|
tensorcircuit/keras.py,sha256=5OF4dfhEeS8sRYglpqYtQsWPeqp7uK0i7-P-6RRJ7zQ,10126
|
|
14
14
|
tensorcircuit/mps_base.py,sha256=UZ-v8vsr_rAsKrfun8prVgbXJ-qsdqKy2DZIHpq3sxo,15400
|
|
15
15
|
tensorcircuit/mpscircuit.py,sha256=COO9xzvA2Whe7Ncp6OqrgtXKmahHgTHxXTELAVHzFSY,36777
|
|
16
16
|
tensorcircuit/noisemodel.py,sha256=vzxpoYEZbHVC4a6g7_Jk4dxsHi4wvhpRFwud8b616Qo,11878
|
|
17
|
-
tensorcircuit/quantum.py,sha256=
|
|
17
|
+
tensorcircuit/quantum.py,sha256=1fZJJJ_o3NF7LaPPPU5Abd82NmMSnNQ8uUp_ClZdp3c,90244
|
|
18
18
|
tensorcircuit/shadows.py,sha256=6XmWNubbuaxFNvZVWu-RXd0lN9Jkk-xwong_K8o8_KE,17014
|
|
19
19
|
tensorcircuit/simplify.py,sha256=O11G3UYiVAc30GOfwXXmhLXwGZrQ8OVwLTMQMZp_XBc,9414
|
|
20
|
-
tensorcircuit/stabilizercircuit.py,sha256=
|
|
21
|
-
tensorcircuit/timeevol.py,sha256=
|
|
20
|
+
tensorcircuit/stabilizercircuit.py,sha256=KbrBVSo2pXnf5JHIrxwRPSPTm7bJVMIcyE4d7-dIfCM,15545
|
|
21
|
+
tensorcircuit/timeevol.py,sha256=GDD6IgzkRhZIyvLkSKJ7ZihnkHQBqoWOBsmBwRAC1UI,28574
|
|
22
22
|
tensorcircuit/torchnn.py,sha256=z_QpM0QC3mydGyWpyp877j-tSFCPyzynCwqrTWaw-IA,4637
|
|
23
23
|
tensorcircuit/translation.py,sha256=VnU7DnYmbk1cWjqa7N68WNLNDn3DwENrMzmbG4_CQco,28611
|
|
24
24
|
tensorcircuit/utils.py,sha256=nEDR1wTh1WF_yV6UyZYlifqOPWdKk_Krr4HjhrWHnGQ,7228
|
|
@@ -40,15 +40,15 @@ tensorcircuit/applications/physics/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQe
|
|
|
40
40
|
tensorcircuit/applications/physics/baseline.py,sha256=RWrzMGnC0PtmpYSFkvCE7r1llR88gncXuCakAAhFE-w,1775
|
|
41
41
|
tensorcircuit/applications/physics/fss.py,sha256=ny3U9ZDmT459PXjA1oUGfarBOlSKSy6fs04vD9s1XH4,3633
|
|
42
42
|
tensorcircuit/backends/__init__.py,sha256=WiUmbUFzM29w3hKfhuKxVUk3PpqDFiXf4za9g0ctpZA,80
|
|
43
|
-
tensorcircuit/backends/abstract_backend.py,sha256=
|
|
43
|
+
tensorcircuit/backends/abstract_backend.py,sha256=fAzyKvZ-1Mw2wvbyuR5IScVGhwZjY7AxBVtRo6viVY0,61743
|
|
44
44
|
tensorcircuit/backends/backend_factory.py,sha256=Z0aQ-RnxOnQzp-SRw8sefAH8XyBSlj2NXZwOlHinbfY,1713
|
|
45
45
|
tensorcircuit/backends/cupy_backend.py,sha256=4vgO3lnQnsvWL5hukhskjJp37EAHqio6z6TVXTQcdjs,15077
|
|
46
|
-
tensorcircuit/backends/jax_backend.py,sha256=
|
|
47
|
-
tensorcircuit/backends/jax_ops.py,sha256=
|
|
48
|
-
tensorcircuit/backends/numpy_backend.py,sha256=
|
|
46
|
+
tensorcircuit/backends/jax_backend.py,sha256=GIWsJwhlz0PD_KcypRkNWcjkegdNdoFMsmo0u0RQqrk,26704
|
|
47
|
+
tensorcircuit/backends/jax_ops.py,sha256=WyUGavch2R9uEFsI1Ap7eP1UcU4s2TItBgGsrVS3Hzs,9320
|
|
48
|
+
tensorcircuit/backends/numpy_backend.py,sha256=hhjrm0GK0d05TBYHNCZrBBBIJQ7V6qN99m1KLl0WKro,14408
|
|
49
49
|
tensorcircuit/backends/pytorch_backend.py,sha256=yhfZSrm99yNW-dmijk8t6zAkbVgLRd4b_aIWKrpT7bY,24230
|
|
50
50
|
tensorcircuit/backends/pytorch_ops.py,sha256=lLxpK6OqfpVwifyFlgsqhpnt-oIn4R5paPMVg51WaW0,3826
|
|
51
|
-
tensorcircuit/backends/tensorflow_backend.py,sha256=
|
|
51
|
+
tensorcircuit/backends/tensorflow_backend.py,sha256=CQhdWjUoqCNHxmJgfYOhUVpwDqjSo0RYrmsiaVWmxCU,37842
|
|
52
52
|
tensorcircuit/backends/tf_ops.py,sha256=FJwDU7LhZrt0VUIx12DJU0gZnWhMv7B7r9sAKG710As,3378
|
|
53
53
|
tensorcircuit/cloud/__init__.py,sha256=n0Lx07GYF6YbdIa6AJCLJk4zlAm5CqaeHszvkxxuoI4,139
|
|
54
54
|
tensorcircuit/cloud/abstraction.py,sha256=6aSxbz0MP21jBVdFbSMrvJPLQH117vGz9sSHbMFoodE,14582
|
|
@@ -86,10 +86,10 @@ tensorcircuit/templates/graphs.py,sha256=cPYrxjoem0xZ-Is9dZKAvEzWZL_FejfIRiCEOTA
|
|
|
86
86
|
tensorcircuit/templates/hamiltonians.py,sha256=Ag8djD6lckTeU7I99gCbXiQAb2VYqzm_p7-hpXo-5u4,5554
|
|
87
87
|
tensorcircuit/templates/lattice.py,sha256=F35ebANk0DSmSHLR0-Q_hUbcznyCmZjb4fKmvCMywmA,58575
|
|
88
88
|
tensorcircuit/templates/measurements.py,sha256=pzc5Aa9S416Ilg4aOY77Z6ZhUlYcXnAkQNQFTuHjFFs,10943
|
|
89
|
-
tensorcircuit_nightly-1.3.0.
|
|
89
|
+
tensorcircuit_nightly-1.3.0.dev20250731.dist-info/licenses/LICENSE,sha256=z8d0m5b2O9McPEK1xHG_dWgUBT6EfBDz6wA0F7xSPTA,11358
|
|
90
90
|
tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
91
91
|
tests/conftest.py,sha256=J9nHlLE3Zspz1rMyzadEuBWhaS5I4Q9sq0lnWybcdIA,1457
|
|
92
|
-
tests/test_backends.py,sha256=
|
|
92
|
+
tests/test_backends.py,sha256=MLxpRWavWF0qWcjVI61lIa3CYGbztvTO8ITFOYX47ao,38312
|
|
93
93
|
tests/test_calibrating.py,sha256=D1Tlv8mucUhg3ULvB5QlYyaDfw7aEERwq69-aGSb1A4,3805
|
|
94
94
|
tests/test_channels.py,sha256=BL4CirU8ku9-_NrI6PZAS5xZ0wrL1UEC1S3wPI9dYQM,12628
|
|
95
95
|
tests/test_circuit.py,sha256=IsSIFEs7hUCSYexMb-ESt1ZUpztHtLA0qz0CZolGdc4,52240
|
|
@@ -115,10 +115,10 @@ tests/test_shadows.py,sha256=1T3kJesVJ5XfZrSncL80xdq-taGCSnTDF3eL15UlavY,5160
|
|
|
115
115
|
tests/test_simplify.py,sha256=35tbOu1QANsPvY1buLwNhqPnMkBOsnBtHn82qaukmgI,1175
|
|
116
116
|
tests/test_stabilizer.py,sha256=MivuZ5pY7GOcEPTanhtrflXostyLBToHyjfPqCU0tG0,5450
|
|
117
117
|
tests/test_templates.py,sha256=Xm9otFFaaBWG9TZpgJ-nNh9MBfRipTzFWL8fBOnie2k,7192
|
|
118
|
-
tests/test_timeevol.py,sha256=
|
|
118
|
+
tests/test_timeevol.py,sha256=zz17x21C-5f8ZvcgkXm30JzLgZMhsKaOCzyHCyS43h0,20333
|
|
119
119
|
tests/test_torchnn.py,sha256=CHLTfWkF7Ses5_XnGFN_uv_JddfgenFEFzaDtSH8XYU,2848
|
|
120
120
|
tests/test_van.py,sha256=kAWz860ivlb5zAJuYpzuBe27qccT-Yf0jatf5uXtTo4,3163
|
|
121
|
-
tensorcircuit_nightly-1.3.0.
|
|
122
|
-
tensorcircuit_nightly-1.3.0.
|
|
123
|
-
tensorcircuit_nightly-1.3.0.
|
|
124
|
-
tensorcircuit_nightly-1.3.0.
|
|
121
|
+
tensorcircuit_nightly-1.3.0.dev20250731.dist-info/METADATA,sha256=QqZGkP34B7fJ3L38AiVOyyAgoYx_pZlrkWyWx8DcWEs,34922
|
|
122
|
+
tensorcircuit_nightly-1.3.0.dev20250731.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
123
|
+
tensorcircuit_nightly-1.3.0.dev20250731.dist-info/top_level.txt,sha256=O_Iqeh2x02lasEYMI9iyPNNNtMzcpg5qvwMOkZQ7n4A,20
|
|
124
|
+
tensorcircuit_nightly-1.3.0.dev20250731.dist-info/RECORD,,
|
tests/test_backends.py
CHANGED
|
@@ -9,6 +9,7 @@ os.environ["TF_FORCE_GPU_ALLOW_GROWTH"] = "true"
|
|
|
9
9
|
import numpy as np
|
|
10
10
|
import pytest
|
|
11
11
|
from pytest_lazyfixture import lazy_fixture as lf
|
|
12
|
+
import scipy
|
|
12
13
|
import tensorflow as tf
|
|
13
14
|
|
|
14
15
|
thisfile = os.path.abspath(__file__)
|
|
@@ -60,6 +61,126 @@ def test_grad_torch(torchb):
|
|
|
60
61
|
np.testing.assert_allclose(f(a), np.ones([2]), atol=1e-5)
|
|
61
62
|
|
|
62
63
|
|
|
64
|
+
@pytest.mark.parametrize("backend", [lf("npb"), lf("tfb"), lf("jaxb")])
|
|
65
|
+
def test_sparse_csr_from_coo(backend):
|
|
66
|
+
# Create a sparse matrix in COO format
|
|
67
|
+
values = tc.backend.convert_to_tensor(np.array([1.0, 2.0, 3.0]))
|
|
68
|
+
values = tc.backend.cast(values, "complex64")
|
|
69
|
+
indices = tc.backend.convert_to_tensor(np.array([[0, 0], [1, 1], [2, 3]]))
|
|
70
|
+
indices = tc.backend.cast(indices, "int64")
|
|
71
|
+
coo_matrix = tc.backend.coo_sparse_matrix(indices, values, shape=[4, 4])
|
|
72
|
+
|
|
73
|
+
# Convert COO to CSR
|
|
74
|
+
csr_matrix = tc.backend.sparse_csr_from_coo(coo_matrix)
|
|
75
|
+
|
|
76
|
+
# Check that the result is still recognized as sparse
|
|
77
|
+
assert tc.backend.is_sparse(csr_matrix) is True
|
|
78
|
+
|
|
79
|
+
# Check that the conversion preserves values by comparing dense representations
|
|
80
|
+
coo_dense = tc.backend.to_dense(coo_matrix)
|
|
81
|
+
csr_dense = tc.backend.to_dense(csr_matrix)
|
|
82
|
+
np.testing.assert_allclose(coo_dense, csr_dense, atol=1e-5)
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
def test_sparse_tensor_matmul_monkey_patch(tfb):
|
|
86
|
+
"""
|
|
87
|
+
Test the monkey-patched __matmul__ method for tf.SparseTensor.
|
|
88
|
+
This test specifically targets the line:
|
|
89
|
+
tf.SparseTensor.__matmul__ = sparse_tensor_matmul
|
|
90
|
+
"""
|
|
91
|
+
# Create a sparse matrix in COO format
|
|
92
|
+
indices = tf.constant([[0, 0], [1, 1], [2, 3]], dtype=tf.int64)
|
|
93
|
+
values = tf.constant([1.0, 2.0, 3.0], dtype=tf.complex64)
|
|
94
|
+
shape = [4, 4]
|
|
95
|
+
sparse_matrix = tf.SparseTensor(indices=indices, values=values, dense_shape=shape)
|
|
96
|
+
|
|
97
|
+
# Test 1: Matrix-vector multiplication with 1D vector
|
|
98
|
+
vector_1d = tf.constant([1.0, 2.0, 3.0, 4.0], dtype=tf.complex64)
|
|
99
|
+
result_1d = sparse_matrix @ vector_1d # Using the monkey-patched @ operator
|
|
100
|
+
|
|
101
|
+
expected_1d = tf.constant([1.0, 4.0, 12.0, 0.0], dtype=tf.complex64)
|
|
102
|
+
|
|
103
|
+
np.testing.assert_allclose(result_1d, expected_1d, atol=1e-6)
|
|
104
|
+
vector_1d = tc.backend.reshape(vector_1d, [4, 1])
|
|
105
|
+
result_1dn = sparse_matrix @ vector_1d # Using the monkey-patched @ operator
|
|
106
|
+
expected_1d = tc.backend.reshape(expected_1d, [4, 1])
|
|
107
|
+
|
|
108
|
+
np.testing.assert_allclose(result_1dn, expected_1d, atol=1e-6)
|
|
109
|
+
|
|
110
|
+
# Test 2: Matrix-matrix multiplication with 2D matrix
|
|
111
|
+
matrix_2d = tf.constant(
|
|
112
|
+
[[1.0, 2.0], [3.0, 4.0], [5.0, 6.0], [7.0, 8.0]], dtype=tf.complex64
|
|
113
|
+
)
|
|
114
|
+
result_2d = sparse_matrix @ matrix_2d # Using the monkey-patched @ operator
|
|
115
|
+
|
|
116
|
+
expected_2d = tf.sparse.sparse_dense_matmul(sparse_matrix, matrix_2d)
|
|
117
|
+
|
|
118
|
+
np.testing.assert_allclose(result_2d.numpy(), expected_2d.numpy(), atol=1e-6)
|
|
119
|
+
|
|
120
|
+
# Test 3: Verify that the operation is consistent with sparse_dense_matmul
|
|
121
|
+
|
|
122
|
+
reference_result = tc.backend.sparse_dense_matmul(sparse_matrix, vector_1d)
|
|
123
|
+
reference_result_squeezed = tc.backend.reshape(reference_result, [-1])
|
|
124
|
+
|
|
125
|
+
np.testing.assert_allclose(result_1d, reference_result_squeezed, atol=1e-6)
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
@pytest.mark.parametrize("backend", [lf("npb"), lf("jaxb")])
|
|
129
|
+
def test_backend_jv(backend, highp):
|
|
130
|
+
def calculate_M(k, x_val):
|
|
131
|
+
safety_factor = 15
|
|
132
|
+
M = max(k, int(abs(x_val))) + int(safety_factor * np.sqrt(abs(x_val)))
|
|
133
|
+
M = max(M, k + 30)
|
|
134
|
+
return M
|
|
135
|
+
|
|
136
|
+
k_values = [5, 20, 50, 200, 500, 3000]
|
|
137
|
+
x_values = [0.0, 0.1, 1.0, 10.0, 100, 1000, 6000]
|
|
138
|
+
for k in k_values:
|
|
139
|
+
for x_val in x_values:
|
|
140
|
+
M = calculate_M(k, x_val)
|
|
141
|
+
f_vals = tc.backend.special_jv(k, x_val, M)
|
|
142
|
+
np.testing.assert_allclose(
|
|
143
|
+
f_vals, scipy.special.jv(np.arange(k), x_val), atol=1e-6
|
|
144
|
+
)
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
@pytest.mark.parametrize("backend", [lf("npb"), lf("jaxb")])
|
|
148
|
+
def test_backend_jaxy_scan(backend):
|
|
149
|
+
def body_fun(carry, x):
|
|
150
|
+
counter, decrementor = carry
|
|
151
|
+
|
|
152
|
+
# 更新状态
|
|
153
|
+
new_counter = counter + 1
|
|
154
|
+
new_decrementor = decrementor - 1
|
|
155
|
+
new_carry = (new_counter, new_decrementor)
|
|
156
|
+
|
|
157
|
+
y = counter + decrementor
|
|
158
|
+
|
|
159
|
+
return new_carry, y
|
|
160
|
+
|
|
161
|
+
init_val = (0, 100)
|
|
162
|
+
|
|
163
|
+
final_carry, stacked_ys = tc.backend.jaxy_scan(
|
|
164
|
+
f=body_fun,
|
|
165
|
+
init=init_val,
|
|
166
|
+
xs=tc.backend.arange(5),
|
|
167
|
+
)
|
|
168
|
+
|
|
169
|
+
expected_final_carry = (5, 95)
|
|
170
|
+
expected_stacked_ys = np.array([100, 100, 100, 100, 100])
|
|
171
|
+
|
|
172
|
+
assert final_carry == expected_final_carry
|
|
173
|
+
|
|
174
|
+
np.testing.assert_array_equal(np.asarray(stacked_ys), expected_stacked_ys)
|
|
175
|
+
|
|
176
|
+
|
|
177
|
+
def test_backend_jv_grad(jaxb, highp):
|
|
178
|
+
def f(x):
|
|
179
|
+
return tc.backend.sum(tc.backend.special_jv(5, x, 100))
|
|
180
|
+
|
|
181
|
+
print(tc.backend.jit(tc.backend.value_and_grad(f))(0.2))
|
|
182
|
+
|
|
183
|
+
|
|
63
184
|
@pytest.mark.parametrize("backend", [lf("npb"), lf("tfb"), lf("jaxb")])
|
|
64
185
|
def test_backend_scatter(backend):
|
|
65
186
|
np.testing.assert_allclose(
|
tests/test_timeevol.py
CHANGED
|
@@ -11,7 +11,7 @@ sys.path.insert(0, modulepath)
|
|
|
11
11
|
import tensorcircuit as tc
|
|
12
12
|
|
|
13
13
|
|
|
14
|
-
def
|
|
14
|
+
def test_circuit_ode_evol(jaxb):
|
|
15
15
|
def h_square(t, b):
|
|
16
16
|
return (tc.backend.sign(t - 1.0) + 1) / 2 * b * tc.gates.x().tensor
|
|
17
17
|
|
|
@@ -19,9 +19,7 @@ def test_ode_evol(jaxb):
|
|
|
19
19
|
c.x(0)
|
|
20
20
|
c.cx(0, 1)
|
|
21
21
|
c.h(2)
|
|
22
|
-
c = tc.timeevol.
|
|
23
|
-
c, [1], h_square, 2.0, tc.backend.convert_to_tensor(0.2)
|
|
24
|
-
)
|
|
22
|
+
c = tc.timeevol.evol_local(c, [1], h_square, 2.0, tc.backend.convert_to_tensor(0.2))
|
|
25
23
|
c.rx(1, theta=np.pi - 0.4)
|
|
26
24
|
np.testing.assert_allclose(c.expectation_ps(z=[1]), 1.0, atol=1e-5)
|
|
27
25
|
|
|
@@ -34,13 +32,156 @@ def test_ode_evol(jaxb):
|
|
|
34
32
|
c.x(0)
|
|
35
33
|
c.cx(0, 1)
|
|
36
34
|
c.h(2)
|
|
37
|
-
c = tc.timeevol.
|
|
35
|
+
c = tc.timeevol.evol_global(
|
|
38
36
|
c, h_square_sparse, 2.0, tc.backend.convert_to_tensor(0.2)
|
|
39
37
|
)
|
|
40
38
|
c.rx(1, theta=np.pi - 0.4)
|
|
41
39
|
np.testing.assert_allclose(c.expectation_ps(z=[1]), 1.0, atol=1e-5)
|
|
42
40
|
|
|
43
41
|
|
|
42
|
+
def test_ode_evol_local(jaxb):
|
|
43
|
+
def local_hamiltonian(t, Omega, phi):
|
|
44
|
+
angle = phi * t
|
|
45
|
+
coeff = Omega * tc.backend.cos(2.0 * t) # Amplitude modulation
|
|
46
|
+
|
|
47
|
+
# Single-qubit Rabi Hamiltonian (2x2 matrix)
|
|
48
|
+
hx = coeff * tc.backend.cos(angle) * tc.gates.x().tensor
|
|
49
|
+
hy = coeff * tc.backend.sin(angle) * tc.gates.y().tensor
|
|
50
|
+
return hx + hy
|
|
51
|
+
|
|
52
|
+
# Initial state: GHZ state |0000⟩ + |1111⟩
|
|
53
|
+
c = tc.Circuit(4)
|
|
54
|
+
c.h(0)
|
|
55
|
+
for i in range(3):
|
|
56
|
+
c.cnot(i, i + 1)
|
|
57
|
+
psi0 = c.state()
|
|
58
|
+
|
|
59
|
+
# Time points
|
|
60
|
+
times = tc.backend.arange(0.0, 3.0, 0.1)
|
|
61
|
+
|
|
62
|
+
# Evolve with local Hamiltonian acting on qubit 1
|
|
63
|
+
states = tc.timeevol.ode_evol_local(
|
|
64
|
+
local_hamiltonian,
|
|
65
|
+
psi0,
|
|
66
|
+
times,
|
|
67
|
+
[1], # Apply to qubit 1
|
|
68
|
+
None,
|
|
69
|
+
1.0,
|
|
70
|
+
2.0, # Omega=1.0, phi=2.0
|
|
71
|
+
)
|
|
72
|
+
assert tc.backend.shape_tuple(states) == (30, 16)
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
def test_ode_evol_global(jaxb):
|
|
76
|
+
# Create a time-dependent transverse field Hamiltonian
|
|
77
|
+
# H(t) = -∑ᵢ Jᵢ(t) ZᵢZᵢ₊₁ - ∑ᵢ hᵢ(t) Xᵢ
|
|
78
|
+
|
|
79
|
+
# Time-dependent coefficients
|
|
80
|
+
def time_dep_J(t):
|
|
81
|
+
return 1.0 + 0.5 * tc.backend.sin(2.0 * t)
|
|
82
|
+
|
|
83
|
+
def time_dep_h(t):
|
|
84
|
+
return 0.5 * tc.backend.cos(1.5 * t)
|
|
85
|
+
|
|
86
|
+
zz_ham = tc.quantum.PauliStringSum2COO(
|
|
87
|
+
[[3, 3, 0, 0], [0, 3, 3, 0], [0, 0, 3, 3]], [1, 1, 1]
|
|
88
|
+
)
|
|
89
|
+
x_ham = tc.quantum.PauliStringSum2COO(
|
|
90
|
+
[[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]], [1, 1, 1, 1]
|
|
91
|
+
)
|
|
92
|
+
|
|
93
|
+
# Hamiltonian construction function
|
|
94
|
+
def hamiltonian_func(t):
|
|
95
|
+
# Create time-dependent ZZ terms
|
|
96
|
+
zz_coeff = time_dep_J(t)
|
|
97
|
+
|
|
98
|
+
# Create time-dependent X terms
|
|
99
|
+
x_coeff = time_dep_h(t)
|
|
100
|
+
|
|
101
|
+
return zz_coeff * zz_ham + x_coeff * x_ham
|
|
102
|
+
|
|
103
|
+
# Initial state: |↑↓↑↓⟩
|
|
104
|
+
c = tc.Circuit(4)
|
|
105
|
+
c.x([1, 3])
|
|
106
|
+
psi0 = c.state()
|
|
107
|
+
|
|
108
|
+
# Time points for evolution
|
|
109
|
+
times = tc.backend.arange(0, 5, 0.5)
|
|
110
|
+
|
|
111
|
+
def zobs(state):
|
|
112
|
+
n = int(np.log2(state.shape[-1]))
|
|
113
|
+
c = tc.Circuit(n, inputs=state)
|
|
114
|
+
return tc.backend.real(c.expectation_ps(z=[0]))
|
|
115
|
+
|
|
116
|
+
# Perform global ODE evolution
|
|
117
|
+
states = tc.timeevol.ode_evol_global(hamiltonian_func, psi0, times, zobs)
|
|
118
|
+
assert tc.backend.shape_tuple(states) == (10,)
|
|
119
|
+
|
|
120
|
+
zz_ham = tc.quantum.PauliStringSum2COO([[3, 3, 0, 0], [0, 3, 3, 0]], [1, 1])
|
|
121
|
+
x_ham = tc.quantum.PauliStringSum2COO([[1, 0, 0, 0], [0, 1, 0, 0]], [1, 1])
|
|
122
|
+
|
|
123
|
+
# Example with parameterized Hamiltonian and optimization
|
|
124
|
+
def parametrized_hamiltonian(t, params):
|
|
125
|
+
# params = [J0, J1, h0, h1] - parameters to optimize
|
|
126
|
+
J_t = params[0] + params[1] * tc.backend.sin(2.0 * t)
|
|
127
|
+
h_t = params[2] + params[3] * tc.backend.cos(1.5 * t)
|
|
128
|
+
|
|
129
|
+
return J_t * zz_ham + h_t * x_ham
|
|
130
|
+
|
|
131
|
+
# Observable function: measure ZZ correlation
|
|
132
|
+
def zz_correlation(state):
|
|
133
|
+
n = int(np.log2(state.shape[0]))
|
|
134
|
+
circuit = tc.Circuit(n, inputs=state)
|
|
135
|
+
return circuit.expectation_ps(z=[0, 1])
|
|
136
|
+
|
|
137
|
+
@tc.backend.jit
|
|
138
|
+
@tc.backend.value_and_grad
|
|
139
|
+
def objective_function(params):
|
|
140
|
+
states = tc.timeevol.ode_evol_global(
|
|
141
|
+
parametrized_hamiltonian,
|
|
142
|
+
psi0,
|
|
143
|
+
tc.backend.convert_to_tensor([0, 1.0]),
|
|
144
|
+
None,
|
|
145
|
+
params,
|
|
146
|
+
)
|
|
147
|
+
# Measure ZZ correlation at final time
|
|
148
|
+
final_state = states[-1]
|
|
149
|
+
return tc.backend.real(zz_correlation(final_state))
|
|
150
|
+
|
|
151
|
+
print(objective_function(tc.backend.ones([4])))
|
|
152
|
+
|
|
153
|
+
|
|
154
|
+
@pytest.mark.parametrize("backend", [lf("npb"), lf("tfb"), lf("jaxb")])
|
|
155
|
+
def test_ed_evol(backend):
|
|
156
|
+
n = 4
|
|
157
|
+
g = tc.templates.graphs.Line1D(n, pbc=False)
|
|
158
|
+
h = tc.quantum.heisenberg_hamiltonian(g, hzz=1.0, hxx=1.0, hyy=1.0, sparse=False)
|
|
159
|
+
|
|
160
|
+
# Initial Neel state: |↑↓↑↓⟩
|
|
161
|
+
c = tc.Circuit(n)
|
|
162
|
+
c.x([1, 3]) # Apply X gates to qubits 1 and 3
|
|
163
|
+
psi0 = c.state()
|
|
164
|
+
|
|
165
|
+
# Imaginary time evolution times
|
|
166
|
+
times = tc.backend.convert_to_tensor([0.0, 0.5, 1.0, 2.0])
|
|
167
|
+
|
|
168
|
+
# Evolve and get states
|
|
169
|
+
states = tc.timeevol.ed_evol(h, psi0, times)
|
|
170
|
+
print(states)
|
|
171
|
+
|
|
172
|
+
def evolve_and_measure(params):
|
|
173
|
+
# Parametrized Hamiltonian
|
|
174
|
+
h_param = tc.quantum.heisenberg_hamiltonian(
|
|
175
|
+
g, hzz=params[0], hxx=params[1], hyy=params[2], sparse=False
|
|
176
|
+
)
|
|
177
|
+
states = tc.timeevol.ed_evol(h_param, psi0, times)
|
|
178
|
+
# Measure observable on final state
|
|
179
|
+
circuit = tc.Circuit(n, inputs=states[-1])
|
|
180
|
+
return tc.backend.real(circuit.expectation_ps(z=[0]))
|
|
181
|
+
|
|
182
|
+
evolve_and_measure(tc.backend.ones([3]))
|
|
183
|
+
|
|
184
|
+
|
|
44
185
|
@pytest.mark.parametrize("backend", [lf("npb"), lf("tfb"), lf("jaxb")])
|
|
45
186
|
def test_hamiltonian_evol_basic(backend):
|
|
46
187
|
"""Test basic functionality of hamiltonian_evol with a simple 2-qubit Hamiltonian"""
|
|
@@ -63,7 +204,7 @@ def test_hamiltonian_evol_basic(backend):
|
|
|
63
204
|
)
|
|
64
205
|
|
|
65
206
|
# Evolve and get states
|
|
66
|
-
states = tc.timeevol.hamiltonian_evol(
|
|
207
|
+
states = tc.timeevol.hamiltonian_evol(h, psi0, times)
|
|
67
208
|
|
|
68
209
|
# Check output shape
|
|
69
210
|
assert states.shape == (3, 4)
|
|
@@ -99,7 +240,7 @@ def test_hamiltonian_evol_with_callback(backend):
|
|
|
99
240
|
return tc.backend.real(c.expectation_ps(z=[0]))
|
|
100
241
|
|
|
101
242
|
# Evolve with callback
|
|
102
|
-
results = tc.timeevol.hamiltonian_evol(
|
|
243
|
+
results = tc.timeevol.hamiltonian_evol(h, psi0, times, callback)
|
|
103
244
|
|
|
104
245
|
# Check output shape - should be scalar for each time point
|
|
105
246
|
assert results.shape == (3,)
|
|
@@ -121,7 +262,7 @@ def test_hamiltonian_evol_imaginary_time(backend):
|
|
|
121
262
|
times = tc.backend.convert_to_tensor([0.0, 10.0])
|
|
122
263
|
|
|
123
264
|
# Evolve
|
|
124
|
-
states = tc.timeevol.hamiltonian_evol(
|
|
265
|
+
states = tc.timeevol.hamiltonian_evol(h, psi0, times)
|
|
125
266
|
|
|
126
267
|
# Ground state is |1⟩ (eigenvalue 1.0), so after long imaginary time
|
|
127
268
|
# evolution, we should approach this state
|
|
@@ -138,7 +279,6 @@ def test_krylov_evol_heisenberg_6_sites(backend):
|
|
|
138
279
|
|
|
139
280
|
# Generate Heisenberg Hamiltonian
|
|
140
281
|
h = tc.quantum.heisenberg_hamiltonian(g, hzz=1.0, hxx=1.0, hyy=1.0, sparse=False)
|
|
141
|
-
print(h.dtype)
|
|
142
282
|
# Initial state - all spins up except last one down
|
|
143
283
|
psi0 = np.zeros((2**n,))
|
|
144
284
|
psi0[62] = 1.0
|
|
@@ -236,3 +376,266 @@ def test_krylov_evol_subspace_accuracy(backend):
|
|
|
236
376
|
# At least verify they have the correct shape
|
|
237
377
|
assert state_small.shape == (1, 2**n)
|
|
238
378
|
assert state_large.shape == (1, 2**n)
|
|
379
|
+
|
|
380
|
+
|
|
381
|
+
@pytest.mark.parametrize("backend", [lf("npb"), lf("tfb"), lf("jaxb")])
|
|
382
|
+
def test_krylov_evol_scan_impl(backend):
|
|
383
|
+
"""Test krylov_evol with scan_impl=True"""
|
|
384
|
+
n = 4
|
|
385
|
+
# Create a 1D chain graph
|
|
386
|
+
g = tc.templates.graphs.Line1D(n, pbc=False)
|
|
387
|
+
|
|
388
|
+
# Generate Heisenberg Hamiltonian
|
|
389
|
+
h = tc.quantum.heisenberg_hamiltonian(g, hzz=1.0, hxx=1.0, hyy=1.0, sparse=True)
|
|
390
|
+
|
|
391
|
+
c = tc.Circuit(n)
|
|
392
|
+
c.x([1, 2])
|
|
393
|
+
psi0 = c.state()
|
|
394
|
+
|
|
395
|
+
# Evolution times
|
|
396
|
+
times = tc.backend.convert_to_tensor([0.0, 0.5])
|
|
397
|
+
|
|
398
|
+
# Perform Krylov evolution with scan implementation
|
|
399
|
+
states_scan = tc.timeevol.krylov_evol(
|
|
400
|
+
h, psi0, times, subspace_dimension=8, scan_impl=True
|
|
401
|
+
)
|
|
402
|
+
|
|
403
|
+
states_scan_dense = tc.timeevol.krylov_evol(
|
|
404
|
+
tc.backend.to_dense(h), psi0, times, subspace_dimension=8, scan_impl=True
|
|
405
|
+
)
|
|
406
|
+
|
|
407
|
+
# Perform Krylov evolution with regular implementation
|
|
408
|
+
states_regular = tc.timeevol.krylov_evol(
|
|
409
|
+
h, psi0, times, subspace_dimension=8, scan_impl=False
|
|
410
|
+
)
|
|
411
|
+
|
|
412
|
+
# Check output shapes
|
|
413
|
+
assert states_scan.shape == (2, 2**n)
|
|
414
|
+
assert states_regular.shape == (2, 2**n)
|
|
415
|
+
|
|
416
|
+
# Results should be the same (up to numerical precision)
|
|
417
|
+
np.testing.assert_allclose(states_scan, states_regular, atol=1e-5)
|
|
418
|
+
np.testing.assert_allclose(states_scan_dense, states_regular, atol=1e-5)
|
|
419
|
+
|
|
420
|
+
# All states should be normalized
|
|
421
|
+
for state in states_scan:
|
|
422
|
+
norm = tc.backend.norm(state)
|
|
423
|
+
np.testing.assert_allclose(norm, 1.0, atol=1e-5)
|
|
424
|
+
|
|
425
|
+
|
|
426
|
+
@pytest.mark.parametrize("backend", [lf("jaxb")])
|
|
427
|
+
def test_krylov_evol_gradient(backend):
|
|
428
|
+
"""Test gradient computation with krylov_evol"""
|
|
429
|
+
n = 5
|
|
430
|
+
# Create a 1D chain graph
|
|
431
|
+
g = tc.templates.graphs.Line1D(n, pbc=False)
|
|
432
|
+
|
|
433
|
+
# Generate Heisenberg Hamiltonian
|
|
434
|
+
h = tc.quantum.heisenberg_hamiltonian(g, hzz=1.0, hxx=1.0, hyy=1.0, sparse=False)
|
|
435
|
+
|
|
436
|
+
c = tc.Circuit(n)
|
|
437
|
+
c.x([1, 2])
|
|
438
|
+
psi0 = c.state()
|
|
439
|
+
|
|
440
|
+
# Evolution time
|
|
441
|
+
t = tc.backend.convert_to_tensor([1.0])
|
|
442
|
+
|
|
443
|
+
# Define a simple loss function based on the evolved state
|
|
444
|
+
def loss_function(t):
|
|
445
|
+
states = tc.timeevol.krylov_evol(
|
|
446
|
+
h, psi0, t, subspace_dimension=8, scan_impl=True
|
|
447
|
+
)
|
|
448
|
+
# Compute the sum of absolute values of the final state as a simple loss
|
|
449
|
+
return tc.backend.sum(tc.backend.abs(states[0]))
|
|
450
|
+
|
|
451
|
+
grad_fn = tc.backend.jit(tc.backend.grad(loss_function))
|
|
452
|
+
gradient = grad_fn(t)
|
|
453
|
+
print(gradient)
|
|
454
|
+
|
|
455
|
+
|
|
456
|
+
@pytest.mark.parametrize(
|
|
457
|
+
"backend, sparse",
|
|
458
|
+
[[lf("npb"), True], [lf("npb"), False], [lf("jaxb"), True], [lf("jaxb"), False]],
|
|
459
|
+
)
|
|
460
|
+
def test_chebyshev_evol_basic(backend, highp, sparse):
|
|
461
|
+
n = 6
|
|
462
|
+
# Create a 1D chain graph
|
|
463
|
+
g = tc.templates.graphs.Line1D(n, pbc=False)
|
|
464
|
+
|
|
465
|
+
# Generate Heisenberg Hamiltonian (dense for better compatibility)
|
|
466
|
+
h = tc.quantum.heisenberg_hamiltonian(
|
|
467
|
+
g, hzz=1.0, hxx=1.0, hyy=1.0, hx=0.2, sparse=sparse
|
|
468
|
+
)
|
|
469
|
+
|
|
470
|
+
# Initial Neel state: |↑↓↑↓⟩
|
|
471
|
+
c = tc.Circuit(n)
|
|
472
|
+
c.x([1, 3, 5]) # Apply X gates to qubits 1 and 3
|
|
473
|
+
psi0 = c.state()
|
|
474
|
+
|
|
475
|
+
# Evolution time
|
|
476
|
+
t = 2.0
|
|
477
|
+
|
|
478
|
+
# Estimate spectral bounds
|
|
479
|
+
e_max, e_min = tc.timeevol.estimate_spectral_bounds(h, n_iter=30)
|
|
480
|
+
|
|
481
|
+
# Estimate parameters
|
|
482
|
+
k = tc.timeevol.estimate_k(t, (e_max, e_min))
|
|
483
|
+
m = tc.timeevol.estimate_M(t, (e_max, e_min), k)
|
|
484
|
+
|
|
485
|
+
# Evolve using Chebyshev method
|
|
486
|
+
psi_chebyshev = tc.timeevol.chebyshev_evol(
|
|
487
|
+
h, psi0, t, (float(e_max) + 0.1, float(e_min) - 0.1), k, m
|
|
488
|
+
)
|
|
489
|
+
|
|
490
|
+
# Check that state is normalized (or close to it)
|
|
491
|
+
norm = tc.backend.norm(psi_chebyshev)
|
|
492
|
+
np.testing.assert_allclose(norm, 1.0, atol=1e-3)
|
|
493
|
+
|
|
494
|
+
# Compare with exact evolution for small system
|
|
495
|
+
if sparse is True:
|
|
496
|
+
h = tc.backend.to_dense(h)
|
|
497
|
+
psi_exact = tc.timeevol.ed_evol(h, psi0, 1.0j * tc.backend.convert_to_tensor([t]))[
|
|
498
|
+
0
|
|
499
|
+
]
|
|
500
|
+
|
|
501
|
+
# States should be close (up to global phase)
|
|
502
|
+
fidelity = np.abs(np.vdot(np.asarray(psi_exact), np.asarray(psi_chebyshev))) ** 2
|
|
503
|
+
assert fidelity > 0.95 # Should be close, but not exact due to approximations
|
|
504
|
+
|
|
505
|
+
|
|
506
|
+
def test_chebyshev_evol_vmap_on_t(jaxb, highp):
|
|
507
|
+
n = 4
|
|
508
|
+
# Create a 1D chain graph
|
|
509
|
+
g = tc.templates.graphs.Line1D(n, pbc=False)
|
|
510
|
+
|
|
511
|
+
# Generate Heisenberg Hamiltonian
|
|
512
|
+
h = tc.quantum.heisenberg_hamiltonian(g, hzz=1.0, hxx=1.0, hyy=1.0, sparse=False)
|
|
513
|
+
|
|
514
|
+
# Initial Neel state
|
|
515
|
+
c = tc.Circuit(n)
|
|
516
|
+
c.x([1, 3])
|
|
517
|
+
psi0 = c.state()
|
|
518
|
+
|
|
519
|
+
# Estimate spectral bounds
|
|
520
|
+
e_max, e_min = tc.timeevol.estimate_spectral_bounds(h, n_iter=20)
|
|
521
|
+
|
|
522
|
+
# Fixed parameters
|
|
523
|
+
k = 50
|
|
524
|
+
m = 150
|
|
525
|
+
|
|
526
|
+
# Define vectorized evolution function
|
|
527
|
+
def evolve_single_time(t):
|
|
528
|
+
return tc.timeevol.chebyshev_evol(
|
|
529
|
+
h, psi0, t, (float(e_max) + 0.1, float(e_min) - 0.1), k, m
|
|
530
|
+
)
|
|
531
|
+
|
|
532
|
+
# Vectorize over times
|
|
533
|
+
times = tc.backend.convert_to_tensor([0.5, 1.0, 1.5])
|
|
534
|
+
vmap_evolve = tc.backend.jit(tc.backend.vmap(evolve_single_time))
|
|
535
|
+
states_vmap = vmap_evolve(times)
|
|
536
|
+
|
|
537
|
+
# Check output shape
|
|
538
|
+
assert states_vmap.shape == (3, 2**n)
|
|
539
|
+
|
|
540
|
+
# Compare with sequential execution
|
|
541
|
+
states_sequential = []
|
|
542
|
+
for t in times:
|
|
543
|
+
state = tc.timeevol.chebyshev_evol(
|
|
544
|
+
h, psi0, float(t), (e_max + 0.1, e_min - 0.1), k, m
|
|
545
|
+
)
|
|
546
|
+
states_sequential.append(state)
|
|
547
|
+
|
|
548
|
+
states_sequential = tc.backend.stack(states_sequential)
|
|
549
|
+
|
|
550
|
+
# Results should be the same
|
|
551
|
+
np.testing.assert_allclose(states_vmap, states_sequential, atol=1e-5)
|
|
552
|
+
|
|
553
|
+
|
|
554
|
+
def test_chebyshev_evol_jit_on_psi(jaxb, highp):
|
|
555
|
+
"""Test JIT compilation capability of chebyshev_evol on psi parameter"""
|
|
556
|
+
n = 4
|
|
557
|
+
# Create a 1D chain graph
|
|
558
|
+
g = tc.templates.graphs.Line1D(n, pbc=False)
|
|
559
|
+
|
|
560
|
+
# Generate Heisenberg Hamiltonian
|
|
561
|
+
h = tc.quantum.heisenberg_hamiltonian(g, hzz=1.0, hxx=0.6, hyy=1.0, sparse=True)
|
|
562
|
+
|
|
563
|
+
# Estimate spectral bounds
|
|
564
|
+
e_max, e_min = tc.timeevol.estimate_spectral_bounds(h, n_iter=20)
|
|
565
|
+
|
|
566
|
+
# Fixed parameters
|
|
567
|
+
t = 1.0
|
|
568
|
+
k = 50
|
|
569
|
+
m = 150
|
|
570
|
+
|
|
571
|
+
# Define JIT-compiled evolution function with psi as argument
|
|
572
|
+
def evolve_state(psi):
|
|
573
|
+
return tc.timeevol.chebyshev_evol(
|
|
574
|
+
h, psi, t, (float(e_max) + 0.1, float(e_min) - 0.1), k, m
|
|
575
|
+
)
|
|
576
|
+
|
|
577
|
+
jit_evolve = tc.backend.jit(evolve_state)
|
|
578
|
+
|
|
579
|
+
# Test with different initial states
|
|
580
|
+
c1 = tc.Circuit(n)
|
|
581
|
+
c1.x([0, 2])
|
|
582
|
+
psi1 = c1.state()
|
|
583
|
+
|
|
584
|
+
c2 = tc.Circuit(n)
|
|
585
|
+
c2.h(0)
|
|
586
|
+
for i in range(n - 1):
|
|
587
|
+
c2.cnot(i, i + 1)
|
|
588
|
+
psi2 = c2.state()
|
|
589
|
+
|
|
590
|
+
# Run JIT-compiled evolution
|
|
591
|
+
result1_jit = jit_evolve(psi1)
|
|
592
|
+
result2_jit = jit_evolve(psi2)
|
|
593
|
+
|
|
594
|
+
# Run regular evolution for comparison
|
|
595
|
+
result1_regular = tc.timeevol.chebyshev_evol(
|
|
596
|
+
h, psi1, t, (e_max + 0.1, e_min - 0.1), k, m
|
|
597
|
+
)
|
|
598
|
+
result2_regular = tc.timeevol.chebyshev_evol(
|
|
599
|
+
h, psi2, t, (e_max + 0.1, e_min - 0.1), k, m
|
|
600
|
+
)
|
|
601
|
+
print(result1_jit)
|
|
602
|
+
# Results should be the same
|
|
603
|
+
np.testing.assert_allclose(result1_jit, result1_regular, atol=1e-5)
|
|
604
|
+
np.testing.assert_allclose(result2_jit, result2_regular, atol=1e-5)
|
|
605
|
+
|
|
606
|
+
|
|
607
|
+
def test_chebyshev_evol_ad_on_t(jaxb, highp):
|
|
608
|
+
n = 5
|
|
609
|
+
# Create a 1D chain graph
|
|
610
|
+
g = tc.templates.graphs.Line1D(n, pbc=True)
|
|
611
|
+
|
|
612
|
+
# Generate Heisenberg Hamiltonian
|
|
613
|
+
h = tc.quantum.heisenberg_hamiltonian(g, hzz=1.0, hxx=1.0, hyy=1.0, sparse=True)
|
|
614
|
+
|
|
615
|
+
# Initial state
|
|
616
|
+
c = tc.Circuit(n)
|
|
617
|
+
c.x([1, 3])
|
|
618
|
+
psi0 = c.state()
|
|
619
|
+
|
|
620
|
+
# Estimate spectral bounds
|
|
621
|
+
e_max, e_min = tc.timeevol.estimate_spectral_bounds(h, n_iter=20)
|
|
622
|
+
|
|
623
|
+
# Fixed parameters
|
|
624
|
+
k = 50
|
|
625
|
+
m = 100
|
|
626
|
+
|
|
627
|
+
# Define loss function for gradient computation
|
|
628
|
+
def loss_function(t):
|
|
629
|
+
psi_t = tc.timeevol.chebyshev_evol(
|
|
630
|
+
h, psi0, t, (float(e_max) + 0.1, float(e_min) - 0.1), k, m
|
|
631
|
+
)
|
|
632
|
+
c = tc.Circuit(5, inputs=psi_t)
|
|
633
|
+
return tc.backend.real(c.expectation_ps(z=[2]))
|
|
634
|
+
|
|
635
|
+
# Compute gradient
|
|
636
|
+
grad_fn = tc.backend.jit(tc.backend.grad(loss_function))
|
|
637
|
+
t_test = tc.backend.convert_to_tensor(1.0)
|
|
638
|
+
gradient = grad_fn(t_test)
|
|
639
|
+
print(gradient)
|
|
640
|
+
# Gradient should be a scalar
|
|
641
|
+
assert gradient.shape == ()
|
|
File without changes
|
|
File without changes
|