tequila-basic 1.9.11__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.11/src/tequila_basic.egg-info → tequila_basic-1.9.12}/PKG-INFO +4 -3
  2. {tequila_basic-1.9.11 → tequila_basic-1.9.12}/README.md +1 -1
  3. {tequila_basic-1.9.11 → tequila_basic-1.9.12}/requirements.txt +3 -2
  4. {tequila_basic-1.9.11 → tequila_basic-1.9.12}/src/tequila/__init__.py +7 -2
  5. {tequila_basic-1.9.11 → tequila_basic-1.9.12}/src/tequila/apps/krylov/krylov.py +41 -4
  6. {tequila_basic-1.9.11 → tequila_basic-1.9.12}/src/tequila/circuit/circuit.py +19 -48
  7. {tequila_basic-1.9.11 → tequila_basic-1.9.12}/src/tequila/circuit/compiler.py +126 -9
  8. {tequila_basic-1.9.11 → tequila_basic-1.9.12}/src/tequila/circuit/gates.py +5 -8
  9. {tequila_basic-1.9.11 → tequila_basic-1.9.12}/src/tequila/circuit/gradient.py +84 -4
  10. {tequila_basic-1.9.11 → tequila_basic-1.9.12}/src/tequila/circuit/postselection.py +40 -5
  11. {tequila_basic-1.9.11 → tequila_basic-1.9.12}/src/tequila/grouping/fermionic_functions.py +3 -3
  12. {tequila_basic-1.9.11 → tequila_basic-1.9.12}/src/tequila/objective/__init__.py +8 -0
  13. {tequila_basic-1.9.11 → tequila_basic-1.9.12}/src/tequila/objective/objective.py +420 -42
  14. tequila_basic-1.9.12/src/tequila/objective/quantum_arg.py +39 -0
  15. {tequila_basic-1.9.11 → tequila_basic-1.9.12}/src/tequila/optimizers/__init__.py +18 -3
  16. {tequila_basic-1.9.11 → tequila_basic-1.9.12}/src/tequila/optimizers/optimizer_base.py +5 -1
  17. tequila_basic-1.9.12/src/tequila/optimizers/optimizer_excsolve.py +142 -0
  18. {tequila_basic-1.9.11 → tequila_basic-1.9.12}/src/tequila/quantumchemistry/chemistry_tools.py +81 -23
  19. {tequila_basic-1.9.11 → tequila_basic-1.9.12}/src/tequila/quantumchemistry/psi4_interface.py +2 -2
  20. {tequila_basic-1.9.11 → tequila_basic-1.9.12}/src/tequila/quantumchemistry/pyscf_interface.py +6 -6
  21. {tequila_basic-1.9.11 → tequila_basic-1.9.12}/src/tequila/quantumchemistry/qc_base.py +109 -82
  22. {tequila_basic-1.9.11 → tequila_basic-1.9.12}/src/tequila/simulators/simulator_api.py +86 -76
  23. {tequila_basic-1.9.11 → tequila_basic-1.9.12}/src/tequila/simulators/simulator_base.py +130 -0
  24. {tequila_basic-1.9.11 → tequila_basic-1.9.12}/src/tequila/simulators/simulator_cudaq.py +16 -16
  25. {tequila_basic-1.9.11 → tequila_basic-1.9.12}/src/tequila/simulators/simulator_qiskit.py +29 -39
  26. {tequila_basic-1.9.11 → tequila_basic-1.9.12}/src/tequila/simulators/simulator_qulacs.py +119 -2
  27. tequila_basic-1.9.12/src/tequila/utils/objective_graph.py +1672 -0
  28. {tequila_basic-1.9.11 → tequila_basic-1.9.12}/src/tequila/version.py +1 -1
  29. {tequila_basic-1.9.11 → tequila_basic-1.9.12/src/tequila_basic.egg-info}/PKG-INFO +4 -3
  30. {tequila_basic-1.9.11 → tequila_basic-1.9.12}/src/tequila_basic.egg-info/SOURCES.txt +3 -1
  31. {tequila_basic-1.9.11 → tequila_basic-1.9.12}/src/tequila_basic.egg-info/requires.txt +2 -1
  32. tequila_basic-1.9.12/tests/test_braket.py +524 -0
  33. {tequila_basic-1.9.11 → tequila_basic-1.9.12}/tests/test_chemistry.py +36 -38
  34. {tequila_basic-1.9.11 → tequila_basic-1.9.12}/tests/test_circuit_unitary.py +3 -7
  35. {tequila_basic-1.9.11 → tequila_basic-1.9.12}/tests/test_gates.py +13 -0
  36. {tequila_basic-1.9.11 → tequila_basic-1.9.12}/tests/test_recompilation_routines.py +51 -1
  37. {tequila_basic-1.9.11 → tequila_basic-1.9.12}/tests/test_scipy.py +1 -45
  38. tequila_basic-1.9.11/src/tequila/objective/braket.py +0 -192
  39. tequila_basic-1.9.11/tests/test_braket.py +0 -274
  40. {tequila_basic-1.9.11 → tequila_basic-1.9.12}/LICENSE +0 -0
  41. {tequila_basic-1.9.11 → tequila_basic-1.9.12}/MANIFEST.in +0 -0
  42. {tequila_basic-1.9.11 → tequila_basic-1.9.12}/setup.cfg +0 -0
  43. {tequila_basic-1.9.11 → tequila_basic-1.9.12}/setup.py +0 -0
  44. {tequila_basic-1.9.11 → tequila_basic-1.9.12}/src/tequila/apps/__init__.py +0 -0
  45. {tequila_basic-1.9.11 → tequila_basic-1.9.12}/src/tequila/apps/_unary_state_prep_impl.py +0 -0
  46. {tequila_basic-1.9.11 → tequila_basic-1.9.12}/src/tequila/apps/adapt/__init__.py +0 -0
  47. {tequila_basic-1.9.11 → tequila_basic-1.9.12}/src/tequila/apps/adapt/adapt.py +0 -0
  48. {tequila_basic-1.9.11 → tequila_basic-1.9.12}/src/tequila/apps/krylov/__init__.py +0 -0
  49. {tequila_basic-1.9.11 → tequila_basic-1.9.12}/src/tequila/apps/robustness/__init__.py +0 -0
  50. {tequila_basic-1.9.11 → tequila_basic-1.9.12}/src/tequila/apps/robustness/helpers.py +0 -0
  51. {tequila_basic-1.9.11 → tequila_basic-1.9.12}/src/tequila/apps/robustness/interval.py +0 -0
  52. {tequila_basic-1.9.11 → tequila_basic-1.9.12}/src/tequila/apps/unary_state_prep.py +0 -0
  53. {tequila_basic-1.9.11 → tequila_basic-1.9.12}/src/tequila/autograd_imports.py +0 -0
  54. {tequila_basic-1.9.11 → tequila_basic-1.9.12}/src/tequila/circuit/__init__.py +0 -0
  55. {tequila_basic-1.9.11 → tequila_basic-1.9.12}/src/tequila/circuit/_gates_impl.py +0 -0
  56. {tequila_basic-1.9.11 → tequila_basic-1.9.12}/src/tequila/circuit/noise.py +0 -0
  57. {tequila_basic-1.9.11 → tequila_basic-1.9.12}/src/tequila/circuit/pyzx.py +0 -0
  58. {tequila_basic-1.9.11 → tequila_basic-1.9.12}/src/tequila/circuit/qasm.py +0 -0
  59. {tequila_basic-1.9.11 → tequila_basic-1.9.12}/src/tequila/circuit/qpic.py +0 -0
  60. {tequila_basic-1.9.11 → tequila_basic-1.9.12}/src/tequila/grouping/__init__.py +0 -0
  61. {tequila_basic-1.9.11 → tequila_basic-1.9.12}/src/tequila/grouping/binary_rep.py +0 -0
  62. {tequila_basic-1.9.11 → tequila_basic-1.9.12}/src/tequila/grouping/binary_utils.py +0 -0
  63. {tequila_basic-1.9.11 → tequila_basic-1.9.12}/src/tequila/grouping/compile_groups.py +0 -0
  64. {tequila_basic-1.9.11 → tequila_basic-1.9.12}/src/tequila/grouping/ev_utils.py +0 -0
  65. {tequila_basic-1.9.11 → tequila_basic-1.9.12}/src/tequila/grouping/fermionic_methods.py +0 -0
  66. {tequila_basic-1.9.11 → tequila_basic-1.9.12}/src/tequila/grouping/overlapping_methods.py +0 -0
  67. {tequila_basic-1.9.11 → tequila_basic-1.9.12}/src/tequila/hamiltonian/__init__.py +0 -0
  68. {tequila_basic-1.9.11 → tequila_basic-1.9.12}/src/tequila/hamiltonian/paulis.py +0 -0
  69. {tequila_basic-1.9.11 → tequila_basic-1.9.12}/src/tequila/hamiltonian/paulistring.py +0 -0
  70. {tequila_basic-1.9.11 → tequila_basic-1.9.12}/src/tequila/hamiltonian/qubit_hamiltonian.py +0 -0
  71. {tequila_basic-1.9.11 → tequila_basic-1.9.12}/src/tequila/ml/__init__.py +0 -0
  72. {tequila_basic-1.9.11 → tequila_basic-1.9.12}/src/tequila/ml/interface_torch.py +0 -0
  73. {tequila_basic-1.9.11 → tequila_basic-1.9.12}/src/tequila/ml/ml_api.py +0 -0
  74. {tequila_basic-1.9.11 → tequila_basic-1.9.12}/src/tequila/ml/utils_ml.py +0 -0
  75. {tequila_basic-1.9.11 → tequila_basic-1.9.12}/src/tequila/objective/qtensor.py +0 -0
  76. {tequila_basic-1.9.11 → tequila_basic-1.9.12}/src/tequila/optimizers/_containers.py +0 -0
  77. {tequila_basic-1.9.11 → tequila_basic-1.9.12}/src/tequila/optimizers/optimizer_gd.py +0 -0
  78. {tequila_basic-1.9.11 → tequila_basic-1.9.12}/src/tequila/optimizers/optimizer_gpyopt.py +0 -0
  79. {tequila_basic-1.9.11 → tequila_basic-1.9.12}/src/tequila/optimizers/optimizer_scipy.py +0 -0
  80. {tequila_basic-1.9.11 → tequila_basic-1.9.12}/src/tequila/quantumchemistry/__init__.py +0 -0
  81. {tequila_basic-1.9.11 → tequila_basic-1.9.12}/src/tequila/quantumchemistry/encodings.py +0 -0
  82. {tequila_basic-1.9.11 → tequila_basic-1.9.12}/src/tequila/quantumchemistry/madness_interface.py +0 -0
  83. {tequila_basic-1.9.11 → tequila_basic-1.9.12}/src/tequila/quantumchemistry/orbital_optimizer.py +0 -0
  84. {tequila_basic-1.9.11 → tequila_basic-1.9.12}/src/tequila/simulators/__init__.py +0 -0
  85. {tequila_basic-1.9.11 → tequila_basic-1.9.12}/src/tequila/simulators/simulator_aqt.py +0 -0
  86. {tequila_basic-1.9.11 → tequila_basic-1.9.12}/src/tequila/simulators/simulator_cirq.py +0 -0
  87. {tequila_basic-1.9.11 → tequila_basic-1.9.12}/src/tequila/simulators/simulator_ddsim.py +0 -0
  88. {tequila_basic-1.9.11 → tequila_basic-1.9.12}/src/tequila/simulators/simulator_mqp.py +0 -0
  89. {tequila_basic-1.9.11 → tequila_basic-1.9.12}/src/tequila/simulators/simulator_pyquil.py +0 -0
  90. {tequila_basic-1.9.11 → tequila_basic-1.9.12}/src/tequila/simulators/simulator_qibo.py +0 -0
  91. {tequila_basic-1.9.11 → tequila_basic-1.9.12}/src/tequila/simulators/simulator_qiskit_gpu.py +0 -0
  92. {tequila_basic-1.9.11 → tequila_basic-1.9.12}/src/tequila/simulators/simulator_qlm.py +0 -0
  93. {tequila_basic-1.9.11 → tequila_basic-1.9.12}/src/tequila/simulators/simulator_qulacs_gpu.py +0 -0
  94. {tequila_basic-1.9.11 → tequila_basic-1.9.12}/src/tequila/simulators/simulator_spex.py +0 -0
  95. {tequila_basic-1.9.11 → tequila_basic-1.9.12}/src/tequila/simulators/simulator_symbolic.py +0 -0
  96. {tequila_basic-1.9.11 → tequila_basic-1.9.12}/src/tequila/simulators/test_spex_simulator.py +0 -0
  97. {tequila_basic-1.9.11 → tequila_basic-1.9.12}/src/tequila/tools/__init__.py +0 -0
  98. {tequila_basic-1.9.11 → tequila_basic-1.9.12}/src/tequila/tools/convenience.py +0 -0
  99. {tequila_basic-1.9.11 → tequila_basic-1.9.12}/src/tequila/tools/qng.py +0 -0
  100. {tequila_basic-1.9.11 → tequila_basic-1.9.12}/src/tequila/tools/random_generators.py +0 -0
  101. {tequila_basic-1.9.11 → tequila_basic-1.9.12}/src/tequila/utils/__init__.py +0 -0
  102. {tequila_basic-1.9.11 → tequila_basic-1.9.12}/src/tequila/utils/bitstrings.py +0 -0
  103. {tequila_basic-1.9.11 → tequila_basic-1.9.12}/src/tequila/utils/exceptions.py +0 -0
  104. {tequila_basic-1.9.11 → tequila_basic-1.9.12}/src/tequila/utils/joined_transformation.py +0 -0
  105. {tequila_basic-1.9.11 → tequila_basic-1.9.12}/src/tequila/utils/keymap.py +0 -0
  106. {tequila_basic-1.9.11 → tequila_basic-1.9.12}/src/tequila/utils/misc.py +0 -0
  107. {tequila_basic-1.9.11 → tequila_basic-1.9.12}/src/tequila/wavefunction/__init__.py +0 -0
  108. {tequila_basic-1.9.11 → tequila_basic-1.9.12}/src/tequila/wavefunction/density_matrix.py +0 -0
  109. {tequila_basic-1.9.11 → tequila_basic-1.9.12}/src/tequila/wavefunction/qubit_wavefunction.py +0 -0
  110. {tequila_basic-1.9.11 → tequila_basic-1.9.12}/src/tequila_basic.egg-info/dependency_links.txt +0 -0
  111. {tequila_basic-1.9.11 → tequila_basic-1.9.12}/src/tequila_basic.egg-info/top_level.txt +0 -0
  112. {tequila_basic-1.9.11 → tequila_basic-1.9.12}/tests/test_TrotErr.py +0 -0
  113. {tequila_basic-1.9.11 → tequila_basic-1.9.12}/tests/test_adapt.py +0 -0
  114. {tequila_basic-1.9.11 → tequila_basic-1.9.12}/tests/test_array.py +0 -0
  115. {tequila_basic-1.9.11 → tequila_basic-1.9.12}/tests/test_binary_pauli.py +0 -0
  116. {tequila_basic-1.9.11 → tequila_basic-1.9.12}/tests/test_binary_utils.py +0 -0
  117. {tequila_basic-1.9.11 → tequila_basic-1.9.12}/tests/test_bitstrings.py +0 -0
  118. {tequila_basic-1.9.11 → tequila_basic-1.9.12}/tests/test_chemistry_f12.py +0 -0
  119. {tequila_basic-1.9.11 → tequila_basic-1.9.12}/tests/test_chemistry_madness.py +0 -0
  120. {tequila_basic-1.9.11 → tequila_basic-1.9.12}/tests/test_circuits.py +0 -0
  121. {tequila_basic-1.9.11 → tequila_basic-1.9.12}/tests/test_fermionic_meas.py +0 -0
  122. {tequila_basic-1.9.11 → tequila_basic-1.9.12}/tests/test_gd_optimizer.py +0 -0
  123. {tequila_basic-1.9.11 → tequila_basic-1.9.12}/tests/test_gpyopt.py +0 -0
  124. {tequila_basic-1.9.11 → tequila_basic-1.9.12}/tests/test_gradient.py +0 -0
  125. {tequila_basic-1.9.11 → tequila_basic-1.9.12}/tests/test_hamiltonian_arithmetic.py +0 -0
  126. {tequila_basic-1.9.11 → tequila_basic-1.9.12}/tests/test_krylov.py +0 -0
  127. {tequila_basic-1.9.11 → tequila_basic-1.9.12}/tests/test_mappings.py +0 -0
  128. {tequila_basic-1.9.11 → tequila_basic-1.9.12}/tests/test_noise.py +0 -0
  129. {tequila_basic-1.9.11 → tequila_basic-1.9.12}/tests/test_noise_opt.py +0 -0
  130. {tequila_basic-1.9.11 → tequila_basic-1.9.12}/tests/test_objectives.py +0 -0
  131. {tequila_basic-1.9.11 → tequila_basic-1.9.12}/tests/test_postselection.py +0 -0
  132. {tequila_basic-1.9.11 → tequila_basic-1.9.12}/tests/test_pyzx.py +0 -0
  133. {tequila_basic-1.9.11 → tequila_basic-1.9.12}/tests/test_qasm.py +0 -0
  134. {tequila_basic-1.9.11 → tequila_basic-1.9.12}/tests/test_qtensor.py +0 -0
  135. {tequila_basic-1.9.11 → tequila_basic-1.9.12}/tests/test_simulator_backends.py +0 -0
  136. {tequila_basic-1.9.11 → tequila_basic-1.9.12}/tests/test_symbolic_simulator.py +0 -0
  137. {tequila_basic-1.9.11 → tequila_basic-1.9.12}/tests/test_torch_interface.py +0 -0
  138. {tequila_basic-1.9.11 → tequila_basic-1.9.12}/tests/test_unary_state_prep.py +0 -0
  139. {tequila_basic-1.9.11 → tequila_basic-1.9.12}/tests/test_variable.py +0 -0
  140. {tequila_basic-1.9.11 → 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.11
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,14 +5,19 @@ 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
 
@@ -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
@@ -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
@@ -449,7 +449,7 @@ class QCircuit:
449
449
  else:
450
450
  return QCircuit(gates=[gate])
451
451
 
452
- def to_matrix(self, variables=None):
452
+ def to_matrix(self, variables=None, numbering: BitNumbering = BitNumbering.MSB, backend: str = None):
453
453
  """
454
454
  take the circuit and return the unitary matrix corresponding to it.
455
455
  Parameters
@@ -464,60 +464,31 @@ class QCircuit:
464
464
  np.ndarray:
465
465
  the unitary matrix corresponding to the circuit.
466
466
  """
467
- import quimb.gates
468
- import quimb.tensor as qtn
469
- from tequila import compile_circuit
467
+ from tequila import format_variable_dictionary
468
+ from tequila.simulators.simulator_api import compile_circuit
470
469
 
471
- num_variables = len(self.extract_variables())
470
+ variables = format_variable_dictionary(variables)
472
471
 
473
- if num_variables == 0:
474
- variables = {}
475
- elif variables is None:
472
+ if variables is None and not (len(self.extract_variables()) == 0):
476
473
  raise TequilaException(
477
- 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
+ )
478
477
  )
479
478
 
480
- compiled_circuit = compile_circuit(
481
- self,
479
+ compiled = compile_circuit(
480
+ abstract_circuit=self,
481
+ variables=variables,
482
+ backend=backend,
482
483
  )
483
- compiled_circuit = compiled_circuit.map_variables(variables)
484
-
485
- gate_mapping = {"Rx": "RX", "Ry": "RY", "Rz": "RZ", "H": "H", "X": "X"}
486
-
487
- quimb_circuit = qtn.Circuit(self.n_qubits)
488
-
489
- # quimb uses MSB convention, so we need to modify the qubit indices
490
- # to LSB
491
- for g in compiled_circuit.gates:
492
- if g.name not in gate_mapping:
493
- raise TequilaException(
494
- f"Gate {g.name} is not supported for conversion to matrix. "
495
- f"Supported gates: {list(gate_mapping.keys())}"
496
- )
497
-
498
- if g.is_parameterized():
499
- quimb_circuit.apply_gate(
500
- gate_mapping[g.name],
501
- params=[float(g.parameter())],
502
- qubits=[abs(t - self.n_qubits + 1) for t in list(g.target)],
503
- parameterize=True,
504
- )
505
- elif g.is_controlled():
506
- quimb_circuit.apply_gate(
507
- gate_mapping[g.name],
508
- qubits=[abs(t - self.n_qubits + 1) for t in list(g.target)],
509
- controls=[abs(c - self.n_qubits + 1) for c in list(g.control)],
510
- )
511
- else:
512
- quimb_circuit.apply_gate(
513
- gate_mapping[g.name],
514
- qubits=[abs(t - self.n_qubits + 1) for t in list(g.target)],
515
- )
516
484
 
517
- uni = quimb_circuit.get_uni()
518
- 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)
519
490
 
520
- return unitary
491
+ return np.column_stack(columns)
521
492
 
522
493
  def to_networkx(self):
523
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,19 +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
90
  A gate that has no effect, but can be used to mark a qubit as being used.
93
91
  This can for example be useful if a qubit is only being used in some variants
94
92
  of a circuit, but you want to prevent the output format from changing.
95
93
  """
96
- # Ugly workaround, we can't simply use paulis.Zero() because this wouldn't mark the qubit as being used.
97
- generator = lambda q: 0 * paulis.X(q)
98
- return _initialize_power_gate(
99
- name="I", power=power, angle=angle, target=target, control=control, generator=generator, *args, **kwargs
100
- )
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)
101
98
 
102
99
 
103
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