tequila-basic 1.9.9__py3-none-any.whl → 1.9.10__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.
- tequila/__init__.py +29 -14
- tequila/apps/__init__.py +14 -5
- tequila/apps/_unary_state_prep_impl.py +145 -112
- tequila/apps/adapt/__init__.py +9 -1
- tequila/apps/adapt/adapt.py +154 -113
- tequila/apps/krylov/__init__.py +1 -1
- tequila/apps/krylov/krylov.py +23 -21
- tequila/apps/robustness/helpers.py +10 -6
- tequila/apps/robustness/interval.py +238 -156
- tequila/apps/unary_state_prep.py +29 -23
- tequila/autograd_imports.py +8 -5
- tequila/circuit/__init__.py +2 -1
- tequila/circuit/_gates_impl.py +135 -67
- tequila/circuit/circuit.py +163 -79
- tequila/circuit/compiler.py +114 -105
- tequila/circuit/gates.py +288 -120
- tequila/circuit/gradient.py +35 -23
- tequila/circuit/noise.py +83 -74
- tequila/circuit/postselection.py +120 -0
- tequila/circuit/pyzx.py +10 -6
- tequila/circuit/qasm.py +201 -83
- tequila/circuit/qpic.py +63 -61
- tequila/grouping/binary_rep.py +148 -146
- tequila/grouping/binary_utils.py +84 -75
- tequila/grouping/compile_groups.py +334 -230
- tequila/grouping/ev_utils.py +77 -41
- tequila/grouping/fermionic_functions.py +383 -308
- tequila/grouping/fermionic_methods.py +170 -123
- tequila/grouping/overlapping_methods.py +69 -52
- tequila/hamiltonian/paulis.py +12 -13
- tequila/hamiltonian/paulistring.py +1 -1
- tequila/hamiltonian/qubit_hamiltonian.py +45 -35
- tequila/ml/__init__.py +1 -0
- tequila/ml/interface_torch.py +19 -16
- tequila/ml/ml_api.py +11 -10
- tequila/ml/utils_ml.py +12 -11
- tequila/objective/__init__.py +8 -3
- tequila/objective/braket.py +55 -47
- tequila/objective/objective.py +87 -55
- tequila/objective/qtensor.py +36 -27
- tequila/optimizers/__init__.py +31 -23
- tequila/optimizers/_containers.py +11 -7
- tequila/optimizers/optimizer_base.py +111 -83
- tequila/optimizers/optimizer_gd.py +258 -231
- tequila/optimizers/optimizer_gpyopt.py +56 -42
- tequila/optimizers/optimizer_scipy.py +157 -112
- tequila/quantumchemistry/__init__.py +66 -38
- tequila/quantumchemistry/chemistry_tools.py +393 -209
- tequila/quantumchemistry/encodings.py +121 -13
- tequila/quantumchemistry/madness_interface.py +170 -96
- tequila/quantumchemistry/orbital_optimizer.py +86 -41
- tequila/quantumchemistry/psi4_interface.py +166 -97
- tequila/quantumchemistry/pyscf_interface.py +70 -23
- tequila/quantumchemistry/qc_base.py +866 -414
- tequila/simulators/__init__.py +0 -3
- tequila/simulators/simulator_api.py +247 -105
- tequila/simulators/simulator_aqt.py +102 -0
- tequila/simulators/simulator_base.py +147 -53
- tequila/simulators/simulator_cirq.py +58 -42
- tequila/simulators/simulator_cudaq.py +600 -0
- tequila/simulators/simulator_ddsim.py +390 -0
- tequila/simulators/simulator_mqp.py +30 -0
- tequila/simulators/simulator_pyquil.py +190 -171
- tequila/simulators/simulator_qibo.py +95 -87
- tequila/simulators/simulator_qiskit.py +119 -107
- tequila/simulators/simulator_qlm.py +52 -26
- tequila/simulators/simulator_qulacs.py +74 -52
- tequila/simulators/simulator_spex.py +95 -60
- tequila/simulators/simulator_symbolic.py +6 -5
- tequila/simulators/test_spex_simulator.py +8 -11
- tequila/tools/convenience.py +4 -4
- tequila/tools/qng.py +72 -64
- tequila/tools/random_generators.py +38 -34
- tequila/utils/bitstrings.py +7 -7
- tequila/utils/exceptions.py +19 -5
- tequila/utils/joined_transformation.py +8 -10
- tequila/utils/keymap.py +0 -5
- tequila/utils/misc.py +6 -4
- tequila/version.py +1 -1
- tequila/wavefunction/qubit_wavefunction.py +47 -28
- {tequila_basic-1.9.9.dist-info → tequila_basic-1.9.10.dist-info}/METADATA +13 -16
- tequila_basic-1.9.10.dist-info/RECORD +93 -0
- {tequila_basic-1.9.9.dist-info → tequila_basic-1.9.10.dist-info}/WHEEL +1 -1
- tequila_basic-1.9.9.dist-info/RECORD +0 -88
- {tequila_basic-1.9.9.dist-info → tequila_basic-1.9.10.dist-info}/licenses/LICENSE +0 -0
- {tequila_basic-1.9.9.dist-info → tequila_basic-1.9.10.dist-info}/top_level.txt +0 -0
tequila/grouping/binary_utils.py
CHANGED
@@ -3,13 +3,13 @@ import numpy as np
|
|
3
3
|
|
4
4
|
|
5
5
|
def get_lagrangian_subspace(binary_matrix):
|
6
|
-
|
7
|
-
Given a list of vectors.
|
8
|
-
Find the lagrangian subspace that spans the vectors.
|
6
|
+
"""
|
7
|
+
Given a list of vectors.
|
8
|
+
Find the lagrangian subspace that spans the vectors.
|
9
9
|
|
10
10
|
Return: A list of vectors that forms the lagrangian subspace and
|
11
|
-
spans the space of the given matrix.
|
12
|
-
|
11
|
+
spans the space of the given matrix.
|
12
|
+
"""
|
13
13
|
null_basis = binary_null_space(np.array(binary_matrix))
|
14
14
|
lagrangian_basis = binary_symplectic_gram_schmidt(null_basis)
|
15
15
|
for vec in lagrangian_basis:
|
@@ -19,9 +19,9 @@ def get_lagrangian_subspace(binary_matrix):
|
|
19
19
|
|
20
20
|
|
21
21
|
def flip_first_second_half(vector):
|
22
|
-
|
23
|
-
Modify: Flip the first half the vector to second half, and vice versa.
|
24
|
-
|
22
|
+
"""
|
23
|
+
Modify: Flip the first half the vector to second half, and vice versa.
|
24
|
+
"""
|
25
25
|
dim = len(vector) // 2
|
26
26
|
tmp = vector[:dim].copy()
|
27
27
|
vector[:dim] = vector[dim:]
|
@@ -29,12 +29,12 @@ def flip_first_second_half(vector):
|
|
29
29
|
|
30
30
|
|
31
31
|
def binary_null_space(binary_matrix):
|
32
|
-
|
33
|
-
Return the basis of binary null space of the given binary matrix.
|
32
|
+
"""
|
33
|
+
Return the basis of binary null space of the given binary matrix.
|
34
34
|
|
35
35
|
Return: a list of binary vectors that forms the null space of the given binary matrix.
|
36
|
-
Modify: gauss_eliminated binary_matrix.
|
37
|
-
|
36
|
+
Modify: gauss_eliminated binary_matrix.
|
37
|
+
"""
|
38
38
|
dim = len(binary_matrix[0, :])
|
39
39
|
I = np.identity(dim)
|
40
40
|
|
@@ -47,8 +47,7 @@ def binary_null_space(binary_matrix):
|
|
47
47
|
non_zero_row = non_zero_row[0][0]
|
48
48
|
for j in range(i + 1, dim):
|
49
49
|
if binary_matrix[non_zero_row, j] != 0:
|
50
|
-
binary_matrix[:, j] = (binary_matrix[:, i] +
|
51
|
-
binary_matrix[:, j]) % 2
|
50
|
+
binary_matrix[:, j] = (binary_matrix[:, i] + binary_matrix[:, j]) % 2
|
52
51
|
I[:, j] = (I[:, i] + I[:, j]) % 2
|
53
52
|
|
54
53
|
null_basis = []
|
@@ -60,15 +59,15 @@ def binary_null_space(binary_matrix):
|
|
60
59
|
|
61
60
|
|
62
61
|
def binary_symplectic_gram_schmidt(coisotropic_space):
|
63
|
-
|
62
|
+
"""
|
64
63
|
Accepts a list of binary vectors, basis which
|
65
64
|
forms coisotropic space in 2*dim binary symplectic space (so len of list > dim)
|
66
65
|
Use Symplectic Gram-Schmidt to find the lagrangian subspace within the coisotropic space
|
67
|
-
that seperates the binary space into X, Y subspaces such that <x_i, y_i> = 1.
|
66
|
+
that seperates the binary space into X, Y subspaces such that <x_i, y_i> = 1.
|
68
67
|
|
69
|
-
Return: A list of the basis vector of the lagrangian subspace X.
|
70
|
-
Modify: coisotropic space to isotropic space.
|
71
|
-
|
68
|
+
Return: A list of the basis vector of the lagrangian subspace X.
|
69
|
+
Modify: coisotropic space to isotropic space.
|
70
|
+
"""
|
72
71
|
dim = len(coisotropic_space[0]) // 2
|
73
72
|
symplectic_dim = len(coisotropic_space) - dim
|
74
73
|
|
@@ -79,21 +78,20 @@ def binary_symplectic_gram_schmidt(coisotropic_space):
|
|
79
78
|
else:
|
80
79
|
for i in range(symplectic_dim):
|
81
80
|
x_cur, y_cur = pick_symplectic_pair(coisotropic_space)
|
82
|
-
binary_symplectic_orthogonalization(coisotropic_space, x_cur,
|
83
|
-
y_cur)
|
81
|
+
binary_symplectic_orthogonalization(coisotropic_space, x_cur, y_cur)
|
84
82
|
x_set.append(x_cur)
|
85
83
|
x_set.extend(coisotropic_space)
|
86
84
|
return x_set
|
87
85
|
|
88
86
|
|
89
87
|
def pick_symplectic_pair(coisotropic_space):
|
90
|
-
|
91
|
-
Pick out one pair in the symplectic space such that
|
88
|
+
"""
|
89
|
+
Pick out one pair in the symplectic space such that
|
92
90
|
<sympX, sympY> = 1
|
93
91
|
|
94
|
-
Return: A symplectic pair.
|
95
|
-
Modify: Pops the chosen pair from given list of vectors.
|
96
|
-
|
92
|
+
Return: A symplectic pair.
|
93
|
+
Modify: Pops the chosen pair from given list of vectors.
|
94
|
+
"""
|
97
95
|
for i, ivec in enumerate(coisotropic_space):
|
98
96
|
for j, jvec in enumerate(coisotropic_space):
|
99
97
|
if i < j:
|
@@ -104,13 +102,13 @@ def pick_symplectic_pair(coisotropic_space):
|
|
104
102
|
|
105
103
|
|
106
104
|
def binary_symplectic_orthogonalization(space, x, y):
|
107
|
-
|
105
|
+
"""
|
108
106
|
Symplectically orthogonalize all vectors in space
|
109
107
|
to the symplectic pair x and y
|
110
108
|
|
111
|
-
Modify: The linear space of space is modified such that each basis vector
|
112
|
-
is symplectically orthogonal to x and y.
|
113
|
-
|
109
|
+
Modify: The linear space of space is modified such that each basis vector
|
110
|
+
is symplectically orthogonal to x and y.
|
111
|
+
"""
|
114
112
|
for i in range(len(space)):
|
115
113
|
vec = space[i]
|
116
114
|
x_overlap = binary_symplectic_inner_product(vec, x)
|
@@ -120,14 +118,13 @@ def binary_symplectic_orthogonalization(space, x, y):
|
|
120
118
|
|
121
119
|
|
122
120
|
def binary_symplectic_inner_product(a, b):
|
123
|
-
|
124
|
-
Return the binary symplectic inner product between two binary vectors a and b.
|
121
|
+
"""
|
122
|
+
Return the binary symplectic inner product between two binary vectors a and b.
|
125
123
|
|
126
|
-
Return: 0 or 1.
|
127
|
-
|
124
|
+
Return: 0 or 1.
|
125
|
+
"""
|
128
126
|
if not len(a) == len(b):
|
129
|
-
raise TequilaException(
|
130
|
-
'Two binary vectors given do not share same number of qubits. ')
|
127
|
+
raise TequilaException("Two binary vectors given do not share same number of qubits. ")
|
131
128
|
dim = len(a) // 2
|
132
129
|
re = a[:dim] @ b[dim:] + b[:dim] @ a[dim:]
|
133
130
|
|
@@ -135,9 +132,9 @@ def binary_symplectic_inner_product(a, b):
|
|
135
132
|
|
136
133
|
|
137
134
|
def binary_solve(basis, target):
|
138
|
-
|
139
|
-
Get the expansion of the target in the given basis in binary space.
|
140
|
-
|
135
|
+
"""
|
136
|
+
Get the expansion of the target in the given basis in binary space.
|
137
|
+
"""
|
141
138
|
coeff = np.zeros(len(basis))
|
142
139
|
tsf_mat, pivot = binary_reduced_row_echelon(basis)
|
143
140
|
for i, pivot_idx in enumerate(pivot):
|
@@ -147,11 +144,11 @@ def binary_solve(basis, target):
|
|
147
144
|
|
148
145
|
|
149
146
|
def binary_reduced_row_echelon(basis):
|
150
|
-
|
151
|
-
Get a list of basis vectors.
|
147
|
+
"""
|
148
|
+
Get a list of basis vectors.
|
152
149
|
Perfrom reduced row echelon and return the pivot and the transformation matrix such that
|
153
150
|
np.array(basis) @ transformation_matrix = reduced_row_echelon_form
|
154
|
-
|
151
|
+
"""
|
155
152
|
num_basis = len(basis)
|
156
153
|
dim = len(basis[0])
|
157
154
|
|
@@ -164,20 +161,21 @@ def binary_reduced_row_echelon(basis):
|
|
164
161
|
non_zero_row = np.where(i_col == 1)[0][0]
|
165
162
|
pivot[i] = non_zero_row
|
166
163
|
for j, j_col in enumerate(reduced_basis):
|
167
|
-
if
|
164
|
+
if i != j and j_col[non_zero_row] == 1:
|
168
165
|
reduced_basis[j] = (j_col + i_col) % 2
|
169
166
|
tsf_mat[:, j] = (tsf_mat[:, i] + tsf_mat[:, j]) % 2
|
170
167
|
return tsf_mat, pivot
|
171
168
|
|
172
169
|
|
173
170
|
def binary_phase(self_binary, other_binary, n_qubit):
|
174
|
-
|
171
|
+
"""
|
175
172
|
Obtain the phase due to binary pauli string self * other. Get 0, 1, 2, 3 for 1, i, -1, -i.
|
176
|
-
|
173
|
+
"""
|
174
|
+
|
177
175
|
def get_phase_helper(this, other):
|
178
|
-
|
179
|
-
Return the phase incured due to multiplying this * other on a single qubit.
|
180
|
-
|
176
|
+
"""
|
177
|
+
Return the phase incured due to multiplying this * other on a single qubit.
|
178
|
+
"""
|
181
179
|
identity = [0, 0]
|
182
180
|
x = [1, 0]
|
183
181
|
y = [1, 1]
|
@@ -218,11 +216,11 @@ def binary_phase(self_binary, other_binary, n_qubit):
|
|
218
216
|
|
219
217
|
|
220
218
|
def gen_single_qubit_term(dim, qub, term):
|
221
|
-
|
222
|
-
Generate single qubit term on the given qubit with given term (0, 1, 2 represents z, x, y)
|
219
|
+
"""
|
220
|
+
Generate single qubit term on the given qubit with given term (0, 1, 2 represents z, x, y)
|
223
221
|
|
224
|
-
Return: A binary vector representing the single qubit term specified.
|
225
|
-
|
222
|
+
Return: A binary vector representing the single qubit term specified.
|
223
|
+
"""
|
226
224
|
word = np.zeros(dim * 2)
|
227
225
|
if term == 0:
|
228
226
|
word[qub + dim] = 1
|
@@ -233,38 +231,47 @@ def gen_single_qubit_term(dim, qub, term):
|
|
233
231
|
word[qub + dim] = 1
|
234
232
|
return word
|
235
233
|
|
234
|
+
|
236
235
|
def term_commutes_with_group(term, group, condition):
|
237
|
-
|
236
|
+
"""
|
238
237
|
Returns if term commutes with a group of terms.
|
239
|
-
|
238
|
+
"""
|
240
239
|
commute = True
|
241
240
|
for group_term in group:
|
242
|
-
if condition ==
|
241
|
+
if condition == "fc":
|
243
242
|
commute = term.commute(group_term)
|
244
|
-
elif condition ==
|
243
|
+
elif condition == "qwc":
|
245
244
|
commute = term.qubit_wise_commute(group_term)
|
246
245
|
else:
|
247
246
|
raise TequilaException(f"There is no commutativity condition {condition}")
|
248
|
-
if not (commute):
|
247
|
+
if not (commute):
|
248
|
+
break
|
249
249
|
return commute
|
250
250
|
|
251
|
-
|
252
|
-
|
251
|
+
|
252
|
+
def sorted_insertion_grouping(terms, condition="fc"):
|
253
|
+
"""
|
253
254
|
Obtain a list of commuting Pauli operator groups using the sorted insertion algorithm.
|
254
|
-
|
255
|
+
"""
|
255
256
|
sorted_terms = sorted(terms, key=lambda x: np.abs(x.coeff), reverse=True)
|
256
|
-
groups = []
|
257
|
+
groups = [] # Initialize groups
|
257
258
|
for term in sorted_terms:
|
258
259
|
found_group = False
|
259
260
|
for idx, group in enumerate(groups):
|
260
261
|
commute = term_commutes_with_group(term, group, condition)
|
261
|
-
if commute:
|
262
|
+
if commute: # Add term if it commutes with the current group.
|
262
263
|
groups[idx].append(term)
|
263
264
|
found_group = True
|
264
|
-
break
|
265
|
-
if not found_group:
|
265
|
+
break
|
266
|
+
if not found_group:
|
267
|
+
groups.append(
|
268
|
+
[
|
269
|
+
term,
|
270
|
+
]
|
271
|
+
) # Initiate new group that does not commute with any existing.
|
266
272
|
return groups
|
267
273
|
|
274
|
+
|
268
275
|
def largest_first(terms, n, cg):
|
269
276
|
"""
|
270
277
|
Color the graph using "largest first" heuristics with the given adjacency matrix
|
@@ -274,13 +281,13 @@ def largest_first(terms, n, cg):
|
|
274
281
|
"""
|
275
282
|
rows = cg.sum(axis=0)
|
276
283
|
ind = np.argsort(rows)[::-1]
|
277
|
-
m = cg[ind
|
284
|
+
m = cg[ind, :][:, ind]
|
278
285
|
colors = dict()
|
279
286
|
c = np.zeros(n, dtype=int)
|
280
|
-
k = 0
|
287
|
+
k = 0 # color
|
281
288
|
for i in range(n):
|
282
|
-
neighbors = np.argwhere(m[i
|
283
|
-
colors_available = set(np.arange(1, k+1)) - set(c[[x[0] for x in neighbors]])
|
289
|
+
neighbors = np.argwhere(m[i, :])
|
290
|
+
colors_available = set(np.arange(1, k + 1)) - set(c[[x[0] for x in neighbors]])
|
284
291
|
term = terms[ind[i]]
|
285
292
|
if not colors_available:
|
286
293
|
k += 1
|
@@ -291,6 +298,7 @@ def largest_first(terms, n, cg):
|
|
291
298
|
colors[c[i]].append(term)
|
292
299
|
return colors
|
293
300
|
|
301
|
+
|
294
302
|
def recursive_largest_first(terms, n, cg):
|
295
303
|
"""
|
296
304
|
Color the graph using "recursive largest first" heuristics with the given adjacency matrix
|
@@ -298,10 +306,11 @@ def recursive_largest_first(terms, n, cg):
|
|
298
306
|
and values as BinaryHamiltonian's
|
299
307
|
Produces better results than LF but is slower
|
300
308
|
"""
|
309
|
+
|
301
310
|
def n_0(m, colored):
|
302
311
|
m_colored = m[list(colored)]
|
303
312
|
l = m_colored[-1]
|
304
|
-
for i in range(len(m_colored)-1):
|
313
|
+
for i in range(len(m_colored) - 1):
|
305
314
|
l += m_colored[i]
|
306
315
|
white_neighbors = np.argwhere(np.logical_not(l))
|
307
316
|
return set([x[0] for x in white_neighbors]) - colored
|
@@ -319,18 +328,18 @@ def recursive_largest_first(terms, n, cg):
|
|
319
328
|
v = np.argmax(m.sum(axis=1))
|
320
329
|
colored_sub = {v}
|
321
330
|
uncolored_sub = set(np.arange(len(decode))) - {v}
|
322
|
-
n0 = n_0(m, colored_sub)#vertices that are not adjacent to any colored vertices
|
331
|
+
n0 = n_0(m, colored_sub) # vertices that are not adjacent to any colored vertices
|
323
332
|
n1 = uncolored_sub - n0
|
324
333
|
while n0:
|
325
|
-
m_uncolored = m[:,list(n1)][list(n0)
|
334
|
+
m_uncolored = m[:, list(n1)][list(n0), :]
|
326
335
|
v = list(n0)[np.argmax(m_uncolored.sum(axis=1))]
|
327
|
-
colored_sub.add(v)
|
328
|
-
uncolored_sub -= {v}
|
336
|
+
colored_sub.add(v) # stable
|
337
|
+
uncolored_sub -= {v} # stable
|
329
338
|
n0 = n_0(m, colored_sub)
|
330
|
-
n1 = uncolored_sub - n0
|
339
|
+
n1 = uncolored_sub - n0 # stable
|
331
340
|
indices = decode[list(colored_sub)]
|
332
341
|
c[indices] = k # stable
|
333
|
-
colors[k] = [terms[i] for i in indices]
|
342
|
+
colors[k] = [terms[i] for i in indices] # stable
|
334
343
|
colored |= set(indices)
|
335
344
|
uncolored = set(np.arange(n)) - colored
|
336
345
|
return colors
|