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
@@ -2,6 +2,7 @@
2
2
  Collections of Fermion-to-Qubit encodings known to tequila
3
3
  Most are Interfaces to OpenFermion
4
4
  """
5
+
5
6
  import abc
6
7
 
7
8
  from tequila import TequilaException
@@ -19,14 +20,17 @@ def known_encodings():
19
20
  "BravyiKitaev": BravyiKitaev,
20
21
  "BravyiKitaevFast": BravyiKitaevFast,
21
22
  "BravyiKitaevTree": BravyiKitaevTree,
22
- "TaperedBravyiKitaev": TaperedBravyKitaev
23
+ "TaperedBravyiKitaev": TaperedBravyKitaev,
24
+ "TaperedBinary": TaperedBinary,
23
25
  }
24
26
  # aliases
25
- encodings = {**encodings,
26
- "ReorderedJordanWigner": lambda **kwargs: JordanWigner(up_then_down=True, **kwargs),
27
- "ReorderedBravyiKitaev": lambda **kwargs: BravyiKitaev(up_then_down=True, **kwargs),
28
- "ReorderedBravyiKitaevTree": lambda **kwargs: BravyiKitaevTree(up_then_down=True, **kwargs),
29
- }
27
+ encodings = {
28
+ **encodings,
29
+ "ReorderedJordanWigner": lambda **kwargs: JordanWigner(up_then_down=True, **kwargs),
30
+ "ReorderedBravyiKitaev": lambda **kwargs: BravyiKitaev(up_then_down=True, **kwargs),
31
+ "ReorderedBravyiKitaevTree": lambda **kwargs: BravyiKitaevTree(up_then_down=True, **kwargs),
32
+ "ReorderedTaperedBinary": lambda **kwargs: TaperedBinary(up_then_down=True, **kwargs),
33
+ }
30
34
  return {k.replace("_", "").replace("-", "").upper(): v for k, v in encodings.items()}
31
35
 
32
36
 
@@ -63,8 +67,9 @@ class EncodingBase(metaclass=abc.ABCMeta):
63
67
  The openfermion QubitOperator of this class ecoding
64
68
  """
65
69
  if self.up_then_down:
66
- op = openfermion.reorder(operator=fermion_operator, order_function=openfermion.up_then_down,
67
- num_modes=2 * self.n_orbitals)
70
+ op = openfermion.reorder(
71
+ operator=fermion_operator, order_function=openfermion.up_then_down, num_modes=2 * self.n_orbitals
72
+ )
68
73
  else:
69
74
  op = fermion_operator
70
75
 
@@ -128,6 +133,7 @@ class EncodingBase(metaclass=abc.ABCMeta):
128
133
  fop = openfermion.FermionOperator(string, 1.0)
129
134
  op = self(fop)
130
135
  from tequila.wavefunction.qubit_wavefunction import QubitWaveFunction
136
+
131
137
  wfn = QubitWaveFunction.from_basis_state(n_qubits, 0)
132
138
  wfn = wfn.apply_qubitoperator(operator=op)
133
139
  assert wfn.length() == 1
@@ -200,6 +206,7 @@ class JordanWigner(EncodingBase):
200
206
  """
201
207
  OpenFermion::jordan_wigner
202
208
  """
209
+
203
210
  _ucc_support = True
204
211
 
205
212
  def do_transform(self, fermion_operator: openfermion.FermionOperator, *args, **kwargs) -> openfermion.QubitOperator:
@@ -275,7 +282,9 @@ class BravyiKitaevFast(EncodingBase):
275
282
  if n_qubits != self.n_orbitals * 2:
276
283
  raise Exception(
277
284
  "BravyiKitaevFast transformation currently only possible for full Hamiltonians (no UCC generators).\nfermion_operator was {}".format(
278
- fermion_operator))
285
+ fermion_operator
286
+ )
287
+ )
279
288
  op = openfermion.get_interaction_operator(fermion_operator)
280
289
  return openfermion.bravyi_kitaev_fast(op)
281
290
 
@@ -311,12 +320,14 @@ class TaperedBravyKitaev(EncodingBase):
311
320
  def do_transform(self, fermion_operator: openfermion.FermionOperator, *args, **kwargs) -> openfermion.QubitOperator:
312
321
  if openfermion.count_qubits(fermion_operator) != self.n_orbitals * 2:
313
322
  raise Exception("TaperedBravyiKitaev not ready for UCC generators yet")
314
- return openfermion.symmetry_conserving_bravyi_kitaev(fermion_operator, active_orbitals=self.active_orbitals,
315
- active_fermions=self.active_fermions)
323
+ return openfermion.symmetry_conserving_bravyi_kitaev(
324
+ fermion_operator, active_orbitals=self.active_orbitals, active_fermions=self.active_fermions
325
+ )
316
326
 
317
327
  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)
328
+ non_tapered_trafo = BravyiKitaevTree(
329
+ up_then_down=True, n_electrons=self.n_electrons, n_orbitals=self.n_orbitals
330
+ )
320
331
  key = non_tapered_trafo.map_state(state=state, *args, **kwargs)
321
332
  n_qubits = self.n_orbitals * 2
322
333
  active_qubits = [i for i in range(n_qubits) if i not in [n_qubits - 1, n_qubits // 2 - 1]]
@@ -325,3 +336,100 @@ class TaperedBravyKitaev(EncodingBase):
325
336
 
326
337
  def me_to_jw(self) -> QCircuit:
327
338
  raise TequilaException("{}::me_to_jw: unimplemented".format(type(self).__name__))
339
+
340
+
341
+ class TaperedBinary(EncodingBase):
342
+ _ucc_support = True
343
+
344
+ """
345
+ Uses OpenFermion::binary_code_transform (checksum code arxiv:1712.07067)
346
+ Reduces Hamiltonian by 2 qubits
347
+ See OpenFermion Documentation for more
348
+ """
349
+
350
+ def __init__(
351
+ self, n_electrons, n_orbitals, active_fermions=None, active_orbitals=None, up_then_down=False, *args, **kwargs
352
+ ):
353
+ if active_fermions is None:
354
+ self.active_fermions = (
355
+ n_electrons # it maybe changed at some point to support different number of alpha and beta electr
356
+ )
357
+ else:
358
+ self.active_fermions = active_fermions
359
+ if active_orbitals is None:
360
+ self.active_orbitals = n_orbitals * 2 # in openfermion those are spin-orbitals
361
+ else:
362
+ self.active_orbitals = active_orbitals
363
+ super().__init__(n_orbitals=n_orbitals, n_electrons=n_electrons, up_then_down=up_then_down, *args, **kwargs)
364
+ self.spin_parity = bool((self.n_electrons / 2) % 2) # total parity of all \sigma\in\{\alpha\beta\} SOs
365
+ from scipy.special import factorial
366
+
367
+ self.modes = self.active_orbitals # asumed n alpha = n beta
368
+
369
+ def __call__(self, fermion_operator: openfermion.FermionOperator, *args, **kwargs) -> QubitHamiltonian:
370
+ """
371
+ :param fermion_operator:
372
+ an openfermion FermionOperator
373
+ :return:
374
+ The openfermion QubitOperator of this class ecoding
375
+ """
376
+ fop = self.do_transform(fermion_operator=fermion_operator, *args, **kwargs)
377
+ fop.compress()
378
+ return self.post_processing(QubitHamiltonian.from_openfermion(fop))
379
+
380
+ def do_transform(self, fermion_operator: openfermion.FermionOperator, *args, **kwargs) -> openfermion.QubitOperator:
381
+ mul = openfermion.interleaved_code(self.modes) * (
382
+ 2 * openfermion.transforms.checksum_code(self.modes // 2, self.spin_parity)
383
+ )
384
+ return openfermion.transforms.binary_code_transform(fermion_operator, mul)
385
+
386
+ def post_processing(self, op: QubitHamiltonian, *args, **kwargs):
387
+ if not self.up_then_down:
388
+ da = {i: 2 * i for i in range(self.n_orbitals - 1)}
389
+ db = {i + self.n_orbitals - 1: 2 * i + 1 for i in range(self.n_orbitals - 1)}
390
+ da.update(db)
391
+ op = op.map_qubits(da)
392
+ return op
393
+
394
+ def map_state(self, state: list, *args, **kwargs):
395
+ if len(state) < (2 * self.n_orbitals - 2):
396
+ state = state + [0] * (2 * self.n_orbitals - len(state) - 2)
397
+ if self.up_then_down:
398
+ return [state[2 * i] for i in range(self.n_orbitals - 1)] + [
399
+ state[2 * i + 1] for i in range(self.n_orbitals - 1)
400
+ ]
401
+ else:
402
+ return state
403
+
404
+ def me_to_jw(self) -> QCircuit:
405
+ """
406
+ In case of upthendown, expected to be qubit_{n_orbital} free, otherwise please map it properly
407
+ """
408
+ U = QCircuit()
409
+ if self.spin_parity: # since we now the spin parity
410
+ U += X(2 * self.n_orbitals - 2) + X(2 * self.n_orbitals - 1)
411
+ for i in range(
412
+ self.n_orbitals - 1
413
+ ): # we can tapper only one electron per \sigma, we need only to find the difference
414
+ U += CNOT(2 * i, 2 * self.n_orbitals - 2)
415
+ U += CNOT(2 * i + 1, 2 * self.n_orbitals - 1)
416
+ if self.up_then_down:
417
+ da = {2 * i: i for i in range(self.n_orbitals)}
418
+ db = {2 * i + 1: self.n_orbitals + i - 1 for i in range(self.n_orbitals)}
419
+ db.update(da)
420
+ U = U.map_qubits(db)
421
+ return U
422
+
423
+ def hcb_to_me(self) -> QCircuit:
424
+ """
425
+ The HCB term of the tappered orbital is not proyected out but should affect to the ExpValue since it is not
426
+ on the Hamiltonian
427
+ """
428
+ U = QCircuit()
429
+ for i in range(self.n_orbitals - 1):
430
+ U += CNOT(
431
+ control=i + i * (not self.up_then_down),
432
+ target=i + self.up_then_down * (self.n_orbitals - 1) + (not self.up_then_down) * (i + 1),
433
+ )
434
+ U.n_qubits = 2 * self.n_orbitals - 2
435
+ return U