Trajectree 0.0.0__py3-none-any.whl → 0.0.1__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.
Files changed (122) hide show
  1. trajectree/__init__.py +3 -0
  2. trajectree/fock_optics/devices.py +1 -1
  3. trajectree/fock_optics/light_sources.py +2 -2
  4. trajectree/fock_optics/measurement.py +3 -3
  5. trajectree/fock_optics/utils.py +6 -6
  6. trajectree/quimb/docs/_pygments/_pygments_dark.py +118 -0
  7. trajectree/quimb/docs/_pygments/_pygments_light.py +118 -0
  8. trajectree/quimb/docs/conf.py +158 -0
  9. trajectree/quimb/docs/examples/ex_mpi_expm_evo.py +62 -0
  10. trajectree/quimb/quimb/__init__.py +507 -0
  11. trajectree/quimb/quimb/calc.py +1491 -0
  12. trajectree/quimb/quimb/core.py +2279 -0
  13. trajectree/quimb/quimb/evo.py +712 -0
  14. trajectree/quimb/quimb/experimental/__init__.py +0 -0
  15. trajectree/quimb/quimb/experimental/autojittn.py +129 -0
  16. trajectree/quimb/quimb/experimental/belief_propagation/__init__.py +109 -0
  17. trajectree/quimb/quimb/experimental/belief_propagation/bp_common.py +397 -0
  18. trajectree/quimb/quimb/experimental/belief_propagation/d1bp.py +316 -0
  19. trajectree/quimb/quimb/experimental/belief_propagation/d2bp.py +653 -0
  20. trajectree/quimb/quimb/experimental/belief_propagation/hd1bp.py +571 -0
  21. trajectree/quimb/quimb/experimental/belief_propagation/hv1bp.py +775 -0
  22. trajectree/quimb/quimb/experimental/belief_propagation/l1bp.py +316 -0
  23. trajectree/quimb/quimb/experimental/belief_propagation/l2bp.py +537 -0
  24. trajectree/quimb/quimb/experimental/belief_propagation/regions.py +194 -0
  25. trajectree/quimb/quimb/experimental/cluster_update.py +286 -0
  26. trajectree/quimb/quimb/experimental/merabuilder.py +865 -0
  27. trajectree/quimb/quimb/experimental/operatorbuilder/__init__.py +15 -0
  28. trajectree/quimb/quimb/experimental/operatorbuilder/operatorbuilder.py +1631 -0
  29. trajectree/quimb/quimb/experimental/schematic.py +7 -0
  30. trajectree/quimb/quimb/experimental/tn_marginals.py +130 -0
  31. trajectree/quimb/quimb/experimental/tnvmc.py +1483 -0
  32. trajectree/quimb/quimb/gates.py +36 -0
  33. trajectree/quimb/quimb/gen/__init__.py +2 -0
  34. trajectree/quimb/quimb/gen/operators.py +1167 -0
  35. trajectree/quimb/quimb/gen/rand.py +713 -0
  36. trajectree/quimb/quimb/gen/states.py +479 -0
  37. trajectree/quimb/quimb/linalg/__init__.py +6 -0
  38. trajectree/quimb/quimb/linalg/approx_spectral.py +1109 -0
  39. trajectree/quimb/quimb/linalg/autoblock.py +258 -0
  40. trajectree/quimb/quimb/linalg/base_linalg.py +719 -0
  41. trajectree/quimb/quimb/linalg/mpi_launcher.py +397 -0
  42. trajectree/quimb/quimb/linalg/numpy_linalg.py +244 -0
  43. trajectree/quimb/quimb/linalg/rand_linalg.py +514 -0
  44. trajectree/quimb/quimb/linalg/scipy_linalg.py +293 -0
  45. trajectree/quimb/quimb/linalg/slepc_linalg.py +892 -0
  46. trajectree/quimb/quimb/schematic.py +1518 -0
  47. trajectree/quimb/quimb/tensor/__init__.py +401 -0
  48. trajectree/quimb/quimb/tensor/array_ops.py +610 -0
  49. trajectree/quimb/quimb/tensor/circuit.py +4824 -0
  50. trajectree/quimb/quimb/tensor/circuit_gen.py +411 -0
  51. trajectree/quimb/quimb/tensor/contraction.py +336 -0
  52. trajectree/quimb/quimb/tensor/decomp.py +1255 -0
  53. trajectree/quimb/quimb/tensor/drawing.py +1646 -0
  54. trajectree/quimb/quimb/tensor/fitting.py +385 -0
  55. trajectree/quimb/quimb/tensor/geometry.py +583 -0
  56. trajectree/quimb/quimb/tensor/interface.py +114 -0
  57. trajectree/quimb/quimb/tensor/networking.py +1058 -0
  58. trajectree/quimb/quimb/tensor/optimize.py +1818 -0
  59. trajectree/quimb/quimb/tensor/tensor_1d.py +4778 -0
  60. trajectree/quimb/quimb/tensor/tensor_1d_compress.py +1854 -0
  61. trajectree/quimb/quimb/tensor/tensor_1d_tebd.py +662 -0
  62. trajectree/quimb/quimb/tensor/tensor_2d.py +5954 -0
  63. trajectree/quimb/quimb/tensor/tensor_2d_compress.py +96 -0
  64. trajectree/quimb/quimb/tensor/tensor_2d_tebd.py +1230 -0
  65. trajectree/quimb/quimb/tensor/tensor_3d.py +2869 -0
  66. trajectree/quimb/quimb/tensor/tensor_3d_tebd.py +46 -0
  67. trajectree/quimb/quimb/tensor/tensor_approx_spectral.py +60 -0
  68. trajectree/quimb/quimb/tensor/tensor_arbgeom.py +3237 -0
  69. trajectree/quimb/quimb/tensor/tensor_arbgeom_compress.py +565 -0
  70. trajectree/quimb/quimb/tensor/tensor_arbgeom_tebd.py +1138 -0
  71. trajectree/quimb/quimb/tensor/tensor_builder.py +5411 -0
  72. trajectree/quimb/quimb/tensor/tensor_core.py +11179 -0
  73. trajectree/quimb/quimb/tensor/tensor_dmrg.py +1472 -0
  74. trajectree/quimb/quimb/tensor/tensor_mera.py +204 -0
  75. trajectree/quimb/quimb/utils.py +892 -0
  76. trajectree/quimb/tests/__init__.py +0 -0
  77. trajectree/quimb/tests/test_accel.py +501 -0
  78. trajectree/quimb/tests/test_calc.py +788 -0
  79. trajectree/quimb/tests/test_core.py +847 -0
  80. trajectree/quimb/tests/test_evo.py +565 -0
  81. trajectree/quimb/tests/test_gen/__init__.py +0 -0
  82. trajectree/quimb/tests/test_gen/test_operators.py +361 -0
  83. trajectree/quimb/tests/test_gen/test_rand.py +296 -0
  84. trajectree/quimb/tests/test_gen/test_states.py +261 -0
  85. trajectree/quimb/tests/test_linalg/__init__.py +0 -0
  86. trajectree/quimb/tests/test_linalg/test_approx_spectral.py +368 -0
  87. trajectree/quimb/tests/test_linalg/test_base_linalg.py +351 -0
  88. trajectree/quimb/tests/test_linalg/test_mpi_linalg.py +127 -0
  89. trajectree/quimb/tests/test_linalg/test_numpy_linalg.py +84 -0
  90. trajectree/quimb/tests/test_linalg/test_rand_linalg.py +134 -0
  91. trajectree/quimb/tests/test_linalg/test_slepc_linalg.py +283 -0
  92. trajectree/quimb/tests/test_tensor/__init__.py +0 -0
  93. trajectree/quimb/tests/test_tensor/test_belief_propagation/__init__.py +0 -0
  94. trajectree/quimb/tests/test_tensor/test_belief_propagation/test_d1bp.py +39 -0
  95. trajectree/quimb/tests/test_tensor/test_belief_propagation/test_d2bp.py +67 -0
  96. trajectree/quimb/tests/test_tensor/test_belief_propagation/test_hd1bp.py +64 -0
  97. trajectree/quimb/tests/test_tensor/test_belief_propagation/test_hv1bp.py +51 -0
  98. trajectree/quimb/tests/test_tensor/test_belief_propagation/test_l1bp.py +142 -0
  99. trajectree/quimb/tests/test_tensor/test_belief_propagation/test_l2bp.py +101 -0
  100. trajectree/quimb/tests/test_tensor/test_circuit.py +816 -0
  101. trajectree/quimb/tests/test_tensor/test_contract.py +67 -0
  102. trajectree/quimb/tests/test_tensor/test_decomp.py +40 -0
  103. trajectree/quimb/tests/test_tensor/test_mera.py +52 -0
  104. trajectree/quimb/tests/test_tensor/test_optimizers.py +488 -0
  105. trajectree/quimb/tests/test_tensor/test_tensor_1d.py +1171 -0
  106. trajectree/quimb/tests/test_tensor/test_tensor_2d.py +606 -0
  107. trajectree/quimb/tests/test_tensor/test_tensor_2d_tebd.py +144 -0
  108. trajectree/quimb/tests/test_tensor/test_tensor_3d.py +123 -0
  109. trajectree/quimb/tests/test_tensor/test_tensor_arbgeom.py +226 -0
  110. trajectree/quimb/tests/test_tensor/test_tensor_builder.py +441 -0
  111. trajectree/quimb/tests/test_tensor/test_tensor_core.py +2066 -0
  112. trajectree/quimb/tests/test_tensor/test_tensor_dmrg.py +388 -0
  113. trajectree/quimb/tests/test_tensor/test_tensor_spectral_approx.py +63 -0
  114. trajectree/quimb/tests/test_tensor/test_tensor_tebd.py +270 -0
  115. trajectree/quimb/tests/test_utils.py +85 -0
  116. trajectree/trajectory.py +2 -2
  117. {trajectree-0.0.0.dist-info → trajectree-0.0.1.dist-info}/METADATA +2 -2
  118. trajectree-0.0.1.dist-info/RECORD +126 -0
  119. trajectree-0.0.0.dist-info/RECORD +0 -16
  120. {trajectree-0.0.0.dist-info → trajectree-0.0.1.dist-info}/WHEEL +0 -0
  121. {trajectree-0.0.0.dist-info → trajectree-0.0.1.dist-info}/licenses/LICENSE +0 -0
  122. {trajectree-0.0.0.dist-info → trajectree-0.0.1.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,283 @@
1
+ from pytest import fixture, mark
2
+ import numpy as np
3
+ import scipy.sparse as sp
4
+ from numpy.testing import assert_allclose
5
+
6
+ from quimb import (
7
+ qu,
8
+ rand_uni,
9
+ ldmul,
10
+ rand_matrix,
11
+ rand_herm,
12
+ rand_pos,
13
+ rand_ket,
14
+ eigh,
15
+ eye,
16
+ norm,
17
+ )
18
+ from quimb.linalg import SLEPC4PY_FOUND
19
+ from quimb.linalg.scipy_linalg import svds_scipy
20
+
21
+ if SLEPC4PY_FOUND:
22
+ from quimb.linalg.slepc_linalg import (
23
+ eigs_slepc,
24
+ svds_slepc,
25
+ convert_mat_to_petsc,
26
+ new_petsc_vec,
27
+ mfn_multiply_slepc,
28
+ ssolve_slepc,
29
+ )
30
+
31
+
32
+ slepc4py_notfound_msg = "No SLEPc4py installation"
33
+ slepc4py_test = mark.skipif(not SLEPC4PY_FOUND, reason=slepc4py_notfound_msg)
34
+
35
+
36
+ @fixture
37
+ def prematsparse():
38
+ u = rand_uni(4)
39
+ a = u @ ldmul(np.array([-1, 2, 4, -3]), u.H)
40
+ a = qu(a, sparse=True)
41
+ return u, a
42
+
43
+
44
+ @fixture
45
+ def bigsparsemat():
46
+ return rand_matrix(100, sparse=True, density=0.1)
47
+
48
+
49
+ # --------------------------------------------------------------------------- #
50
+ # TESTS #
51
+ # --------------------------------------------------------------------------- #
52
+
53
+
54
+ @slepc4py_test
55
+ class TestConvertToPETScConversion:
56
+ def test_csr(self):
57
+ a = rand_matrix(2, sparse=True, density=0.5)
58
+ b = convert_mat_to_petsc(a)
59
+ assert b.getType() == "seqaij"
60
+
61
+ def test_bsr(self):
62
+ a = sp.kron(rand_matrix(2), eye(2, sparse=True), format="bsr")
63
+ b = convert_mat_to_petsc(a)
64
+ assert b.getType() == "seqbaij"
65
+ assert b.getBlockSize() == 2
66
+
67
+ # def test_vec(self):
68
+ # a = np.array([1, 2, 3, 4])
69
+ # b = convert_mat_to_petsc(a)
70
+ # assert_allclose(b.getArray(), a)
71
+
72
+ def test_dense(self):
73
+ a = rand_matrix(3)
74
+ b = convert_mat_to_petsc(a)
75
+ assert b.getType() == "seqdense"
76
+
77
+ def test_new_petsc_vector(self):
78
+ a = new_petsc_vec(4)
79
+ assert a.getArray() is not None
80
+
81
+
82
+ @slepc4py_test
83
+ class TestSlepceigs:
84
+ def test_internal_eigvals(self, prematsparse):
85
+ u, a = prematsparse
86
+ lk = eigs_slepc(a, k=2, sigma=0.5, return_vecs=False)
87
+ assert_allclose(lk, [-1, 2])
88
+
89
+ @mark.parametrize(
90
+ "which, output",
91
+ [
92
+ ("lm", 4),
93
+ ("sa", -3),
94
+ ],
95
+ )
96
+ def test_eigs_slepc_groundenergy(self, prematsparse, which, output):
97
+ u, a = prematsparse
98
+ lk = eigs_slepc(a, k=1, which=which, return_vecs=False)
99
+ assert_allclose(lk, output)
100
+
101
+ @mark.parametrize("dtype", ["real", "complex"])
102
+ def test_eigs_slepc_eigvecs(self, dtype):
103
+ h = rand_herm(32, sparse=True, density=0.5)
104
+ if dtype == "real":
105
+ h = h.real
106
+ lks, vks = eigs_slepc(h, k=5)
107
+ lka, vka = eigh(h, k=5, backend="scipy")
108
+ assert vks.shape == vka.shape
109
+ assert h.dtype == vks.dtype
110
+
111
+ assert_allclose(lks, lka)
112
+ assert_allclose(abs(vka.H @ vks), np.eye(5), atol=1e-8)
113
+
114
+
115
+ @slepc4py_test
116
+ class TestSlepcSvds:
117
+ def test_simple(self, prematsparse):
118
+ u, a = prematsparse
119
+ lk = svds_slepc(a, k=1, return_vecs=False)
120
+ assert_allclose(lk, 4)
121
+
122
+ @mark.parametrize("SVDType", ["cross", "lanczos"])
123
+ def test_random_compare_scipy(self, bigsparsemat, SVDType):
124
+ a = bigsparsemat
125
+ lk = svds_slepc(a, k=5, return_vecs=False, SVDType=SVDType)
126
+ ls = svds_scipy(a, k=5, return_vecs=False)
127
+ assert_allclose(lk, ls)
128
+
129
+ @mark.parametrize("SVDType", ["cross", "lanczos"])
130
+ def test_unitary_vectors(self, bigsparsemat, SVDType):
131
+ a = bigsparsemat
132
+ uk, sk, vk = svds_slepc(a, k=10, return_vecs=True, SVDType=SVDType)
133
+ assert_allclose(uk.H @ uk, eye(10), atol=1e-6)
134
+ assert_allclose(vk @ vk.H, eye(10), atol=1e-6)
135
+ pk, lk, qk = svds_scipy(a, k=10, return_vecs=True)
136
+ assert_allclose(sk, lk)
137
+ assert pk.shape == uk.shape
138
+ assert vk.shape == qk.shape
139
+ assert_allclose(abs(uk.H @ pk), eye(10), atol=1e-6)
140
+ assert_allclose(abs(qk @ vk.H), eye(10), atol=1e-6)
141
+
142
+
143
+ @slepc4py_test
144
+ class TestSlepcMfnMultiply:
145
+ def test_exp_sparse(self):
146
+ a = rand_herm(100, sparse=True, density=0.1)
147
+ k = rand_ket(100)
148
+
149
+ out = mfn_multiply_slepc(a, k)
150
+
151
+ al, av = eigh(a.toarray())
152
+ expected = av @ np.diag(np.exp(al)) @ av.conj().T @ k
153
+
154
+ assert_allclose(out, expected)
155
+
156
+ def test_sqrt_sparse(self):
157
+ import scipy.sparse as sp
158
+
159
+ a = rand_pos(32, sparse=True, density=0.1)
160
+ a = a + 0.001 * sp.eye(32)
161
+ k = rand_ket(32)
162
+
163
+ out = mfn_multiply_slepc(a, k, fntype="sqrt", isherm=True)
164
+
165
+ al, av = eigh(a.toarray())
166
+ al[al < 0] = 0.0 # very small neg values spoil sqrt
167
+ expected = av @ np.diag(np.sqrt(al)) @ av.conj().T @ k
168
+
169
+ assert_allclose(out, expected, rtol=1e-6)
170
+
171
+
172
+ @slepc4py_test
173
+ class TestShellMatrix:
174
+ def test_extermal_eigen(self):
175
+ a = rand_herm(100, sparse=True)
176
+ alo = sp.linalg.aslinearoperator(a)
177
+
178
+ el_us, ev_us = sp.linalg.eigsh(alo, k=1, which="LA")
179
+ el_u, ev_u = eigs_slepc(alo, k=1, which="LA")
180
+
181
+ assert_allclose(el_us, el_u)
182
+ assert_allclose(np.abs(ev_us.conj().T @ ev_u), 1.0)
183
+
184
+ el_ls, ev_ls = sp.linalg.eigsh(alo, k=1, which="SA")
185
+ el_l, ev_l = eigs_slepc(alo, k=1, which="SA")
186
+
187
+ assert_allclose(el_ls, el_l)
188
+ assert_allclose(np.abs(ev_ls.conj().T @ ev_l), 1.0)
189
+
190
+ def test_internal_interior_default(self):
191
+ a = rand_herm(100, sparse=True)
192
+ alo = sp.linalg.aslinearoperator(a)
193
+ el, ev = eigs_slepc(alo, k=1, which="TR", sigma=0.0)
194
+ el_s, ev_s = sp.linalg.eigsh(a.tocsc(), k=1, which="LM", sigma=0.0)
195
+
196
+ assert_allclose(el_s, el, rtol=1e-5)
197
+ assert_allclose(np.abs(ev_s.conj().T @ ev), 1.0)
198
+
199
+ def test_internal_shift_invert_linear_solver(self):
200
+ a = rand_herm(100, sparse=True, seed=42)
201
+ alo = sp.linalg.aslinearoperator(a)
202
+
203
+ st_opts = {
204
+ "STType": "sinvert",
205
+ "KSPType": "bcgs", # / 'gmres'
206
+ "PCType": "none",
207
+ }
208
+
209
+ el, ev = eigs_slepc(
210
+ alo,
211
+ k=1,
212
+ which="TR",
213
+ sigma=0.0,
214
+ tol=1e-6,
215
+ st_opts=st_opts,
216
+ EPSType="krylovschur",
217
+ )
218
+ el_s, ev_s = sp.linalg.eigsh(a.tocsc(), k=1, which="LM", sigma=0.0)
219
+
220
+ assert_allclose(el_s, el, rtol=1e-5)
221
+ assert_allclose(np.abs(ev_s.conj().T @ ev), 1.0)
222
+
223
+ def test_internal_shift_invert_precond(self):
224
+ a = rand_herm(20, sparse=True, seed=42)
225
+ alo = sp.linalg.aslinearoperator(a)
226
+
227
+ st_opts = {
228
+ "STType": "precond",
229
+ "KSPType": "preonly",
230
+ "PCType": "none",
231
+ }
232
+
233
+ el, ev = eigs_slepc(
234
+ alo, k=1, which="TR", sigma=0.0, st_opts=st_opts, EPSType="gd"
235
+ )
236
+ el_s, ev_s = sp.linalg.eigsh(a.tocsc(), k=1, which="LM", sigma=0.0)
237
+
238
+ assert_allclose(el_s, el, rtol=1e-6)
239
+ assert_allclose(np.abs(ev_s.conj().T @ ev), 1.0)
240
+
241
+ def test_internal_shift_invert_precond_jd(self):
242
+ a = rand_herm(20, sparse=True, seed=42)
243
+ alo = sp.linalg.aslinearoperator(a)
244
+
245
+ st_opts = {
246
+ "STType": "precond",
247
+ "KSPType": "bcgs", # / 'gmres'
248
+ "PCType": "none",
249
+ }
250
+
251
+ el, ev = eigs_slepc(
252
+ alo, k=1, which="TR", sigma=0.0, st_opts=st_opts, EPSType="jd"
253
+ )
254
+ el_s, ev_s = sp.linalg.eigsh(a.tocsc(), k=1, which="LM", sigma=0.0)
255
+
256
+ assert_allclose(el_s, el, rtol=1e-6)
257
+ assert_allclose(np.abs(ev_s.conj().T @ ev), 1.0)
258
+
259
+
260
+ @slepc4py_test
261
+ class TestCISS:
262
+ def test_1(self):
263
+ a = rand_herm(100, sparse=True)
264
+ el, ev = eigh(a.toarray())
265
+ which = abs(el) < 0.2
266
+ el, ev = el[which], ev[:, which]
267
+
268
+ offset = norm(a, "fro")
269
+ a = a + offset * sp.eye(a.shape[0])
270
+
271
+ sl, sv = eigs_slepc(a, k=6, l_win=(-0.2 + offset, 0.2 + offset))
272
+ sl -= offset
273
+ assert_allclose(el, sl)
274
+ assert_allclose(np.abs(sv.H @ ev), np.eye(el.size), atol=1e-11)
275
+
276
+
277
+ @slepc4py_test
278
+ class TestSSolve:
279
+ def test_simple_dense(self):
280
+ a = rand_herm(2**4, sparse=True)
281
+ y = rand_ket(2**4)
282
+ x = ssolve_slepc(a, y)
283
+ assert_allclose(a @ x, y, atol=1e-12, rtol=1e-6)
File without changes
@@ -0,0 +1,39 @@
1
+ import pytest
2
+
3
+ import quimb as qu
4
+ import quimb.tensor as qtn
5
+ from quimb.experimental.belief_propagation import (
6
+ D1BP,
7
+ contract_d1bp,
8
+ )
9
+
10
+
11
+ def test_contract_tree_exact():
12
+ tn = qtn.TN_rand_tree(20, 3)
13
+ Z = tn.contract()
14
+ info = {}
15
+ Z_bp = contract_d1bp(tn, info=info, progbar=True)
16
+ assert info["converged"]
17
+ assert Z == pytest.approx(Z_bp, rel=1e-12)
18
+
19
+
20
+ @pytest.mark.parametrize("damping", [0.0, 0.1])
21
+ def test_contract_normal(damping):
22
+ tn = qtn.TN2D_from_fill_fn(lambda s: qu.randn(s, dist="uniform"), 6, 6, 2)
23
+ Z = tn.contract()
24
+ info = {}
25
+ Z_bp = contract_d1bp(tn, damping=damping, info=info, progbar=True)
26
+ assert info["converged"]
27
+ assert Z == pytest.approx(Z_bp, rel=1e-1)
28
+
29
+
30
+ def test_get_gauged_tn():
31
+ tn = qtn.TN2D_from_fill_fn(lambda s: qu.randn(s, dist="uniform"), 6, 6, 2)
32
+ Z = tn.contract()
33
+ bp = D1BP(tn)
34
+ bp.run()
35
+ Zbp = bp.contract()
36
+ assert Z == pytest.approx(Zbp, rel=1e-1)
37
+ tn_gauged = bp.get_gauged_tn()
38
+ Zg = qu.prod(array.item(0) for array in tn_gauged.arrays)
39
+ assert Z == pytest.approx(Zg, rel=1e-1)
@@ -0,0 +1,67 @@
1
+ import pytest
2
+
3
+ import quimb.tensor as qtn
4
+ from quimb.experimental.belief_propagation.d2bp import (
5
+ compress_d2bp,
6
+ contract_d2bp,
7
+ sample_d2bp,
8
+ )
9
+
10
+
11
+ @pytest.mark.parametrize("damping", [0.0, 0.1])
12
+ @pytest.mark.parametrize("dtype", ["float32", "complex64"])
13
+ def test_contract(damping, dtype):
14
+ peps = qtn.PEPS.rand(3, 4, 3, seed=42, dtype=dtype)
15
+ # normalize exactly
16
+ peps /= (peps.H @ peps) ** 0.5
17
+ info = {}
18
+ N_ap = contract_d2bp(peps, damping=damping, info=info, progbar=True)
19
+ assert info["converged"]
20
+ assert N_ap == pytest.approx(1.0, rel=0.3)
21
+
22
+
23
+ @pytest.mark.parametrize("dtype", ["float32", "complex64"])
24
+ def test_tree_exact(dtype):
25
+ psi = qtn.TN_rand_tree(20, 3, 2, dtype=dtype, seed=42)
26
+ norm2 = psi.H @ psi
27
+ info = {}
28
+ norm2_bp = contract_d2bp(psi, info=info, progbar=True)
29
+ assert info["converged"]
30
+ assert norm2_bp == pytest.approx(norm2, rel=1e-4)
31
+
32
+
33
+ @pytest.mark.parametrize("damping", [0.0, 0.1])
34
+ @pytest.mark.parametrize("dtype", ["float32", "complex64"])
35
+ def test_compress(damping, dtype):
36
+ peps = qtn.PEPS.rand(3, 4, 3, seed=42, dtype=dtype)
37
+ # test that using the BP compression gives better fidelity than purely
38
+ # local, naive compression scheme
39
+ peps_c1 = peps.compress_all(max_bond=2)
40
+ info = {}
41
+ peps_c2 = compress_d2bp(
42
+ peps, max_bond=2, damping=damping, info=info, progbar=True
43
+ )
44
+ assert info["converged"]
45
+ fid1 = peps_c1.H @ peps_c2
46
+ fid2 = peps_c2.H @ peps_c2
47
+ assert abs(fid2) > abs(fid1)
48
+
49
+
50
+ @pytest.mark.parametrize("dtype", ["float32", "complex64"])
51
+ def test_sample(dtype):
52
+ peps = qtn.PEPS.rand(3, 4, 3, seed=42, dtype=dtype)
53
+ # normalize exactly
54
+ peps /= (peps.H @ peps) ** 0.5
55
+ config, peps_config, omega = sample_d2bp(peps, seed=42, progbar=True)
56
+ assert all(ix in config for ix in peps.site_inds)
57
+ assert 0.0 < omega < 1.0
58
+ assert peps_config.outer_inds() == ()
59
+
60
+ ptotal = 0.0
61
+ nrepeat = 4
62
+ for _ in range(nrepeat):
63
+ _, peps_config, _ = sample_d2bp(peps, seed=42, progbar=True)
64
+ ptotal += abs(peps_config.contract()) ** 2
65
+
66
+ # check we are doing better than random guessing
67
+ assert ptotal > nrepeat * 2**-peps.nsites
@@ -0,0 +1,64 @@
1
+ import pytest
2
+
3
+ import quimb as qu
4
+ import quimb.tensor as qtn
5
+ from quimb.experimental.belief_propagation.hd1bp import (
6
+ HD1BP,
7
+ contract_hd1bp,
8
+ sample_hd1bp,
9
+ )
10
+
11
+
12
+ @pytest.mark.parametrize("damping", [0.0, 0.1])
13
+ def test_contract_hyper(damping):
14
+ htn = qtn.HTN_random_ksat(3, 50, alpha=2.0, seed=42, mode="dense")
15
+ info = {}
16
+ num_solutions = contract_hd1bp(
17
+ htn, damping=damping, info=info, progbar=True
18
+ )
19
+ assert info["converged"]
20
+ assert num_solutions == pytest.approx(309273226, rel=0.1)
21
+
22
+
23
+ def test_contract_tree_exact():
24
+ tn = qtn.TN_rand_tree(20, 3)
25
+ Z = tn.contract()
26
+ info = {}
27
+ Z_bp = contract_hd1bp(tn, info=info, progbar=True)
28
+ assert info["converged"]
29
+ assert Z == pytest.approx(Z_bp, rel=1e-12)
30
+
31
+
32
+ @pytest.mark.parametrize("damping", [0.0, 0.1])
33
+ def test_contract_normal(damping):
34
+ tn = qtn.TN2D_from_fill_fn(lambda s: qu.randn(s, dist="uniform"), 6, 6, 2)
35
+ Z = tn.contract()
36
+ info = {}
37
+ Z_bp = contract_hd1bp(tn, damping=damping, info=info, progbar=True)
38
+ assert info["converged"]
39
+ assert Z == pytest.approx(Z_bp, rel=1e-1)
40
+
41
+
42
+ @pytest.mark.parametrize("damping", [0.0, 0.1])
43
+ def test_sample(damping):
44
+ nvars = 20
45
+ htn = qtn.HTN_random_ksat(3, nvars, alpha=2.0, seed=42, mode="dense")
46
+ config, tn_config, omega = sample_hd1bp(
47
+ htn, damping=damping, seed=42, progbar=True
48
+ )
49
+ assert len(config) == nvars
50
+ assert tn_config.num_indices == 0
51
+ assert tn_config.contract() == pytest.approx(1.0)
52
+ assert 0.0 < omega < 1.0
53
+
54
+
55
+ def test_get_gauged_tn():
56
+ tn = qtn.TN2D_from_fill_fn(lambda s: qu.randn(s, dist="uniform"), 6, 6, 2)
57
+ Z = tn.contract()
58
+ bp = HD1BP(tn)
59
+ bp.run()
60
+ Zbp = bp.contract()
61
+ assert Z == pytest.approx(Zbp, rel=1e-1)
62
+ tn_gauged = bp.get_gauged_tn()
63
+ Zg = qu.prod(array.item(0) for array in tn_gauged.arrays)
64
+ assert Z == pytest.approx(Zg, rel=1e-1)
@@ -0,0 +1,51 @@
1
+ import pytest
2
+
3
+ import quimb as qu
4
+ import quimb.tensor as qtn
5
+ from quimb.experimental.belief_propagation.hv1bp import (
6
+ contract_hv1bp,
7
+ sample_hv1bp,
8
+ )
9
+
10
+
11
+ @pytest.mark.parametrize("damping", [0.0, 0.1, 0.5])
12
+ def test_contract_hyper(damping):
13
+ htn = qtn.HTN_random_ksat(3, 50, alpha=2.0, seed=42, mode="dense")
14
+ info = {}
15
+ num_solutions = contract_hv1bp(
16
+ htn, damping=damping, info=info, progbar=True
17
+ )
18
+ assert info["converged"]
19
+ assert num_solutions == pytest.approx(309273226, rel=0.1)
20
+
21
+
22
+ def test_contract_tree_exact():
23
+ tn = qtn.TN_rand_tree(20, 3)
24
+ Z = tn.contract()
25
+ info = {}
26
+ Z_bp = contract_hv1bp(tn, info=info, progbar=True)
27
+ assert info["converged"]
28
+ assert Z == pytest.approx(Z_bp, rel=1e-12)
29
+
30
+
31
+ @pytest.mark.parametrize("damping", [0.0, 0.1, 0.5])
32
+ def test_contract_normal(damping):
33
+ tn = qtn.TN2D_from_fill_fn(lambda s: qu.randn(s, dist="uniform"), 6, 6, 2)
34
+ Z = tn.contract()
35
+ info = {}
36
+ Z_bp = contract_hv1bp(tn, damping=damping, info=info, progbar=True)
37
+ assert info["converged"]
38
+ assert Z == pytest.approx(Z_bp, rel=1e-1)
39
+
40
+
41
+ @pytest.mark.parametrize("damping", [0.0, 0.1])
42
+ def test_sample(damping):
43
+ nvars = 20
44
+ htn = qtn.HTN_random_ksat(3, nvars, alpha=2.0, seed=42, mode="dense")
45
+ config, tn_config, omega = sample_hv1bp(
46
+ htn, damping=damping, seed=42, progbar=True
47
+ )
48
+ assert len(config) == nvars
49
+ assert tn_config.num_indices == 0
50
+ assert tn_config.contract() == pytest.approx(1.0)
51
+ assert 0.0 < omega < 1.0
@@ -0,0 +1,142 @@
1
+ import pytest
2
+
3
+ import quimb as qu
4
+ import quimb.tensor as qtn
5
+ from quimb.experimental.belief_propagation.l1bp import contract_l1bp
6
+ from quimb.experimental.belief_propagation.d2bp import contract_d2bp
7
+
8
+
9
+ @pytest.mark.parametrize("dtype", ["float32", "complex64"])
10
+ def test_contract_tree_exact(dtype):
11
+ tn = qtn.TN_rand_tree(10, 3, seed=42, dtype=dtype)
12
+ Z_ex = tn.contract()
13
+ info = {}
14
+ Z_bp = contract_l1bp(tn, info=info, progbar=True)
15
+ assert info["converged"]
16
+ assert Z_ex == pytest.approx(Z_bp, rel=5e-6)
17
+
18
+
19
+ @pytest.mark.parametrize("dtype", ["float32", "complex64"])
20
+ @pytest.mark.parametrize("damping", [0.0, 0.1])
21
+ def test_contract_loopy_approx(dtype, damping):
22
+ tn = qtn.TN2D_rand(3, 4, 5, dtype=dtype, dist="uniform")
23
+ Z_ex = tn.contract()
24
+ info = {}
25
+ Z_bp = contract_l1bp(tn, damping=damping, info=info, progbar=True)
26
+ assert info["converged"]
27
+ assert Z_ex == pytest.approx(Z_bp, rel=0.1)
28
+
29
+
30
+ @pytest.mark.parametrize("dtype", ["float32", "complex64"])
31
+ @pytest.mark.parametrize("damping", [0.0, 0.1])
32
+ @pytest.mark.parametrize("update", ("parallel", "sequential"))
33
+ def test_contract_double_loopy_approx(dtype, damping, update):
34
+ peps = qtn.PEPS.rand(4, 3, 2, seed=42, dtype=dtype)
35
+ tn = peps.H & peps
36
+ Z_ex = tn.contract()
37
+ info = {}
38
+ Z_bp1 = contract_l1bp(
39
+ tn, damping=damping, update=update, info=info, progbar=True
40
+ )
41
+ assert info["converged"]
42
+ assert Z_bp1 == pytest.approx(Z_ex, rel=0.3)
43
+ # compare with 2-norm BP on the peps directly
44
+ Z_bp2 = contract_d2bp(peps)
45
+ assert Z_bp1 == pytest.approx(Z_bp2, rel=5e-6)
46
+
47
+
48
+ @pytest.mark.parametrize("dtype", ["float32", "complex64"])
49
+ def test_contract_tree_triple_sandwich_exact(dtype):
50
+ edges = qtn.edges_tree_rand(20, 3, seed=42)
51
+ ket = qtn.TN_from_edges_rand(
52
+ edges,
53
+ 3,
54
+ phys_dim=2,
55
+ seed=42,
56
+ site_ind_id="k{}",
57
+ dtype=dtype,
58
+ )
59
+ op = qtn.TN_from_edges_rand(
60
+ edges,
61
+ 2,
62
+ phys_dim=2,
63
+ seed=42,
64
+ site_ind_id=("k{}", "b{}"),
65
+ dtype=dtype,
66
+ )
67
+ bra = qtn.TN_from_edges_rand(
68
+ edges,
69
+ 3,
70
+ phys_dim=2,
71
+ seed=42,
72
+ site_ind_id="b{}",
73
+ dtype=dtype,
74
+ )
75
+ tn = bra.H | op | ket
76
+ Z_ex = tn.contract()
77
+ info = {}
78
+ Z_bp = contract_l1bp(tn, info=info, progbar=True)
79
+ assert info["converged"]
80
+ assert Z_ex == pytest.approx(Z_bp, rel=5e-6)
81
+
82
+
83
+ @pytest.mark.parametrize("dtype", ["float32", "complex64"])
84
+ @pytest.mark.parametrize("damping", [0.0, 0.1])
85
+ def test_contract_tree_triple_sandwich_loopy_approx(dtype, damping):
86
+ edges = qtn.edges_2d_hexagonal(2, 3)
87
+ ket = qtn.TN_from_edges_rand(
88
+ edges,
89
+ 3,
90
+ phys_dim=2,
91
+ seed=42,
92
+ site_ind_id="k{}",
93
+ dtype=dtype,
94
+ # make the wavefunction postive to make easier
95
+ dist="uniform",
96
+ )
97
+ ket /= (ket.H @ ket) ** 0.5
98
+
99
+ G_ket = ket.gate(qu.pauli("Z"), [(1, 1, "A")], propagate_tags="sites")
100
+ tn = ket.H | G_ket
101
+ Z_ex = tn.contract()
102
+ info = {}
103
+ Z_bp = contract_l1bp(tn, damping=damping, info=info, progbar=True)
104
+ assert info["converged"]
105
+ assert Z_bp == pytest.approx(Z_ex, rel=0.5)
106
+
107
+
108
+ def test_contract_cluster_approx():
109
+ tn = qtn.TN2D_classical_ising_partition_function(8, 8, 0.4, h=0.2)
110
+ f_ex = qu.log(tn.contract())
111
+ f_bp = qu.log(contract_l1bp(tn))
112
+ assert f_bp == pytest.approx(f_ex, rel=0.3)
113
+ cluster_tags = []
114
+ for i in range(0, 8, 2):
115
+ for j in range(0, 8, 2):
116
+ cluster_tag = f"C{i},{j}"
117
+ tn[i, j].add_tag(cluster_tag)
118
+ tn[i, j + 1].add_tag(cluster_tag)
119
+ tn[i + 1, j].add_tag(cluster_tag)
120
+ tn[i + 1, j + 1].add_tag(cluster_tag)
121
+ cluster_tags.append(cluster_tag)
122
+ info = {}
123
+ f_bp2 = qu.log(
124
+ contract_l1bp(tn, site_tags=cluster_tags, info=info, progbar=True)
125
+ )
126
+ assert info["converged"]
127
+ assert f_bp == pytest.approx(f_ex, rel=0.1)
128
+ assert abs(1 - f_ex / f_bp2) < abs(1 - f_ex / f_bp)
129
+
130
+
131
+ def test_mps():
132
+ # catch bug to do with structured contract and output inds
133
+ L = 6
134
+ psi = qtn.MPS_rand_state(L=L, seed=20, bond_dim=3)
135
+ psiG = psi.copy()
136
+ psiG.gate_(qu.pauli("X"), 5, contract=True)
137
+ expec = psi.H & psiG
138
+ O = contract_l1bp(
139
+ expec,
140
+ site_tags=[f"I{i}" for i in range(L)],
141
+ )
142
+ assert O == pytest.approx(expec ^ ..., abs=1e-6)