qadence 1.5.2__tar.gz → 1.6.1__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 (158) hide show
  1. {qadence-1.5.2 → qadence-1.6.1}/.pre-commit-config.yaml +1 -0
  2. {qadence-1.5.2 → qadence-1.6.1}/PKG-INFO +15 -9
  3. {qadence-1.5.2 → qadence-1.6.1}/mkdocs.yml +1 -1
  4. {qadence-1.5.2 → qadence-1.6.1}/pyproject.toml +14 -12
  5. {qadence-1.5.2 → qadence-1.6.1}/qadence/__init__.py +33 -5
  6. {qadence-1.5.2 → qadence-1.6.1}/qadence/backend.py +2 -2
  7. {qadence-1.5.2 → qadence-1.6.1}/qadence/backends/adjoint.py +8 -4
  8. {qadence-1.5.2 → qadence-1.6.1}/qadence/backends/braket/backend.py +3 -2
  9. {qadence-1.5.2 → qadence-1.6.1}/qadence/backends/braket/config.py +2 -2
  10. {qadence-1.5.2 → qadence-1.6.1}/qadence/backends/gpsr.py +1 -1
  11. {qadence-1.5.2 → qadence-1.6.1}/qadence/backends/horqrux/backend.py +23 -31
  12. {qadence-1.5.2 → qadence-1.6.1}/qadence/backends/horqrux/config.py +2 -2
  13. {qadence-1.5.2 → qadence-1.6.1}/qadence/backends/pulser/backend.py +82 -45
  14. {qadence-1.5.2 → qadence-1.6.1}/qadence/backends/pulser/config.py +0 -28
  15. qadence-1.6.1/qadence/backends/pulser/convert_ops.py +55 -0
  16. {qadence-1.5.2 → qadence-1.6.1}/qadence/backends/pulser/pulses.py +2 -2
  17. {qadence-1.5.2 → qadence-1.6.1}/qadence/backends/pyqtorch/backend.py +3 -2
  18. {qadence-1.5.2 → qadence-1.6.1}/qadence/backends/pyqtorch/config.py +2 -2
  19. {qadence-1.5.2 → qadence-1.6.1}/qadence/backends/pyqtorch/convert_ops.py +40 -16
  20. {qadence-1.5.2 → qadence-1.6.1}/qadence/blocks/block_to_tensor.py +7 -6
  21. {qadence-1.5.2 → qadence-1.6.1}/qadence/blocks/matrix.py +2 -2
  22. {qadence-1.5.2 → qadence-1.6.1}/qadence/blocks/primitive.py +2 -1
  23. {qadence-1.5.2 → qadence-1.6.1}/qadence/blocks/utils.py +2 -2
  24. {qadence-1.5.2 → qadence-1.6.1}/qadence/circuit.py +5 -2
  25. {qadence-1.5.2 → qadence-1.6.1}/qadence/constructors/__init__.py +1 -10
  26. {qadence-1.5.2 → qadence-1.6.1}/qadence/constructors/ansatze.py +1 -65
  27. {qadence-1.5.2 → qadence-1.6.1}/qadence/constructors/daqc/daqc.py +3 -2
  28. {qadence-1.5.2 → qadence-1.6.1}/qadence/constructors/daqc/gen_parser.py +3 -2
  29. {qadence-1.5.2 → qadence-1.6.1}/qadence/constructors/daqc/utils.py +3 -3
  30. {qadence-1.5.2 → qadence-1.6.1}/qadence/constructors/feature_maps.py +2 -90
  31. {qadence-1.5.2 → qadence-1.6.1}/qadence/constructors/hamiltonians.py +2 -6
  32. {qadence-1.5.2 → qadence-1.6.1}/qadence/constructors/rydberg_feature_maps.py +2 -2
  33. {qadence-1.5.2 → qadence-1.6.1}/qadence/decompose.py +2 -2
  34. {qadence-1.5.2 → qadence-1.6.1}/qadence/engines/torch/differentiable_expectation.py +7 -0
  35. {qadence-1.5.2 → qadence-1.6.1}/qadence/extensions.py +4 -15
  36. qadence-1.6.1/qadence/log_config.yaml +24 -0
  37. qadence-1.6.1/qadence/logger.py +17 -0
  38. {qadence-1.5.2 → qadence-1.6.1}/qadence/measurements/shadow.py +3 -16
  39. {qadence-1.5.2 → qadence-1.6.1}/qadence/ml_tools/config.py +11 -1
  40. {qadence-1.5.2 → qadence-1.6.1}/qadence/ml_tools/models.py +10 -2
  41. {qadence-1.5.2 → qadence-1.6.1}/qadence/ml_tools/printing.py +1 -3
  42. {qadence-1.5.2 → qadence-1.6.1}/qadence/ml_tools/saveload.py +23 -6
  43. {qadence-1.5.2 → qadence-1.6.1}/qadence/ml_tools/train_grad.py +39 -6
  44. {qadence-1.5.2 → qadence-1.6.1}/qadence/ml_tools/train_no_grad.py +2 -2
  45. {qadence-1.5.2 → qadence-1.6.1}/qadence/models/quantum_model.py +13 -6
  46. {qadence-1.5.2 → qadence-1.6.1}/qadence/noise/readout.py +2 -3
  47. {qadence-1.5.2 → qadence-1.6.1}/qadence/operations/__init__.py +0 -2
  48. {qadence-1.5.2 → qadence-1.6.1}/qadence/operations/analog.py +2 -12
  49. {qadence-1.5.2 → qadence-1.6.1}/qadence/operations/control_ops.py +3 -2
  50. {qadence-1.5.2 → qadence-1.6.1}/qadence/operations/ham_evo.py +5 -7
  51. {qadence-1.5.2 → qadence-1.6.1}/qadence/operations/parametric.py +3 -2
  52. {qadence-1.5.2 → qadence-1.6.1}/qadence/operations/primitive.py +2 -2
  53. {qadence-1.5.2 → qadence-1.6.1}/qadence/overlap.py +7 -12
  54. {qadence-1.5.2 → qadence-1.6.1}/qadence/parameters.py +2 -2
  55. {qadence-1.5.2 → qadence-1.6.1}/qadence/serialization.py +2 -2
  56. {qadence-1.5.2 → qadence-1.6.1}/qadence/states.py +20 -5
  57. {qadence-1.5.2 → qadence-1.6.1}/qadence/transpile/block.py +2 -2
  58. {qadence-1.5.2 → qadence-1.6.1}/qadence/types.py +2 -2
  59. {qadence-1.5.2 → qadence-1.6.1}/qadence/utils.py +42 -3
  60. {qadence-1.5.2 → qadence-1.6.1}/renovate.json +7 -4
  61. qadence-1.5.2/qadence/backends/pulser/convert_ops.py +0 -42
  62. qadence-1.5.2/qadence/logger.py +0 -35
  63. {qadence-1.5.2 → qadence-1.6.1}/.coveragerc +0 -0
  64. {qadence-1.5.2 → qadence-1.6.1}/.github/dependabot.yml +0 -0
  65. {qadence-1.5.2 → qadence-1.6.1}/.github/workflows/build_docs.yml +0 -0
  66. {qadence-1.5.2 → qadence-1.6.1}/.github/workflows/dependabot.yml +0 -0
  67. {qadence-1.5.2 → qadence-1.6.1}/.github/workflows/lint.yml +0 -0
  68. {qadence-1.5.2 → qadence-1.6.1}/.github/workflows/test_all.yml +0 -0
  69. {qadence-1.5.2 → qadence-1.6.1}/.github/workflows/test_examples.yml +0 -0
  70. {qadence-1.5.2 → qadence-1.6.1}/.github/workflows/test_fast.yml +0 -0
  71. {qadence-1.5.2 → qadence-1.6.1}/.gitignore +0 -0
  72. {qadence-1.5.2 → qadence-1.6.1}/LICENSE +0 -0
  73. {qadence-1.5.2 → qadence-1.6.1}/MANIFEST.in +0 -0
  74. {qadence-1.5.2 → qadence-1.6.1}/README.md +0 -0
  75. {qadence-1.5.2 → qadence-1.6.1}/qadence/analog/__init__.py +0 -0
  76. {qadence-1.5.2 → qadence-1.6.1}/qadence/analog/addressing.py +0 -0
  77. {qadence-1.5.2 → qadence-1.6.1}/qadence/analog/constants.py +0 -0
  78. {qadence-1.5.2 → qadence-1.6.1}/qadence/analog/device.py +0 -0
  79. {qadence-1.5.2 → qadence-1.6.1}/qadence/analog/hamiltonian_terms.py +0 -0
  80. {qadence-1.5.2 → qadence-1.6.1}/qadence/analog/parse_analog.py +0 -0
  81. {qadence-1.5.2 → qadence-1.6.1}/qadence/backends/__init__.py +0 -0
  82. {qadence-1.5.2 → qadence-1.6.1}/qadence/backends/api.py +0 -0
  83. {qadence-1.5.2 → qadence-1.6.1}/qadence/backends/braket/__init__.py +0 -0
  84. {qadence-1.5.2 → qadence-1.6.1}/qadence/backends/braket/convert_ops.py +0 -0
  85. {qadence-1.5.2 → qadence-1.6.1}/qadence/backends/horqrux/__init__.py +0 -0
  86. {qadence-1.5.2 → qadence-1.6.1}/qadence/backends/horqrux/convert_ops.py +0 -0
  87. {qadence-1.5.2 → qadence-1.6.1}/qadence/backends/jax_utils.py +0 -0
  88. {qadence-1.5.2 → qadence-1.6.1}/qadence/backends/pulser/__init__.py +0 -0
  89. {qadence-1.5.2 → qadence-1.6.1}/qadence/backends/pulser/channels.py +0 -0
  90. {qadence-1.5.2 → qadence-1.6.1}/qadence/backends/pulser/cloud.py +0 -0
  91. {qadence-1.5.2 → qadence-1.6.1}/qadence/backends/pulser/devices.py +0 -0
  92. {qadence-1.5.2 → qadence-1.6.1}/qadence/backends/pulser/waveforms.py +0 -0
  93. {qadence-1.5.2 → qadence-1.6.1}/qadence/backends/pyqtorch/__init__.py +0 -0
  94. {qadence-1.5.2 → qadence-1.6.1}/qadence/backends/utils.py +0 -0
  95. {qadence-1.5.2 → qadence-1.6.1}/qadence/blocks/__init__.py +0 -0
  96. {qadence-1.5.2 → qadence-1.6.1}/qadence/blocks/abstract.py +0 -0
  97. {qadence-1.5.2 → qadence-1.6.1}/qadence/blocks/analog.py +0 -0
  98. {qadence-1.5.2 → qadence-1.6.1}/qadence/blocks/composite.py +0 -0
  99. {qadence-1.5.2 → qadence-1.6.1}/qadence/blocks/embedding.py +0 -0
  100. {qadence-1.5.2 → qadence-1.6.1}/qadence/blocks/manipulate.py +0 -0
  101. {qadence-1.5.2 → qadence-1.6.1}/qadence/constructors/daqc/__init__.py +0 -0
  102. {qadence-1.5.2 → qadence-1.6.1}/qadence/constructors/iia.py +0 -0
  103. {qadence-1.5.2 → qadence-1.6.1}/qadence/constructors/qft.py +0 -0
  104. {qadence-1.5.2 → qadence-1.6.1}/qadence/constructors/rydberg_hea.py +0 -0
  105. {qadence-1.5.2 → qadence-1.6.1}/qadence/constructors/utils.py +0 -0
  106. {qadence-1.5.2 → qadence-1.6.1}/qadence/divergences.py +0 -0
  107. {qadence-1.5.2 → qadence-1.6.1}/qadence/draw/__init__.py +0 -0
  108. {qadence-1.5.2 → qadence-1.6.1}/qadence/draw/assets/dark/measurement.png +0 -0
  109. {qadence-1.5.2 → qadence-1.6.1}/qadence/draw/assets/dark/measurement.svg +0 -0
  110. {qadence-1.5.2 → qadence-1.6.1}/qadence/draw/assets/light/measurement.png +0 -0
  111. {qadence-1.5.2 → qadence-1.6.1}/qadence/draw/assets/light/measurement.svg +0 -0
  112. {qadence-1.5.2 → qadence-1.6.1}/qadence/draw/themes.py +0 -0
  113. {qadence-1.5.2 → qadence-1.6.1}/qadence/draw/utils.py +0 -0
  114. {qadence-1.5.2 → qadence-1.6.1}/qadence/draw/vizbackend.py +0 -0
  115. {qadence-1.5.2 → qadence-1.6.1}/qadence/engines/__init__.py +0 -0
  116. {qadence-1.5.2 → qadence-1.6.1}/qadence/engines/differentiable_backend.py +0 -0
  117. {qadence-1.5.2 → qadence-1.6.1}/qadence/engines/jax/__init__.py +0 -0
  118. {qadence-1.5.2 → qadence-1.6.1}/qadence/engines/jax/differentiable_backend.py +0 -0
  119. {qadence-1.5.2 → qadence-1.6.1}/qadence/engines/jax/differentiable_expectation.py +0 -0
  120. {qadence-1.5.2 → qadence-1.6.1}/qadence/engines/torch/__init__.py +0 -0
  121. {qadence-1.5.2 → qadence-1.6.1}/qadence/engines/torch/differentiable_backend.py +0 -0
  122. {qadence-1.5.2 → qadence-1.6.1}/qadence/exceptions/__init__.py +0 -0
  123. {qadence-1.5.2 → qadence-1.6.1}/qadence/exceptions/exceptions.py +0 -0
  124. {qadence-1.5.2 → qadence-1.6.1}/qadence/execution.py +0 -0
  125. {qadence-1.5.2 → qadence-1.6.1}/qadence/finitediff.py +0 -0
  126. {qadence-1.5.2 → qadence-1.6.1}/qadence/libs.py +0 -0
  127. {qadence-1.5.2 → qadence-1.6.1}/qadence/measurements/__init__.py +0 -0
  128. {qadence-1.5.2 → qadence-1.6.1}/qadence/measurements/protocols.py +0 -0
  129. {qadence-1.5.2 → qadence-1.6.1}/qadence/measurements/samples.py +0 -0
  130. {qadence-1.5.2 → qadence-1.6.1}/qadence/measurements/tomography.py +0 -0
  131. {qadence-1.5.2 → qadence-1.6.1}/qadence/measurements/utils.py +0 -0
  132. {qadence-1.5.2 → qadence-1.6.1}/qadence/mitigations/__init__.py +0 -0
  133. {qadence-1.5.2 → qadence-1.6.1}/qadence/mitigations/analog_zne.py +0 -0
  134. {qadence-1.5.2 → qadence-1.6.1}/qadence/mitigations/protocols.py +0 -0
  135. {qadence-1.5.2 → qadence-1.6.1}/qadence/mitigations/readout.py +0 -0
  136. {qadence-1.5.2 → qadence-1.6.1}/qadence/ml_tools/__init__.py +0 -0
  137. {qadence-1.5.2 → qadence-1.6.1}/qadence/ml_tools/data.py +0 -0
  138. {qadence-1.5.2 → qadence-1.6.1}/qadence/ml_tools/optimize_step.py +0 -0
  139. {qadence-1.5.2 → qadence-1.6.1}/qadence/ml_tools/parameters.py +0 -0
  140. {qadence-1.5.2 → qadence-1.6.1}/qadence/ml_tools/tensors.py +0 -0
  141. {qadence-1.5.2 → qadence-1.6.1}/qadence/ml_tools/utils.py +0 -0
  142. {qadence-1.5.2 → qadence-1.6.1}/qadence/models/__init__.py +0 -0
  143. {qadence-1.5.2 → qadence-1.6.1}/qadence/models/qnn.py +0 -0
  144. {qadence-1.5.2 → qadence-1.6.1}/qadence/noise/__init__.py +0 -0
  145. {qadence-1.5.2 → qadence-1.6.1}/qadence/noise/protocols.py +0 -0
  146. {qadence-1.5.2 → qadence-1.6.1}/qadence/protocols.py +0 -0
  147. {qadence-1.5.2 → qadence-1.6.1}/qadence/py.typed +0 -0
  148. {qadence-1.5.2 → qadence-1.6.1}/qadence/qubit_support.py +0 -0
  149. {qadence-1.5.2 → qadence-1.6.1}/qadence/register.py +0 -0
  150. {qadence-1.5.2 → qadence-1.6.1}/qadence/serial_expr_grammar.peg +0 -0
  151. {qadence-1.5.2 → qadence-1.6.1}/qadence/transpile/__init__.py +0 -0
  152. {qadence-1.5.2 → qadence-1.6.1}/qadence/transpile/apply_fn.py +0 -0
  153. {qadence-1.5.2 → qadence-1.6.1}/qadence/transpile/circuit.py +0 -0
  154. {qadence-1.5.2 → qadence-1.6.1}/qadence/transpile/digitalize.py +0 -0
  155. {qadence-1.5.2 → qadence-1.6.1}/qadence/transpile/flatten.py +0 -0
  156. {qadence-1.5.2 → qadence-1.6.1}/qadence/transpile/invert.py +0 -0
  157. {qadence-1.5.2 → qadence-1.6.1}/qadence/transpile/transpile.py +0 -0
  158. {qadence-1.5.2 → qadence-1.6.1}/setup.py +0 -0
@@ -23,6 +23,7 @@ repos:
23
23
  rev: v1.9.0
24
24
  hooks:
25
25
  - id: mypy
26
+ args: [--install-types, --non-interactive]
26
27
  exclude: examples|docs
27
28
 
28
29
  - repo: https://github.com/DanielNoord/pydocstringformatter
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: qadence
3
- Version: 1.5.2
3
+ Version: 1.6.1
4
4
  Summary: Pasqal interface for circuit-based quantum computing SDKs
5
5
  Author-email: Aleksander Wennersteen <aleksander.wennersteen@pasqal.com>, Gert-Jan Both <gert-jan.both@pasqal.com>, Niklas Heim <niklas.heim@pasqal.com>, Mario Dagrada <mario.dagrada@pasqal.com>, Vincent Elfving <vincent.elfving@pasqal.com>, Dominik Seitz <dominik.seitz@pasqal.com>, Roland Guichard <roland.guichard@pasqal.com>, "Joao P. Moutinho" <joao.moutinho@pasqal.com>, Vytautas Abramavicius <vytautas.abramavicius@pasqal.com>, Gergana Velikova <gergana.velikova@pasqal.com>, Eduardo Maschio <eduardo.maschio@pasqal.com>
6
6
  License: Apache 2.0
@@ -11,9 +11,10 @@ Classifier: Programming Language :: Python :: 3
11
11
  Classifier: Programming Language :: Python :: 3.9
12
12
  Classifier: Programming Language :: Python :: 3.10
13
13
  Classifier: Programming Language :: Python :: 3.11
14
+ Classifier: Programming Language :: Python :: 3.12
14
15
  Classifier: Programming Language :: Python :: Implementation :: CPython
15
16
  Classifier: Programming Language :: Python :: Implementation :: PyPy
16
- Requires-Python: <3.13,>=3.9
17
+ Requires-Python: >=3.9
17
18
  Requires-Dist: arpeggio==2.0.2
18
19
  Requires-Dist: deepdiff
19
20
  Requires-Dist: jsonschema
@@ -21,20 +22,24 @@ Requires-Dist: matplotlib
21
22
  Requires-Dist: nevergrad
22
23
  Requires-Dist: numpy
23
24
  Requires-Dist: openfermion
24
- Requires-Dist: pyqtorch==1.1.0
25
+ Requires-Dist: pyqtorch==1.1.2
26
+ Requires-Dist: pyyaml
25
27
  Requires-Dist: rich
26
28
  Requires-Dist: scipy
27
29
  Requires-Dist: sympytorch>=0.1.2
28
30
  Requires-Dist: tensorboard>=2.12.0
29
31
  Requires-Dist: torch
30
32
  Provides-Extra: all
31
- Requires-Dist: amazon-braket-sdk==1.71.0; extra == 'all'
32
- Requires-Dist: graphviz; extra == 'all'
33
+ Requires-Dist: braket; extra == 'all'
33
34
  Requires-Dist: libs; extra == 'all'
34
35
  Requires-Dist: protocols; extra == 'all'
35
- Requires-Dist: pulser>=0.15.2; extra == 'all'
36
+ Requires-Dist: pulser; extra == 'all'
37
+ Requires-Dist: visualization; extra == 'all'
36
38
  Provides-Extra: braket
37
- Requires-Dist: amazon-braket-sdk==1.71.0; extra == 'braket'
39
+ Requires-Dist: amazon-braket-sdk<1.71.2; extra == 'braket'
40
+ Provides-Extra: dlprof
41
+ Requires-Dist: nvidia-dlprof[pytorch]; extra == 'dlprof'
42
+ Requires-Dist: nvidia-pyindex; extra == 'dlprof'
38
43
  Provides-Extra: horqrux
39
44
  Requires-Dist: einops; extra == 'horqrux'
40
45
  Requires-Dist: flax; extra == 'horqrux'
@@ -48,8 +53,9 @@ Requires-Dist: qadence-libs; extra == 'libs'
48
53
  Provides-Extra: protocols
49
54
  Requires-Dist: qadence-protocols; extra == 'protocols'
50
55
  Provides-Extra: pulser
51
- Requires-Dist: pasqal-cloud>=0.3.5; extra == 'pulser'
52
- Requires-Dist: pulser>=v0.15.2; extra == 'pulser'
56
+ Requires-Dist: pasqal-cloud==0.8.1; extra == 'pulser'
57
+ Requires-Dist: pulser-core==0.18.1; extra == 'pulser'
58
+ Requires-Dist: pulser-simulation==0.18.1; extra == 'pulser'
53
59
  Provides-Extra: visualization
54
60
  Requires-Dist: graphviz; extra == 'visualization'
55
61
  Description-Content-Type: text/markdown
@@ -50,6 +50,7 @@ nav:
50
50
  - Quantum circuits differentiation: tutorials/advanced_tutorials/differentiability.md
51
51
  - Custom quantum models: tutorials/advanced_tutorials/custom-models.md
52
52
  - Projector blocks: tutorials/advanced_tutorials/projectors.md
53
+ - Profiling and debugging on CUDA devices: tutorials/advanced_tutorials/profiling-and-debugging.md
53
54
 
54
55
  - Realistic simulations:
55
56
  - tutorials/realistic_sims/index.md
@@ -80,7 +81,6 @@ nav:
80
81
  - Backends:
81
82
  - Abstract backend: api/backends/backend.md
82
83
  - PyQTorch: api/backends/pyqtorch.md
83
- - Amazon Braket: api/backends/braket.md
84
84
  - Pulser: api/backends/pulser.md
85
85
  - DifferentiableBackend: api/backends/differentiable.md
86
86
 
@@ -19,9 +19,9 @@ authors = [
19
19
  { name = "Gergana Velikova", email = "gergana.velikova@pasqal.com" },
20
20
  { name = "Eduardo Maschio", email = "eduardo.maschio@pasqal.com" },
21
21
  ]
22
- requires-python = ">=3.9,<3.13"
22
+ requires-python = ">=3.9"
23
23
  license = {text = "Apache 2.0"}
24
- version = "1.5.2"
24
+ version = "1.6.1"
25
25
  classifiers=[
26
26
  "License :: OSI Approved :: Apache Software License",
27
27
  "Programming Language :: Python",
@@ -29,6 +29,7 @@ classifiers=[
29
29
  "Programming Language :: Python :: 3.9",
30
30
  "Programming Language :: Python :: 3.10",
31
31
  "Programming Language :: Python :: 3.11",
32
+ "Programming Language :: Python :: 3.12",
32
33
  "Programming Language :: Python :: Implementation :: CPython",
33
34
  "Programming Language :: Python :: Implementation :: PyPy",
34
35
  ]
@@ -43,7 +44,8 @@ dependencies = [
43
44
  "jsonschema",
44
45
  "nevergrad",
45
46
  "scipy",
46
- "pyqtorch==1.1.0",
47
+ "pyqtorch==1.1.2",
48
+ "pyyaml",
47
49
  "matplotlib",
48
50
  "Arpeggio==2.0.2",
49
51
  ]
@@ -53,8 +55,8 @@ allow-direct-references = true
53
55
  allow-ambiguous-features = true
54
56
 
55
57
  [project.optional-dependencies]
56
- pulser = ["pulser>=v0.15.2", "pasqal-cloud>=0.3.5"]
57
- braket = ["amazon-braket-sdk==1.71.0"]
58
+ pulser = ["pulser-core==0.18.1", "pulser-simulation==0.18.1","pasqal-cloud==0.8.1"]
59
+ braket = ["amazon-braket-sdk<1.71.2"]
58
60
  visualization = [
59
61
  "graphviz",
60
62
  # FIXME: will be needed once we support latex labels
@@ -71,15 +73,13 @@ horqrux = [
71
73
  "sympy2jax"]
72
74
  protocols = ["qadence-protocols"]
73
75
  libs = ["qadence-libs"]
76
+ dlprof = ["nvidia-pyindex", "nvidia-dlprof[pytorch]"]
74
77
  all = [
75
- "pulser>=0.15.2",
76
- "amazon-braket-sdk==1.71.0",
77
- "graphviz",
78
+ "pulser",
79
+ "braket",
80
+ "visualization",
78
81
  "protocols",
79
82
  "libs",
80
- # FIXME: will be needed once we support latex labels
81
- # "latex2svg @ git+https://github.com/Moonbase59/latex2svg.git#egg=latex2svg",
82
- # "scour",
83
83
  ]
84
84
 
85
85
  [tool.hatch.envs.default]
@@ -90,6 +90,7 @@ dependencies = [
90
90
  "pytest-cov",
91
91
  "pytest-mypy",
92
92
  "pytest-xdist",
93
+ "types-PyYAML",
93
94
  "ipykernel",
94
95
  "pre-commit",
95
96
  "black",
@@ -181,9 +182,10 @@ line-length = 100
181
182
  required-imports = ["from __future__ import annotations"]
182
183
 
183
184
  [tool.ruff.per-file-ignores]
184
- "__init__.py" = ["F401"]
185
+ "__init__.py" = ["F401", "E402"]
185
186
  "qadence/operations/primitive.py" = ["E742"] # Avoid ambiguous class name warning for identity.
186
187
  "qadence/backends/horqrux/convert_ops.py" = ["E741"] # Avoid ambiguous class name warning for 0.
188
+ "examples/*" = ["E402"] # Allow torch seed to be set before qadence imports
187
189
 
188
190
  [tool.ruff.mccabe]
189
191
  max-complexity = 15
@@ -1,10 +1,43 @@
1
1
  from __future__ import annotations
2
2
 
3
+ import logging
4
+ import logging.config
5
+ import os
3
6
  from importlib import import_module
7
+ from pathlib import Path
4
8
 
9
+ import yaml
5
10
  from torch import cdouble, set_default_dtype
6
11
  from torch import float64 as torchfloat64
7
12
 
13
+ DEFAULT_FLOAT_DTYPE = torchfloat64
14
+ DEFAULT_COMPLEX_DTYPE = cdouble
15
+ set_default_dtype(DEFAULT_FLOAT_DTYPE)
16
+
17
+ logging_levels = {
18
+ "DEBUG": logging.DEBUG,
19
+ "INFO": logging.INFO,
20
+ "WARNING": logging.WARNING,
21
+ "ERROR": logging.ERROR,
22
+ "CRITICAL": logging.CRITICAL,
23
+ }
24
+ LOG_CONFIG_PATH = os.environ.get("QADENCE_LOG_CONFIG", f"{Path(__file__).parent}/log_config.yaml")
25
+ LOG_BASE_LEVEL = os.environ.get("QADENCE_LOG_LEVEL", "").upper()
26
+
27
+ with open(LOG_CONFIG_PATH, "r") as stream:
28
+ log_config = yaml.load(stream, Loader=yaml.FullLoader)
29
+ logging.config.dictConfig(log_config)
30
+
31
+ logger: logging.Logger = logging.getLogger(__name__)
32
+ LOG_LEVEL = logging_levels.get(LOG_BASE_LEVEL, logging.INFO) # type: ignore[arg-type]
33
+ logger.setLevel(LOG_LEVEL)
34
+ [
35
+ h.setLevel(LOG_LEVEL) # type: ignore[func-returns-value]
36
+ for h in logger.handlers
37
+ if h.get_name() == "console"
38
+ ]
39
+ logger.debug(f"Qadence logger successfully setup with log level {LOG_LEVEL}")
40
+
8
41
  from .analog import *
9
42
  from .backend import *
10
43
  from .backends import *
@@ -28,11 +61,6 @@ from .transpile import *
28
61
  from .types import *
29
62
  from .utils import *
30
63
 
31
- DEFAULT_FLOAT_DTYPE = torchfloat64
32
- DEFAULT_COMPLEX_DTYPE = cdouble
33
- set_default_dtype(DEFAULT_FLOAT_DTYPE)
34
-
35
-
36
64
  """Fetch the functions defined in the __all__ of each sub-module.
37
65
 
38
66
  Import to the qadence name space. Make sure each added submodule has the respective definition:
@@ -3,6 +3,7 @@ from __future__ import annotations
3
3
  from abc import ABC, abstractmethod
4
4
  from collections import Counter
5
5
  from dataclasses import dataclass, fields
6
+ from logging import getLogger
6
7
  from typing import Any, Callable, Iterator, Tuple
7
8
 
8
9
  from openfermion import QubitOperator
@@ -20,14 +21,13 @@ from qadence.blocks import (
20
21
  )
21
22
  from qadence.blocks.analog import ConstantAnalogRotation, InteractionBlock
22
23
  from qadence.circuit import QuantumCircuit
23
- from qadence.logger import get_logger
24
24
  from qadence.measurements import Measurements
25
25
  from qadence.mitigations import Mitigations
26
26
  from qadence.noise import Noise
27
27
  from qadence.parameters import stringify
28
28
  from qadence.types import ArrayLike, BackendName, DiffMode, Endianness, Engine, ParamDictType
29
29
 
30
- logger = get_logger(__file__)
30
+ logger = getLogger(__name__)
31
31
 
32
32
 
33
33
  @dataclass
@@ -7,7 +7,7 @@ from pyqtorch.circuit import QuantumCircuit as PyQCircuit
7
7
  from pyqtorch.parametric import Parametric as PyQParametric
8
8
  from pyqtorch.primitive import Primitive as PyQPrimitive
9
9
  from pyqtorch.utils import inner_prod, param_dict
10
- from torch import Tensor, no_grad, tensor
10
+ from torch import Tensor, no_grad, zeros
11
11
  from torch.autograd import Function
12
12
  from torch.nn import Module
13
13
 
@@ -125,7 +125,7 @@ class AdjointExpectation(Function):
125
125
  ctx.projected_state, op.dagger(values), op.qubit_support
126
126
  )
127
127
  elif isinstance(op, PyQCircuit):
128
- grads = [g for sub_op in op.reverse() for g in _apply_adjoint(ctx, sub_op)]
128
+ grads = [g for sub_op in op.operations[::-1] for g in _apply_adjoint(ctx, sub_op)]
129
129
  elif isinstance(op, PyQPrimitive):
130
130
  ctx.out_state = apply_operator(ctx.out_state, op.dagger(values), op.qubit_support)
131
131
  if isinstance(op, PyQParametric) and values[op.param_name].requires_grad:
@@ -147,13 +147,17 @@ class AdjointExpectation(Function):
147
147
 
148
148
  grads = list(
149
149
  reversed(
150
- [grad_out * g for op in ctx.circuit.reverse() for g in _apply_adjoint(ctx, op)]
150
+ [
151
+ grad_out * g
152
+ for op in ctx.circuit.operations[::-1]
153
+ for g in _apply_adjoint(ctx, op)
154
+ ]
151
155
  )
152
156
  )
153
157
  num_grads = len(grads)
154
158
  num_params = len(ctx.saved_tensors)
155
159
  diff = num_params - num_grads
156
- grads = grads + [tensor([0]) for _ in range(diff)]
160
+ grads = grads + [zeros(1, device=ctx.circuit.device) for _ in range(diff)]
157
161
  # Set observable grads to 0
158
162
  ctx.save_for_backward(*grads)
159
163
  return (None, None, None, None, *grads)
@@ -2,6 +2,7 @@ from __future__ import annotations
2
2
 
3
3
  from collections import Counter
4
4
  from dataclasses import dataclass, field
5
+ from logging import getLogger
5
6
  from typing import Any
6
7
 
7
8
  import numpy as np
@@ -15,7 +16,6 @@ from qadence.backend import ConvertedCircuit, ConvertedObservable
15
16
  from qadence.backends.utils import to_list_of_dicts
16
17
  from qadence.blocks import AbstractBlock, block_to_tensor
17
18
  from qadence.circuit import QuantumCircuit
18
- from qadence.logger import get_logger
19
19
  from qadence.measurements import Measurements
20
20
  from qadence.mitigations import Mitigations
21
21
  from qadence.mitigations.protocols import apply_mitigation
@@ -29,7 +29,7 @@ from qadence.utils import Endianness
29
29
  from .config import Configuration, default_passes
30
30
  from .convert_ops import convert_block
31
31
 
32
- logger = get_logger(__file__)
32
+ logger = getLogger(__name__)
33
33
 
34
34
 
35
35
  def promote_parameters(parameters: dict[str, Tensor | float]) -> dict[str, float]:
@@ -56,6 +56,7 @@ class Backend(BackendInterface):
56
56
  native_endianness: Endianness = Endianness.BIG
57
57
  config: Configuration = field(default_factory=Configuration)
58
58
  engine: Engine = Engine.TORCH
59
+ logger.debug("Initialised")
59
60
 
60
61
  # braket specifics
61
62
  # TODO: include it in the configuration?
@@ -1,13 +1,13 @@
1
1
  from __future__ import annotations
2
2
 
3
3
  from dataclasses import dataclass, field
4
+ from logging import getLogger
4
5
  from typing import Callable
5
6
 
6
7
  from qadence.backend import BackendConfiguration
7
- from qadence.logger import get_logger
8
8
  from qadence.transpile import digitalize, fill_identities
9
9
 
10
- logger = get_logger(__name__)
10
+ logger = getLogger(__name__)
11
11
 
12
12
  default_passes: list[Callable] = [fill_identities, digitalize]
13
13
 
@@ -20,7 +20,7 @@ def general_psr(spectrum: Tensor, n_eqs: int | None = None, shift_prefac: float
20
20
  sorted_unique_spectral_gaps = torch.tensor(list(sorted_unique_spectral_gaps))
21
21
 
22
22
  if n_eqs == 1:
23
- return partial(single_gap_psr, spectral_gap=sorted_unique_spectral_gaps.item())
23
+ return single_gap_psr
24
24
  else:
25
25
  return partial(
26
26
  multi_gap_psr,
@@ -2,6 +2,7 @@ from __future__ import annotations
2
2
 
3
3
  from collections import Counter
4
4
  from dataclasses import dataclass, field
5
+ from logging import getLogger
5
6
  from typing import Any
6
7
 
7
8
  import jax
@@ -28,6 +29,8 @@ from qadence.utils import int_to_basis
28
29
  from .config import Configuration, default_passes
29
30
  from .convert_ops import HorqruxCircuit, convert_block, convert_observable
30
31
 
32
+ logger = getLogger(__name__)
33
+
31
34
 
32
35
  @dataclass(frozen=True, eq=True)
33
36
  class Backend(BackendInterface):
@@ -43,6 +46,7 @@ class Backend(BackendInterface):
43
46
  native_endianness: Endianness = Endianness.BIG
44
47
  config: Configuration = field(default_factory=Configuration)
45
48
  engine: Engine = Engine.JAX
49
+ logger.debug("Initialised")
46
50
 
47
51
  def circuit(self, circuit: QuantumCircuit) -> ConvertedCircuit:
48
52
  passes = self.config.transpilation_passes
@@ -191,28 +195,6 @@ class Backend(BackendInterface):
191
195
  if n_shots < 1:
192
196
  raise ValueError("You can only call sample with n_shots>0.")
193
197
 
194
- def _sample(
195
- _probs: ArrayLike, n_shots: int, endianness: Endianness, n_qubits: int
196
- ) -> Counter:
197
- _logits = jax.vmap(lambda _p: jnp.log(_p / (1 - _p)))(_probs)
198
-
199
- def _smple(accumulator: ArrayLike, i: int) -> tuple[ArrayLike, None]:
200
- accumulator = accumulator.at[i].set(
201
- jax.random.categorical(jax.random.PRNGKey(i), _logits)
202
- )
203
- return accumulator, None
204
-
205
- samples = jax.lax.scan(
206
- _smple, jnp.empty_like(jnp.arange(n_shots)), jnp.arange(n_shots)
207
- )[0]
208
- return Counter(
209
- {
210
- int_to_basis(k=k, n_qubits=n_qubits, endianness=endianness): count.item()
211
- for k, count in enumerate(jnp.bincount(samples))
212
- if count > 0
213
- }
214
- )
215
-
216
198
  wf = self.run(
217
199
  circuit=circuit,
218
200
  param_values=param_values,
@@ -221,16 +203,26 @@ class Backend(BackendInterface):
221
203
  unhorqify_state=False,
222
204
  )
223
205
  probs = jnp.abs(jnp.float_power(wf, 2.0)).ravel()
224
- samples = [
225
- _sample(
226
- _probs=probs,
227
- n_shots=n_shots,
228
- endianness=endianness,
229
- n_qubits=circuit.abstract.n_qubits,
230
- ),
231
- ]
206
+ key = jax.random.PRNGKey(0)
207
+ # JAX handles pseudo random number generation by tracking an explicit state via a random key
208
+ # For more details, see https://jax.readthedocs.io/en/latest/random-numbers.html
209
+ samples = jax.vmap(
210
+ lambda subkey: jax.random.choice(
211
+ key=subkey, a=jnp.arange(0, 2**circuit.abstract.n_qubits), p=probs
212
+ )
213
+ )(jax.random.split(key, n_shots))
232
214
 
233
- return samples
215
+ return [
216
+ Counter(
217
+ {
218
+ int_to_basis(
219
+ k=k, n_qubits=circuit.abstract.n_qubits, endianness=endianness
220
+ ): count.item()
221
+ for k, count in enumerate(jnp.bincount(samples))
222
+ if count > 0
223
+ }
224
+ )
225
+ ]
234
226
 
235
227
  def assign_parameters(self, circuit: ConvertedCircuit, param_values: ParamDictType) -> Any:
236
228
  raise NotImplementedError
@@ -1,18 +1,18 @@
1
1
  from __future__ import annotations
2
2
 
3
3
  from dataclasses import dataclass
4
+ from logging import getLogger
4
5
  from typing import Callable
5
6
 
6
7
  from qadence.analog import add_background_hamiltonian
7
8
  from qadence.backend import BackendConfiguration
8
- from qadence.logger import get_logger
9
9
  from qadence.transpile import (
10
10
  blockfn_to_circfn,
11
11
  flatten,
12
12
  scale_primitive_blocks_only,
13
13
  )
14
14
 
15
- logger = get_logger(__name__)
15
+ logger = getLogger(__name__)
16
16
 
17
17
 
18
18
  def default_passes(config: Configuration) -> list[Callable]:
@@ -1,7 +1,9 @@
1
1
  from __future__ import annotations
2
2
 
3
3
  from collections import Counter
4
+ from collections.abc import Iterable
4
5
  from dataclasses import dataclass, field
6
+ from logging import getLogger
5
7
  from typing import Any
6
8
 
7
9
  import numpy as np
@@ -10,7 +12,7 @@ import torch
10
12
  from pulser import Register as PulserRegister
11
13
  from pulser import Sequence
12
14
  from pulser_simulation import SimConfig
13
- from pulser_simulation.simresults import SimulationResults
15
+ from pulser_simulation.simresults import CoherentResults, SimulationResults
14
16
  from pulser_simulation.simulation import QutipEmulator
15
17
  from torch import Tensor
16
18
 
@@ -19,7 +21,6 @@ from qadence.backend import ConvertedCircuit, ConvertedObservable
19
21
  from qadence.backends.utils import to_list_of_dicts
20
22
  from qadence.blocks import AbstractBlock
21
23
  from qadence.circuit import QuantumCircuit
22
- from qadence.logger import get_logger
23
24
  from qadence.measurements import Measurements
24
25
  from qadence.mitigations import Mitigations
25
26
  from qadence.mitigations.protocols import apply_mitigation
@@ -37,7 +38,7 @@ from .convert_ops import convert_observable
37
38
  from .devices import IdealDevice, RealisticDevice
38
39
  from .pulses import add_addressing_pattern, add_pulses
39
40
 
40
- logger = get_logger(__file__)
41
+ logger = getLogger(__name__)
41
42
 
42
43
 
43
44
  def _convert_init_state(state: Tensor) -> np.ndarray:
@@ -70,27 +71,6 @@ def make_sequence(circ: QuantumCircuit, config: Configuration) -> Sequence:
70
71
  f"Specified device of type {device_specs.type} is not supported by the pulser backend."
71
72
  )
72
73
 
73
- ########
74
- # FIXME: Remove the block below in V1.5.0
75
- if config.spacing is not None:
76
- logger.warning(
77
- "Passing register spacing in the backend configuration is deprecated. "
78
- "Please pass it in the register directly, as detailed in the register tutorial."
79
- )
80
- # Rescales the register coordinates, as was done with the previous "spacing" argument.
81
- qadence_register = qadence_register.rescale_coords(scaling=config.spacing)
82
- else:
83
- if qadence_register.min_distance < 4.0:
84
- # Throws warning for minimum distance below 4 because the typical values used
85
- # for the standard pulser device parameters is ~7-8, so this likely means the user
86
- # forgot to set the spacing at register creation.
87
- logger.warning(
88
- "Register with distance between atoms smaller than 4µm detected. "
89
- "Pulser backend no longer has a default spacing of 8µm applied to the register. "
90
- "Make sure you set the desired spacing as detailed in the register tutorial."
91
- )
92
- ########
93
-
94
74
  pulser_register = create_register(qadence_register)
95
75
 
96
76
  sequence = Sequence(pulser_register, device)
@@ -160,6 +140,7 @@ class Backend(BackendInterface):
160
140
  native_endianness: Endianness = Endianness.BIG
161
141
  config: Configuration = field(default_factory=Configuration)
162
142
  engine: Engine = Engine.TORCH
143
+ logger.debug("Initialised")
163
144
 
164
145
  def circuit(self, circ: QuantumCircuit) -> Sequence:
165
146
  passes = self.config.transpilation_passes
@@ -250,30 +231,52 @@ class Backend(BackendInterface):
250
231
  self,
251
232
  circuit: ConvertedCircuit,
252
233
  noise: Noise,
253
- param_values: dict[str, Tensor] = {},
234
+ param_values: dict[str, Tensor] = dict(),
254
235
  state: Tensor | None = None,
255
236
  endianness: Endianness = Endianness.BIG,
256
- ) -> list:
237
+ ) -> Tensor:
257
238
  vals = to_list_of_dicts(param_values)
258
239
  noise_probs = noise.options.get("noise_probs", None)
259
240
  if noise_probs is None:
260
- KeyError(f"A range of noise probabilies should be passed. Got {noise_probs}.")
261
-
262
- noisy_batched_dm = []
241
+ KeyError("A `noise probs` option should be passed to the <class QuantumModel>.")
242
+ if not (isinstance(noise_probs, float) or isinstance(noise_probs, Iterable)):
243
+ KeyError(
244
+ "A single or a range of noise probabilities"
245
+ " should be passed. Got {type(noise_probs)}."
246
+ )
263
247
 
264
- # Pulser requires numpy types.
265
- for noise_prob in noise_probs.numpy():
266
- batched_dm = []
267
- sim_config = {"noise": noise.protocol, noise.protocol + "_prob": noise_prob}
248
+ def run_noisy_sim(noise_prob: float) -> Tensor:
249
+ batched_dm = np.zeros(
250
+ (len(vals), 2**circuit.abstract.n_qubits, 2**circuit.abstract.n_qubits),
251
+ dtype=np.complex128,
252
+ )
253
+ sim_config = {"noise": noise.protocol, noise.protocol + "_rate": noise_prob}
268
254
  self.config.sim_config = SimConfig(**sim_config)
269
255
 
270
256
  for i, param_values_el in enumerate(vals):
271
257
  sequence = self.assign_parameters(circuit, param_values_el)
272
- sim_result = simulate_sequence(sequence, self.config, state)
273
- batched_dm.append(sim_result)
274
- noisy_batched_dm.append(batched_dm)
258
+ sim_result: CoherentResults = simulate_sequence(sequence, self.config, state)
259
+ final_state = sim_result.get_final_state().data.toarray()
260
+ batched_dm[i] = np.flip(final_state)
261
+ return torch.from_numpy(batched_dm)
275
262
 
276
- return noisy_batched_dm
263
+ # Pulser requires numpy types.
264
+ if isinstance(noise_probs, Iterable):
265
+ noisy_batched_dms = []
266
+ for noise_prob in noise_probs:
267
+ noisy_sim = run_noisy_sim(noise_prob)
268
+ if not param_values:
269
+ noisy_sim = noisy_sim[0]
270
+ noisy_batched_dms.append(noisy_sim)
271
+ noisy_batched_dms = torch.stack(noisy_batched_dms)
272
+ else:
273
+ noisy_batched_dms = run_noisy_sim(noise_probs)
274
+
275
+ if endianness != self.native_endianness:
276
+ from qadence.transpile import invert_endianness
277
+
278
+ noisy_batched_dms = invert_endianness(noisy_batched_dms)
279
+ return noisy_batched_dms
277
280
 
278
281
  def sample(
279
282
  self,
@@ -327,14 +330,48 @@ class Backend(BackendInterface):
327
330
  ) -> Tensor:
328
331
  observable = observable if isinstance(observable, list) else [observable]
329
332
  if mitigation is None:
330
- state = self.run(circuit, param_values=param_values, state=state, endianness=endianness)
331
- support = sorted(list(circuit.abstract.register.support))
332
- res_list = [
333
- obs.native(state, param_values, qubit_support=support) for obs in observable
334
- ]
335
- res = torch.transpose(torch.stack(res_list), 0, 1)
336
- res = res if len(res.shape) > 0 else res.reshape(1)
337
- return res.real
333
+ if noise is None:
334
+ state = self.run(
335
+ circuit, param_values=param_values, state=state, endianness=endianness
336
+ )
337
+ support = sorted(list(circuit.abstract.register.support))
338
+ res_list = [
339
+ obs.native(state, param_values, qubit_support=support) for obs in observable
340
+ ]
341
+ res = torch.transpose(torch.stack(res_list), 0, 1)
342
+ res = res if len(res.shape) > 0 else res.reshape(1)
343
+ return res.real
344
+ elif noise is not None:
345
+ dms = self.run_dm(
346
+ circuit=circuit,
347
+ noise=noise,
348
+ param_values=param_values,
349
+ state=state,
350
+ endianness=endianness,
351
+ )
352
+ support = sorted(list(circuit.abstract.register.support))
353
+ # TODO: There should be a better check for batched density matrices.
354
+ if dms.size()[0] > 1:
355
+ res_list = [
356
+ [
357
+ obs.native(
358
+ dm.squeeze(), param_values, qubit_support=support, noise=noise
359
+ )
360
+ for dm in dms
361
+ ]
362
+ for obs in observable
363
+ ]
364
+ res = torch.stack(
365
+ [torch.transpose(torch.stack(res), 0, -1) for res in res_list]
366
+ )
367
+
368
+ else:
369
+ res_list = [
370
+ obs.native(dms, param_values, qubit_support=support) for obs in observable
371
+ ]
372
+ res = torch.transpose(torch.stack(res_list), 0, 1)
373
+ res = res if len(res.shape) > 0 else res.reshape(1)
374
+ return res.real
338
375
  elif mitigation is not None:
339
376
  logger.warning(
340
377
  "Mitigation protocol is deprecated. Use qadence-protocols instead.",