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.
Files changed (86) hide show
  1. tequila/__init__.py +29 -14
  2. tequila/apps/__init__.py +14 -5
  3. tequila/apps/_unary_state_prep_impl.py +145 -112
  4. tequila/apps/adapt/__init__.py +9 -1
  5. tequila/apps/adapt/adapt.py +154 -113
  6. tequila/apps/krylov/__init__.py +1 -1
  7. tequila/apps/krylov/krylov.py +23 -21
  8. tequila/apps/robustness/helpers.py +10 -6
  9. tequila/apps/robustness/interval.py +238 -156
  10. tequila/apps/unary_state_prep.py +29 -23
  11. tequila/autograd_imports.py +8 -5
  12. tequila/circuit/__init__.py +2 -1
  13. tequila/circuit/_gates_impl.py +135 -67
  14. tequila/circuit/circuit.py +163 -79
  15. tequila/circuit/compiler.py +114 -105
  16. tequila/circuit/gates.py +288 -120
  17. tequila/circuit/gradient.py +35 -23
  18. tequila/circuit/noise.py +83 -74
  19. tequila/circuit/postselection.py +120 -0
  20. tequila/circuit/pyzx.py +10 -6
  21. tequila/circuit/qasm.py +201 -83
  22. tequila/circuit/qpic.py +63 -61
  23. tequila/grouping/binary_rep.py +148 -146
  24. tequila/grouping/binary_utils.py +84 -75
  25. tequila/grouping/compile_groups.py +334 -230
  26. tequila/grouping/ev_utils.py +77 -41
  27. tequila/grouping/fermionic_functions.py +383 -308
  28. tequila/grouping/fermionic_methods.py +170 -123
  29. tequila/grouping/overlapping_methods.py +69 -52
  30. tequila/hamiltonian/paulis.py +12 -13
  31. tequila/hamiltonian/paulistring.py +1 -1
  32. tequila/hamiltonian/qubit_hamiltonian.py +45 -35
  33. tequila/ml/__init__.py +1 -0
  34. tequila/ml/interface_torch.py +19 -16
  35. tequila/ml/ml_api.py +11 -10
  36. tequila/ml/utils_ml.py +12 -11
  37. tequila/objective/__init__.py +8 -3
  38. tequila/objective/braket.py +55 -47
  39. tequila/objective/objective.py +87 -55
  40. tequila/objective/qtensor.py +36 -27
  41. tequila/optimizers/__init__.py +31 -23
  42. tequila/optimizers/_containers.py +11 -7
  43. tequila/optimizers/optimizer_base.py +111 -83
  44. tequila/optimizers/optimizer_gd.py +258 -231
  45. tequila/optimizers/optimizer_gpyopt.py +56 -42
  46. tequila/optimizers/optimizer_scipy.py +157 -112
  47. tequila/quantumchemistry/__init__.py +66 -38
  48. tequila/quantumchemistry/chemistry_tools.py +393 -209
  49. tequila/quantumchemistry/encodings.py +121 -13
  50. tequila/quantumchemistry/madness_interface.py +170 -96
  51. tequila/quantumchemistry/orbital_optimizer.py +86 -41
  52. tequila/quantumchemistry/psi4_interface.py +166 -97
  53. tequila/quantumchemistry/pyscf_interface.py +70 -23
  54. tequila/quantumchemistry/qc_base.py +866 -414
  55. tequila/simulators/__init__.py +0 -3
  56. tequila/simulators/simulator_api.py +247 -105
  57. tequila/simulators/simulator_aqt.py +102 -0
  58. tequila/simulators/simulator_base.py +147 -53
  59. tequila/simulators/simulator_cirq.py +58 -42
  60. tequila/simulators/simulator_cudaq.py +600 -0
  61. tequila/simulators/simulator_ddsim.py +390 -0
  62. tequila/simulators/simulator_mqp.py +30 -0
  63. tequila/simulators/simulator_pyquil.py +190 -171
  64. tequila/simulators/simulator_qibo.py +95 -87
  65. tequila/simulators/simulator_qiskit.py +119 -107
  66. tequila/simulators/simulator_qlm.py +52 -26
  67. tequila/simulators/simulator_qulacs.py +74 -52
  68. tequila/simulators/simulator_spex.py +95 -60
  69. tequila/simulators/simulator_symbolic.py +6 -5
  70. tequila/simulators/test_spex_simulator.py +8 -11
  71. tequila/tools/convenience.py +4 -4
  72. tequila/tools/qng.py +72 -64
  73. tequila/tools/random_generators.py +38 -34
  74. tequila/utils/bitstrings.py +7 -7
  75. tequila/utils/exceptions.py +19 -5
  76. tequila/utils/joined_transformation.py +8 -10
  77. tequila/utils/keymap.py +0 -5
  78. tequila/utils/misc.py +6 -4
  79. tequila/version.py +1 -1
  80. tequila/wavefunction/qubit_wavefunction.py +47 -28
  81. {tequila_basic-1.9.9.dist-info → tequila_basic-1.9.10.dist-info}/METADATA +13 -16
  82. tequila_basic-1.9.10.dist-info/RECORD +93 -0
  83. {tequila_basic-1.9.9.dist-info → tequila_basic-1.9.10.dist-info}/WHEEL +1 -1
  84. tequila_basic-1.9.9.dist-info/RECORD +0 -88
  85. {tequila_basic-1.9.9.dist-info → tequila_basic-1.9.10.dist-info}/licenses/LICENSE +0 -0
  86. {tequila_basic-1.9.9.dist-info → tequila_basic-1.9.10.dist-info}/top_level.txt +0 -0
@@ -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 (i != j and j_col[non_zero_row] == 1):
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 == 'fc':
241
+ if condition == "fc":
243
242
  commute = term.commute(group_term)
244
- elif condition == 'qwc':
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): break
247
+ if not (commute):
248
+ break
249
249
  return commute
250
250
 
251
- def sorted_insertion_grouping(terms, condition='fc'):
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 = [] #Initialize 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: # Add term if it commutes with the current group.
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: groups.append([term, ]) #Initiate new group that does not commute with any existing.
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,:][:,ind]
284
+ m = cg[ind, :][:, ind]
278
285
  colors = dict()
279
286
  c = np.zeros(n, dtype=int)
280
- k = 0 #color
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) #stable
328
- uncolored_sub -= {v} #stable
336
+ colored_sub.add(v) # stable
337
+ uncolored_sub -= {v} # stable
329
338
  n0 = n_0(m, colored_sub)
330
- n1 = uncolored_sub - n0 #stable
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] # stable
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