Trajectree 0.0.1__py3-none-any.whl → 0.0.3__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.
- trajectree/__init__.py +0 -3
- trajectree/fock_optics/devices.py +1 -1
- trajectree/fock_optics/light_sources.py +2 -2
- trajectree/fock_optics/measurement.py +9 -9
- trajectree/fock_optics/outputs.py +10 -6
- trajectree/fock_optics/utils.py +9 -6
- trajectree/sequence/swap.py +5 -4
- trajectree/trajectory.py +5 -4
- {trajectree-0.0.1.dist-info → trajectree-0.0.3.dist-info}/METADATA +2 -3
- trajectree-0.0.3.dist-info/RECORD +16 -0
- trajectree/quimb/docs/_pygments/_pygments_dark.py +0 -118
- trajectree/quimb/docs/_pygments/_pygments_light.py +0 -118
- trajectree/quimb/docs/conf.py +0 -158
- trajectree/quimb/docs/examples/ex_mpi_expm_evo.py +0 -62
- trajectree/quimb/quimb/__init__.py +0 -507
- trajectree/quimb/quimb/calc.py +0 -1491
- trajectree/quimb/quimb/core.py +0 -2279
- trajectree/quimb/quimb/evo.py +0 -712
- trajectree/quimb/quimb/experimental/__init__.py +0 -0
- trajectree/quimb/quimb/experimental/autojittn.py +0 -129
- trajectree/quimb/quimb/experimental/belief_propagation/__init__.py +0 -109
- trajectree/quimb/quimb/experimental/belief_propagation/bp_common.py +0 -397
- trajectree/quimb/quimb/experimental/belief_propagation/d1bp.py +0 -316
- trajectree/quimb/quimb/experimental/belief_propagation/d2bp.py +0 -653
- trajectree/quimb/quimb/experimental/belief_propagation/hd1bp.py +0 -571
- trajectree/quimb/quimb/experimental/belief_propagation/hv1bp.py +0 -775
- trajectree/quimb/quimb/experimental/belief_propagation/l1bp.py +0 -316
- trajectree/quimb/quimb/experimental/belief_propagation/l2bp.py +0 -537
- trajectree/quimb/quimb/experimental/belief_propagation/regions.py +0 -194
- trajectree/quimb/quimb/experimental/cluster_update.py +0 -286
- trajectree/quimb/quimb/experimental/merabuilder.py +0 -865
- trajectree/quimb/quimb/experimental/operatorbuilder/__init__.py +0 -15
- trajectree/quimb/quimb/experimental/operatorbuilder/operatorbuilder.py +0 -1631
- trajectree/quimb/quimb/experimental/schematic.py +0 -7
- trajectree/quimb/quimb/experimental/tn_marginals.py +0 -130
- trajectree/quimb/quimb/experimental/tnvmc.py +0 -1483
- trajectree/quimb/quimb/gates.py +0 -36
- trajectree/quimb/quimb/gen/__init__.py +0 -2
- trajectree/quimb/quimb/gen/operators.py +0 -1167
- trajectree/quimb/quimb/gen/rand.py +0 -713
- trajectree/quimb/quimb/gen/states.py +0 -479
- trajectree/quimb/quimb/linalg/__init__.py +0 -6
- trajectree/quimb/quimb/linalg/approx_spectral.py +0 -1109
- trajectree/quimb/quimb/linalg/autoblock.py +0 -258
- trajectree/quimb/quimb/linalg/base_linalg.py +0 -719
- trajectree/quimb/quimb/linalg/mpi_launcher.py +0 -397
- trajectree/quimb/quimb/linalg/numpy_linalg.py +0 -244
- trajectree/quimb/quimb/linalg/rand_linalg.py +0 -514
- trajectree/quimb/quimb/linalg/scipy_linalg.py +0 -293
- trajectree/quimb/quimb/linalg/slepc_linalg.py +0 -892
- trajectree/quimb/quimb/schematic.py +0 -1518
- trajectree/quimb/quimb/tensor/__init__.py +0 -401
- trajectree/quimb/quimb/tensor/array_ops.py +0 -610
- trajectree/quimb/quimb/tensor/circuit.py +0 -4824
- trajectree/quimb/quimb/tensor/circuit_gen.py +0 -411
- trajectree/quimb/quimb/tensor/contraction.py +0 -336
- trajectree/quimb/quimb/tensor/decomp.py +0 -1255
- trajectree/quimb/quimb/tensor/drawing.py +0 -1646
- trajectree/quimb/quimb/tensor/fitting.py +0 -385
- trajectree/quimb/quimb/tensor/geometry.py +0 -583
- trajectree/quimb/quimb/tensor/interface.py +0 -114
- trajectree/quimb/quimb/tensor/networking.py +0 -1058
- trajectree/quimb/quimb/tensor/optimize.py +0 -1818
- trajectree/quimb/quimb/tensor/tensor_1d.py +0 -4778
- trajectree/quimb/quimb/tensor/tensor_1d_compress.py +0 -1854
- trajectree/quimb/quimb/tensor/tensor_1d_tebd.py +0 -662
- trajectree/quimb/quimb/tensor/tensor_2d.py +0 -5954
- trajectree/quimb/quimb/tensor/tensor_2d_compress.py +0 -96
- trajectree/quimb/quimb/tensor/tensor_2d_tebd.py +0 -1230
- trajectree/quimb/quimb/tensor/tensor_3d.py +0 -2869
- trajectree/quimb/quimb/tensor/tensor_3d_tebd.py +0 -46
- trajectree/quimb/quimb/tensor/tensor_approx_spectral.py +0 -60
- trajectree/quimb/quimb/tensor/tensor_arbgeom.py +0 -3237
- trajectree/quimb/quimb/tensor/tensor_arbgeom_compress.py +0 -565
- trajectree/quimb/quimb/tensor/tensor_arbgeom_tebd.py +0 -1138
- trajectree/quimb/quimb/tensor/tensor_builder.py +0 -5411
- trajectree/quimb/quimb/tensor/tensor_core.py +0 -11179
- trajectree/quimb/quimb/tensor/tensor_dmrg.py +0 -1472
- trajectree/quimb/quimb/tensor/tensor_mera.py +0 -204
- trajectree/quimb/quimb/utils.py +0 -892
- trajectree/quimb/tests/__init__.py +0 -0
- trajectree/quimb/tests/test_accel.py +0 -501
- trajectree/quimb/tests/test_calc.py +0 -788
- trajectree/quimb/tests/test_core.py +0 -847
- trajectree/quimb/tests/test_evo.py +0 -565
- trajectree/quimb/tests/test_gen/__init__.py +0 -0
- trajectree/quimb/tests/test_gen/test_operators.py +0 -361
- trajectree/quimb/tests/test_gen/test_rand.py +0 -296
- trajectree/quimb/tests/test_gen/test_states.py +0 -261
- trajectree/quimb/tests/test_linalg/__init__.py +0 -0
- trajectree/quimb/tests/test_linalg/test_approx_spectral.py +0 -368
- trajectree/quimb/tests/test_linalg/test_base_linalg.py +0 -351
- trajectree/quimb/tests/test_linalg/test_mpi_linalg.py +0 -127
- trajectree/quimb/tests/test_linalg/test_numpy_linalg.py +0 -84
- trajectree/quimb/tests/test_linalg/test_rand_linalg.py +0 -134
- trajectree/quimb/tests/test_linalg/test_slepc_linalg.py +0 -283
- trajectree/quimb/tests/test_tensor/__init__.py +0 -0
- trajectree/quimb/tests/test_tensor/test_belief_propagation/__init__.py +0 -0
- trajectree/quimb/tests/test_tensor/test_belief_propagation/test_d1bp.py +0 -39
- trajectree/quimb/tests/test_tensor/test_belief_propagation/test_d2bp.py +0 -67
- trajectree/quimb/tests/test_tensor/test_belief_propagation/test_hd1bp.py +0 -64
- trajectree/quimb/tests/test_tensor/test_belief_propagation/test_hv1bp.py +0 -51
- trajectree/quimb/tests/test_tensor/test_belief_propagation/test_l1bp.py +0 -142
- trajectree/quimb/tests/test_tensor/test_belief_propagation/test_l2bp.py +0 -101
- trajectree/quimb/tests/test_tensor/test_circuit.py +0 -816
- trajectree/quimb/tests/test_tensor/test_contract.py +0 -67
- trajectree/quimb/tests/test_tensor/test_decomp.py +0 -40
- trajectree/quimb/tests/test_tensor/test_mera.py +0 -52
- trajectree/quimb/tests/test_tensor/test_optimizers.py +0 -488
- trajectree/quimb/tests/test_tensor/test_tensor_1d.py +0 -1171
- trajectree/quimb/tests/test_tensor/test_tensor_2d.py +0 -606
- trajectree/quimb/tests/test_tensor/test_tensor_2d_tebd.py +0 -144
- trajectree/quimb/tests/test_tensor/test_tensor_3d.py +0 -123
- trajectree/quimb/tests/test_tensor/test_tensor_arbgeom.py +0 -226
- trajectree/quimb/tests/test_tensor/test_tensor_builder.py +0 -441
- trajectree/quimb/tests/test_tensor/test_tensor_core.py +0 -2066
- trajectree/quimb/tests/test_tensor/test_tensor_dmrg.py +0 -388
- trajectree/quimb/tests/test_tensor/test_tensor_spectral_approx.py +0 -63
- trajectree/quimb/tests/test_tensor/test_tensor_tebd.py +0 -270
- trajectree/quimb/tests/test_utils.py +0 -85
- trajectree-0.0.1.dist-info/RECORD +0 -126
- {trajectree-0.0.1.dist-info → trajectree-0.0.3.dist-info}/WHEEL +0 -0
- {trajectree-0.0.1.dist-info → trajectree-0.0.3.dist-info}/licenses/LICENSE +0 -0
- {trajectree-0.0.1.dist-info → trajectree-0.0.3.dist-info}/top_level.txt +0 -0
|
@@ -1,847 +0,0 @@
|
|
|
1
|
-
import itertools
|
|
2
|
-
|
|
3
|
-
from pytest import fixture, raises, mark
|
|
4
|
-
import scipy.sparse as sp
|
|
5
|
-
import numpy as np
|
|
6
|
-
from numpy.testing import assert_allclose, assert_almost_equal
|
|
7
|
-
|
|
8
|
-
import quimb as qu
|
|
9
|
-
|
|
10
|
-
stypes = ("csr", "csc", "bsr", "coo")
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
@fixture
|
|
14
|
-
def od1():
|
|
15
|
-
return qu.rand_matrix(3)
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
@fixture
|
|
19
|
-
def os1():
|
|
20
|
-
return qu.rand_matrix(3, sparse=True, density=0.5)
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
class TestSparseMatrix:
|
|
24
|
-
@mark.parametrize("stype", stypes)
|
|
25
|
-
def test_simple(self, stype):
|
|
26
|
-
a = qu.core.sparse_matrix([[0, 3], [1, 2]], stype)
|
|
27
|
-
assert a.format == stype
|
|
28
|
-
assert a.dtype == complex
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
class TestQuimbify:
|
|
32
|
-
def test_vector_create(self):
|
|
33
|
-
x = [1, 2, 3j]
|
|
34
|
-
p = qu.qu(x, qtype="ket")
|
|
35
|
-
assert type(p) == qu.qarray
|
|
36
|
-
assert p.dtype == complex
|
|
37
|
-
assert p.shape == (3, 1)
|
|
38
|
-
p = qu.qu(x, qtype="bra")
|
|
39
|
-
assert p.shape == (1, 3)
|
|
40
|
-
assert_almost_equal(p[0, 2], -3.0j)
|
|
41
|
-
|
|
42
|
-
def test_dop_create(self):
|
|
43
|
-
x = np.random.randn(3, 3)
|
|
44
|
-
p = qu.qu(x, qtype="dop")
|
|
45
|
-
assert type(p) == qu.qarray
|
|
46
|
-
assert p.dtype == complex
|
|
47
|
-
assert p.shape == (3, 3)
|
|
48
|
-
|
|
49
|
-
def test_convert_vector_to_dop(self):
|
|
50
|
-
x = [1, 2, 3j]
|
|
51
|
-
p = qu.qu(x, qtype="r")
|
|
52
|
-
assert_allclose(
|
|
53
|
-
p,
|
|
54
|
-
qu.qarray(
|
|
55
|
-
[
|
|
56
|
-
[1.0 + 0.0j, 2.0 + 0.0j, 0.0 - 3.0j],
|
|
57
|
-
[2.0 + 0.0j, 4.0 + 0.0j, 0.0 - 6.0j],
|
|
58
|
-
[0.0 + 3.0j, 0.0 + 6.0j, 9.0 + 0.0j],
|
|
59
|
-
]
|
|
60
|
-
),
|
|
61
|
-
)
|
|
62
|
-
|
|
63
|
-
def test_chopped(self):
|
|
64
|
-
x = [9e-16, 1]
|
|
65
|
-
p = qu.qu(x, "k", chopped=False)
|
|
66
|
-
assert p[0, 0] != 0.0
|
|
67
|
-
p = qu.qu(x, "k", chopped=True)
|
|
68
|
-
assert p[0, 0] == 0.0
|
|
69
|
-
|
|
70
|
-
def test_normalized(self):
|
|
71
|
-
x = [3j, 4j]
|
|
72
|
-
p = qu.qu(x, "k", normalized=False)
|
|
73
|
-
assert_almost_equal(qu.tr(p.H @ p), 25.0)
|
|
74
|
-
p = qu.qu(x, "k", normalized=True)
|
|
75
|
-
assert_almost_equal(qu.tr(p.H @ p), 1.0)
|
|
76
|
-
p = qu.qu(x, "dop", normalized=True)
|
|
77
|
-
assert_almost_equal(qu.tr(p), 1.0)
|
|
78
|
-
|
|
79
|
-
def test_sparse_create(self):
|
|
80
|
-
x = [[1, 0], [3, 0]]
|
|
81
|
-
p = qu.qu(x, "dop", sparse=False)
|
|
82
|
-
assert type(p) == qu.qarray
|
|
83
|
-
p = qu.qu(x, "dop", sparse=True)
|
|
84
|
-
assert type(p) == sp.csr_matrix
|
|
85
|
-
assert p.dtype == complex
|
|
86
|
-
assert p.nnz == 2
|
|
87
|
-
|
|
88
|
-
def test_sparse_convert_to_dop(self):
|
|
89
|
-
x = [1, 0, 9e-16, 0, 3j]
|
|
90
|
-
p = qu.qu(x, "ket", sparse=True)
|
|
91
|
-
q = qu.qu(p, "dop", sparse=True)
|
|
92
|
-
assert q.shape == (5, 5)
|
|
93
|
-
assert q.nnz == 9
|
|
94
|
-
assert_almost_equal(q[4, 4], 9.0)
|
|
95
|
-
q = qu.qu(p, "dop", sparse=True, normalized=True)
|
|
96
|
-
assert_almost_equal(qu.tr(q), 1.0)
|
|
97
|
-
|
|
98
|
-
@mark.parametrize(
|
|
99
|
-
"qtype, shape, out",
|
|
100
|
-
(
|
|
101
|
-
("bra", (1, 4), [[1, 0, 2, -3j]]),
|
|
102
|
-
("ket", (4, 1), [[1], [0], [2], [3j]]),
|
|
103
|
-
(
|
|
104
|
-
"dop",
|
|
105
|
-
(4, 4),
|
|
106
|
-
[[1, 0, 2, -3j], [0, 0, 0, 0], [2, 0, 4, -6j], [3j, 0, 6j, 9]],
|
|
107
|
-
),
|
|
108
|
-
),
|
|
109
|
-
)
|
|
110
|
-
@mark.parametrize("format_in", stypes)
|
|
111
|
-
@mark.parametrize("format_out", (None,) + stypes)
|
|
112
|
-
@mark.parametrize("dtype", [float, complex, np.float64, np.complex128])
|
|
113
|
-
def test_reshape_sparse(
|
|
114
|
-
self, qtype, shape, out, format_in, format_out, dtype
|
|
115
|
-
):
|
|
116
|
-
import warnings
|
|
117
|
-
|
|
118
|
-
in_ = [[1], [0], [2], [3j]]
|
|
119
|
-
x = qu.core.sparse_matrix(in_, stype=format_in)
|
|
120
|
-
|
|
121
|
-
with warnings.catch_warnings():
|
|
122
|
-
warnings.simplefilter("ignore")
|
|
123
|
-
y = qu.qu(x, qtype=qtype, stype=format_out, dtype=dtype)
|
|
124
|
-
|
|
125
|
-
assert y.shape == shape
|
|
126
|
-
assert y.dtype == dtype
|
|
127
|
-
if format_out is None:
|
|
128
|
-
format_out = format_in
|
|
129
|
-
assert y.format == format_out
|
|
130
|
-
|
|
131
|
-
if np.issubdtype(dtype, np.floating):
|
|
132
|
-
assert_allclose(y.toarray(), np.real(out), atol=1e-12)
|
|
133
|
-
else:
|
|
134
|
-
assert_allclose(y.toarray(), out)
|
|
135
|
-
|
|
136
|
-
@mark.parametrize(
|
|
137
|
-
"qtype, shape, out",
|
|
138
|
-
(
|
|
139
|
-
("bra", (1, 4), [[1, 0, 2, -3j]]),
|
|
140
|
-
("ket", (4, 1), [[1], [0], [2], [3j]]),
|
|
141
|
-
(
|
|
142
|
-
"dop",
|
|
143
|
-
(4, 4),
|
|
144
|
-
[[1, 0, 2, -3j], [0, 0, 0, 0], [2, 0, 4, -6j], [3j, 0, 6j, 9]],
|
|
145
|
-
),
|
|
146
|
-
),
|
|
147
|
-
)
|
|
148
|
-
@mark.parametrize("format_out", (None,) + stypes)
|
|
149
|
-
def test_dense_to_sparse_format(self, qtype, shape, out, format_out):
|
|
150
|
-
x = [[1], [0], [2], [3j]]
|
|
151
|
-
y = qu.qu(x, qtype=qtype, stype=format_out, sparse=True)
|
|
152
|
-
assert y.shape == shape
|
|
153
|
-
assert y.dtype == complex
|
|
154
|
-
if format_out is None:
|
|
155
|
-
format_out = "csr"
|
|
156
|
-
assert y.format == format_out
|
|
157
|
-
assert_allclose(y.toarray(), out)
|
|
158
|
-
|
|
159
|
-
@mark.parametrize(
|
|
160
|
-
"qtype, shape", (["bra", (1, 4)], ["ket", (4, 1)], ["dop", (4, 4)])
|
|
161
|
-
)
|
|
162
|
-
@mark.parametrize("format_out", stypes)
|
|
163
|
-
def test_give_sformat_only(self, qtype, shape, format_out):
|
|
164
|
-
x = [[1], [0], [2], [3j]]
|
|
165
|
-
y = qu.qu(x, qtype=qtype, stype=format_out)
|
|
166
|
-
assert qu.issparse(y)
|
|
167
|
-
assert y.shape == shape
|
|
168
|
-
assert y.format == format_out
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
class TestInferSize:
|
|
172
|
-
@mark.parametrize(
|
|
173
|
-
"d,base,n", ([8, 2, 3], [16, 2, 4], [9, 3, 2], [81, 3, 4])
|
|
174
|
-
)
|
|
175
|
-
def test_infer_size(self, d, base, n):
|
|
176
|
-
p = qu.rand_ket(d)
|
|
177
|
-
assert qu.infer_size(p, base) == n
|
|
178
|
-
|
|
179
|
-
def test_raises(self):
|
|
180
|
-
p = qu.rand_ket(2) & qu.rand_ket(3)
|
|
181
|
-
with raises(ValueError):
|
|
182
|
-
qu.infer_size(p, base=2)
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
class TestTrace:
|
|
186
|
-
@mark.parametrize(
|
|
187
|
-
"inpt, outpt", ([[[2, 1], [4, 5]], 7], [[[2, 1], [4, 5j]], 2 + 5j])
|
|
188
|
-
)
|
|
189
|
-
@mark.parametrize(
|
|
190
|
-
"sparse, func",
|
|
191
|
-
([False, qu.core._trace_dense], [True, qu.core._trace_sparse]),
|
|
192
|
-
)
|
|
193
|
-
def test_simple(self, inpt, outpt, sparse, func):
|
|
194
|
-
a = qu.qu(inpt, sparse=sparse)
|
|
195
|
-
assert qu.trace(a) == outpt
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
class TestITrace:
|
|
199
|
-
@mark.parametrize("axes", [(0, 1), ((0,), (1,))])
|
|
200
|
-
def test_axes_types(self, axes):
|
|
201
|
-
a = qu.rand_matrix(4)
|
|
202
|
-
b = qu.itrace(a, axes)
|
|
203
|
-
assert_allclose(b, np.trace(a))
|
|
204
|
-
|
|
205
|
-
def test_complex_dims(self):
|
|
206
|
-
a = np.random.rand(4, 3, 2, 2, 4, 3)
|
|
207
|
-
atr = qu.itrace(a, ((0, 1, 2), (4, 5, 3)))
|
|
208
|
-
btr = np.trace(
|
|
209
|
-
np.trace(np.trace(a, axis1=1, axis2=5), axis1=1, axis2=2)
|
|
210
|
-
)
|
|
211
|
-
assert_allclose(atr, btr)
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
class TestNormalize:
|
|
215
|
-
def test_normalize_ket(self):
|
|
216
|
-
a = qu.qu([1, -1j], "ket")
|
|
217
|
-
b = qu.nmlz(a, inplace=False)
|
|
218
|
-
assert_almost_equal(qu.trace(b.H @ b), 1.0)
|
|
219
|
-
assert_almost_equal(qu.trace(a.H @ a), 2.0)
|
|
220
|
-
|
|
221
|
-
def test_normalize_bra(self):
|
|
222
|
-
a = qu.qu([1, -1j], "bra")
|
|
223
|
-
b = qu.nmlz(a, inplace=False)
|
|
224
|
-
assert_almost_equal(qu.trace(b @ b.H), 1.0)
|
|
225
|
-
|
|
226
|
-
def test_normalize_dop(self):
|
|
227
|
-
a = qu.qu([1, -1j], "dop")
|
|
228
|
-
b = qu.nmlz(a, inplace=False)
|
|
229
|
-
assert_almost_equal(qu.trace(b), 1.0)
|
|
230
|
-
|
|
231
|
-
def test_normalize_inplace_ket(self):
|
|
232
|
-
a = qu.qu([1, -1j], "ket")
|
|
233
|
-
a.nmlz(inplace=True)
|
|
234
|
-
assert_almost_equal(qu.trace(a.H @ a), 1.0)
|
|
235
|
-
|
|
236
|
-
def test_normalize_inplace_bra(self):
|
|
237
|
-
a = qu.qu([1, -1j], "bra")
|
|
238
|
-
a.nmlz(inplace=True)
|
|
239
|
-
assert_almost_equal(qu.trace(a @ a.H), 1.0)
|
|
240
|
-
|
|
241
|
-
def test_normalize_inplace_dop(self):
|
|
242
|
-
a = qu.qu([1, -1j], "dop")
|
|
243
|
-
b = qu.nmlz(a, inplace=True)
|
|
244
|
-
assert_almost_equal(qu.trace(a), 1.0)
|
|
245
|
-
assert_almost_equal(qu.trace(b), 1.0)
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
class TestDimMap:
|
|
249
|
-
@mark.parametrize("numpy", [False, True])
|
|
250
|
-
def test_1d(self, numpy):
|
|
251
|
-
dims = [10, 11, 12, 13]
|
|
252
|
-
coos = (1, 2, 3)
|
|
253
|
-
if numpy:
|
|
254
|
-
dims, coos = np.asarray(dims), np.asarray(coos)
|
|
255
|
-
ndims, ncoos = qu.dim_map(dims, coos)
|
|
256
|
-
assert_allclose([ndims[c] for c in ncoos], (11, 12, 13))
|
|
257
|
-
coos = ([-1], [2], [5])
|
|
258
|
-
with raises(ValueError):
|
|
259
|
-
ndims, ncoos = qu.dim_map(dims, coos)
|
|
260
|
-
ndims, ncoos = qu.dim_map(dims, coos, cyclic=True)
|
|
261
|
-
assert_allclose([ndims[c] for c in ncoos], (13, 12, 11))
|
|
262
|
-
ndims, ncoos = qu.dim_map(dims, coos, trim=True)
|
|
263
|
-
assert_allclose([ndims[c] for c in ncoos], [12])
|
|
264
|
-
|
|
265
|
-
def test_2d(self):
|
|
266
|
-
dims = [[200, 201, 202, 203], [210, 211, 212, 213]]
|
|
267
|
-
coos = ((1, 2), (1, 3), (0, 3))
|
|
268
|
-
ndims, ncoos = qu.dim_map(dims, coos)
|
|
269
|
-
assert_allclose([ndims[c] for c in ncoos], (212, 213, 203))
|
|
270
|
-
coos = ((-1, 1), (1, 2), (3, 4))
|
|
271
|
-
with raises(ValueError):
|
|
272
|
-
ndims, ncoos = qu.dim_map(dims, coos)
|
|
273
|
-
ndims, ncoos = qu.dim_map(dims, coos, cyclic=True)
|
|
274
|
-
assert_allclose([ndims[c] for c in ncoos], (211, 212, 210))
|
|
275
|
-
ndims, ncoos = qu.dim_map(dims, coos, trim=True)
|
|
276
|
-
assert_allclose([ndims[c] for c in ncoos], [212])
|
|
277
|
-
|
|
278
|
-
def test_3d(self):
|
|
279
|
-
dims = [
|
|
280
|
-
[[3000, 3001, 3002], [3010, 3011, 3012], [3020, 3021, 3022]],
|
|
281
|
-
[[3100, 3101, 3102], [3110, 3111, 3112], [3120, 3121, 3122]],
|
|
282
|
-
]
|
|
283
|
-
coos = ((0, 0, 2), (1, 1, 2), (1, 2, 0))
|
|
284
|
-
ndims, ncoos = qu.dim_map(dims, coos)
|
|
285
|
-
assert_allclose([ndims[c] for c in ncoos], (3002, 3112, 3120))
|
|
286
|
-
coos = ((0, -1, 2), (1, 2, 2), (4, -1, 3))
|
|
287
|
-
with raises(ValueError):
|
|
288
|
-
ndims, ncoos = qu.dim_map(dims, coos)
|
|
289
|
-
ndims, ncoos = qu.dim_map(dims, coos, cyclic=True)
|
|
290
|
-
assert_allclose([ndims[c] for c in ncoos], (3022, 3122, 3020))
|
|
291
|
-
ndims, ncoos = qu.dim_map(dims, coos, trim=True)
|
|
292
|
-
assert_allclose([ndims[c] for c in ncoos], [3122])
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
class TestDimCompress:
|
|
296
|
-
def test_edge(self):
|
|
297
|
-
dims = [2, 3, 2, 4, 5]
|
|
298
|
-
coos = [0, 4]
|
|
299
|
-
ndims, ncoos = qu.dim_compress(dims, coos)
|
|
300
|
-
assert ndims == (2, 24, 5)
|
|
301
|
-
assert ncoos == (0, 2)
|
|
302
|
-
|
|
303
|
-
def test_middle(self):
|
|
304
|
-
dims = [5, 3, 2, 5, 4, 3, 2]
|
|
305
|
-
coos = [1, 2, 3, 5]
|
|
306
|
-
ndims, ncoos = qu.dim_compress(dims, coos)
|
|
307
|
-
assert ndims == (5, 30, 4, 3, 2)
|
|
308
|
-
assert ncoos == (1, 3)
|
|
309
|
-
|
|
310
|
-
def test_single(self):
|
|
311
|
-
dims = [5, 3, 2, 5, 4, 3, 2]
|
|
312
|
-
coos = 3
|
|
313
|
-
ndims, ncoos = qu.dim_compress(dims, coos)
|
|
314
|
-
assert ndims == (30, 5, 24)
|
|
315
|
-
assert ncoos == (1,)
|
|
316
|
-
|
|
317
|
-
@mark.parametrize(
|
|
318
|
-
"dims, inds, ndims, ninds",
|
|
319
|
-
[([2, 2], [0, 1], (4,), (0,)), ([4], [0], (4,), (0,))],
|
|
320
|
-
)
|
|
321
|
-
def test_tiny(self, dims, inds, ndims, ninds):
|
|
322
|
-
dims, inds = qu.dim_compress(dims, inds)
|
|
323
|
-
assert dims == ndims
|
|
324
|
-
assert inds == ninds
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
class TestEye:
|
|
328
|
-
def test_eye_dense(self):
|
|
329
|
-
a = qu.eye(3, sparse=False)
|
|
330
|
-
assert a.shape == (3, 3)
|
|
331
|
-
assert isinstance(a, qu.qarray)
|
|
332
|
-
assert a.dtype == complex
|
|
333
|
-
|
|
334
|
-
def test_eye_sparse(self):
|
|
335
|
-
a = qu.eye(3, sparse=True)
|
|
336
|
-
assert a.shape == (3, 3)
|
|
337
|
-
assert isinstance(a, sp.csr_matrix)
|
|
338
|
-
assert a.dtype == complex
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
class TestKron:
|
|
342
|
-
@mark.parametrize("parallel", [True, False])
|
|
343
|
-
def test_kron_basic(self, parallel):
|
|
344
|
-
a = qu.rand_ket(2)
|
|
345
|
-
b = qu.rand_ket(4)
|
|
346
|
-
c = qu.rand_ket(4)
|
|
347
|
-
d = qu.rand_ket(5)
|
|
348
|
-
t = qu.kron(a, b, c, d, parallel=parallel)
|
|
349
|
-
assert_allclose(t, a & b & c & d)
|
|
350
|
-
|
|
351
|
-
@mark.parametrize("sparse", [True, False])
|
|
352
|
-
@mark.parametrize("ri,rf", ([0, 4], [75, 89], [150, 168], [0, 168]))
|
|
353
|
-
def test_kron_ownership(self, sparse, ri, rf):
|
|
354
|
-
dims = [7, 2, 4, 3]
|
|
355
|
-
ops = [qu.rand_matrix(d, sparse=sparse) for d in dims]
|
|
356
|
-
X1 = qu.kron(*ops)[ri:rf, :]
|
|
357
|
-
X2 = qu.kron(*ops, ownership=(ri, rf))
|
|
358
|
-
assert_allclose(X1.toarray(), X2.toarray())
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
class Testikron:
|
|
362
|
-
def test_basic(self):
|
|
363
|
-
a = qu.rand_matrix(2)
|
|
364
|
-
i = qu.eye(2)
|
|
365
|
-
dims = [2, 2, 2]
|
|
366
|
-
b = qu.ikron([a], dims, [0])
|
|
367
|
-
assert_allclose(b, a & i & i)
|
|
368
|
-
b = qu.ikron([a], dims, [1])
|
|
369
|
-
assert_allclose(b, i & a & i)
|
|
370
|
-
b = qu.ikron([a], dims, [2])
|
|
371
|
-
assert_allclose(b, i & i & a)
|
|
372
|
-
b = qu.ikron([a], dims, [0, 2])
|
|
373
|
-
assert_allclose(b, a & i & a)
|
|
374
|
-
b = qu.ikron([a], dims, [0, 1, 2])
|
|
375
|
-
assert_allclose(b, a & a & a)
|
|
376
|
-
|
|
377
|
-
def test_mid_multi(self):
|
|
378
|
-
a = [qu.rand_matrix(2) for i in range(3)]
|
|
379
|
-
i = qu.eye(2)
|
|
380
|
-
dims = [2, 2, 2, 2, 2, 2]
|
|
381
|
-
inds = [1, 2, 4]
|
|
382
|
-
b = qu.ikron(a, dims, inds)
|
|
383
|
-
assert_allclose(b, i & a[0] & a[1] & i & a[2] & i)
|
|
384
|
-
|
|
385
|
-
def test_mid_multi_reverse(self):
|
|
386
|
-
a = [qu.rand_matrix(2) for i in range(3)]
|
|
387
|
-
i = qu.eye(2)
|
|
388
|
-
dims = [2, 2, 2, 2, 2, 2]
|
|
389
|
-
inds = [5, 4, 1]
|
|
390
|
-
b = qu.ikron(a, dims, inds)
|
|
391
|
-
assert_allclose(b, i & a[2] & i & i & a[1] & a[0])
|
|
392
|
-
|
|
393
|
-
def test_auto(self):
|
|
394
|
-
a = qu.rand_matrix(2)
|
|
395
|
-
i = qu.eye(2)
|
|
396
|
-
b = qu.ikron([a], (2, -1, 2), [1])
|
|
397
|
-
assert_allclose(b, i & a & i)
|
|
398
|
-
|
|
399
|
-
def test_ndarrays(self):
|
|
400
|
-
a = qu.rand_matrix(2)
|
|
401
|
-
i = qu.eye(2)
|
|
402
|
-
b = qu.ikron([a], np.array([2, 2, 2]), [0, 2])
|
|
403
|
-
assert_allclose(b, a & i & a)
|
|
404
|
-
b = qu.ikron([a], [2, 2, 2], np.array([0, 2]))
|
|
405
|
-
assert_allclose(b, a & i & a)
|
|
406
|
-
|
|
407
|
-
def test_overlap(self):
|
|
408
|
-
a = [qu.rand_matrix(4) for i in range(2)]
|
|
409
|
-
dims1 = [2, 2, 2, 2, 2, 2]
|
|
410
|
-
dims2 = [2, 4, 4, 2]
|
|
411
|
-
b = qu.ikron(a, dims1, [1, 2, 3, 4])
|
|
412
|
-
c = qu.ikron(a, dims2, [1, 2])
|
|
413
|
-
assert_allclose(c, b)
|
|
414
|
-
dims2 = [4, 2, 2, 4]
|
|
415
|
-
b = qu.ikron(a, dims1, [0, 1, 4, 5])
|
|
416
|
-
c = qu.ikron(a, dims2, [0, 3])
|
|
417
|
-
assert_allclose(c, b)
|
|
418
|
-
|
|
419
|
-
def test_holey_overlap(self):
|
|
420
|
-
a = qu.rand_matrix(8)
|
|
421
|
-
dims1 = (2, 2, 2, 2, 2)
|
|
422
|
-
dims2 = (2, 8, 2)
|
|
423
|
-
b = qu.ikron(a, dims1, (1, 3))
|
|
424
|
-
c = qu.ikron(a, dims2, 1)
|
|
425
|
-
assert_allclose(b, c)
|
|
426
|
-
dims1 = (2, 2, 2, 2, 2)
|
|
427
|
-
dims2 = (2, 2, 8)
|
|
428
|
-
b = qu.ikron(a, dims1, (2, 4))
|
|
429
|
-
c = qu.ikron(a, dims2, 2)
|
|
430
|
-
assert_allclose(b, c)
|
|
431
|
-
dims1 = (2, 2, 2, 2, 2)
|
|
432
|
-
dims2 = (8, 2, 2)
|
|
433
|
-
b = qu.ikron(a, dims1, (0, 2))
|
|
434
|
-
c = qu.ikron(a, dims2, 0)
|
|
435
|
-
assert_allclose(b, c)
|
|
436
|
-
|
|
437
|
-
def test_sparse(self):
|
|
438
|
-
i = qu.eye(2, sparse=True)
|
|
439
|
-
a = qu.qu(qu.rand_matrix(2), sparse=True)
|
|
440
|
-
b = qu.ikron(a, [2, 2, 2], 1) # infer sparse
|
|
441
|
-
assert qu.issparse(b)
|
|
442
|
-
assert_allclose(b.toarray(), (i & a & i).toarray())
|
|
443
|
-
a = qu.rand_matrix(2)
|
|
444
|
-
b = qu.ikron(a, [2, 2, 2], 1, sparse=True) # explicit sparse
|
|
445
|
-
assert qu.issparse(b)
|
|
446
|
-
assert_allclose(b.toarray(), (i & a & i).toarray())
|
|
447
|
-
|
|
448
|
-
def test_2d_simple(self):
|
|
449
|
-
a = (qu.rand_matrix(2), qu.rand_matrix(2))
|
|
450
|
-
dims = ((2, 3), (3, 2))
|
|
451
|
-
inds = ((0, 0), (1, 1))
|
|
452
|
-
b = qu.ikron(a, dims, inds)
|
|
453
|
-
assert b.shape == (36, 36)
|
|
454
|
-
assert_allclose(b, a[0] & qu.eye(9) & a[1])
|
|
455
|
-
|
|
456
|
-
@mark.parametrize("stype", (None,) + stypes)
|
|
457
|
-
@mark.parametrize(
|
|
458
|
-
"pos", [0, 1, 2, (0,), (1,), (2,), (0, 1), (1, 2), (0, 2)]
|
|
459
|
-
)
|
|
460
|
-
@mark.parametrize("coo_build", [False, True])
|
|
461
|
-
def test_sparse_format_outputs(self, os1, stype, pos, coo_build):
|
|
462
|
-
x = qu.ikron(os1, [3, 3, 3], pos, stype=stype, coo_build=coo_build)
|
|
463
|
-
assert x.format == "csr" if stype is None else stype
|
|
464
|
-
|
|
465
|
-
@mark.parametrize("stype", (None,) + stypes)
|
|
466
|
-
@mark.parametrize(
|
|
467
|
-
"pos", [0, 1, 2, (0,), (1,), (2,), (0, 1), (1, 2), (0, 2)]
|
|
468
|
-
)
|
|
469
|
-
@mark.parametrize("coo_build", [False, True])
|
|
470
|
-
def test_sparse_format_outputs_with_dense(
|
|
471
|
-
self, od1, stype, pos, coo_build
|
|
472
|
-
):
|
|
473
|
-
x = qu.ikron(
|
|
474
|
-
od1, [3, 3, 3], pos, sparse=True, stype=stype, coo_build=coo_build
|
|
475
|
-
)
|
|
476
|
-
try:
|
|
477
|
-
default = "bsr" if (2 in pos and not coo_build) else "csr"
|
|
478
|
-
except TypeError:
|
|
479
|
-
default = "bsr" if (pos == 2 and not coo_build) else "csr"
|
|
480
|
-
assert x.format == default if stype is None else stype
|
|
481
|
-
|
|
482
|
-
@mark.parametrize("sparse", [True, False])
|
|
483
|
-
@mark.parametrize("ri,rf", ([0, 4], [75, 89], [150, 168], [0, 168]))
|
|
484
|
-
def test_ikron_ownership(self, sparse, ri, rf):
|
|
485
|
-
dims = [7, 2, 4, 3]
|
|
486
|
-
X = qu.rand_matrix(2, sparse=sparse)
|
|
487
|
-
Y = qu.rand_matrix(3, sparse=sparse)
|
|
488
|
-
X1 = qu.ikron((X, Y), dims, (1, 3))[ri:rf, :]
|
|
489
|
-
X2 = qu.ikron((X, Y), dims, (1, 3), ownership=(ri, rf))
|
|
490
|
-
assert_allclose(X1.toarray(), X2.toarray())
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
class TestPermikron:
|
|
494
|
-
def test_dop_spread(self):
|
|
495
|
-
a = qu.rand_rho(4)
|
|
496
|
-
b = qu.pkron(a, [2, 2, 2], [0, 2])
|
|
497
|
-
c = (
|
|
498
|
-
(a & qu.eye(2))
|
|
499
|
-
.toarray().reshape([2, 2, 2, 2, 2, 2])
|
|
500
|
-
.transpose([0, 2, 1, 3, 5, 4])
|
|
501
|
-
.reshape([8, 8])
|
|
502
|
-
)
|
|
503
|
-
assert_allclose(b, c)
|
|
504
|
-
|
|
505
|
-
def test_dop_reverse(self):
|
|
506
|
-
a = qu.rand_rho(4)
|
|
507
|
-
b = qu.pkron(a, np.array([2, 2, 2]), [2, 0])
|
|
508
|
-
c = (
|
|
509
|
-
(a & qu.eye(2))
|
|
510
|
-
.toarray().reshape([2, 2, 2, 2, 2, 2])
|
|
511
|
-
.transpose([1, 2, 0, 4, 5, 3])
|
|
512
|
-
.reshape([8, 8])
|
|
513
|
-
)
|
|
514
|
-
assert_allclose(b, c)
|
|
515
|
-
|
|
516
|
-
def test_dop_reverse_sparse(self):
|
|
517
|
-
a = qu.rand_rho(4, sparse=True, density=0.5)
|
|
518
|
-
b = qu.pkron(a, np.array([2, 2, 2]), [2, 0])
|
|
519
|
-
c = (
|
|
520
|
-
(a & qu.eye(2))
|
|
521
|
-
.toarray().reshape([2, 2, 2, 2, 2, 2])
|
|
522
|
-
.transpose([1, 2, 0, 4, 5, 3])
|
|
523
|
-
.reshape([8, 8])
|
|
524
|
-
)
|
|
525
|
-
assert_allclose(b.toarray(), c)
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
class TestPermute:
|
|
529
|
-
def test_permute_ket(self):
|
|
530
|
-
a = qu.up() & qu.plus() & qu.yplus()
|
|
531
|
-
b = qu.permute(a, [2, 2, 2], [2, 0, 1])
|
|
532
|
-
assert_allclose(b, qu.yplus() & qu.up() & qu.plus())
|
|
533
|
-
|
|
534
|
-
def test_permute_op(self):
|
|
535
|
-
a = qu.pauli("x") & qu.pauli("y") & qu.pauli("z")
|
|
536
|
-
b = qu.permute(a, [2, 2, 2], [2, 0, 1])
|
|
537
|
-
assert_allclose(b, qu.pauli("z") & qu.pauli("x") & qu.pauli("y"))
|
|
538
|
-
|
|
539
|
-
def test_entangled_permute(self):
|
|
540
|
-
dims = [2, 2, 2]
|
|
541
|
-
a = qu.bell_state(0) & qu.up()
|
|
542
|
-
assert_allclose(qu.mutinf_subsys(a, dims, 0, 1), 2.0)
|
|
543
|
-
b = qu.permute(a, dims, [1, 2, 0])
|
|
544
|
-
assert_allclose(qu.mutinf_subsys(b, dims, 0, 1), 0.0, atol=1e-12)
|
|
545
|
-
assert_allclose(qu.mutinf_subsys(b, dims, 0, 2), 2.0)
|
|
546
|
-
|
|
547
|
-
def test_permute_sparse_ket(self):
|
|
548
|
-
dims = [3, 2, 5, 4]
|
|
549
|
-
a = qu.rand_ket(qu.prod(dims), sparse=True, density=0.5)
|
|
550
|
-
b = qu.permute(a, dims, [3, 1, 2, 0])
|
|
551
|
-
c = qu.permute(a.toarray(), dims, [3, 1, 2, 0])
|
|
552
|
-
assert_allclose(b.toarray(), c)
|
|
553
|
-
|
|
554
|
-
def test_permute_sparse_op(self):
|
|
555
|
-
dims = [3, 2, 5, 4]
|
|
556
|
-
a = qu.rand_rho(qu.prod(dims), sparse=True, density=0.5)
|
|
557
|
-
b = qu.permute(a, dims, [3, 1, 2, 0])
|
|
558
|
-
c = qu.permute(a.toarray(), dims, [3, 1, 2, 0])
|
|
559
|
-
assert_allclose(b.toarray(), c)
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
class TestPartialTraceDense:
|
|
563
|
-
def test_partial_trace_basic(self):
|
|
564
|
-
a = qu.rand_rho(2**2)
|
|
565
|
-
b = qu.partial_trace(a, [2, 2], 0)
|
|
566
|
-
assert isinstance(b, qu.qarray)
|
|
567
|
-
assert qu.isherm(b)
|
|
568
|
-
assert_allclose(qu.tr(b), 1.0)
|
|
569
|
-
|
|
570
|
-
def test_ptr_compare_to_manual(self):
|
|
571
|
-
a = qu.rand_rho(2**2)
|
|
572
|
-
b = qu.partial_trace(a, [2, 2], 0)
|
|
573
|
-
c = a.toarray().reshape([2, 2, 2, 2]).trace(axis1=1, axis2=3)
|
|
574
|
-
assert_allclose(b, c)
|
|
575
|
-
b = qu.partial_trace(a, [2, 2], 1)
|
|
576
|
-
c = a.toarray().reshape([2, 2, 2, 2]).trace(axis1=0, axis2=2)
|
|
577
|
-
assert_allclose(b, c)
|
|
578
|
-
|
|
579
|
-
def test_partial_trace_early_return(self):
|
|
580
|
-
a = qu.qu([0.5, 0.5, 0.5, 0.5], "ket")
|
|
581
|
-
b = qu.partial_trace(a, [2, 2], [0, 1])
|
|
582
|
-
assert_allclose(a @ a.H, b)
|
|
583
|
-
a = qu.qu([0.5, 0.5, 0.5, 0.5], "dop")
|
|
584
|
-
b = qu.partial_trace(a, [2, 2], [0, 1])
|
|
585
|
-
assert_allclose(a, b)
|
|
586
|
-
|
|
587
|
-
def test_partial_trace_return_type(self):
|
|
588
|
-
a = qu.qu([0, 2**-0.5, 2**-0.5, 0], "ket")
|
|
589
|
-
b = qu.partial_trace(a, [2, 2], 1)
|
|
590
|
-
assert type(b) == qu.qarray
|
|
591
|
-
a = qu.qu([0, 2**-0.5, 2**-0.5, 0], "dop")
|
|
592
|
-
b = qu.partial_trace(a, [2, 2], 1)
|
|
593
|
-
assert type(b) == qu.qarray
|
|
594
|
-
|
|
595
|
-
def test_partial_trace_single_ket(self):
|
|
596
|
-
dims = [2, 3, 4]
|
|
597
|
-
a = np.random.randn(qu.prod(dims), 1)
|
|
598
|
-
for i, dim in enumerate(dims):
|
|
599
|
-
b = qu.partial_trace(a, dims, i)
|
|
600
|
-
assert b.shape[0] == dim
|
|
601
|
-
|
|
602
|
-
def test_partial_trace_multi_ket(self):
|
|
603
|
-
dims = [2, 3, 4]
|
|
604
|
-
a = np.random.randn(qu.prod(dims), 1)
|
|
605
|
-
for i1, i2 in itertools.combinations([0, 1, 2], 2):
|
|
606
|
-
b = qu.partial_trace(a, dims, [i1, i2])
|
|
607
|
-
assert b.shape[1] == dims[i1] * dims[i2]
|
|
608
|
-
|
|
609
|
-
def test_partial_trace_dop_product_state(self):
|
|
610
|
-
dims = [3, 2, 4, 2, 3]
|
|
611
|
-
ps = [qu.rand_rho(dim) for dim in dims]
|
|
612
|
-
pt = qu.kron(*ps)
|
|
613
|
-
for i, dim in enumerate(dims):
|
|
614
|
-
p = qu.partial_trace(pt, dims, i)
|
|
615
|
-
assert_allclose(p, ps[i])
|
|
616
|
-
|
|
617
|
-
def test_partial_trace_bell_states(self):
|
|
618
|
-
for lab in ("psi-", "psi+", "phi-", "phi+"):
|
|
619
|
-
psi = qu.bell_state(lab, qtype="dop")
|
|
620
|
-
rhoa = qu.partial_trace(psi, [2, 2], 0)
|
|
621
|
-
assert_allclose(rhoa, qu.eye(2) / 2)
|
|
622
|
-
|
|
623
|
-
def test_partial_trace_supply_ndarray(self):
|
|
624
|
-
a = qu.rand_rho(2**3)
|
|
625
|
-
dims = np.array([2, 2, 2])
|
|
626
|
-
keep = np.array(1)
|
|
627
|
-
b = qu.partial_trace(a, dims, keep)
|
|
628
|
-
assert b.shape[0] == 2
|
|
629
|
-
|
|
630
|
-
def test_partial_trace_order_doesnt_matter(self):
|
|
631
|
-
a = qu.rand_rho(2**3)
|
|
632
|
-
dims = np.array([2, 2, 2])
|
|
633
|
-
b1 = qu.partial_trace(a, dims, [0, 2])
|
|
634
|
-
b2 = qu.partial_trace(a, dims, [2, 0])
|
|
635
|
-
assert_allclose(b1, b2)
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
class TestTraceLose:
|
|
639
|
-
def test_rps(self):
|
|
640
|
-
a, b, c = (
|
|
641
|
-
qu.rand_rho(2, sparse=True, density=0.5),
|
|
642
|
-
qu.rand_rho(3, sparse=True, density=0.5),
|
|
643
|
-
qu.rand_rho(2, sparse=True, density=0.5),
|
|
644
|
-
)
|
|
645
|
-
abc = a & b & c
|
|
646
|
-
pab = qu.core._trace_lose(abc, [2, 3, 2], 2)
|
|
647
|
-
assert_allclose(pab, (a & b).toarray())
|
|
648
|
-
pac = qu.core._trace_lose(abc, [2, 3, 2], 1)
|
|
649
|
-
assert_allclose(pac, (a & c).toarray())
|
|
650
|
-
pbc = qu.core._trace_lose(abc, [2, 3, 2], 0)
|
|
651
|
-
assert_allclose(pbc, (b & c).toarray())
|
|
652
|
-
|
|
653
|
-
def test_bell_state(self):
|
|
654
|
-
a = qu.bell_state("psi-", sparse=True)
|
|
655
|
-
b = qu.core._trace_lose(a @ a.H, [2, 2], 0)
|
|
656
|
-
assert_allclose(b, qu.eye(2) / 2)
|
|
657
|
-
b = qu.core._trace_lose(a @ a.H, [2, 2], 1)
|
|
658
|
-
assert_allclose(b, qu.eye(2) / 2)
|
|
659
|
-
|
|
660
|
-
def test_vs_ptr(self):
|
|
661
|
-
a = qu.rand_rho(6, sparse=True, density=0.5)
|
|
662
|
-
b = qu.core._trace_lose(a, [2, 3], 1)
|
|
663
|
-
c = qu.partial_trace(a.toarray(), [2, 3], 0)
|
|
664
|
-
assert_allclose(b, c)
|
|
665
|
-
b = qu.core._trace_lose(a, [2, 3], 0)
|
|
666
|
-
c = qu.partial_trace(a.toarray(), [2, 3], 1)
|
|
667
|
-
assert_allclose(b, c)
|
|
668
|
-
|
|
669
|
-
def test_vec_dense(self):
|
|
670
|
-
a = qu.rand_ket(4)
|
|
671
|
-
b = qu.core._trace_lose(a, [2, 2], 1)
|
|
672
|
-
c = qu.partial_trace(a.toarray(), [2, 2], 0)
|
|
673
|
-
assert_allclose(b, c)
|
|
674
|
-
b = qu.core._trace_lose(a, [2, 2], 0)
|
|
675
|
-
c = qu.partial_trace(a.toarray(), [2, 2], 1)
|
|
676
|
-
assert_allclose(b, c)
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
class TestTraceKeep:
|
|
680
|
-
def test_rps(self):
|
|
681
|
-
a, b, c = (
|
|
682
|
-
qu.rand_rho(2, sparse=True, density=0.5),
|
|
683
|
-
qu.rand_rho(3, sparse=True, density=0.5),
|
|
684
|
-
qu.rand_rho(2, sparse=True, density=0.5),
|
|
685
|
-
)
|
|
686
|
-
abc = a & b & c
|
|
687
|
-
pc = qu.core._trace_keep(abc, [2, 3, 2], 2)
|
|
688
|
-
assert_allclose(pc, c.toarray())
|
|
689
|
-
pb = qu.core._trace_keep(abc, [2, 3, 2], 1)
|
|
690
|
-
assert_allclose(pb, b.toarray())
|
|
691
|
-
pa = qu.core._trace_keep(abc, [2, 3, 2], 0)
|
|
692
|
-
assert_allclose(pa, a.toarray())
|
|
693
|
-
|
|
694
|
-
def test_bell_state(self):
|
|
695
|
-
a = qu.bell_state("psi-", sparse=True)
|
|
696
|
-
b = qu.core._trace_keep(a @ a.H, [2, 2], 0)
|
|
697
|
-
assert_allclose(b, qu.eye(2) / 2)
|
|
698
|
-
b = qu.core._trace_keep(a @ a.H, [2, 2], 1)
|
|
699
|
-
assert_allclose(b, qu.eye(2) / 2)
|
|
700
|
-
|
|
701
|
-
def test_vs_ptr(self):
|
|
702
|
-
a = qu.rand_rho(6, sparse=True, density=0.5)
|
|
703
|
-
b = qu.core._trace_keep(a, [2, 3], 0)
|
|
704
|
-
c = qu.partial_trace(a.toarray(), [2, 3], 0)
|
|
705
|
-
assert_allclose(b, c)
|
|
706
|
-
b = qu.core._trace_keep(a, [2, 3], 1)
|
|
707
|
-
c = qu.partial_trace(a.toarray(), [2, 3], 1)
|
|
708
|
-
assert_allclose(b, c)
|
|
709
|
-
|
|
710
|
-
def test_vec_dense(self):
|
|
711
|
-
a = qu.rand_ket(4)
|
|
712
|
-
b = qu.core._trace_keep(a, [2, 2], 0)
|
|
713
|
-
c = qu.partial_trace(a.toarray(), [2, 2], 0)
|
|
714
|
-
assert_allclose(b, c)
|
|
715
|
-
b = qu.core._trace_keep(a, [2, 2], 1)
|
|
716
|
-
c = qu.partial_trace(a.toarray(), [2, 2], 1)
|
|
717
|
-
assert_allclose(b, c)
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
class TestPartialTraceSparse:
|
|
721
|
-
def test_partial_trace_sparse_basic(self):
|
|
722
|
-
a = qu.rand_rho(4)
|
|
723
|
-
b = qu.partial_trace(a, [2, 2], 0)
|
|
724
|
-
assert type(b) == qu.qarray
|
|
725
|
-
assert qu.isherm(b)
|
|
726
|
-
assert_allclose(qu.tr(b), 1.0)
|
|
727
|
-
|
|
728
|
-
def test_partial_trace_simple_single(self):
|
|
729
|
-
a = qu.rand_rho(12, sparse=True, density=0.5)
|
|
730
|
-
dims = [2, 3, 2]
|
|
731
|
-
b = qu.partial_trace(a, dims, 1)
|
|
732
|
-
c = (
|
|
733
|
-
a.toarray().reshape([*dims, *dims])
|
|
734
|
-
.trace(axis1=2, axis2=5)
|
|
735
|
-
.trace(axis1=0, axis2=2)
|
|
736
|
-
)
|
|
737
|
-
assert_allclose(c, b)
|
|
738
|
-
|
|
739
|
-
def test_partial_trace_simple_double(self):
|
|
740
|
-
a = qu.rand_rho(12, sparse=True, density=0.5)
|
|
741
|
-
dims = [2, 3, 2]
|
|
742
|
-
b = qu.partial_trace(a, dims, [0, 2])
|
|
743
|
-
c = qu.partial_trace(a.toarray(), dims, [0, 2])
|
|
744
|
-
assert_allclose(b, c)
|
|
745
|
-
b = qu.partial_trace(a, dims, [1, 2])
|
|
746
|
-
c = qu.partial_trace(a.toarray(), dims, [1, 2])
|
|
747
|
-
assert_allclose(b, c)
|
|
748
|
-
|
|
749
|
-
def test_partial_trace_simple_ket(self):
|
|
750
|
-
a = qu.rand_ket(12, sparse=True, density=0.5)
|
|
751
|
-
dims = [2, 3, 2]
|
|
752
|
-
b = qu.partial_trace(a, dims, [0, 1])
|
|
753
|
-
c = qu.partial_trace(a.toarray(), dims, [0, 1])
|
|
754
|
-
assert_allclose(b, c)
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
class TestChop:
|
|
758
|
-
def test_chop_inplace(self):
|
|
759
|
-
a = qu.qu([-1j, 0.1 + 0.2j])
|
|
760
|
-
qu.chop(a, tol=0.11, inplace=True)
|
|
761
|
-
assert_allclose(a, qu.qu([-1j, 0.2j]))
|
|
762
|
-
# Sparse
|
|
763
|
-
a = qu.qu([-1j, 0.1 + 0.2j], sparse=True)
|
|
764
|
-
qu.chop(a, tol=0.11, inplace=True)
|
|
765
|
-
b = qu.qu([-1j, 0.2j], sparse=True)
|
|
766
|
-
assert (a != b).nnz == 0
|
|
767
|
-
|
|
768
|
-
def test_chop_inplace_dop(self):
|
|
769
|
-
a = qu.qu([1, 0.1], "dop")
|
|
770
|
-
qu.chop(a, tol=0.11, inplace=True)
|
|
771
|
-
assert_allclose(a, qu.qu([1, 0], "dop"))
|
|
772
|
-
a = qu.qu([1, 0.1], "dop", sparse=True)
|
|
773
|
-
qu.chop(a, tol=0.11, inplace=True)
|
|
774
|
-
b = qu.qu([1, 0.0], "dop", sparse=True)
|
|
775
|
-
assert (a != b).nnz == 0
|
|
776
|
-
|
|
777
|
-
def test_chop_copy(self):
|
|
778
|
-
a = qu.qu([-1j, 0.1 + 0.2j])
|
|
779
|
-
b = qu.chop(a, tol=0.11, inplace=False)
|
|
780
|
-
assert_allclose(a, qu.qu([-1j, 0.1 + 0.2j]))
|
|
781
|
-
assert_allclose(b, qu.qu([-1j, 0.2j]))
|
|
782
|
-
# Sparse
|
|
783
|
-
a = qu.qu([-1j, 0.1 + 0.2j], sparse=True)
|
|
784
|
-
b = qu.chop(a, tol=0.11, inplace=False)
|
|
785
|
-
ao = qu.qu([-1j, 0.1 + 0.2j], sparse=True)
|
|
786
|
-
bo = qu.qu([-1j, 0.2j], sparse=True)
|
|
787
|
-
assert (a != ao).nnz == 0
|
|
788
|
-
assert (b != bo).nnz == 0
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
class TestExpec:
|
|
792
|
-
@mark.parametrize("qtype1", ["ket", "dop"])
|
|
793
|
-
@mark.parametrize("spars1", [True, False])
|
|
794
|
-
@mark.parametrize("qtype2", ["ket", "dop"])
|
|
795
|
-
@mark.parametrize("spars2", [True, False])
|
|
796
|
-
def test_all(self, qtype1, spars1, qtype2, spars2):
|
|
797
|
-
a = qu.qu([[1], [2j], [3]], qtype=qtype1, sparse=spars1)
|
|
798
|
-
b = qu.qu([[1j], [2], [3j]], qtype=qtype2, sparse=spars2)
|
|
799
|
-
c = qu.expec(a, b)
|
|
800
|
-
assert not isinstance(c, complex)
|
|
801
|
-
assert_allclose(c, 36)
|
|
802
|
-
|
|
803
|
-
@mark.parametrize("qtype", ["ket", "dop"])
|
|
804
|
-
@mark.parametrize("sparse", [True, False])
|
|
805
|
-
@mark.parametrize("s", ["x", "y", "z"])
|
|
806
|
-
def test_negative_expec(self, qtype, sparse, s):
|
|
807
|
-
a = qu.singlet(qtype=qtype)
|
|
808
|
-
b = qu.pauli(s, sparse=sparse) & qu.pauli(s, sparse=sparse)
|
|
809
|
-
assert_allclose(qu.expec(a, b), -1)
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
class TestNumbaFuncs:
|
|
813
|
-
@mark.parametrize("size", [300, 3000, (300, 5), (3000, 5)])
|
|
814
|
-
@mark.parametrize(
|
|
815
|
-
"X_dtype", ["float32", "float64", "complex64", "complex128"]
|
|
816
|
-
)
|
|
817
|
-
@mark.parametrize("c_dtype", ["float32", "float64"])
|
|
818
|
-
def test_subtract_update(
|
|
819
|
-
self,
|
|
820
|
-
size,
|
|
821
|
-
X_dtype,
|
|
822
|
-
c_dtype,
|
|
823
|
-
):
|
|
824
|
-
X = qu.randn(size, dtype=X_dtype)
|
|
825
|
-
Y = qu.randn(size, dtype=X_dtype)
|
|
826
|
-
c = qu.randn(1, dtype=c_dtype)[0]
|
|
827
|
-
res = X - c * Y
|
|
828
|
-
qu.core.subtract_update_(X, c, Y)
|
|
829
|
-
assert_allclose(res, X, rtol=1e-6)
|
|
830
|
-
|
|
831
|
-
@mark.parametrize("size", [300, 3000, (300, 5), (3000, 5)])
|
|
832
|
-
@mark.parametrize(
|
|
833
|
-
"X_dtype", ["float32", "float64", "complex64", "complex128"]
|
|
834
|
-
)
|
|
835
|
-
@mark.parametrize("c_dtype", ["float32", "float64"])
|
|
836
|
-
def test_divide_update(
|
|
837
|
-
self,
|
|
838
|
-
size,
|
|
839
|
-
X_dtype,
|
|
840
|
-
c_dtype,
|
|
841
|
-
):
|
|
842
|
-
X = qu.randn(size, dtype=X_dtype)
|
|
843
|
-
Y = np.empty_like(X)
|
|
844
|
-
c = qu.randn(1, dtype=c_dtype).item()
|
|
845
|
-
res = X / c
|
|
846
|
-
qu.core.divide_update_(X, c, Y)
|
|
847
|
-
assert_allclose(res, Y, rtol=1e-6)
|