Trajectree 0.0.1__py3-none-any.whl → 0.0.2__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 +3 -3
- trajectree/fock_optics/utils.py +6 -6
- trajectree/trajectory.py +2 -2
- {trajectree-0.0.1.dist-info → trajectree-0.0.2.dist-info}/METADATA +2 -3
- trajectree-0.0.2.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.2.dist-info}/WHEEL +0 -0
- {trajectree-0.0.1.dist-info → trajectree-0.0.2.dist-info}/licenses/LICENSE +0 -0
- {trajectree-0.0.1.dist-info → trajectree-0.0.2.dist-info}/top_level.txt +0 -0
|
@@ -1,411 +0,0 @@
|
|
|
1
|
-
"""Functions for generating specific, e.g. ansatz, circuits."""
|
|
2
|
-
|
|
3
|
-
import math
|
|
4
|
-
import random
|
|
5
|
-
import itertools
|
|
6
|
-
|
|
7
|
-
from .. import rand, seed_rand
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
def inject_u3s(
|
|
11
|
-
ent_gates,
|
|
12
|
-
gate2="cz",
|
|
13
|
-
avoid_doubling=False,
|
|
14
|
-
seed=None,
|
|
15
|
-
):
|
|
16
|
-
r"""Take a sequence of pairs denoting qubits to entangle and interleave one
|
|
17
|
-
single qubit gate inbetween every leg. For example:
|
|
18
|
-
|
|
19
|
-
ent_gates = [(0, 1), (2, 3), (1, 2)]
|
|
20
|
-
|
|
21
|
-
Would go get made into a circuit like::
|
|
22
|
-
|
|
23
|
-
| | | | | | | |
|
|
24
|
-
| | | | | u u |
|
|
25
|
-
| | | | | | | |
|
|
26
|
-
| o++o | u o++o u
|
|
27
|
-
| | | | | | | |
|
|
28
|
-
| | | | --> | u u |
|
|
29
|
-
| | | | | | | |
|
|
30
|
-
o++o o++o o++o o++o
|
|
31
|
-
| | | | | | | |
|
|
32
|
-
| | | | u u u u
|
|
33
|
-
| | | | | | | |
|
|
34
|
-
|
|
35
|
-
Technically, this generates a bipartite graph between single qubit and two
|
|
36
|
-
qubit tensors, and should be the most expressive circuit possible for that
|
|
37
|
-
'budget' of entangling gates.
|
|
38
|
-
|
|
39
|
-
Parameters
|
|
40
|
-
----------
|
|
41
|
-
ent_gates : sequence[tuple[int]]
|
|
42
|
-
A 'stack' of entangling gate pairs to apply.
|
|
43
|
-
gate2 : {'cx', 'cy', 'cz', 'iswap', ..., str}, optional
|
|
44
|
-
The gate to use for the entanling pairs.
|
|
45
|
-
avoid_doubling : bool, optional
|
|
46
|
-
Whether to avoid placing an entangling gate directly above the same
|
|
47
|
-
entangling gate (there will still be single qubit gates interleaved).
|
|
48
|
-
|
|
49
|
-
Returns
|
|
50
|
-
-------
|
|
51
|
-
Circuit
|
|
52
|
-
"""
|
|
53
|
-
if seed is not None:
|
|
54
|
-
seed_rand(seed)
|
|
55
|
-
|
|
56
|
-
# keep track of where not to apply another entangling gate
|
|
57
|
-
just_entangled = set()
|
|
58
|
-
|
|
59
|
-
# keep track of where its worth putting a U3
|
|
60
|
-
n = max(itertools.chain.from_iterable(ent_gates)) + 1
|
|
61
|
-
needs_u3 = [True] * n
|
|
62
|
-
|
|
63
|
-
# create the circuit!
|
|
64
|
-
gates = []
|
|
65
|
-
# consume list of pairs to entangle
|
|
66
|
-
while ent_gates:
|
|
67
|
-
# break up entanling gates with U3s where necesary
|
|
68
|
-
for i in range(n):
|
|
69
|
-
if needs_u3[i]:
|
|
70
|
-
gates.append(("U3", *rand(3, scale=2 * math.pi), i))
|
|
71
|
-
needs_u3[i] = False
|
|
72
|
-
|
|
73
|
-
# try and get the next entanling gate which is not 'doubled'
|
|
74
|
-
for k, pair in enumerate(ent_gates):
|
|
75
|
-
# (just_entangled will never be populated if avoid_doubling=False)
|
|
76
|
-
if pair not in just_entangled:
|
|
77
|
-
break
|
|
78
|
-
|
|
79
|
-
i, j = ent_gates.pop(k)
|
|
80
|
-
gates.append((gate2, i, j))
|
|
81
|
-
|
|
82
|
-
# 1 2 3 4
|
|
83
|
-
# ^ ^ ^ ^
|
|
84
|
-
# | | | |
|
|
85
|
-
# o++o o++o
|
|
86
|
-
# | | | |
|
|
87
|
-
# | o++o | <- if we have just placed (2, 3), disable it in next
|
|
88
|
-
# | | | | round but enable (1, 2) and (3, 4) etc
|
|
89
|
-
# ^ ^ ^ ^
|
|
90
|
-
if avoid_doubling:
|
|
91
|
-
just_entangled = {
|
|
92
|
-
ij for ij in just_entangled if (i not in ij) and (j not in ij)
|
|
93
|
-
}
|
|
94
|
-
just_entangled.add((i, j))
|
|
95
|
-
|
|
96
|
-
# update the register of where to place U3s
|
|
97
|
-
needs_u3[i] = needs_u3[j] = True
|
|
98
|
-
|
|
99
|
-
# place the final layer of U3s
|
|
100
|
-
for i in range(n):
|
|
101
|
-
if needs_u3[i]:
|
|
102
|
-
gates.append(("U3", *rand(3, scale=2 * math.pi), i))
|
|
103
|
-
|
|
104
|
-
return gates
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
def gates_to_param_circuit(gates, n, parametrize="U3", **circuit_opts):
|
|
108
|
-
"""Turn the sequence ``gates`` into a ``Circuit`` of ``n`` qubits, with any
|
|
109
|
-
gates that appear in ``parametrize`` being... parametrized.
|
|
110
|
-
|
|
111
|
-
Parameters
|
|
112
|
-
----------
|
|
113
|
-
gates : sequence[tuple[str, float, int]]
|
|
114
|
-
The gates describing the circuit.
|
|
115
|
-
n : int
|
|
116
|
-
The number of qubits to make the circuit act one.
|
|
117
|
-
parametrize : str or sequence[str], optional
|
|
118
|
-
Which gates to parametrize.
|
|
119
|
-
circuit_opts
|
|
120
|
-
Supplied to :class:`~quimb.tensor.circuit.Circuit`.
|
|
121
|
-
|
|
122
|
-
Returns
|
|
123
|
-
-------
|
|
124
|
-
Circuit
|
|
125
|
-
"""
|
|
126
|
-
from .circuit import Circuit
|
|
127
|
-
|
|
128
|
-
if isinstance(parametrize, str):
|
|
129
|
-
parametrize = (parametrize,)
|
|
130
|
-
|
|
131
|
-
circ = Circuit(n, **circuit_opts)
|
|
132
|
-
for g in gates:
|
|
133
|
-
circ.apply_gate(*g, parametrize=g[0] in parametrize)
|
|
134
|
-
|
|
135
|
-
return circ
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
def circ_ansatz_1D_zigzag(n, depth, gate2="cz", seed=None, **circuit_opts):
|
|
139
|
-
r"""A 1D circuit ansatz with forward and backward layers of entangling
|
|
140
|
-
gates interleaved with U3 single qubit unitaries::
|
|
141
|
-
|
|
142
|
-
| | | |
|
|
143
|
-
u u | |
|
|
144
|
-
o++o u |
|
|
145
|
-
| | | u
|
|
146
|
-
| o++o |
|
|
147
|
-
| | u |
|
|
148
|
-
| | o++o
|
|
149
|
-
u u u u
|
|
150
|
-
| | o++o
|
|
151
|
-
| | u |
|
|
152
|
-
| o++o |
|
|
153
|
-
| u | u
|
|
154
|
-
o++o u |
|
|
155
|
-
u u | |
|
|
156
|
-
| | | |
|
|
157
|
-
|
|
158
|
-
Parameters
|
|
159
|
-
----------
|
|
160
|
-
n : int
|
|
161
|
-
The number of qubits.
|
|
162
|
-
depth : int
|
|
163
|
-
The number of entangling gates per pair.
|
|
164
|
-
gate2 : {'cx', 'cy', 'cz', 'iswap', ..., str}, optional
|
|
165
|
-
The gate to use for the entanling pairs.
|
|
166
|
-
seed : int, optional
|
|
167
|
-
Random seed for parameters.
|
|
168
|
-
opts
|
|
169
|
-
Supplied to :func:`~quimb.tensor.circuit_gen.gates_to_param_circuit`.
|
|
170
|
-
|
|
171
|
-
Returns
|
|
172
|
-
-------
|
|
173
|
-
Circuit
|
|
174
|
-
|
|
175
|
-
See Also
|
|
176
|
-
--------
|
|
177
|
-
circ_ansatz_1D_rand, circ_ansatz_1D_brickwork
|
|
178
|
-
"""
|
|
179
|
-
ent_gates = []
|
|
180
|
-
forward_layer = [(i, i + 1) for i in range(n - 1)]
|
|
181
|
-
backward_layer = [(i + 1, i) for i in range(n - 2, -1, -1)]
|
|
182
|
-
|
|
183
|
-
for d in range(depth):
|
|
184
|
-
if d % 2 == 0:
|
|
185
|
-
ent_gates.extend(forward_layer)
|
|
186
|
-
else:
|
|
187
|
-
ent_gates.extend(backward_layer)
|
|
188
|
-
|
|
189
|
-
# inject U3 gates!
|
|
190
|
-
gates = inject_u3s(ent_gates, gate2=gate2, seed=seed)
|
|
191
|
-
circ = gates_to_param_circuit(gates, n, **circuit_opts)
|
|
192
|
-
|
|
193
|
-
return circ
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
def circ_ansatz_1D_brickwork(
|
|
197
|
-
n, depth, cyclic=False, gate2="cz", seed=None, **circuit_opts
|
|
198
|
-
):
|
|
199
|
-
r"""A 1D circuit ansatz with odd and even layers of entangling
|
|
200
|
-
gates interleaved with U3 single qubit unitaries::
|
|
201
|
-
|
|
202
|
-
| | | | |
|
|
203
|
-
| u u u u
|
|
204
|
-
u o++o o++o
|
|
205
|
-
| u u u |
|
|
206
|
-
o++o o++o u
|
|
207
|
-
| u u u |
|
|
208
|
-
u o++o o++o
|
|
209
|
-
| u u u |
|
|
210
|
-
o++o o++o u
|
|
211
|
-
| u u u u
|
|
212
|
-
u o++o o++o
|
|
213
|
-
| u u u |
|
|
214
|
-
o++o o++o u
|
|
215
|
-
u u u u |
|
|
216
|
-
| | | | |
|
|
217
|
-
|
|
218
|
-
Parameters
|
|
219
|
-
----------
|
|
220
|
-
n : int
|
|
221
|
-
The number of qubits.
|
|
222
|
-
depth : int
|
|
223
|
-
The number of entangling gates per pair.
|
|
224
|
-
cyclic : bool, optional
|
|
225
|
-
Whether to add entangling gates between qubits 0 and n - 1.
|
|
226
|
-
gate2 : {'cx', 'cy', 'cz', 'iswap', ..., str}, optional
|
|
227
|
-
The gate to use for the entanling pairs.
|
|
228
|
-
seed : int, optional
|
|
229
|
-
Random seed for parameters.
|
|
230
|
-
opts
|
|
231
|
-
Supplied to :func:`~quimb.tensor.circuit_gen.gates_to_param_circuit`.
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
Returns
|
|
235
|
-
-------
|
|
236
|
-
Circuit
|
|
237
|
-
|
|
238
|
-
See Also
|
|
239
|
-
--------
|
|
240
|
-
circ_ansatz_1D_zigzag, circ_ansatz_1D_rand
|
|
241
|
-
"""
|
|
242
|
-
ent_gates = []
|
|
243
|
-
for d in range(depth):
|
|
244
|
-
# the even pairs layer
|
|
245
|
-
ent_gates.extend((i, i + 1) for i in range(0, n - 1, 2))
|
|
246
|
-
if cyclic and (n % 2 == 1):
|
|
247
|
-
ent_gates.append((n - 1, 0))
|
|
248
|
-
|
|
249
|
-
# the odd pairs layer
|
|
250
|
-
ent_gates.extend((i, i + 1) for i in range(1, n - 1, 2))
|
|
251
|
-
if cyclic and (n % 2 == 0):
|
|
252
|
-
ent_gates.append((n - 1, 0))
|
|
253
|
-
|
|
254
|
-
# inject U3 gates!
|
|
255
|
-
gates = inject_u3s(ent_gates, gate2=gate2, seed=seed)
|
|
256
|
-
circ = gates_to_param_circuit(gates, n, **circuit_opts)
|
|
257
|
-
|
|
258
|
-
return circ
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
def circ_ansatz_1D_rand(
|
|
262
|
-
n,
|
|
263
|
-
depth,
|
|
264
|
-
seed=None,
|
|
265
|
-
cyclic=False,
|
|
266
|
-
gate2="cz",
|
|
267
|
-
avoid_doubling=True,
|
|
268
|
-
**circuit_opts,
|
|
269
|
-
):
|
|
270
|
-
"""A 1D circuit ansatz with randomly place entangling gates interleaved
|
|
271
|
-
with U3 single qubit unitaries.
|
|
272
|
-
|
|
273
|
-
Parameters
|
|
274
|
-
----------
|
|
275
|
-
n : int
|
|
276
|
-
The number of qubits.
|
|
277
|
-
depth : int
|
|
278
|
-
The number of entangling gates per pair.
|
|
279
|
-
seed : int, optional
|
|
280
|
-
Random seed.
|
|
281
|
-
cyclic : bool, optional
|
|
282
|
-
Whether to add entangling gates between qubits 0 and n - 1.
|
|
283
|
-
gate2 : {'cx', 'cy', 'cz', 'iswap', ..., str}, optional
|
|
284
|
-
The gate to use for the entanling pairs.
|
|
285
|
-
avoid_doubling : bool, optional
|
|
286
|
-
Whether to avoid placing an entangling gate directly above the same
|
|
287
|
-
entangling gate (there will still be single qubit gates interleaved).
|
|
288
|
-
opts
|
|
289
|
-
Supplied to :func:`~quimb.tensor.circuit_gen.gates_to_param_circuit`.
|
|
290
|
-
|
|
291
|
-
Returns
|
|
292
|
-
-------
|
|
293
|
-
Circuit
|
|
294
|
-
|
|
295
|
-
See Also
|
|
296
|
-
--------
|
|
297
|
-
circ_ansatz_1D_zigzag, circ_ansatz_1D_brickwork
|
|
298
|
-
"""
|
|
299
|
-
if seed is not None:
|
|
300
|
-
random.seed(seed)
|
|
301
|
-
|
|
302
|
-
# the set number of entangling pairs to distribute randomly
|
|
303
|
-
ent_gates = [(i, i + 1) for i in range(n - 1) for _ in range(depth)]
|
|
304
|
-
if cyclic:
|
|
305
|
-
ent_gates.extend((n - 1, 0) for _ in range(depth))
|
|
306
|
-
|
|
307
|
-
# randomly permute the order
|
|
308
|
-
random.shuffle(ent_gates)
|
|
309
|
-
|
|
310
|
-
# inject U3 gates!
|
|
311
|
-
gates = inject_u3s(
|
|
312
|
-
ent_gates, avoid_doubling=avoid_doubling, gate2=gate2, seed=seed
|
|
313
|
-
)
|
|
314
|
-
circ = gates_to_param_circuit(gates, n, **circuit_opts)
|
|
315
|
-
|
|
316
|
-
return circ
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
def circ_a2a_rand(
|
|
320
|
-
n,
|
|
321
|
-
depth,
|
|
322
|
-
seed=None,
|
|
323
|
-
gate2="cz",
|
|
324
|
-
):
|
|
325
|
-
if not isinstance(seed, random.Random):
|
|
326
|
-
rng = random.Random(seed)
|
|
327
|
-
|
|
328
|
-
qubits = list(range(n))
|
|
329
|
-
|
|
330
|
-
ent_gates = []
|
|
331
|
-
for _ in range(depth):
|
|
332
|
-
rng.shuffle(qubits)
|
|
333
|
-
for i, j in zip(qubits[::2], qubits[1::2]):
|
|
334
|
-
ent_gates.append((i, j))
|
|
335
|
-
|
|
336
|
-
gates = inject_u3s(ent_gates, gate2=gate2, seed=seed)
|
|
337
|
-
circ = gates_to_param_circuit(gates, n)
|
|
338
|
-
|
|
339
|
-
return circ
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
def circ_qaoa(
|
|
343
|
-
terms,
|
|
344
|
-
depth,
|
|
345
|
-
gammas,
|
|
346
|
-
betas,
|
|
347
|
-
**circuit_opts,
|
|
348
|
-
):
|
|
349
|
-
r"""Generate the QAOA circuit for weighted graph described by ``terms``.
|
|
350
|
-
|
|
351
|
-
.. math::
|
|
352
|
-
|
|
353
|
-
|{\bar{\gamma}, \bar{\beta}}\rangle = U_B (\beta _p)
|
|
354
|
-
U_C (\gamma _p) \cdots U_B (\beta _1) U_C (\gamma _1) |{+}\rangle
|
|
355
|
-
|
|
356
|
-
with
|
|
357
|
-
|
|
358
|
-
.. math::
|
|
359
|
-
|
|
360
|
-
U_C (\gamma) = e^{-i \gamma \mathcal{C}} = \prod \limits_{i, j
|
|
361
|
-
\in E(G)} e^{-i \gamma w_{i j} Z_i Z_j}
|
|
362
|
-
|
|
363
|
-
and
|
|
364
|
-
|
|
365
|
-
.. math::
|
|
366
|
-
|
|
367
|
-
U_B (\beta) = \prod \limits_{i \in G} e^{-i \beta X_i}
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
Parameters
|
|
371
|
-
----------
|
|
372
|
-
terms : dict[tuple[int], float]
|
|
373
|
-
The mapping of integer pair keys ``(i, j)`` to the edge weight values,
|
|
374
|
-
``wij``. The integers should be a contiguous range enumerated from
|
|
375
|
-
zero, with the total number of qubits being inferred from this.
|
|
376
|
-
depth : int
|
|
377
|
-
The number of layers of gates to apply, ``p`` above.
|
|
378
|
-
gammas : iterable of float
|
|
379
|
-
The interaction angles for each layer.
|
|
380
|
-
betas : iterable of float
|
|
381
|
-
The rotation angles for each layer.
|
|
382
|
-
circuit_opts
|
|
383
|
-
Supplied to :class:`~quimb.tensor.circuit.Circuit`. Note
|
|
384
|
-
``gate_opts={'contract': False}`` is set by default (it can be
|
|
385
|
-
overridden) since the RZZ gate, even though it has a rank-2
|
|
386
|
-
decomposition, is also diagonal.
|
|
387
|
-
"""
|
|
388
|
-
from .circuit import Circuit
|
|
389
|
-
|
|
390
|
-
circuit_opts.setdefault("gate_opts", {})
|
|
391
|
-
circuit_opts["gate_opts"].setdefault("contract", False)
|
|
392
|
-
|
|
393
|
-
n = max(itertools.chain.from_iterable(terms)) + 1
|
|
394
|
-
|
|
395
|
-
gates = []
|
|
396
|
-
|
|
397
|
-
# layer of hadamards to get into plus state
|
|
398
|
-
for i in range(n):
|
|
399
|
-
gates.append((0, "h", i))
|
|
400
|
-
|
|
401
|
-
for d in range(depth):
|
|
402
|
-
for (i, j), wij in terms.items():
|
|
403
|
-
gates.append((d, "rzz", wij * gammas[d], i, j))
|
|
404
|
-
|
|
405
|
-
for i in range(n):
|
|
406
|
-
gates.append((d, "rx", -betas[d] * 2, i))
|
|
407
|
-
|
|
408
|
-
circ = Circuit(n, **circuit_opts)
|
|
409
|
-
circ.apply_gates(gates)
|
|
410
|
-
|
|
411
|
-
return circ
|