tequila-basic 1.9.5__py3-none-any.whl → 1.9.6__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/circuit/gates.py CHANGED
@@ -940,7 +940,7 @@ def QubitExcitation(angle: typing.Union[numbers.Real, Variable, typing.Hashable]
940
940
  except:
941
941
  raise Exception("QubitExcitation: Needs an even number of targets")
942
942
 
943
- return QCircuit.wrap_gate(QubitExcitationImpl(angle=angle, target=target, assume_real=assume_real, compile_options=compile_options))
943
+ return QCircuit.wrap_gate(QubitExcitationImpl(angle=angle, target=target, assume_real=assume_real, compile_options=compile_options, control=control))
944
944
 
945
945
 
946
946
  """
tequila/circuit/qpic.py CHANGED
@@ -224,7 +224,7 @@ def export_to(circuit,
224
224
  'always_use_generators': True,
225
225
  'group_together': "BARRIER"
226
226
  }
227
- elif not hasattr("style", "items"):
227
+ elif not hasattr(style, "items"):
228
228
  raise Exception(
229
229
  "style needs to be `tequila`, or `standard` or `generators` or a dictionary, you gave: {}".format(
230
230
  str(style)))
@@ -26,7 +26,7 @@ class BinaryHamiltonian:
26
26
  del Hof.terms[()]
27
27
  hamiltonian = QubitHamiltonian.from_openfermion(Hof)
28
28
  if n_qubits is None:
29
- n_qubits = hamiltonian.n_qubits
29
+ n_qubits = max(hamiltonian.qubits)+1
30
30
  binary_terms = [
31
31
  BinaryPauliString(
32
32
  p.binary(n_qubits).binary,
@@ -2,12 +2,12 @@ import os
2
2
  import typing
3
3
  import warnings
4
4
  from dataclasses import dataclass
5
-
5
+ from copy import deepcopy
6
+ from numbers import Real
6
7
  import numpy
7
8
 
8
- from tequila import BitString, QCircuit, TequilaException
9
+ from tequila import BitString, QCircuit, TequilaException,Variable,compile_circuit
9
10
  from tequila.circuit import gates
10
-
11
11
  try:
12
12
  from openfermion.ops.representations import get_active_space_integrals # needs openfermion 1.3
13
13
  except ImportError as E:
@@ -50,16 +50,132 @@ class FermionicGateImpl(gates.QubitExcitationImpl):
50
50
  self._name = "FermionicExcitation"
51
51
  self.transformation = transformation
52
52
  self.indices = indices
53
-
53
+ if not hasattr(indices[0],"__len__"):
54
+ self.indices = [(indices[2 * i], indices[2 * i+1]) for i in range(len(indices) // 2)]
55
+ self.sign = self.format_excitation_variables(self.indices)
56
+ self.indices = self.format_excitation_indices(self.indices)
54
57
  def compile(self, *args, **kwargs):
55
58
  if self.is_convertable_to_qubit_excitation():
56
59
  target = []
57
60
  for x in self.indices:
58
61
  for y in x:
59
62
  target.append(y)
60
- return gates.QubitExcitation(target=target, angle=-self.parameter, control=self.control)
63
+ return gates.QubitExcitation(target=target, angle=self.parameter, control=self.control)
64
+ else:
65
+ if self.transformation.lower().strip("_") == "jordanwigner":
66
+ return self.fermionic_excitation(angle=self.sign*self.parameter, indices=self.indices, control=self.control,opt=False)
67
+ else:
68
+ return gates.Trotterized(generator=self.generator, control=self.control, angle=self.parameter, steps=1)
69
+ def format_excitation_indices(self, idx):
70
+ """
71
+ Consistent formatting of excitation indices
72
+ idx = [(p0,q0),(p1,q1),...,(pn,qn)]
73
+ sorted as: p0<p1<pn and pi<qi
74
+ :param idx: list of index tuples describing a single(!) fermionic excitation
75
+ :return: list of index tuples
76
+ """
77
+
78
+ idx = [tuple(sorted(x)) for x in idx]
79
+ idx = sorted(idx, key=lambda x: x[0])
80
+ return list(idx)
81
+ def format_excitation_variables(self, idx):
82
+ """
83
+ Consistent formatting of excitation variable
84
+ idx = [(p0,q0),(p1,q1),...,(pn,qn)]
85
+ sorted as: pi<qi and p0 < p1 < p2
86
+ :param idx: list of index tuples describing a single(!) fermionic excitation
87
+ :return: sign of the variable with re-ordered indices
88
+ """
89
+ sig = 1
90
+ for pair in idx:
91
+ if pair[1]>pair[0]:
92
+ sig *= -1
93
+ for pair in range(len(idx)-1):
94
+ if idx[pair+1][0]>idx[pair][0]:
95
+ sig *= -1
96
+ return sig
97
+ def cCRy(self, target: int, dcontrol: typing.Union[list, int], control: typing.Union[list, int],
98
+ angle: typing.Union[Real, Variable, typing.Hashable], case: int = 1) -> QCircuit:
99
+ '''
100
+ Compilation of CRy as on https://doi.org/10.1103/PhysRevA.102.062612
101
+ If not control passed, Ry returned
102
+ Parameters
103
+ ----------
104
+ case: if 1 employs eq. 12 from the paper, if 0 eq. 13
105
+ '''
106
+ if control is not None and not len(control):
107
+ control = None
108
+ if isinstance(dcontrol, int):
109
+ dcontrol = [dcontrol]
110
+ if not len(dcontrol):
111
+ return compile_circuit(gates.Ry(angle=angle, target=target, control=control))
61
112
  else:
62
- return gates.Trotterized(generator=self.generator, control=self.control, angle=self.parameter, steps=1)
113
+ if isinstance(angle, str):
114
+ angle = Variable(angle)
115
+ U = QCircuit()
116
+ aux = dcontrol[0]
117
+ ctr = deepcopy(dcontrol)
118
+ ctr.pop(0)
119
+ if case:
120
+ U += self.cCRy(target=target, dcontrol=ctr, angle=angle / 2, case=1, control=control) + gates.H(
121
+ aux) + gates.CNOT(target, aux)
122
+ U += self.cCRy(target=target, dcontrol=ctr, angle=-angle / 2, case=0, control=control) + gates.CNOT(
123
+ target, aux) + gates.H(aux)
124
+ else:
125
+ U += gates.H(aux) + gates.CNOT(target, aux) + self.cCRy(target=target, dcontrol=ctr, angle=-angle / 2,
126
+ case=0, control=control)
127
+ U += gates.CNOT(target, aux) + gates.H(aux) + self.cCRy(target=target, dcontrol=ctr, angle=angle / 2,
128
+ case=1, control=control)
129
+ return U
130
+
131
+ def fermionic_excitation(self, angle: typing.Union[Real, Variable, typing.Hashable], indices: typing.List,
132
+ control: typing.Union[int, typing.List] = None, opt: bool = True) -> QCircuit:
133
+ '''
134
+ Excitation [(i,j),(k,l)],... compiled following https://doi.org/10.1103/PhysRevA.102.062612
135
+ opt: whether to optimized CNOT H CNOT --> Rz Rz CNOT Rz
136
+ '''
137
+ lto = []
138
+ lfrom = []
139
+ if isinstance(indices,tuple) and not hasattr(indices[0],"__len__"):
140
+ indices = [(indices[2 * i], indices[2 * i + 1]) for i in range(len(indices) // 2)]
141
+ for pair in indices:
142
+ lfrom.append(pair[0])
143
+ lto.append(pair[1])
144
+ Upair = QCircuit()
145
+ if isinstance(angle, str) or isinstance(angle, tuple):
146
+ angle = Variable(angle)
147
+ for i in range(len(lfrom) - 1):
148
+ Upair += gates.CNOT(lfrom[i + 1], lfrom[i])
149
+ Upair += gates.CNOT(lto[i + 1], lto[i])
150
+ Upair += gates.X(lto[i]) + gates.X(lfrom[i])
151
+ Upair += gates.CNOT(lto[-1], lfrom[-1])
152
+ crt = lfrom[::-1] + lto
153
+ Uladder = QCircuit()
154
+ pairs = lfrom + lto
155
+ pairs.sort()
156
+ orbs = []
157
+ for o in range(len(pairs) // 2):
158
+ orbs += [*range(pairs[2 * o] + 1, pairs[2 * o + 1])]
159
+ if len(orbs):
160
+ for o in range(len(orbs) - 1):
161
+ Uladder += gates.CNOT(orbs[o], orbs[o + 1])
162
+ Uladder += compile_circuit(gates.CZ(orbs[-1], lto[-1]))
163
+ crt.pop(-1)
164
+ if control is not None and (isinstance(control, int) or len(control) == 1):
165
+ if isinstance(control, int):
166
+ crt.append(control)
167
+ else:
168
+ crt = crt + control
169
+ control = []
170
+ Ur = self.cCRy(target=lto[-1], dcontrol=crt, angle=angle, control=control)
171
+ Upair2 = Upair.dagger()
172
+ if opt:
173
+ Ur.gates.pop(-1)
174
+ Ur.gates.pop(-1)
175
+ Upair2.gates.pop(0)
176
+ Ur += gates.Rz(numpy.pi / 2, target=lto[-1]) + gates.Rz(-numpy.pi / 2, target=lfrom[-1])
177
+ Ur += gates.CNOT(lto[-1], lfrom[-1]) + gates.Rz(numpy.pi / 2, target=lfrom[-1]) + gates.H(lfrom[-1])
178
+ return Upair + Uladder + Ur + Uladder.dagger() + Upair2
63
179
 
64
180
  def __str(self):
65
181
  if self.indices is not None:
@@ -2,16 +2,21 @@
2
2
  Collections of Fermion-to-Qubit encodings known to tequila
3
3
  Most are Interfaces to OpenFermion
4
4
  """
5
+ import abc
6
+
7
+ from tequila import TequilaException
5
8
  from tequila.circuit.circuit import QCircuit
6
- from tequila.circuit.gates import X
9
+ from tequila.circuit.gates import X, CNOT
7
10
  from tequila.hamiltonian.qubit_hamiltonian import QubitHamiltonian
8
11
  import openfermion
12
+ import numpy
13
+
9
14
 
10
15
  def known_encodings():
11
16
  # convenience for testing and I/O
12
- encodings= {
13
- "JordanWigner":JordanWigner,
14
- "BravyiKitaev":BravyiKitaev,
17
+ encodings = {
18
+ "JordanWigner": JordanWigner,
19
+ "BravyiKitaev": BravyiKitaev,
15
20
  "BravyiKitaevFast": BravyiKitaevFast,
16
21
  "BravyiKitaevTree": BravyiKitaevTree,
17
22
  "TaperedBravyiKitaev": TaperedBravyKitaev
@@ -22,14 +27,14 @@ def known_encodings():
22
27
  "ReorderedBravyiKitaev": lambda **kwargs: BravyiKitaev(up_then_down=True, **kwargs),
23
28
  "ReorderedBravyiKitaevTree": lambda **kwargs: BravyiKitaevTree(up_then_down=True, **kwargs),
24
29
  }
25
- return {k.replace("_","").replace("-","").upper():v for k,v in encodings.items()}
30
+ return {k.replace("_", "").replace("-", "").upper(): v for k, v in encodings.items()}
26
31
 
27
- class EncodingBase:
28
32
 
33
+ class EncodingBase(metaclass=abc.ABCMeta):
29
34
  # true if the encoding is fully integrated
30
35
  # false: can only do special things (like building the Hamiltionian)
31
36
  # but is not consistent with UCC gate generation
32
- _ucc_support=False
37
+ _ucc_support = False
33
38
 
34
39
  @property
35
40
  def supports_ucc(self):
@@ -37,20 +42,20 @@ class EncodingBase:
37
42
 
38
43
  @property
39
44
  def name(self):
40
- prefix=""
45
+ prefix = ""
41
46
  if self.up_then_down:
42
- prefix="Reordered"
47
+ prefix = "Reordered"
43
48
  if hasattr(self, "_name"):
44
- return prefix+self._name
49
+ return prefix + self._name
45
50
  else:
46
- return prefix+type(self).__name__
51
+ return prefix + type(self).__name__
47
52
 
48
53
  def __init__(self, n_electrons, n_orbitals, up_then_down=False, *args, **kwargs):
49
54
  self.n_electrons = n_electrons
50
55
  self.n_orbitals = n_orbitals
51
56
  self.up_then_down = up_then_down
52
57
 
53
- def __call__(self, fermion_operator:openfermion.FermionOperator, *args, **kwargs) -> QubitHamiltonian:
58
+ def __call__(self, fermion_operator: openfermion.FermionOperator, *args, **kwargs) -> QubitHamiltonian:
54
59
  """
55
60
  :param fermion_operator:
56
61
  an openfermion FermionOperator
@@ -58,7 +63,8 @@ class EncodingBase:
58
63
  The openfermion QubitOperator of this class ecoding
59
64
  """
60
65
  if self.up_then_down:
61
- op = openfermion.reorder(operator=fermion_operator, order_function=openfermion.up_then_down, num_modes=2*self.n_orbitals)
66
+ op = openfermion.reorder(operator=fermion_operator, order_function=openfermion.up_then_down,
67
+ num_modes=2 * self.n_orbitals)
62
68
  else:
63
69
  op = fermion_operator
64
70
 
@@ -73,18 +79,18 @@ class EncodingBase:
73
79
  if self.up_then_down:
74
80
  return i
75
81
  else:
76
- return 2*i
82
+ return 2 * i
77
83
 
78
84
  def down(self, i):
79
85
  if self.up_then_down:
80
- return i+self.n_orbitals
86
+ return i + self.n_orbitals
81
87
  else:
82
- return 2*i+1
88
+ return 2 * i + 1
83
89
 
84
- def do_transform(self, fermion_operator:openfermion.FermionOperator, *args, **kwargs) -> openfermion.QubitOperator:
90
+ def do_transform(self, fermion_operator: openfermion.FermionOperator, *args, **kwargs) -> openfermion.QubitOperator:
85
91
  raise Exception("{}::do_transform: called base class".format(type(self).__name__))
86
92
 
87
- def map_state(self, state:list, *args, **kwargs) -> list:
93
+ def map_state(self, state: list, *args, **kwargs) -> list:
88
94
  """
89
95
  Expects a state in spin-orbital ordering
90
96
  Returns the corresponding qubit state in the class encoding
@@ -112,7 +118,7 @@ class EncodingBase:
112
118
  # default is a lazy workaround, but it workds
113
119
  n_qubits = 2 * self.n_orbitals
114
120
 
115
- spin_orbitals = sorted([i for i,x in enumerate(state) if int(x)==1])
121
+ spin_orbitals = sorted([i for i, x in enumerate(state) if int(x) == 1])
116
122
 
117
123
  string = "1.0 ["
118
124
  for i in spin_orbitals:
@@ -128,26 +134,82 @@ class EncodingBase:
128
134
  key = list(wfn.keys())[0].array
129
135
  return key
130
136
 
131
- def hcb_to_me(self, *args, **kwargs):
132
- return None
137
+ @abc.abstractmethod
138
+ def me_to_jw(self) -> QCircuit:
139
+ """
140
+ This method needs to be implemented to enable default conversions via Jordan-Wigner
141
+ """
142
+ pass
143
+
144
+ # independent conversion methods, these are used for default conversions
145
+ # arXiv:1808.10402 IV. B. 2, Eq. 57
146
+ # original: https://doi.org/10.1063/1.4768229
147
+ def _jw_to_bk(self) -> QCircuit:
148
+ U = QCircuit() # Constructs empty circuit
149
+
150
+ flipper = False
151
+ for i in range(self.n_orbitals * 2):
152
+ # even qubits only hold their own value
153
+ if i % 2 == 0:
154
+ continue
155
+
156
+ # sum always includes the last qubit
157
+ U += CNOT(control=i - 1, target=i)
158
+
159
+ # every second odd qubit ties together with the last odd qubit
160
+ if flipper:
161
+ U += CNOT(control=i - 2, target=i)
162
+
163
+ flipper = not flipper
164
+
165
+ # we have now created the 4x4 blocks on the diagonal of this operators matrix
166
+
167
+ # every power of 2 connects to the last power of 2
168
+ # this corresponds to the last row in the recursive definitions being all 1s
169
+ x = numpy.log2(i + 1)
170
+ if x.is_integer() and x >= 3:
171
+ x = int(x)
172
+ U += CNOT(control=2 ** (x - 1) - 1, target=i)
173
+
174
+ return U
175
+
176
+ def _hcb_to_jw(self):
177
+ U = QCircuit()
178
+ for i in range(self.n_orbitals):
179
+ U += X(target=self.down(i), control=self.up(i))
180
+ return U
181
+
182
+ # Convenience Methods
183
+ def jw_to_me(self) -> QCircuit:
184
+ return self.me_to_jw().dagger()
185
+
186
+ def me_to_bk(self) -> QCircuit:
187
+ return self.me_to_jw() + self._jw_to_bk()
188
+
189
+ def bk_to_me(self) -> QCircuit:
190
+ return self.me_to_bk().dagger()
191
+
192
+ def hcb_to_me(self) -> QCircuit:
193
+ return self._hcb_to_jw() + self.jw_to_me()
133
194
 
134
195
  def __str__(self):
135
196
  return type(self).__name__
136
197
 
198
+
137
199
  class JordanWigner(EncodingBase):
138
200
  """
139
201
  OpenFermion::jordan_wigner
140
202
  """
141
- _ucc_support=True
203
+ _ucc_support = True
142
204
 
143
- def do_transform(self, fermion_operator:openfermion.FermionOperator, *args, **kwargs) -> openfermion.QubitOperator:
205
+ def do_transform(self, fermion_operator: openfermion.FermionOperator, *args, **kwargs) -> openfermion.QubitOperator:
144
206
  return openfermion.jordan_wigner(fermion_operator, *args, **kwargs)
145
207
 
146
- def map_state(self, state:list, *args, **kwargs):
147
- state = state + [0]*(self.n_orbitals-len(state))
148
- result = [0]*len(state)
208
+ def map_state(self, state: list, *args, **kwargs):
209
+ state = state + [0] * (self.n_orbitals - len(state))
210
+ result = [0] * len(state)
149
211
  if self.up_then_down:
150
- return [state[2*i] for i in range(self.n_orbitals)] + [state[2*i+1] for i in range(self.n_orbitals)]
212
+ return [state[2 * i] for i in range(self.n_orbitals)] + [state[2 * i + 1] for i in range(self.n_orbitals)]
151
213
  else:
152
214
  return state
153
215
 
@@ -157,15 +219,34 @@ class JordanWigner(EncodingBase):
157
219
  U += X(target=self.down(i), control=self.up(i))
158
220
  return U
159
221
 
222
+ def me_to_jw(self) -> QCircuit:
223
+ return QCircuit()
224
+
225
+ def jw_to_me(self) -> QCircuit:
226
+ return QCircuit()
227
+
228
+
160
229
  class BravyiKitaev(EncodingBase):
161
230
  """
162
231
  Uses OpenFermion::bravyi_kitaev
163
232
  """
164
233
 
165
- _ucc_support=True
234
+ _ucc_support = True
235
+
236
+ def do_transform(self, fermion_operator: openfermion.FermionOperator, *args, **kwargs) -> openfermion.QubitOperator:
237
+ return openfermion.bravyi_kitaev(fermion_operator, n_qubits=self.n_orbitals * 2)
238
+
239
+ def me_to_jw(self) -> QCircuit:
240
+ return self._jw_to_bk().dagger()
166
241
 
167
- def do_transform(self, fermion_operator:openfermion.FermionOperator, *args, **kwargs) -> openfermion.QubitOperator:
168
- return openfermion.bravyi_kitaev(fermion_operator, n_qubits=self.n_orbitals*2)
242
+ def jw_to_me(self) -> QCircuit:
243
+ return self._jw_to_bk()
244
+
245
+ def bk_to_me(self) -> QCircuit:
246
+ return QCircuit()
247
+
248
+ def me_to_bk(self) -> QCircuit:
249
+ return QCircuit()
169
250
 
170
251
 
171
252
  class BravyiKitaevTree(EncodingBase):
@@ -173,28 +254,37 @@ class BravyiKitaevTree(EncodingBase):
173
254
  Uses OpenFermion::bravyi_kitaev_tree
174
255
  """
175
256
 
176
- _ucc_support=True
257
+ _ucc_support = True
258
+
259
+ def do_transform(self, fermion_operator: openfermion.FermionOperator, *args, **kwargs) -> openfermion.QubitOperator:
260
+ return openfermion.bravyi_kitaev_tree(fermion_operator, n_qubits=self.n_orbitals * 2)
261
+
262
+ def me_to_jw(self) -> QCircuit:
263
+ raise TequilaException("{}::me_to_jw: unimplemented".format(type(self).__name__))
177
264
 
178
- def do_transform(self, fermion_operator:openfermion.FermionOperator, *args, **kwargs) -> openfermion.QubitOperator:
179
- return openfermion.bravyi_kitaev_tree(fermion_operator, n_qubits=self.n_orbitals*2)
180
265
 
181
266
  class BravyiKitaevFast(EncodingBase):
182
267
  """
183
268
  Uses OpenFermion::bravyi_kitaev_tree
184
269
  """
185
270
 
186
- _ucc_support=False
271
+ _ucc_support = False
187
272
 
188
- def do_transform(self, fermion_operator:openfermion.FermionOperator, *args, **kwargs) -> openfermion.QubitOperator:
273
+ def do_transform(self, fermion_operator: openfermion.FermionOperator, *args, **kwargs) -> openfermion.QubitOperator:
189
274
  n_qubits = openfermion.count_qubits(fermion_operator)
190
- if n_qubits != self.n_orbitals*2:
191
- raise Exception("BravyiKitaevFast transformation currently only possible for full Hamiltonians (no UCC generators).\nfermion_operator was {}".format(fermion_operator))
275
+ if n_qubits != self.n_orbitals * 2:
276
+ raise Exception(
277
+ "BravyiKitaevFast transformation currently only possible for full Hamiltonians (no UCC generators).\nfermion_operator was {}".format(
278
+ fermion_operator))
192
279
  op = openfermion.get_interaction_operator(fermion_operator)
193
280
  return openfermion.bravyi_kitaev_fast(op)
194
281
 
195
- class TaperedBravyKitaev(EncodingBase):
282
+ def me_to_jw(self) -> QCircuit:
283
+ raise TequilaException("{}::me_to_jw: unimplemented".format(type(self).__name__))
196
284
 
197
- _ucc_support=False
285
+
286
+ class TaperedBravyKitaev(EncodingBase):
287
+ _ucc_support = False
198
288
 
199
289
  """
200
290
  Uses OpenFermion::symmetry_conserving_bravyi_kitaev (tapered bravyi_kitaev_tree arxiv:1701.07072)
@@ -202,6 +292,7 @@ class TaperedBravyKitaev(EncodingBase):
202
292
  See OpenFermion Documentation for more
203
293
  Does not work for UCC generators yet
204
294
  """
295
+
205
296
  def __init__(self, n_electrons, n_orbitals, active_fermions=None, active_orbitals=None, *args, **kwargs):
206
297
  if active_fermions is None:
207
298
  self.active_fermions = n_electrons
@@ -209,7 +300,7 @@ class TaperedBravyKitaev(EncodingBase):
209
300
  self.active_fermions = active_fermions
210
301
 
211
302
  if active_orbitals is None:
212
- self.active_orbitals = n_orbitals*2 # in openfermion those are spin-orbitals
303
+ self.active_orbitals = n_orbitals * 2 # in openfermion those are spin-orbitals
213
304
  else:
214
305
  self.active_orbitals = active_orbitals
215
306
 
@@ -217,17 +308,20 @@ class TaperedBravyKitaev(EncodingBase):
217
308
  raise Exception("Don't pass up_then_down argument to {}, it can't be changed".format(type(self).__name__))
218
309
  super().__init__(n_orbitals=n_orbitals, n_electrons=n_electrons, up_then_down=False, *args, **kwargs)
219
310
 
220
- def do_transform(self, fermion_operator:openfermion.FermionOperator, *args, **kwargs) -> openfermion.QubitOperator:
221
- if openfermion.count_qubits(fermion_operator) != self.n_orbitals*2:
311
+ def do_transform(self, fermion_operator: openfermion.FermionOperator, *args, **kwargs) -> openfermion.QubitOperator:
312
+ if openfermion.count_qubits(fermion_operator) != self.n_orbitals * 2:
222
313
  raise Exception("TaperedBravyiKitaev not ready for UCC generators yet")
223
- return openfermion.symmetry_conserving_bravyi_kitaev(fermion_operator, active_orbitals=self.active_orbitals, active_fermions=self.active_fermions)
314
+ return openfermion.symmetry_conserving_bravyi_kitaev(fermion_operator, active_orbitals=self.active_orbitals,
315
+ active_fermions=self.active_fermions)
224
316
 
225
- def map_state(self, state:list, *args, **kwargs):
226
- non_tapered_trafo = BravyiKitaevTree(up_then_down=True, n_electrons=self.n_electrons, n_orbitals=self.n_orbitals)
317
+ def map_state(self, state: list, *args, **kwargs):
318
+ non_tapered_trafo = BravyiKitaevTree(up_then_down=True, n_electrons=self.n_electrons,
319
+ n_orbitals=self.n_orbitals)
227
320
  key = non_tapered_trafo.map_state(state=state, *args, **kwargs)
228
- n_qubits = self.n_orbitals*2
321
+ n_qubits = self.n_orbitals * 2
229
322
  active_qubits = [i for i in range(n_qubits) if i not in [n_qubits - 1, n_qubits // 2 - 1]]
230
323
  key = [key[i] for i in active_qubits]
231
324
  return key
232
325
 
233
-
326
+ def me_to_jw(self) -> QCircuit:
327
+ raise TequilaException("{}::me_to_jw: unimplemented".format(type(self).__name__))
@@ -420,7 +420,10 @@ class QuantumChemistryMadness(QuantumChemistryBase):
420
420
 
421
421
  """
422
422
  # check if the used qubit encoding has a hcb transformation
423
- have_hcb_trafo = self.transformation.hcb_to_me() is not None
423
+ try:
424
+ have_hcb_trafo = self.transformation.hcb_to_me() is not None
425
+ except:
426
+ have_hcb_trafo = False
424
427
  name = name.upper()
425
428
 
426
429
  # Default Method
@@ -17,7 +17,7 @@ from .encodings import known_encodings
17
17
 
18
18
  import typing, numpy, numbers
19
19
  from itertools import product
20
-
20
+ import tequila.grouping.fermionic_functions as ff
21
21
 
22
22
 
23
23
  try:
@@ -32,8 +32,7 @@ except:
32
32
  except Exception as E:
33
33
  raise Exception("{}\nIssue with Tequila Chemistry: Please update openfermion".format(str(E)))
34
34
  import warnings
35
-
36
-
35
+ OPTIMIZED_ORDERING = "Optimized"
37
36
  class QuantumChemistryBase:
38
37
  """
39
38
  Base Class for tequila chemistry functionality
@@ -113,7 +112,11 @@ class QuantumChemistryBase:
113
112
  h1 = molecule.integral_manager.one_body_integrals
114
113
  h2 = molecule.integral_manager.two_body_integrals
115
114
  S = molecule.integral_manager.overlap_integrals
116
- active_orbitals = [o.idx_total for o in molecule.integral_manager.active_orbitals]
115
+ if "active_orbitals" not in kwargs:
116
+ active_orbitals = [o.idx_total for o in molecule.integral_manager.active_orbitals]
117
+ else:
118
+ active_orbitals = kwargs["active_orbitals"]
119
+ kwargs.pop("active_orbitals")
117
120
  if transformation is None:
118
121
  transformation = molecule.transformation
119
122
  parameters = molecule.parameters
@@ -125,7 +128,8 @@ class QuantumChemistryBase:
125
128
  active_orbitals= active_orbitals,
126
129
  transformation=transformation,
127
130
  orbital_type=molecule.integral_manager._orbital_type,
128
- parameters=parameters, *args, **kwargs)
131
+ parameters=parameters,
132
+ reference_orbitals= molecule.integral_manager.active_space.reference_orbitals,*args, **kwargs)
129
133
 
130
134
  def supports_ucc(self):
131
135
  """
@@ -441,10 +445,14 @@ class QuantumChemistryBase:
441
445
 
442
446
  generator = self.make_excitation_generator(indices=indices, remove_constant_term=control is None)
443
447
  p0 = self.make_excitation_generator(indices=indices, form="P0", remove_constant_term=control is None)
444
-
448
+ if self.transformation.up_then_down:
449
+ idx = []
450
+ for pair in indices:
451
+ idx.append((pair[0]//2+(pair[0]%2)*self.n_orbitals,pair[1]//2+(pair[1]%2)*self.n_orbitals))
452
+ else:idx = indices
445
453
  return QCircuit.wrap_gate(
446
454
  FermionicGateImpl(angle=angle, generator=generator, p0=p0,
447
- transformation=type(self.transformation).__name__.lower(), indices=indices,
455
+ transformation=type(self.transformation).__name__.lower(), indices=idx,
448
456
  assume_real=assume_real,
449
457
  control=control, **kwargs))
450
458
 
@@ -1239,7 +1247,13 @@ class QuantumChemistryBase:
1239
1247
  indices = self.make_upccgsd_indices(key=name)
1240
1248
 
1241
1249
  # check if the used qubit encoding has a hcb transformation
1242
- have_hcb_trafo = self.transformation.hcb_to_me() is not None
1250
+ have_hcb_trafo = True
1251
+ try:
1252
+ if self.transformation.hcb_to_me() is None:
1253
+ have_hcb_trafo = False
1254
+ except:
1255
+ have_hcb_trafo = False
1256
+
1243
1257
 
1244
1258
  # consistency checks for optimization
1245
1259
  if have_hcb_trafo and hcb_optimization is None and include_reference:
@@ -1487,7 +1501,8 @@ class QuantumChemistryBase:
1487
1501
  factor = 1.0 / trotter_steps
1488
1502
  for step in range(trotter_steps):
1489
1503
  for idx, angle in indices.items():
1490
- UCCSD += self.make_excitation_gate(indices=idx, angle=factor * angle)
1504
+ converted = [(idx[2 * i], idx[2 * i + 1]) for i in range(len(idx) // 2)]
1505
+ UCCSD += self.make_excitation_gate(indices=converted, angle=factor * angle)
1491
1506
  if hasattr(initial_amplitudes,
1492
1507
  "lower") and initial_amplitudes.lower() == "mp2" and parametrized and add_singles:
1493
1508
  # mp2 has no singles, need to initialize them here (if not parametrized initializling as 0.0 makes no sense though)
@@ -1721,7 +1736,8 @@ class QuantumChemistryBase:
1721
1736
  return None
1722
1737
 
1723
1738
  def compute_rdms(self, U: QCircuit = None, variables: Variables = None, spin_free: bool = True,
1724
- get_rdm1: bool = True, get_rdm2: bool = True, ordering="dirac", use_hcb: bool = False):
1739
+ get_rdm1: bool = True, get_rdm2: bool = True, ordering="dirac", use_hcb: bool = False,
1740
+ rdm_trafo: QubitHamiltonian = None, decompose=None):
1725
1741
  """
1726
1742
  Computes the one- and two-particle reduced density matrices (rdm1 and rdm2) given
1727
1743
  a unitary U. This method uses the standard ordering in physics as denoted below.
@@ -1749,6 +1765,9 @@ class QuantumChemistryBase:
1749
1765
  get_rdm1, get_rdm2 :
1750
1766
  Set whether either one or both rdm1, rdm2 should be computed. If both are needed at some point,
1751
1767
  it is recommended to compute them at once.
1768
+ rdm_trafo :
1769
+ The rdm operators can be transformed, e.g., a^dagger_i a_j -> U^dagger a^dagger_i a_j U,
1770
+ where U represents the transformation. The default is set to None, implying that U equas the identity.
1752
1771
 
1753
1772
  Returns
1754
1773
  -------
@@ -1993,8 +2012,18 @@ class QuantumChemistryBase:
1993
2012
  # Transform operator lists to QubitHamiltonians
1994
2013
  if (not use_hcb):
1995
2014
  qops = [_get_qop_hermitian(op) for op in qops]
2015
+
1996
2016
  # Compute expected values
1997
- evals = simulate(ExpectationValue(H=qops, U=U, shape=[len(qops)]), variables=variables)
2017
+ if rdm_trafo is None:
2018
+ if decompose is not None:
2019
+ print("MANIPULATED")
2020
+ X = decompose(H=qops, U=U)
2021
+ evals = simulate(X, variables=variables)
2022
+ else:
2023
+ evals = simulate(ExpectationValue(H=qops, U=U, shape=[len(qops)]), variables=variables)
2024
+ else:
2025
+ qops = [rdm_trafo.dagger()*qops[i]*rdm_trafo for i in range(len(qops))]
2026
+ evals = simulate(ExpectationValue(H=qops, U=U, shape=[len(qops)]), variables=variables)
1998
2027
 
1999
2028
  # Assemble density matrices
2000
2029
  # If self._rdm1, self._rdm2 exist, reset them if they are of the other spin-type
@@ -2127,6 +2156,58 @@ class QuantumChemistryBase:
2127
2156
  n_ri=n_ri, external_info=external_info, **kwargs)
2128
2157
  return correction.compute()
2129
2158
 
2159
+ def n_rotation(self, i, phi):
2160
+ '''
2161
+ Creates a quantum circuit that applies a phase rotation based on phi to both components (up and down) of a given qubit.
2162
+
2163
+ Parameters:
2164
+ - i (int): The index of the qubit to which the rotation will be applied.
2165
+ - phi (float): The rotation angle. The actual rotation applied will be multiplied with -2 for both components.
2166
+
2167
+ Returns:
2168
+ - QCircuit: A quantum circuit object containing the sequence of rotations applied to the up and down components of the specified qubit.
2169
+ '''
2170
+
2171
+ # Generate number operators for the up and down components of the qubit.
2172
+ n_up = self.make_number_op(2*i)
2173
+ n_down = self.make_number_op(2*i+1)
2174
+
2175
+ # Start a new circuit and apply rotations to each component.
2176
+ circuit = gates.GeneralizedRotation(generator = n_up, angle=-2*phi)
2177
+ circuit += gates.GeneralizedRotation(generator = n_down, angle=-2*phi)
2178
+ return circuit
2179
+
2180
+ def get_givens_circuit(self, unitary, tol = 1e-12, ordering = OPTIMIZED_ORDERING):
2181
+ '''
2182
+ Constructs a quantum circuit from a given real unitary matrix using Givens rotations.
2183
+
2184
+ This method decomposes a unitary matrix into a series of Givens and Rz (phase) rotations,
2185
+ then constructs and returns a quantum circuit that implements this sequence of rotations.
2186
+
2187
+ Parameters:
2188
+ - unitary (numpy.array): A real unitary matrix representing the transformation to implement.
2189
+ - tol (float): A tolerance threshold below which matrix elements are considered zero.
2190
+ - ordering (list of tuples or 'Optimized'): Custom ordering of indices for Givens rotations or 'Optimized' to generate them automatically.
2191
+
2192
+ Returns:
2193
+ - QCircuit: A quantum circuit implementing the series of rotations decomposed from the unitary.
2194
+ '''
2195
+ # Decompose the unitary matrix into Givens and phase (Rz) rotations.
2196
+ theta_list, phi_list = get_givens_decomposition(unitary, tol, ordering)
2197
+
2198
+ # Initialize an empty quantum circuit.
2199
+ circuit = QCircuit()
2200
+
2201
+ # Add all Rz (phase) rotations to the circuit.
2202
+ for phi in phi_list:
2203
+ circuit += self.n_rotation(phi[1], phi[0])
2204
+
2205
+ # Add all Givens rotations to the circuit.
2206
+ for theta in reversed(theta_list):
2207
+ circuit += self.UR(theta[1], theta[2], theta[0]*2)
2208
+
2209
+ return circuit
2210
+
2130
2211
 
2131
2212
  def print_basis_info(self):
2132
2213
  return self.integral_manager.print_basis_info()
@@ -2147,3 +2228,140 @@ class QuantumChemistryBase:
2147
2228
  result += "\nmore information with: self.print_basis_info()\n"
2148
2229
 
2149
2230
  return result
2231
+
2232
+ def givens_matrix(n, p, q, theta):
2233
+ '''
2234
+ Construct a complex Givens rotation matrix of dimension n by theta between rows/columns p and q.
2235
+ '''
2236
+ '''
2237
+ Generates a Givens rotation matrix of size n x n to rotate by angle theta in the (p, q) plane. This matrix can be complex
2238
+
2239
+ Parameters:
2240
+ - n (int): The size of the Givens rotation matrix.
2241
+ - p (int): The first index for the rotation plane.
2242
+ - q (int): The second index for the rotation plane.
2243
+ - theta (float): The rotation angle.
2244
+
2245
+ Returns:
2246
+ - numpy.array: The Givens rotation matrix.
2247
+ '''
2248
+ matrix = numpy.eye(n) # Matrix to hold complex numbers
2249
+ cos_theta = numpy.cos(theta)
2250
+ sin_theta = numpy.sin(theta)
2251
+
2252
+ # Directly assign cosine and sine without complex phase adjustment
2253
+ matrix[p, p] = cos_theta
2254
+ matrix[q, q] = cos_theta
2255
+ matrix[p, q] = sin_theta
2256
+ matrix[q, p] = -sin_theta
2257
+
2258
+ return matrix
2259
+
2260
+ def get_givens_decomposition(unitary, tol = 1e-12, ordering = OPTIMIZED_ORDERING, return_diagonal = False):
2261
+ '''
2262
+ Decomposes a real unitary matrix into Givens rotations (theta) and Rz rotations (phi).
2263
+
2264
+ Parameters:
2265
+ - unitary (numpy.array): A real unitary matrix to decompose. It cannot be complex.
2266
+ - tol (float): Tolerance for considering matrix elements as zero. Elements with absolute value less than tol are treated as zero.
2267
+ - ordering (list of tuples or 'Optimized'): Custom ordering of indices for Givens rotations or 'Optimized' to generate them automatically.
2268
+ - return_diagonal (bool): If True, the function also returns the diagonal matrix as part of the output.
2269
+
2270
+ Returns:
2271
+ - list: A list of tuples, each representing a Givens rotation. Each tuple contains the rotation angle theta and indices (i,j) of the rotation.
2272
+ - list: A list of tuples, each representing an Rz rotation. Each tuple contains the rotation angle phi and the index (i) of the rotation.
2273
+ - numpy.array (optional): The diagonal matrix after applying all Givens rotations, returned if return_diagonal is True.
2274
+ '''
2275
+ U = unitary # no need to copy as we don't modify the original
2276
+ U[abs(U) < tol] = 0 # Zeroing out the small elements as per the tolerance level.
2277
+ n = U.shape[0]
2278
+
2279
+ # Determine optimized ordering if specified.
2280
+ if ordering == OPTIMIZED_ORDERING:
2281
+ ordering = ff.depth_eff_order_mf(n)
2282
+
2283
+ theta_list = []
2284
+ phi_list = []
2285
+
2286
+ def calcTheta(U, c, r):
2287
+ '''Calculate and apply the Givens rotation for a specific matrix element.'''
2288
+ t = numpy.arctan2(-U[r,c], U[r-1,c])
2289
+ theta_list.append((t, r, r-1))
2290
+ g = givens_matrix(n,r,r-1,t)
2291
+ U = numpy.dot(g, U)
2292
+
2293
+ return U
2294
+
2295
+ # Apply and store Givens rotations as per the given or computed ordering.
2296
+ if ordering is None:
2297
+ for c in range(n):
2298
+ for r in range(n-1, c, -1):
2299
+ U = calcTheta(U, c, r)
2300
+ else:
2301
+ for r, c in ordering:
2302
+ U = calcTheta(U, c, r)
2303
+
2304
+ # Calculating the Rz rotations based on the phases of the diagonal elements.
2305
+ # For real elements this means a 180 degree shift, i.e. a sign change.
2306
+ for i in range(n):
2307
+ ph = numpy.angle(U[i,i])
2308
+ phi_list.append((ph, i))
2309
+
2310
+ # Filtering out rotations without significance.
2311
+ theta_list_new = []
2312
+ for i, theta in enumerate(theta_list):
2313
+ if abs(theta[0] % (2*numpy.pi)) > tol:
2314
+ theta_list_new.append(theta)
2315
+
2316
+ phi_list_new = []
2317
+ for i, phi in enumerate(phi_list):
2318
+ if abs(phi[0]) > tol:
2319
+ phi_list_new.append(phi)
2320
+
2321
+ if return_diagonal:
2322
+ # Optionally return the resulting diagonal
2323
+ return theta_list_new, phi_list_new, U
2324
+ else:
2325
+ return theta_list_new, phi_list_new
2326
+
2327
+ def reconstruct_matrix_from_givens(n, theta_list, phi_list, to_real_if_possible = True, tol = 1e-12):
2328
+ '''
2329
+ Reconstructs a matrix from given Givens rotations and Rz diagonal rotations.
2330
+ This function is effectively an inverse of get_givens_decomposition, and therefore only works with data in the same format as its output.
2331
+
2332
+ Parameters:
2333
+ - n (int): The size of the unitary matrix to be reconstructed.
2334
+ - theta_list (list of tuples): Each tuple contains (angle, i, j) representing a Givens rotation of `angle` radians, applied to rows/columns `i` and `j`.
2335
+ - phi_list (list of tuples): Each tuple contains (angle, i), representing an Rz rotation by `angle` radians applied to the `i`th diagonal element.
2336
+ - to_real_if_possible (bool): If True, converts the matrix to real if its imaginary part is effectively zero.
2337
+ - tol (float): The tolerance whether to swap a complex rotation for a sign change.
2338
+
2339
+ Returns:
2340
+ - numpy.ndarray: The reconstructed complex or real matrix, depending on the `to_real_if_possible` flag and matrix composition.
2341
+ '''
2342
+ # Start with an identity matrix
2343
+ reconstructed = numpy.eye(n, dtype=complex)
2344
+
2345
+ # Apply Rz rotations for diagonal elements
2346
+ for phi in phi_list:
2347
+ angle, i = phi
2348
+ # Directly apply a sign flip if the rotation angle is π
2349
+ if numpy.isclose(angle, numpy.pi, atol=tol):
2350
+ reconstructed[i, i] *= -1
2351
+ else:
2352
+ reconstructed[i, i] *= numpy.exp(1j * angle)
2353
+
2354
+ # Apply Givens rotations in reverse order
2355
+ for theta in reversed(theta_list):
2356
+ angle, i, j = theta
2357
+ g = givens_matrix(n, i, j, angle)
2358
+ reconstructed = numpy.dot(g.conj().T, reconstructed) # Transpose of Givens matrix applied to the left
2359
+
2360
+ # Convert matrix to real if its imaginary part is negligible unless disabled via to_real_if_possible
2361
+ if to_real_if_possible:
2362
+ # Directly apply a sign flip if the rotation angle is π
2363
+ if numpy.all(reconstructed.imag == 0):
2364
+ # Convert to real by taking the real part
2365
+ reconstructed = reconstructed.real
2366
+
2367
+ return reconstructed
@@ -36,9 +36,12 @@ try:
36
36
  HAS_QISKIT = True
37
37
  INSTALLED_SIMULATORS["qiskit"] = BackendTypes(BackendCircuitQiskit, BackendExpectationValueQiskit)
38
38
  INSTALLED_SAMPLERS["qiskit"] = BackendTypes(BackendCircuitQiskit, BackendExpectationValueQiskit)
39
- INSTALLED_NOISE_SAMPLERS["qiskit"] = BackendTypes(BackendCircuitQiskit, BackendExpectationValueQiskit)
39
+ from tequila.simulators.simulator_qiskit import HAS_NOISE as HAS_QISKIT_NOISE
40
+ if HAS_QISKIT_NOISE:
41
+ INSTALLED_NOISE_SAMPLERS["qiskit"] = BackendTypes(BackendCircuitQiskit, BackendExpectationValueQiskit)
40
42
  except ImportError:
41
43
  HAS_QISKIT = False
44
+ HAS_QISKIT_NOISE = False
42
45
 
43
46
  HAS_QIBO = True
44
47
  try:
@@ -133,6 +136,8 @@ def show_available_simulators():
133
136
  str(k in INSTALLED_SAMPLERS),
134
137
  str(k in INSTALLED_NOISE_SAMPLERS),
135
138
  str(k in INSTALLED_BACKENDS)))
139
+ if HAS_QISKIT and not HAS_QISKIT_NOISE:
140
+ print("missing qiskit_aer: no noisy simulation")
136
141
 
137
142
 
138
143
  def pick_backend(backend: str = None, samples: int = None, noise: NoiseModel = None, device=None,
@@ -3,12 +3,20 @@ from tequila.wavefunction.qubit_wavefunction import QubitWaveFunction
3
3
  from tequila import TequilaException, TequilaWarning
4
4
  from tequila import BitString, BitNumbering, BitStringLSB
5
5
  from tequila.utils.keymap import KeyMapRegisterToSubregister
6
- import qiskit, numpy, warnings
7
- import qiskit.providers.aer.noise as qiskitnoise
8
6
  from tequila.utils import to_float
9
- import qiskit.test.mock.backends
10
- from qiskit.providers.ibmq import IBMQBackend
7
+ import qiskit, numpy, warnings
11
8
 
9
+ HAS_NOISE=True
10
+ try:
11
+ from qiskit_aer import noise as qiskitnoise
12
+ except:
13
+ HAS_NOISE = False
14
+
15
+ HAS_IBMQ=True
16
+ try:
17
+ from qiskit.providers.ibmq import IBMQBackend
18
+ except:
19
+ HAS_IBMQ=False
12
20
 
13
21
  def get_bit_flip(p):
14
22
  """
@@ -137,7 +145,7 @@ class BackendCircuitQiskit(BackendCircuit):
137
145
  }
138
146
 
139
147
  numbering = BitNumbering.LSB
140
-
148
+
141
149
  def __init__(self, abstract_circuit: QCircuit, variables, qubit_map=None, noise=None,
142
150
  device=None, *args, **kwargs):
143
151
  """
@@ -169,7 +177,7 @@ class BackendCircuitQiskit(BackendCircuit):
169
177
  'Rx': (lambda c: c.rx, lambda c: c.mcrx),
170
178
  'Ry': (lambda c: c.ry, lambda c: c.mcry),
171
179
  'Rz': (lambda c: c.rz, lambda c: c.mcrz),
172
- 'Phase': (lambda c: c.u1, lambda c: c.cu1),
180
+ 'Phase': (lambda c: c.p, lambda c: c.cp),
173
181
  'SWAP': (lambda c: c.swap, lambda c: c.cswap),
174
182
  }
175
183
 
@@ -2,6 +2,7 @@ import numpy as np
2
2
  from tequila.circuit import gates
3
3
  from tequila.circuit.circuit import QCircuit
4
4
  from tequila.hamiltonian.qubit_hamiltonian import QubitHamiltonian
5
+ from scipy.stats import unitary_group, ortho_group
5
6
 
6
7
  def make_random_circuit(n_qubits: int, rotation_gates: list=['rx', 'ry', 'rz'], n_rotations: int=None,
7
8
  enable_controls: bool=None) -> QCircuit:
@@ -75,3 +76,19 @@ def make_random_hamiltonian(n_qubits: int , paulis: list=['X','Y','Z'], n_ps: in
75
76
 
76
77
  H = QubitHamiltonian(ham)
77
78
  return H
79
+
80
+ def generate_random_unitary(size, complex = False):
81
+ '''
82
+ Generates a random unitary (or furthermore orthogonal if complex is False) matrix of a specified size.
83
+
84
+ Parameters:
85
+ - size (int): The size of the unitary matrix to be generated.
86
+ - complex (bool, optional): Whether the unitary should be complex.
87
+
88
+ Returns:
89
+ - numpy.ndarray: A randomly generated unitary matrix.
90
+ '''
91
+ if complex:
92
+ return unitary_group.rvs(size)
93
+ else:
94
+ return ortho_group.rvs(size)
tequila/version.py CHANGED
@@ -1,2 +1,2 @@
1
- __version__ = "1.9.5"
1
+ __version__ = "1.9.6"
2
2
  __author__ = "Tequila Developers "
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: tequila-basic
3
- Version: 1.9.5
3
+ Version: 1.9.6
4
4
  Summary: A High-Level Abstraction Framework for Quantum Algorithms
5
5
  Home-page: https://github.com/tequilahub/tequila
6
6
  Author: Tequila Developers
@@ -32,7 +32,7 @@ Tequila can execute the underlying quantum expectation values on state of the ar
32
32
  - [talks and slides](https://kottmanj.github.io/talks_and_material/)
33
33
 
34
34
  # Installation
35
- Recommended Python version is 3.9 - 3.10.
35
+ Recommended Python version is 3.9 (3.10).
36
36
  Tequila supports linux, osx and windows. However, not all optional dependencies are supported on windows.
37
37
 
38
38
  ## Install from PyPi
@@ -269,11 +269,7 @@ Quantum Equation of Motion with Orbital Optimization for Computing Molecular Pro
269
269
  Let us know, if you want your research project and/or tutorial to be included in this list!
270
270
 
271
271
  # Dependencies
272
- Support for additional optimizers or quantum backends can be activated by intalling them in your environment.
273
- Tequila will then detect them automatically.
274
- Currently those are: [Phoenics](https://github.com/aspuru-guzik-group/phoenics)
275
- and [GPyOpt](https://sheffieldml.github.io/GPyOpt/).
276
- Quantum backends are treated in the same way.
272
+ Support for specific backends (quantum simulators, optimizers, quantum chemistry) can be activated by intalling them in your environment.
277
273
 
278
274
  ## Quantum Backends
279
275
  Currently supported
@@ -407,5 +403,3 @@ Tequila runs on Mac OSX.
407
403
  You might get in trouble with installing qulacs since it currently does not work with Apple's clang compiler.
408
404
  You need to install latest GNU compile (at least gcc-7 and g++7) and set them as default before installing qulacs over pip.
409
405
 
410
- ## Qibo and GPyOpt
411
- Currently you can't use Qibo and GPyOpt within the same environment.
@@ -1,6 +1,6 @@
1
1
  tequila/__init__.py,sha256=FV8-j7GEw_VYadsZUp3M2mGRQxVUYYG3W1jiI6in3CY,1959
2
2
  tequila/autograd_imports.py,sha256=t7V5uYaI0GzjD7pSjkYtiaj3BzSvkm_RL2KcYfNwNhM,1529
3
- tequila/version.py,sha256=TrfaFu9jLo_4f8zxqIwjs8NumC_hbB4Op1r-ZZIEnyY,57
3
+ tequila/version.py,sha256=eF54kEK_euvFMukAbk5bfXdISBhBIxw4DzJuY9f-z3c,57
4
4
  tequila/apps/__init__.py,sha256=GJb04napv8AAx5EHxS5C1CMv9kxQeu7aA-ZMWk6X_eQ,1623
5
5
  tequila/apps/_unary_state_prep_impl.py,sha256=SzRtI0Nx29ODygvYYdC1NnSTCL70wY7NTAvqhiwpMDs,21757
6
6
  tequila/apps/unary_state_prep.py,sha256=QCrD9Ty2RkXc1Mh_MitFPIdaPs_fLxp_dtWVBZi0tSE,9403
@@ -15,14 +15,14 @@ tequila/circuit/__init__.py,sha256=ZgoUEjU_NggxjKYkJjh5aO-6VdUjnO5CLxKB44rHzQc,3
15
15
  tequila/circuit/_gates_impl.py,sha256=iB40Sg9l9UoCCayu0l4vGjgvEHUVVbXMaGdUtXIHa1w,17821
16
16
  tequila/circuit/circuit.py,sha256=u1qwDFNrZspgea4BFcxwG-hk43ZKAtO2GVCchuctu4s,32044
17
17
  tequila/circuit/compiler.py,sha256=fsHnnNZo43VWUl_n34P21b4GAi7k2kwoYdx0xlbAuZY,32685
18
- tequila/circuit/gates.py,sha256=pOvX9_vACFyUAZRG4EGW3_aZGXysUJwUV8oFiKyLJ50,35906
18
+ tequila/circuit/gates.py,sha256=buNzNZaflRzVFe1oihCprUBZVL5KcZXyd_kqiWkNbTo,35923
19
19
  tequila/circuit/gradient.py,sha256=Y4dNL6nkZUEkKJvaA3hxaSEa8_b_3XZwxy3j8tGsOmA,10465
20
20
  tequila/circuit/noise.py,sha256=2LJ7Xq5f78x9p4imIz76l_lABQZwgNteNBFkWmUAQvo,8322
21
21
  tequila/circuit/pyzx.py,sha256=XHhKoklhEcbpYkgkWHBLmKF-vyt_Oz-pX-Ctvd4nAOQ,1472
22
22
  tequila/circuit/qasm.py,sha256=iB5stV6Exo3bAn7ac1PgFKH53XD-57b9lpmzjavJK7k,15418
23
- tequila/circuit/qpic.py,sha256=rjNAStvgNtqa89wJ3pmuzPoPWGZVI0gxARZuUnGtJa0,10789
23
+ tequila/circuit/qpic.py,sha256=sUMXsuYqIgtYF1Cs37Trxtaw6xHNjR4ykrM2fB4T2-I,10787
24
24
  tequila/grouping/__init__.py,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
25
- tequila/grouping/binary_rep.py,sha256=VVM2o6B_RC0uH8kqE4yNxTzkGlgUm-CJTZ6z5J7R9I8,19406
25
+ tequila/grouping/binary_rep.py,sha256=MiiAr_xie2fanscfJN0EKToGlCH7po7dEOZKE7c81vM,19411
26
26
  tequila/grouping/binary_utils.py,sha256=ubV8zv3nmz2o74A2W69LeCH6bIZZLHw48lk8ROv-jas,10916
27
27
  tequila/grouping/compile_groups.py,sha256=a9it48zZxJs167nz1FWS_oEmPHPuXq0oLaCs1hJgyBE,66415
28
28
  tequila/grouping/ev_utils.py,sha256=4pnzjRYyOB4KTZsfhs7YSU8Ez4jCJP3YSFKtMOjSwgY,8968
@@ -48,20 +48,20 @@ tequila/optimizers/optimizer_gd.py,sha256=QF84K2XDn_-0w9htDlEpIaaGGtfudNamIvVCgx
48
48
  tequila/optimizers/optimizer_gpyopt.py,sha256=-aVuutZUScyo6_4q4PyvMMa_OVd3L8ev9Ge2fXyWGV8,11280
49
49
  tequila/optimizers/optimizer_scipy.py,sha256=zqRVQ-Whr74KCGP7Zg1jQkl9S3j9s1kS4oCrCtX30gY,18949
50
50
  tequila/quantumchemistry/__init__.py,sha256=KP99PNJYVwBcfQGwL-MB9IBLSBJNRPf-5WN9NLqT-Rg,7424
51
- tequila/quantumchemistry/chemistry_tools.py,sha256=2zpQU8p_xV2mDQ6Q1tWqQPdAvt2OqjQV8PcGgiOo0UU,41353
52
- tequila/quantumchemistry/encodings.py,sha256=y9h6rjq1K9IPVBMbRFQWXyBuAIZzgh2DVw2IUKtpuIM,8656
53
- tequila/quantumchemistry/madness_interface.py,sha256=f5c19Whb9Ene9UnkU1aKFqcGFkvN_TrR1o_G7xuC5dE,36304
51
+ tequila/quantumchemistry/chemistry_tools.py,sha256=thHsovI-pMJJbEFBuYUAXg2ptitnGe9CeD0mdsh3iV8,46989
52
+ tequila/quantumchemistry/encodings.py,sha256=YPpFjo4GacWYNxIvDSe6PhNSWBKu6Zm4IlEdy51eUJM,11577
53
+ tequila/quantumchemistry/madness_interface.py,sha256=ivwDoaUDyAB6lJoFri0pZpvOZbihGavIuybcc40xTD0,36372
54
54
  tequila/quantumchemistry/orbital_optimizer.py,sha256=P_y4Q1qK-C46wgBjL4FBnSHeVSoKlzmkCG5eQWFU4_k,12376
55
55
  tequila/quantumchemistry/psi4_interface.py,sha256=syNaDvlSmCsyB4f7idn3VGbMKyKo83vJHD5y5LpHwaM,29953
56
56
  tequila/quantumchemistry/pyscf_interface.py,sha256=XgecUnKKg2rGiKqsYCJnDQ89ekkDkKuwc3qHULLMYck,6152
57
- tequila/quantumchemistry/qc_base.py,sha256=Bmz2lHsbtiJkb07ZZJ5EPAoW0TywQOxZgwagVHT3rEg,96531
57
+ tequila/quantumchemistry/qc_base.py,sha256=x8bQUW35rlHeqd2NheWQrr7cDWYf_niU4FOR5HY2Dgk,106384
58
58
  tequila/simulators/__init__.py,sha256=VFw4sJIt4Zc0-__eYnksN8Ku9qMhbPpHJEkXMWUiD30,4
59
- tequila/simulators/simulator_api.py,sha256=mLYA6GzujaNAGrDq1rtLQrW8tFZsCeyYnOnWRTlU6Eo,24172
59
+ tequila/simulators/simulator_api.py,sha256=Rvaljb2yFVMLHzj7ImzMCiTbY1fN59wcxFrE67n-QcU,24413
60
60
  tequila/simulators/simulator_base.py,sha256=93d-f4fNkJ2CtpL9OpgKcypmZH96Mdd9ESdZYn9jH48,33174
61
61
  tequila/simulators/simulator_cirq.py,sha256=z8G3dtZluaQZWPaNs4o3SBKfC33GClC-nplVOyhI1sg,16535
62
62
  tequila/simulators/simulator_pyquil.py,sha256=Xm8fDg9PTFOg3apzd0T8hNKHy4sFrJIbSdnLtvtm-HM,24240
63
63
  tequila/simulators/simulator_qibo.py,sha256=evOGd_-uyUQaQu60K02KIIqtTqjn1jW6XS9ux2TsC9M,25095
64
- tequila/simulators/simulator_qiskit.py,sha256=KZhyvbziCEOx-oO5bfyZlU0cEBkZNW1uvuHLPkVNrJo,23429
64
+ tequila/simulators/simulator_qiskit.py,sha256=d96aqOyQFyqM1W7aJBN_uhBYzt-WxsCZTlhEM-pJhLQ,23506
65
65
  tequila/simulators/simulator_qlm.py,sha256=28c7GmRGWWkbVrvtaw9S4ERkL0fg-TGceayybtQ4K6w,15398
66
66
  tequila/simulators/simulator_qulacs.py,sha256=0XdCA3y7KCqYfL7S4FOssZgxAgs0Hd1GohleNZHSRuA,19728
67
67
  tequila/simulators/simulator_qulacs_gpu.py,sha256=J-QB4jWeZL176G7UFtPkCEReGJXA0mY4iDavfUF07Oo,659
@@ -69,7 +69,7 @@ tequila/simulators/simulator_symbolic.py,sha256=H5E9OwFdBYV1lovNPMK3a8cyU8m_EIHm
69
69
  tequila/tools/__init__.py,sha256=mJChgkme6v6Ohj2s3tJ96Mq4U0kmVmc6d8Y6_1pEZMg,72
70
70
  tequila/tools/convenience.py,sha256=9WYQJvx5i2QwQG8c7lssYTUv5hzW8h16JTr1GHxYf18,1291
71
71
  tequila/tools/qng.py,sha256=p19A1rcKo06DAyBVUCQzNhwIGni6eAT6IGPnEPhKa4Y,21326
72
- tequila/tools/random_generators.py,sha256=g9c78n_HoBB9WCu77LiGNzZ8lomca0ijHlSI5dHocpU,2863
72
+ tequila/tools/random_generators.py,sha256=UwkDMmNxxSPgaH1LNBswZUiHnLDd8arI3F5QshfBtBY,3417
73
73
  tequila/utils/__init__.py,sha256=nlulDMHcq-XyBZf3NPx2bn_tcixi2mvhRc6MhU9TBWI,317
74
74
  tequila/utils/bitstrings.py,sha256=b2qaicAuDvzb9guTCZvQ1XCgN3dHaJuQ1nlubDgatD4,5689
75
75
  tequila/utils/exceptions.py,sha256=QK7AcDO2-7Itr8Aw6rLP_WtSkH6rfT8PHWcvNM6sQnc,1188
@@ -78,8 +78,8 @@ tequila/utils/keymap.py,sha256=RgQzeHEfRVee0-uoH-QsLYsGsXyMhEp3n33KCH-EV2k,3735
78
78
  tequila/utils/misc.py,sha256=e62ASkFReaLJQXnBXzyYukzXZnXNoURsM1luoMeIXiE,919
79
79
  tequila/wavefunction/__init__.py,sha256=q4DVL0lGFg03PogRMYA6S8MQqqmLYQiU9VNOF-YQxfQ,50
80
80
  tequila/wavefunction/qubit_wavefunction.py,sha256=16Y9vRj6Yc6sBAKRUHVXJG4lJLDjWyN1b5fugf2LAmI,11881
81
- tequila_basic-1.9.5.dist-info/LICENSE,sha256=oG1FtUav5_xrym9ByiG5emJDQRcbnAfTB08fRV9TCiE,1114
82
- tequila_basic-1.9.5.dist-info/METADATA,sha256=dkAMyh6gVEZDDlmGeJ2NFZVvmXbjE3jpxYYrDY-7XbI,19694
83
- tequila_basic-1.9.5.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
84
- tequila_basic-1.9.5.dist-info/top_level.txt,sha256=VBH0gl6mDMbcLHKlO0yEAqtcq08DqBHz4gRJ9jafl5w,8
85
- tequila_basic-1.9.5.dist-info/RECORD,,
81
+ tequila_basic-1.9.6.dist-info/LICENSE,sha256=oG1FtUav5_xrym9ByiG5emJDQRcbnAfTB08fRV9TCiE,1114
82
+ tequila_basic-1.9.6.dist-info/METADATA,sha256=vtmnWlAqZZdQ0Rylr2_fgVF66QaUZOsBY9uOZGYHM_w,19409
83
+ tequila_basic-1.9.6.dist-info/WHEEL,sha256=y4mX-SOX4fYIkonsAGA5N0Oy-8_gI4FXw5HNI1xqvWg,91
84
+ tequila_basic-1.9.6.dist-info/top_level.txt,sha256=VBH0gl6mDMbcLHKlO0yEAqtcq08DqBHz4gRJ9jafl5w,8
85
+ tequila_basic-1.9.6.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: bdist_wheel (0.43.0)
2
+ Generator: setuptools (70.2.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5