tequila-basic 1.9.10__tar.gz → 1.9.12__tar.gz

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 (140) hide show
  1. {tequila_basic-1.9.10/src/tequila_basic.egg-info → tequila_basic-1.9.12}/PKG-INFO +4 -3
  2. {tequila_basic-1.9.10 → tequila_basic-1.9.12}/README.md +1 -1
  3. {tequila_basic-1.9.10 → tequila_basic-1.9.12}/requirements.txt +3 -2
  4. {tequila_basic-1.9.10 → tequila_basic-1.9.12}/src/tequila/__init__.py +8 -2
  5. {tequila_basic-1.9.10 → tequila_basic-1.9.12}/src/tequila/apps/__init__.py +1 -1
  6. {tequila_basic-1.9.10 → tequila_basic-1.9.12}/src/tequila/apps/krylov/krylov.py +41 -4
  7. {tequila_basic-1.9.10 → tequila_basic-1.9.12}/src/tequila/circuit/_gates_impl.py +1 -1
  8. {tequila_basic-1.9.10 → tequila_basic-1.9.12}/src/tequila/circuit/circuit.py +22 -48
  9. {tequila_basic-1.9.10 → tequila_basic-1.9.12}/src/tequila/circuit/compiler.py +126 -9
  10. {tequila_basic-1.9.10 → tequila_basic-1.9.12}/src/tequila/circuit/gates.py +8 -12
  11. {tequila_basic-1.9.10 → tequila_basic-1.9.12}/src/tequila/circuit/gradient.py +84 -4
  12. {tequila_basic-1.9.10 → tequila_basic-1.9.12}/src/tequila/circuit/postselection.py +40 -5
  13. {tequila_basic-1.9.10 → tequila_basic-1.9.12}/src/tequila/grouping/fermionic_functions.py +3 -3
  14. {tequila_basic-1.9.10 → tequila_basic-1.9.12}/src/tequila/hamiltonian/paulis.py +1 -1
  15. {tequila_basic-1.9.10 → tequila_basic-1.9.12}/src/tequila/hamiltonian/qubit_hamiltonian.py +4 -1
  16. {tequila_basic-1.9.10 → tequila_basic-1.9.12}/src/tequila/objective/__init__.py +8 -0
  17. {tequila_basic-1.9.10 → tequila_basic-1.9.12}/src/tequila/objective/objective.py +420 -42
  18. tequila_basic-1.9.12/src/tequila/objective/quantum_arg.py +39 -0
  19. {tequila_basic-1.9.10 → tequila_basic-1.9.12}/src/tequila/optimizers/__init__.py +18 -3
  20. {tequila_basic-1.9.10 → tequila_basic-1.9.12}/src/tequila/optimizers/optimizer_base.py +5 -1
  21. tequila_basic-1.9.12/src/tequila/optimizers/optimizer_excsolve.py +142 -0
  22. {tequila_basic-1.9.10 → tequila_basic-1.9.12}/src/tequila/optimizers/optimizer_gd.py +1 -1
  23. {tequila_basic-1.9.10 → tequila_basic-1.9.12}/src/tequila/quantumchemistry/chemistry_tools.py +81 -23
  24. {tequila_basic-1.9.10 → tequila_basic-1.9.12}/src/tequila/quantumchemistry/encodings.py +1 -1
  25. {tequila_basic-1.9.10 → tequila_basic-1.9.12}/src/tequila/quantumchemistry/orbital_optimizer.py +12 -2
  26. {tequila_basic-1.9.10 → tequila_basic-1.9.12}/src/tequila/quantumchemistry/psi4_interface.py +2 -2
  27. {tequila_basic-1.9.10 → tequila_basic-1.9.12}/src/tequila/quantumchemistry/pyscf_interface.py +120 -16
  28. {tequila_basic-1.9.10 → tequila_basic-1.9.12}/src/tequila/quantumchemistry/qc_base.py +140 -87
  29. {tequila_basic-1.9.10 → tequila_basic-1.9.12}/src/tequila/simulators/simulator_api.py +151 -86
  30. {tequila_basic-1.9.10 → tequila_basic-1.9.12}/src/tequila/simulators/simulator_base.py +211 -3
  31. {tequila_basic-1.9.10 → tequila_basic-1.9.12}/src/tequila/simulators/simulator_cudaq.py +16 -16
  32. {tequila_basic-1.9.10 → tequila_basic-1.9.12}/src/tequila/simulators/simulator_pyquil.py +1 -1
  33. {tequila_basic-1.9.10 → tequila_basic-1.9.12}/src/tequila/simulators/simulator_qiskit.py +109 -39
  34. {tequila_basic-1.9.10 → tequila_basic-1.9.12}/src/tequila/simulators/simulator_qulacs.py +119 -2
  35. tequila_basic-1.9.12/src/tequila/utils/objective_graph.py +1672 -0
  36. {tequila_basic-1.9.10 → tequila_basic-1.9.12}/src/tequila/version.py +1 -1
  37. tequila_basic-1.9.12/src/tequila/wavefunction/density_matrix.py +229 -0
  38. {tequila_basic-1.9.10 → tequila_basic-1.9.12}/src/tequila/wavefunction/qubit_wavefunction.py +38 -1
  39. {tequila_basic-1.9.10 → tequila_basic-1.9.12/src/tequila_basic.egg-info}/PKG-INFO +4 -3
  40. {tequila_basic-1.9.10 → tequila_basic-1.9.12}/src/tequila_basic.egg-info/SOURCES.txt +4 -1
  41. {tequila_basic-1.9.10 → tequila_basic-1.9.12}/src/tequila_basic.egg-info/requires.txt +2 -1
  42. tequila_basic-1.9.12/tests/test_braket.py +524 -0
  43. {tequila_basic-1.9.10 → tequila_basic-1.9.12}/tests/test_chemistry.py +137 -38
  44. {tequila_basic-1.9.10 → tequila_basic-1.9.12}/tests/test_circuit_unitary.py +3 -7
  45. {tequila_basic-1.9.10 → tequila_basic-1.9.12}/tests/test_gates.py +13 -0
  46. {tequila_basic-1.9.10 → tequila_basic-1.9.12}/tests/test_recompilation_routines.py +51 -1
  47. {tequila_basic-1.9.10 → tequila_basic-1.9.12}/tests/test_scipy.py +1 -45
  48. {tequila_basic-1.9.10 → tequila_basic-1.9.12}/tests/test_simulator_backends.py +66 -7
  49. tequila_basic-1.9.10/src/tequila/objective/braket.py +0 -192
  50. tequila_basic-1.9.10/tests/test_braket.py +0 -274
  51. {tequila_basic-1.9.10 → tequila_basic-1.9.12}/LICENSE +0 -0
  52. {tequila_basic-1.9.10 → tequila_basic-1.9.12}/MANIFEST.in +0 -0
  53. {tequila_basic-1.9.10 → tequila_basic-1.9.12}/setup.cfg +0 -0
  54. {tequila_basic-1.9.10 → tequila_basic-1.9.12}/setup.py +0 -0
  55. {tequila_basic-1.9.10 → tequila_basic-1.9.12}/src/tequila/apps/_unary_state_prep_impl.py +0 -0
  56. {tequila_basic-1.9.10 → tequila_basic-1.9.12}/src/tequila/apps/adapt/__init__.py +0 -0
  57. {tequila_basic-1.9.10 → tequila_basic-1.9.12}/src/tequila/apps/adapt/adapt.py +0 -0
  58. {tequila_basic-1.9.10 → tequila_basic-1.9.12}/src/tequila/apps/krylov/__init__.py +0 -0
  59. {tequila_basic-1.9.10 → tequila_basic-1.9.12}/src/tequila/apps/robustness/__init__.py +0 -0
  60. {tequila_basic-1.9.10 → tequila_basic-1.9.12}/src/tequila/apps/robustness/helpers.py +0 -0
  61. {tequila_basic-1.9.10 → tequila_basic-1.9.12}/src/tequila/apps/robustness/interval.py +0 -0
  62. {tequila_basic-1.9.10 → tequila_basic-1.9.12}/src/tequila/apps/unary_state_prep.py +0 -0
  63. {tequila_basic-1.9.10 → tequila_basic-1.9.12}/src/tequila/autograd_imports.py +0 -0
  64. {tequila_basic-1.9.10 → tequila_basic-1.9.12}/src/tequila/circuit/__init__.py +0 -0
  65. {tequila_basic-1.9.10 → tequila_basic-1.9.12}/src/tequila/circuit/noise.py +0 -0
  66. {tequila_basic-1.9.10 → tequila_basic-1.9.12}/src/tequila/circuit/pyzx.py +0 -0
  67. {tequila_basic-1.9.10 → tequila_basic-1.9.12}/src/tequila/circuit/qasm.py +0 -0
  68. {tequila_basic-1.9.10 → tequila_basic-1.9.12}/src/tequila/circuit/qpic.py +0 -0
  69. {tequila_basic-1.9.10 → tequila_basic-1.9.12}/src/tequila/grouping/__init__.py +0 -0
  70. {tequila_basic-1.9.10 → tequila_basic-1.9.12}/src/tequila/grouping/binary_rep.py +0 -0
  71. {tequila_basic-1.9.10 → tequila_basic-1.9.12}/src/tequila/grouping/binary_utils.py +0 -0
  72. {tequila_basic-1.9.10 → tequila_basic-1.9.12}/src/tequila/grouping/compile_groups.py +0 -0
  73. {tequila_basic-1.9.10 → tequila_basic-1.9.12}/src/tequila/grouping/ev_utils.py +0 -0
  74. {tequila_basic-1.9.10 → tequila_basic-1.9.12}/src/tequila/grouping/fermionic_methods.py +0 -0
  75. {tequila_basic-1.9.10 → tequila_basic-1.9.12}/src/tequila/grouping/overlapping_methods.py +0 -0
  76. {tequila_basic-1.9.10 → tequila_basic-1.9.12}/src/tequila/hamiltonian/__init__.py +0 -0
  77. {tequila_basic-1.9.10 → tequila_basic-1.9.12}/src/tequila/hamiltonian/paulistring.py +0 -0
  78. {tequila_basic-1.9.10 → tequila_basic-1.9.12}/src/tequila/ml/__init__.py +0 -0
  79. {tequila_basic-1.9.10 → tequila_basic-1.9.12}/src/tequila/ml/interface_torch.py +0 -0
  80. {tequila_basic-1.9.10 → tequila_basic-1.9.12}/src/tequila/ml/ml_api.py +0 -0
  81. {tequila_basic-1.9.10 → tequila_basic-1.9.12}/src/tequila/ml/utils_ml.py +0 -0
  82. {tequila_basic-1.9.10 → tequila_basic-1.9.12}/src/tequila/objective/qtensor.py +0 -0
  83. {tequila_basic-1.9.10 → tequila_basic-1.9.12}/src/tequila/optimizers/_containers.py +0 -0
  84. {tequila_basic-1.9.10 → tequila_basic-1.9.12}/src/tequila/optimizers/optimizer_gpyopt.py +0 -0
  85. {tequila_basic-1.9.10 → tequila_basic-1.9.12}/src/tequila/optimizers/optimizer_scipy.py +0 -0
  86. {tequila_basic-1.9.10 → tequila_basic-1.9.12}/src/tequila/quantumchemistry/__init__.py +0 -0
  87. {tequila_basic-1.9.10 → tequila_basic-1.9.12}/src/tequila/quantumchemistry/madness_interface.py +0 -0
  88. {tequila_basic-1.9.10 → tequila_basic-1.9.12}/src/tequila/simulators/__init__.py +0 -0
  89. {tequila_basic-1.9.10 → tequila_basic-1.9.12}/src/tequila/simulators/simulator_aqt.py +0 -0
  90. {tequila_basic-1.9.10 → tequila_basic-1.9.12}/src/tequila/simulators/simulator_cirq.py +0 -0
  91. {tequila_basic-1.9.10 → tequila_basic-1.9.12}/src/tequila/simulators/simulator_ddsim.py +0 -0
  92. {tequila_basic-1.9.10 → tequila_basic-1.9.12}/src/tequila/simulators/simulator_mqp.py +0 -0
  93. {tequila_basic-1.9.10 → tequila_basic-1.9.12}/src/tequila/simulators/simulator_qibo.py +0 -0
  94. {tequila_basic-1.9.10 → tequila_basic-1.9.12}/src/tequila/simulators/simulator_qiskit_gpu.py +0 -0
  95. {tequila_basic-1.9.10 → tequila_basic-1.9.12}/src/tequila/simulators/simulator_qlm.py +0 -0
  96. {tequila_basic-1.9.10 → tequila_basic-1.9.12}/src/tequila/simulators/simulator_qulacs_gpu.py +0 -0
  97. {tequila_basic-1.9.10 → tequila_basic-1.9.12}/src/tequila/simulators/simulator_spex.py +0 -0
  98. {tequila_basic-1.9.10 → tequila_basic-1.9.12}/src/tequila/simulators/simulator_symbolic.py +0 -0
  99. {tequila_basic-1.9.10 → tequila_basic-1.9.12}/src/tequila/simulators/test_spex_simulator.py +0 -0
  100. {tequila_basic-1.9.10 → tequila_basic-1.9.12}/src/tequila/tools/__init__.py +0 -0
  101. {tequila_basic-1.9.10 → tequila_basic-1.9.12}/src/tequila/tools/convenience.py +0 -0
  102. {tequila_basic-1.9.10 → tequila_basic-1.9.12}/src/tequila/tools/qng.py +0 -0
  103. {tequila_basic-1.9.10 → tequila_basic-1.9.12}/src/tequila/tools/random_generators.py +0 -0
  104. {tequila_basic-1.9.10 → tequila_basic-1.9.12}/src/tequila/utils/__init__.py +0 -0
  105. {tequila_basic-1.9.10 → tequila_basic-1.9.12}/src/tequila/utils/bitstrings.py +0 -0
  106. {tequila_basic-1.9.10 → tequila_basic-1.9.12}/src/tequila/utils/exceptions.py +0 -0
  107. {tequila_basic-1.9.10 → tequila_basic-1.9.12}/src/tequila/utils/joined_transformation.py +0 -0
  108. {tequila_basic-1.9.10 → tequila_basic-1.9.12}/src/tequila/utils/keymap.py +0 -0
  109. {tequila_basic-1.9.10 → tequila_basic-1.9.12}/src/tequila/utils/misc.py +0 -0
  110. {tequila_basic-1.9.10 → tequila_basic-1.9.12}/src/tequila/wavefunction/__init__.py +0 -0
  111. {tequila_basic-1.9.10 → tequila_basic-1.9.12}/src/tequila_basic.egg-info/dependency_links.txt +0 -0
  112. {tequila_basic-1.9.10 → tequila_basic-1.9.12}/src/tequila_basic.egg-info/top_level.txt +0 -0
  113. {tequila_basic-1.9.10 → tequila_basic-1.9.12}/tests/test_TrotErr.py +0 -0
  114. {tequila_basic-1.9.10 → tequila_basic-1.9.12}/tests/test_adapt.py +0 -0
  115. {tequila_basic-1.9.10 → tequila_basic-1.9.12}/tests/test_array.py +0 -0
  116. {tequila_basic-1.9.10 → tequila_basic-1.9.12}/tests/test_binary_pauli.py +0 -0
  117. {tequila_basic-1.9.10 → tequila_basic-1.9.12}/tests/test_binary_utils.py +0 -0
  118. {tequila_basic-1.9.10 → tequila_basic-1.9.12}/tests/test_bitstrings.py +0 -0
  119. {tequila_basic-1.9.10 → tequila_basic-1.9.12}/tests/test_chemistry_f12.py +0 -0
  120. {tequila_basic-1.9.10 → tequila_basic-1.9.12}/tests/test_chemistry_madness.py +0 -0
  121. {tequila_basic-1.9.10 → tequila_basic-1.9.12}/tests/test_circuits.py +0 -0
  122. {tequila_basic-1.9.10 → tequila_basic-1.9.12}/tests/test_fermionic_meas.py +0 -0
  123. {tequila_basic-1.9.10 → tequila_basic-1.9.12}/tests/test_gd_optimizer.py +0 -0
  124. {tequila_basic-1.9.10 → tequila_basic-1.9.12}/tests/test_gpyopt.py +0 -0
  125. {tequila_basic-1.9.10 → tequila_basic-1.9.12}/tests/test_gradient.py +0 -0
  126. {tequila_basic-1.9.10 → tequila_basic-1.9.12}/tests/test_hamiltonian_arithmetic.py +0 -0
  127. {tequila_basic-1.9.10 → tequila_basic-1.9.12}/tests/test_krylov.py +0 -0
  128. {tequila_basic-1.9.10 → tequila_basic-1.9.12}/tests/test_mappings.py +0 -0
  129. {tequila_basic-1.9.10 → tequila_basic-1.9.12}/tests/test_noise.py +0 -0
  130. {tequila_basic-1.9.10 → tequila_basic-1.9.12}/tests/test_noise_opt.py +0 -0
  131. {tequila_basic-1.9.10 → tequila_basic-1.9.12}/tests/test_objectives.py +0 -0
  132. {tequila_basic-1.9.10 → tequila_basic-1.9.12}/tests/test_postselection.py +0 -0
  133. {tequila_basic-1.9.10 → tequila_basic-1.9.12}/tests/test_pyzx.py +0 -0
  134. {tequila_basic-1.9.10 → tequila_basic-1.9.12}/tests/test_qasm.py +0 -0
  135. {tequila_basic-1.9.10 → tequila_basic-1.9.12}/tests/test_qtensor.py +0 -0
  136. {tequila_basic-1.9.10 → tequila_basic-1.9.12}/tests/test_symbolic_simulator.py +0 -0
  137. {tequila_basic-1.9.10 → tequila_basic-1.9.12}/tests/test_torch_interface.py +0 -0
  138. {tequila_basic-1.9.10 → tequila_basic-1.9.12}/tests/test_unary_state_prep.py +0 -0
  139. {tequila_basic-1.9.10 → tequila_basic-1.9.12}/tests/test_variable.py +0 -0
  140. {tequila_basic-1.9.10 → tequila_basic-1.9.12}/tests/test_zzz_cleanup.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: tequila-basic
3
- Version: 1.9.10
3
+ Version: 1.9.12
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
@@ -13,7 +13,8 @@ Requires-Dist: sympy
13
13
  Requires-Dist: autograd
14
14
  Requires-Dist: setuptools
15
15
  Requires-Dist: pytest
16
- Requires-Dist: openfermion~=1.0
16
+ Requires-Dist: openfermion>=1.0
17
+ Requires-Dist: excitationsolve
17
18
  Requires-Dist: dataclasses; python_version < "3.7"
18
19
  Dynamic: author
19
20
  Dynamic: author-email
@@ -45,7 +46,7 @@ Further sources:
45
46
  - [talks and slides](https://kottmanj.github.io/talks_and_material/)
46
47
 
47
48
  # Installation
48
- Recommended Python version is 3.10 (3.11).
49
+ Recommended Python version is 3.11 (3.10 or 3.12 shouldn't be a problem either).
49
50
  Tequila supports linux, osx and windows. However, not all optional dependencies (especially chemistry) are supported on windows.
50
51
 
51
52
  ## Install from PyPi
@@ -18,7 +18,7 @@ Further sources:
18
18
  - [talks and slides](https://kottmanj.github.io/talks_and_material/)
19
19
 
20
20
  # Installation
21
- Recommended Python version is 3.10 (3.11).
21
+ Recommended Python version is 3.11 (3.10 or 3.12 shouldn't be a problem either).
22
22
  Tequila supports linux, osx and windows. However, not all optional dependencies (especially chemistry) are supported on windows.
23
23
 
24
24
  ## Install from PyPi
@@ -7,9 +7,10 @@ sympy
7
7
  autograd # autograd works better on OSX-ARM64 (M1 and M2) and Windows, feel free to try jax however (no big differences)
8
8
  setuptools
9
9
  pytest
10
- openfermion ~= 1.0 # can not be smaller than 1.0
10
+ openfermion >= 1.0 # can not be smaller than 1.0
11
11
  #cmake # needed by #qulacs, can be removed otherwise, now in #qulacs requirements
12
12
  #qulacs # default simulator (best integration), remove if the installation gives you trouble and just install one of the other supported backend. Version restriction only for noise models, otherwise the new version is fine
13
+ excitationsolve
13
14
 
14
15
  #optional quantum backends
15
16
  #cirq >= 0.9.2 #
@@ -18,7 +19,6 @@ openfermion ~= 1.0 # can not be smaller than 1.0
18
19
  #pyquil<3.0 # you also need to install the forest-sdk
19
20
  ##qulacs-gpu # you can't have #qulacs and #qulacs-gpu at the same time
20
21
  #qibo <= 0.1.1 # can not be installed in the same environment as gpyopt
21
- #quimb
22
22
  #mqt.ddsim == 2.0.0b2 # requires qiskit < 2
23
23
 
24
24
  #optional optimizers
@@ -28,3 +28,4 @@ openfermion ~= 1.0 # can not be smaller than 1.0
28
28
  #pyzx
29
29
  #pyscf # if used also restrict h5py version untill the issue is fixed upstream in pyscf
30
30
  #h5py <= 3.1 # version 3.3.0 leads to crashes when pyscf is imported
31
+ #pygridsynth # used to compile Pauli rotations into Clifford + T gates
@@ -5,19 +5,25 @@ from tequila.objective import (
5
5
  Objective,
6
6
  VectorObjective,
7
7
  ExpectationValue,
8
+ BraKet,
9
+ RealBraKet,
10
+ ImagBraKet,
8
11
  Variable,
9
12
  assign_variable,
10
13
  format_variable_dictionary,
11
14
  vectorize,
15
+ make_transition,
16
+ make_overlap,
17
+ Overlap,
18
+ Fidelity,
12
19
  )
13
20
  from tequila.objective import QTensor
14
- from tequila.objective.braket import BraKet, make_transition, make_overlap, Overlap, Fidelity
15
-
16
21
  from tequila.optimizers import INSTALLED_OPTIMIZERS, show_available_optimizers
17
22
  from tequila.optimizers import minimize, minimize_scipy, minimize_gd, optimizer_scipy
18
23
 
19
24
  from tequila.simulators.simulator_api import (
20
25
  simulate,
26
+ simulate_density,
21
27
  compile,
22
28
  compile_to_function,
23
29
  draw,
@@ -10,7 +10,7 @@ def gem(circuits: list, H, variables: dict = None, *args, **kwargs):
10
10
  with matries Hij = <i|H|j>, Sij = <i|j> and states |i> = U[i]|00...0> generated by the circuits given
11
11
  returns the energies E and vectors C (same format as numpy.linalg.eigh)
12
12
  the total wavefunction for energy i is then:
13
- |E(i)> = \sum_k C[k,i] U[k] |0..0>
13
+ |E(i)> = \\sum_k C[k,i] U[k] |0..0>
14
14
 
15
15
  Parameters
16
16
  ----------
@@ -1,6 +1,7 @@
1
1
  import copy
2
2
  import scipy
3
- from tequila import BraKet, QTensor, simulate
3
+ from tequila import QTensor, simulate
4
+ from tequila.objective import BraKetImpl, RealBraKet
4
5
  from tequila.hamiltonian.qubit_hamiltonian import QubitHamiltonian
5
6
 
6
7
 
@@ -37,13 +38,13 @@ def krylov_method(
37
38
  for i in range(n_krylov_states):
38
39
  for j in range(i, n_krylov_states):
39
40
  if assume_real:
40
- h_real = BraKet(bra=krylov_circs_x[i], ket=krylov_circs_x[j], operator=H)[0]
41
+ h_real = BraKetImpl(bra=krylov_circs_x[i], ket=krylov_circs_x[j], operator=H).compile()[0]
41
42
  h_im = 0
42
43
  else:
43
- h_real, h_im = BraKet(bra=krylov_circs_x[i], ket=krylov_circs_x[j], operator=H)
44
+ h_real, h_im = BraKetImpl(bra=krylov_circs_x[i], ket=krylov_circs_x[j], operator=H).compile()
44
45
  HM[i, j] = h_real + 1j * h_im
45
46
  HM[j, i] = h_real - 1j * h_im
46
- s_real, s_im = BraKet(bra=krylov_circs_x[i], ket=krylov_circs_x[j])
47
+ s_real, s_im = BraKetImpl(bra=krylov_circs_x[i], ket=krylov_circs_x[j]).compile()
47
48
  SM[i, j] = s_real + 1j * s_im
48
49
  SM[j, i] = s_real - 1j * s_im
49
50
 
@@ -53,3 +54,39 @@ def krylov_method(
53
54
  v, vv = scipy.linalg.eigh(h, s)
54
55
 
55
56
  return v, vv
57
+
58
+
59
+ # Improved version
60
+
61
+ # def krylov_method(
62
+ # krylov_circs: list, H: QubitHamiltonian, variables: dict = None, assume_real: bool = False, *args, **kwargs
63
+ # ) -> tuple:
64
+ # n_krylov_states = len(krylov_circs)
65
+
66
+ # if variables is not None:
67
+ # krylov_circs_x = [U.map_variables(variables) for U in krylov_circs]
68
+ # else:
69
+ # krylov_circs_x = copy.deepcopy(krylov_circs)
70
+
71
+ # HM = numpy.zeros((n_krylov_states, n_krylov_states), dtype=complex)
72
+ # SM = numpy.zeros((n_krylov_states, n_krylov_states), dtype=complex)
73
+
74
+ # for i in range(n_krylov_states):
75
+ # for j in range(i, n_krylov_states):
76
+ # h_bk = BraKetImpl(bra=krylov_circs_x[i], ket=krylov_circs_x[j], operator=H)
77
+ # s_bk = BraKetImpl(bra=krylov_circs_x[i], ket=krylov_circs_x[j], operator=None)
78
+
79
+ # h_val = simulate(h_bk, *args, **kwargs)
80
+ # s_val = simulate(s_bk, *args, **kwargs)
81
+
82
+ # if assume_real:
83
+ # h_val = h_val.real
84
+
85
+ # HM[i, j] = h_val
86
+ # HM[j, i] = h_val.conjugate()
87
+
88
+ # SM[i, j] = s_val
89
+ # SM[j, i] = s_val.conjugate()
90
+
91
+ # v, vv = scipy.linalg.eigh(HM, SM)
92
+ # return v, vv
@@ -242,7 +242,7 @@ class DifferentiableGateImpl(ParametrizedGateImpl):
242
242
  -------
243
243
  List of Tuples: [(weight, shifted_gate), (weight, shifted_gate)]
244
244
  The gradient compiler will assemble this the following way
245
- <H>_U with U = AU(a)B --> \sum weight <H>_V , with V=A shifted_gate
245
+ <H>_U with U = AU(a)B --> \\sum weight <H>_V , with V=A shifted_gate
246
246
 
247
247
  shifted_gate can also be a whole circuit (either as QCircuit object or a list of gates)
248
248
  """
@@ -1,7 +1,7 @@
1
1
  from __future__ import annotations
2
2
  from tequila.circuit._gates_impl import QGateImpl, assign_variable, list_assignment, GlobalPhaseGateImpl, PhaseGateImpl
3
3
  from tequila.utils.exceptions import TequilaException, TequilaWarning
4
- from tequila.utils.bitstrings import BitNumbering
4
+ from tequila.utils.bitstrings import BitNumbering, reverse_int_bits
5
5
  import typing
6
6
  import copy
7
7
  from collections import defaultdict
@@ -63,6 +63,9 @@ class QCircuit:
63
63
  moms = []
64
64
  moms.append(Moment())
65
65
  for g in self.gates:
66
+ if not g.qubits:
67
+ continue
68
+
66
69
  qus = g.qubits
67
70
  spots = [table[q] for q in qus]
68
71
 
@@ -446,7 +449,7 @@ class QCircuit:
446
449
  else:
447
450
  return QCircuit(gates=[gate])
448
451
 
449
- def to_matrix(self, variables=None):
452
+ def to_matrix(self, variables=None, numbering: BitNumbering = BitNumbering.MSB, backend: str = None):
450
453
  """
451
454
  take the circuit and return the unitary matrix corresponding to it.
452
455
  Parameters
@@ -461,60 +464,31 @@ class QCircuit:
461
464
  np.ndarray:
462
465
  the unitary matrix corresponding to the circuit.
463
466
  """
464
- import quimb.gates
465
- import quimb.tensor as qtn
466
- from tequila import compile_circuit
467
+ from tequila import format_variable_dictionary
468
+ from tequila.simulators.simulator_api import compile_circuit
467
469
 
468
- num_variables = len(self.extract_variables())
470
+ variables = format_variable_dictionary(variables)
469
471
 
470
- if num_variables == 0:
471
- variables = {}
472
- elif variables is None:
472
+ if variables is None and not (len(self.extract_variables()) == 0):
473
473
  raise TequilaException(
474
- f"QCircuit.to_matrix(): no variables provided, but the circuit has {num_variables} variables"
474
+ "You called simulate for a parametrized type but forgot to pass down the variables: {}".format(
475
+ self.extract_variables()
476
+ )
475
477
  )
476
478
 
477
- compiled_circuit = compile_circuit(
478
- self,
479
+ compiled = compile_circuit(
480
+ abstract_circuit=self,
481
+ variables=variables,
482
+ backend=backend,
479
483
  )
480
- compiled_circuit = compiled_circuit.map_variables(variables)
481
-
482
- gate_mapping = {"Rx": "RX", "Ry": "RY", "Rz": "RZ", "H": "H", "X": "X"}
483
-
484
- quimb_circuit = qtn.Circuit(self.n_qubits)
485
-
486
- # quimb uses MSB convention, so we need to modify the qubit indices
487
- # to LSB
488
- for g in compiled_circuit.gates:
489
- if g.name not in gate_mapping:
490
- raise TequilaException(
491
- f"Gate {g.name} is not supported for conversion to matrix. "
492
- f"Supported gates: {list(gate_mapping.keys())}"
493
- )
494
-
495
- if g.is_parameterized():
496
- quimb_circuit.apply_gate(
497
- gate_mapping[g.name],
498
- params=[float(g.parameter())],
499
- qubits=[abs(t - self.n_qubits + 1) for t in list(g.target)],
500
- parameterize=True,
501
- )
502
- elif g.is_controlled():
503
- quimb_circuit.apply_gate(
504
- gate_mapping[g.name],
505
- qubits=[abs(t - self.n_qubits + 1) for t in list(g.target)],
506
- controls=[abs(c - self.n_qubits + 1) for c in list(g.control)],
507
- )
508
- else:
509
- quimb_circuit.apply_gate(
510
- gate_mapping[g.name],
511
- qubits=[abs(t - self.n_qubits + 1) for t in list(g.target)],
512
- )
513
484
 
514
- uni = quimb_circuit.get_uni()
515
- unitary = np.array(uni.to_dense())
485
+ columns = []
486
+ for i in range(2**self.n_qubits):
487
+ initial_state = reverse_int_bits(i, nbits=self.n_qubits) if numbering == BitNumbering.LSB else i
488
+ output = compiled.simulate(variables=variables, initial_state=initial_state).to_array(numbering, copy=False)
489
+ columns.append(output)
516
490
 
517
- return unitary
491
+ return np.column_stack(columns)
518
492
 
519
493
  def to_networkx(self):
520
494
  """
@@ -1,6 +1,9 @@
1
+ import numbers
2
+ import warnings
3
+
1
4
  from tequila import TequilaException
2
5
  from tequila.circuit.circuit import QCircuit
3
- from tequila.circuit.gates import Rx, Ry, H, X, Rz, ExpPauli, CNOT, Phase, T, Z, GlobalPhase
6
+ from tequila.circuit.gates import Rx, Ry, H, X, S, Rz, ExpPauli, CNOT, Phase, T, Z, GlobalPhase
4
7
  from tequila.circuit._gates_impl import (
5
8
  RotationGateImpl,
6
9
  PhaseGateImpl,
@@ -12,7 +15,7 @@ from tequila.circuit._gates_impl import (
12
15
  from tequila.utils import to_float
13
16
  from tequila.objective.objective import Variable, FixedVariable
14
17
  from tequila.objective.objective import Objective
15
- from tequila.objective.objective import ExpectationValueImpl
18
+ from tequila.objective.objective import BraKetImpl, ExpectationValueImpl
16
19
  import numpy
17
20
  from numpy import pi as pi
18
21
 
@@ -70,6 +73,7 @@ class CircuitCompiler:
70
73
  c.gradient_mode = False
71
74
  c.y_gate = False
72
75
  c.ry_gate = False
76
+ c.pauli_rotations = False
73
77
 
74
78
  for k, v in kwargs.items():
75
79
  if k in c.__dict__:
@@ -79,6 +83,13 @@ class CircuitCompiler:
79
83
  c.cc_max = False
80
84
  return c
81
85
 
86
+ @classmethod
87
+ def error_correctable_gate_set(cls, epsilon, *args, **kwargs):
88
+ c = cls.all_flags_true(args, kwargs)
89
+ c.pauli_rotations = True
90
+ c.epsilon = epsilon
91
+ return c
92
+
82
93
  def __init__(
83
94
  self,
84
95
  multitarget=False,
@@ -102,9 +113,10 @@ class CircuitCompiler:
102
113
  y_gate=False,
103
114
  ch_gate=False,
104
115
  hadamard=False,
116
+ pauli_rotations=False,
117
+ epsilon=1e-6,
105
118
  ):
106
119
  """
107
- all parameters are booleans.
108
120
  Parameters
109
121
  ----------
110
122
  multitarget:
@@ -145,6 +157,11 @@ class CircuitCompiler:
145
157
  whether or not to break down all y gates
146
158
  ch_gate:
147
159
  whether or not to break down all controlled-H gates
160
+ pauli_rotations:
161
+ whether or not to approximate rotations with Clifford and T gates
162
+ epsilon:
163
+ The maximum absolute error when compilations are not exact.
164
+ Currently only applies to the rotations compilation.
148
165
  """
149
166
  self.multitarget = multitarget
150
167
  self.multicontrol = multicontrol
@@ -167,6 +184,8 @@ class CircuitCompiler:
167
184
  self.ry_gate = ry_gate
168
185
  self.y_gate = y_gate
169
186
  self.ch_gate = ch_gate
187
+ self.pauli_rotations = pauli_rotations
188
+ self.epsilon = epsilon
170
189
 
171
190
  def __call__(
172
191
  self, objective: typing.Union[Objective, QCircuit, ExpectationValueImpl], variables=None, *args, **kwargs
@@ -249,7 +268,21 @@ class CircuitCompiler:
249
268
  the arg, compiled
250
269
  """
251
270
 
252
- if isinstance(arg, ExpectationValueImpl) or (hasattr(arg, "U") and hasattr(arg, "H")):
271
+ if isinstance(arg, BraKetImpl):
272
+ # a braket has U and H as well, but its U is only the ket: compiling it like an
273
+ # expectation value below would silently drop the bra
274
+ ket = self.compile_circuit(abstract_circuit=arg.ket, *args, **kwargs)
275
+ return BraKetImpl(
276
+ ket=ket,
277
+ bra=ket if arg.bra is arg.ket else self.compile_circuit(abstract_circuit=arg.bra, *args, **kwargs),
278
+ operator=arg.operator,
279
+ contraction=arg._contraction,
280
+ shape=arg._shape,
281
+ samples=arg.samples,
282
+ *arg._args,
283
+ **arg._kwargs,
284
+ )
285
+ elif isinstance(arg, ExpectationValueImpl) or (hasattr(arg, "U") and hasattr(arg, "H")):
253
286
  return ExpectationValueImpl(H=arg.H, U=self.compile_circuit(abstract_circuit=arg.U, *args, **kwargs))
254
287
  elif hasattr(arg, "abstract_expectationvalue"):
255
288
  E = arg.abstract_expectationvalue
@@ -296,6 +329,9 @@ class CircuitCompiler:
296
329
 
297
330
  compiled_gates = []
298
331
 
332
+ # Keep a dicitionary of compiled pauli_rotations
333
+ pauli_dict = {}
334
+
299
335
  for idx, gate in gatelist:
300
336
  cg = gate
301
337
  controlled = gate.is_controlled()
@@ -333,6 +369,10 @@ class CircuitCompiler:
333
369
  if self.ry_gate:
334
370
  cg = compile_ry(gate=cg, controlled_rotation=self.controlled_rotation)
335
371
  if controlled:
372
+ if self.toffoli:
373
+ cg = compile_toffoli(gate=cg)
374
+ if self.phase:
375
+ cg = compile_phase(gate=cg)
336
376
  if self.cc_max or self.multicontrol:
337
377
  cg = compile_to_single_control(gate=cg)
338
378
  if self.controlled_exponential_pauli:
@@ -343,12 +383,10 @@ class CircuitCompiler:
343
383
  cg = compile_controlled_phase(gate=cg)
344
384
  if self.phase:
345
385
  cg = compile_phase(gate=cg)
346
- if self.toffoli:
347
- cg = compile_toffoli(gate=cg)
348
- if self.phase:
349
- cg = compile_phase(gate=cg)
350
386
  if self.controlled_rotation:
351
387
  cg = compile_controlled_rotation(gate=cg)
388
+ if self.pauli_rotations:
389
+ cg = compile_pauli_rotations(gate=cg, epsilon=self.epsilon, pauli_dict=pauli_dict)
352
390
 
353
391
  compiled_gates.append((idx, cg))
354
392
 
@@ -586,7 +624,7 @@ def compile_toffoli(gate) -> QCircuit:
586
624
  A QCircuit; the result of compilation.
587
625
  """
588
626
 
589
- if gate.name.lower != "x":
627
+ if not (gate.name.lower() == "x" and len(gate.control) == 2):
590
628
  return QCircuit.wrap_gate(gate)
591
629
  control = gate.control
592
630
  c1 = control[1]
@@ -1039,3 +1077,82 @@ def compile_ch(gate: QGateImpl) -> QCircuit:
1039
1077
  )
1040
1078
  else:
1041
1079
  return QCircuit.wrap_gate(gate)
1080
+
1081
+
1082
+ @compiler
1083
+ def compile_pauli_rotations(gate: QGateImpl, epsilon: float, pauli_dict: dict) -> QCircuit:
1084
+ """
1085
+ Compile uncontrolled Pauli rotations gates into Clifford + T gates.
1086
+
1087
+ Parameters
1088
+ ----------
1089
+ gate:
1090
+ the gate.
1091
+ epsilon:
1092
+ the maximum absolute error of the compilation.
1093
+
1094
+ Returns
1095
+ -------
1096
+ QCircuit, the result of compilation.
1097
+ """
1098
+ from pygridsynth import gridsynth_gates
1099
+
1100
+ # In principle, we could compile controlled Pauli rotations with the same method by making all
1101
+ # the resulting gates controlled, but then this compilation makes no sense, since its point is
1102
+ # to compile to a Clifford + T gateset. Compiling controlled rotations to uncontrolled ones
1103
+ # should be handled by other compiler passes.
1104
+ if gate.name.lower() in ["rx", "ry", "rz"] and not gate.is_controlled():
1105
+ if not isinstance(gate.parameter, numbers.Number):
1106
+ raise TequilaCompilerException("Can't compile parametrized rotations to Clifford + T gates")
1107
+
1108
+ # Compute bucket by rounding to the next multiple of epsilon
1109
+ bucket = int(numpy.round(gate.parameter / (2 * epsilon)))
1110
+ rounded_parameter = bucket * (2 * epsilon)
1111
+ if bucket in pauli_dict:
1112
+ result = pauli_dict[bucket]
1113
+ elif bucket == 0:
1114
+ result = QCircuit()
1115
+ else:
1116
+ with warnings.catch_warnings():
1117
+ # Silence warning about using floats
1118
+ warnings.simplefilter(action="ignore", category=UserWarning, lineno=362)
1119
+ gates = gridsynth_gates(theta=rounded_parameter, epsilon=epsilon, up_to_phase=True)
1120
+
1121
+ result = QCircuit()
1122
+ v = numpy.array([1, 0], dtype=complex)
1123
+ H_mat = numpy.array([[1, 1], [1, -1]]) / numpy.sqrt(2)
1124
+ T_val = numpy.exp(pi / 4 * 1j)
1125
+ for g in reversed(gates):
1126
+ match g:
1127
+ case "X":
1128
+ result += X(target=0)
1129
+ v = v[::-1]
1130
+ case "H":
1131
+ result += H(target=0)
1132
+ v = H_mat @ v
1133
+ case "S":
1134
+ result += S(target=0)
1135
+ v[1] *= 1j
1136
+ case "T":
1137
+ result += T(target=0)
1138
+ v[1] *= T_val
1139
+ case c:
1140
+ raise ValueError(f"Got unexpected gate {c}")
1141
+
1142
+ global_phase = -rounded_parameter / 2 - numpy.angle(v[0])
1143
+ result += GlobalPhase(angle=global_phase)
1144
+ pauli_dict[bucket] = result
1145
+
1146
+ result = result.map_qubits({0: gate.target[0]})
1147
+
1148
+ if gate.name.lower() in ["rx", "ry"]:
1149
+ result = H(target=gate.target) + result + H(target=gate.target)
1150
+
1151
+ if gate.name.lower() == "ry":
1152
+ result = (
1153
+ S(target=gate.target) + S(target=gate.target) + S(target=gate.target) + result + S(target=gate.target)
1154
+ )
1155
+
1156
+ return result
1157
+ else:
1158
+ return QCircuit.wrap_gate(gate)
@@ -85,20 +85,16 @@ def Phase(
85
85
  return QCircuit.wrap_gate(gates)
86
86
 
87
87
 
88
- def I(
89
- target: typing.Union[list, int], control: typing.Union[list, int] = None, power=None, angle=None, *args, **kwargs
90
- ) -> QCircuit:
88
+ def I(target: typing.Union[list, int], control: typing.Union[list, int] = None, *args, **kwargs) -> QCircuit:
91
89
  """
92
- This function provides a primitive implementation of the identity gate as a place
93
- holder gate with no physical effect.
94
- The user can add this gate into the circuit and get it also when
95
- calling functions regarding the circuit's stats (i.e. gates included)
90
+ A gate that has no effect, but can be used to mark a qubit as being used.
91
+ This can for example be useful if a qubit is only being used in some variants
92
+ of a circuit, but you want to prevent the output format from changing.
96
93
  """
97
- # zero generator for a no-operation gate
98
- generator = lambda q: 0
99
- return _initialize_power_gate(
100
- name="I", power=power, angle=angle, target=target, control=control, generator=generator, *args, **kwargs
101
- )
94
+ target = list_assignment(target)
95
+ control = list_assignment(control) if control is not None else None
96
+ gates = [impl.QGateImpl(name="I", target=q, control=control) for q in target]
97
+ return QCircuit.wrap_gate(gates)
102
98
 
103
99
 
104
100
  def S(target: typing.Union[list, int], control: typing.Union[list, int] = None) -> QCircuit:
@@ -1,6 +1,7 @@
1
1
  from tequila.circuit.compiler import CircuitCompiler
2
2
  from tequila.objective.objective import (
3
3
  Objective,
4
+ BraKetImpl,
4
5
  ExpectationValueImpl,
5
6
  Variable,
6
7
  assign_variable,
@@ -11,8 +12,10 @@ from tequila import TequilaException
11
12
  from tequila.objective import QTensor
12
13
  from tequila.simulators.simulator_api import compile
13
14
  import typing
14
- from numpy import vectorize
15
+ from numpy import vectorize, isclose
16
+ from copy import deepcopy
15
17
  from tequila.autograd_imports import jax, __AUTOGRAD__BACKEND__
18
+ from tequila.circuit._gates_impl import DifferentiableGateImpl
16
19
 
17
20
 
18
21
  def grad(objective: typing.Union[Objective, QTensor], variable: Variable = None, no_compile=False, *args, **kwargs):
@@ -78,7 +81,9 @@ def grad(objective: typing.Union[Objective, QTensor], variable: Variable = None,
78
81
 
79
82
  if isinstance(objective, ExpectationValueImpl):
80
83
  return __grad_expectationvalue(E=objective, variable=variable)
81
- elif objective.is_expectationvalue():
84
+ elif objective.is_expectationvalue() and not isinstance(compiled.args[-1], BraKetImpl):
85
+ # is_expectationvalue() only tests for a quantum argument, and a braket is not an
86
+ # expectation value: let it fall through to __grad_objective/__grad_inner
82
87
  return __grad_expectationvalue(E=compiled.args[-1], variable=variable)
83
88
  elif isinstance(compiled, Objective) or (hasattr(compiled, "args") and hasattr(compiled, "transformation")):
84
89
  return __grad_objective(objective=compiled, variable=variable)
@@ -91,12 +96,20 @@ def __grad_objective(objective: Objective, variable: Variable):
91
96
  transformation = objective.transformation
92
97
  dO = None
93
98
 
99
+ # an objective holding a braket is complex valued, and the plain autograd gradient only
100
+ # accepts real output. the arithmetic combining the arguments (sums, products, quotients)
101
+ # is holomorphic, so the outer derivative is well defined and just has to be asked for
102
+ holomorphic = any(isinstance(arg, BraKetImpl) for arg in args)
103
+
94
104
  processed_expectationvalues = {}
95
105
  for i, arg in enumerate(args):
96
106
  if __AUTOGRAD__BACKEND__ == "jax":
97
- df = jax.grad(transformation, argnums=i)
107
+ df = jax.grad(transformation, argnums=i, holomorphic=holomorphic)
98
108
  elif __AUTOGRAD__BACKEND__ == "autograd":
99
- df = jax.grad(transformation, argnum=i)
109
+ if holomorphic:
110
+ df = jax.holomorphic_grad(transformation, i)
111
+ else:
112
+ df = jax.grad(transformation, argnum=i)
100
113
  else:
101
114
  raise TequilaException("Can't differentiate without autograd or jax")
102
115
 
@@ -206,6 +219,10 @@ def __grad_inner(arg, variable):
206
219
  E = arg.abstract_expectationvalue
207
220
  dE = __grad_expectationvalue(E, variable=variable)
208
221
  return compile(dE, **arg._input_args)
222
+ elif isinstance(arg, BraKetImpl):
223
+ # real, imaginary = arg.compile()
224
+ # return grad(real, variable) + 1.0j * grad(imaginary, variable)
225
+ return __grad_braKet(objective=arg, variable=variable)
209
226
  elif hasattr(arg, "grad"):
210
227
  return arg.grad(variable)
211
228
  else:
@@ -267,3 +284,66 @@ def __grad_shift_rule(unitary, g, i, variable, hamiltonian):
267
284
  return dOinc
268
285
  else:
269
286
  raise TequilaException("No shift found for gate {}\nWas the compiler called?".format(g))
287
+
288
+
289
+ def __grad_braKet(objective: BraKetImpl, variable: Variable = None) -> Objective:
290
+ r"""
291
+ Gradient of <bra|H|ket> by differentiating the amplitudes of bra and ket directly,
292
+ instead of differentiating the Hadamard tests that BraKetImpl.compile() produces.
293
+ Every term of the result is again a BraKetImpl with one gate of bra or ket modified.
294
+ :param objective: the BraKetImpl to differentiate
295
+ :param variable: the variable to differentiate with respect to. None gives a dict with all of them
296
+ :return: an Objective (or dict of Objectives) whose simulation gives the gradient
297
+ """
298
+ # <U|U> = 1 does not depend on anything
299
+ if variable not in objective.extract_variables() or objective.is_self_overlap:
300
+ return Objective()
301
+ if objective.is_diagonal:
302
+ return __grad_expectationvalue(objective, variable)
303
+
304
+ if not (objective.bra.verify()):
305
+ raise TequilaException("error in grad_braket unitary is {}".format(objective.bra))
306
+ if not (objective.ket.verify()):
307
+ raise TequilaException("error in grad_braket unitary is {}".format(objective.ket))
308
+
309
+ def make_braket(bra, ket):
310
+ return Objective(
311
+ args=[
312
+ BraKetImpl(
313
+ ket=ket,
314
+ bra=bra,
315
+ operator=objective.operator,
316
+ contraction=objective._contraction,
317
+ shape=objective._shape,
318
+ samples=objective.samples,
319
+ *objective._args,
320
+ **objective._kwargs,
321
+ )
322
+ ]
323
+ )
324
+
325
+ dO = Objective()
326
+ for is_bra, U in [(False, deepcopy(objective.ket)), (True, deepcopy(objective.bra))]:
327
+ for i, g in U._parameter_map.get(variable, []):
328
+ if hasattr(g, "shifted_gates"):
329
+ g = deepcopy(g)
330
+ if not g.is_controlled() and type(g).shifted_gates is DifferentiableGateImpl.shifted_gates:
331
+ shifted = g.shifted_gates(r=g.eigenvalues_magnitude / 2)
332
+ else:
333
+ shifted = g.shifted_gates()
334
+ g.assume_real = False
335
+ inner = __grad_inner(g.parameter, variable)
336
+ if isinstance(inner, float) and isclose(inner, 0, atol=1.0e-6):
337
+ continue
338
+ for x in shifted:
339
+ w, g = x
340
+ Ux = U.replace_gates(positions=[i], circuits=[g])
341
+ if is_bra:
342
+ # the bra enters complex conjugated
343
+ dO += w.conjugate() * inner * make_braket(bra=Ux, ket=objective.ket)
344
+ else:
345
+ dO += w * inner * make_braket(bra=objective.bra, ket=Ux)
346
+ else:
347
+ raise TequilaException("No shift found for gate {}\nWas the compiler called?".format(g))
348
+ assert dO is not None
349
+ return dO