qadence 1.8.0__tar.gz → 1.9.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.
- {qadence-1.8.0 → qadence-1.9.1}/PKG-INFO +3 -4
- {qadence-1.8.0 → qadence-1.9.1}/mkdocs.yml +4 -2
- {qadence-1.8.0 → qadence-1.9.1}/pyproject.toml +3 -3
- {qadence-1.8.0 → qadence-1.9.1}/qadence/__init__.py +1 -1
- {qadence-1.8.0 → qadence-1.9.1}/qadence/analog/parse_analog.py +1 -2
- {qadence-1.8.0 → qadence-1.9.1}/qadence/backends/gpsr.py +8 -2
- {qadence-1.8.0 → qadence-1.9.1}/qadence/backends/pulser/backend.py +7 -23
- {qadence-1.8.0 → qadence-1.9.1}/qadence/backends/pyqtorch/backend.py +80 -5
- {qadence-1.8.0 → qadence-1.9.1}/qadence/backends/pyqtorch/config.py +10 -3
- {qadence-1.8.0 → qadence-1.9.1}/qadence/backends/pyqtorch/convert_ops.py +63 -2
- {qadence-1.8.0 → qadence-1.9.1}/qadence/blocks/primitive.py +1 -0
- {qadence-1.8.0 → qadence-1.9.1}/qadence/execution.py +0 -2
- {qadence-1.8.0 → qadence-1.9.1}/qadence/log_config.yaml +10 -0
- {qadence-1.8.0 → qadence-1.9.1}/qadence/measurements/shadow.py +97 -128
- {qadence-1.8.0 → qadence-1.9.1}/qadence/measurements/utils.py +2 -2
- {qadence-1.8.0 → qadence-1.9.1}/qadence/mitigations/readout.py +12 -6
- {qadence-1.8.0 → qadence-1.9.1}/qadence/ml_tools/__init__.py +4 -8
- qadence-1.9.1/qadence/ml_tools/callbacks/__init__.py +30 -0
- qadence-1.9.1/qadence/ml_tools/callbacks/callback.py +451 -0
- qadence-1.9.1/qadence/ml_tools/callbacks/callbackmanager.py +214 -0
- {qadence-1.8.0/qadence/ml_tools → qadence-1.9.1/qadence/ml_tools/callbacks}/saveload.py +11 -11
- qadence-1.9.1/qadence/ml_tools/callbacks/writer_registry.py +441 -0
- {qadence-1.8.0 → qadence-1.9.1}/qadence/ml_tools/config.py +132 -258
- {qadence-1.8.0 → qadence-1.9.1}/qadence/ml_tools/data.py +7 -3
- qadence-1.9.1/qadence/ml_tools/loss/__init__.py +10 -0
- qadence-1.9.1/qadence/ml_tools/loss/loss.py +87 -0
- qadence-1.9.1/qadence/ml_tools/optimize_step.py +89 -0
- qadence-1.9.1/qadence/ml_tools/stages.py +46 -0
- qadence-1.9.1/qadence/ml_tools/train_utils/__init__.py +7 -0
- qadence-1.9.1/qadence/ml_tools/train_utils/base_trainer.py +555 -0
- qadence-1.9.1/qadence/ml_tools/train_utils/config_manager.py +184 -0
- qadence-1.9.1/qadence/ml_tools/trainer.py +708 -0
- {qadence-1.8.0 → qadence-1.9.1}/qadence/model.py +1 -1
- qadence-1.9.1/qadence/noise/__init__.py +6 -0
- {qadence-1.8.0 → qadence-1.9.1}/qadence/noise/protocols.py +18 -53
- {qadence-1.8.0 → qadence-1.9.1}/qadence/operations/ham_evo.py +87 -26
- {qadence-1.8.0 → qadence-1.9.1}/qadence/transpile/noise.py +12 -5
- {qadence-1.8.0 → qadence-1.9.1}/qadence/types.py +15 -3
- qadence-1.8.0/qadence/ml_tools/optimize_step.py +0 -54
- qadence-1.8.0/qadence/ml_tools/printing.py +0 -154
- qadence-1.8.0/qadence/ml_tools/train_grad.py +0 -395
- qadence-1.8.0/qadence/ml_tools/train_no_grad.py +0 -199
- qadence-1.8.0/qadence/noise/__init__.py +0 -6
- qadence-1.8.0/qadence/noise/readout.py +0 -218
- {qadence-1.8.0 → qadence-1.9.1}/.coveragerc +0 -0
- {qadence-1.8.0 → qadence-1.9.1}/.github/ISSUE_TEMPLATE/bug-report.yml +0 -0
- {qadence-1.8.0 → qadence-1.9.1}/.github/ISSUE_TEMPLATE/config.yml +0 -0
- {qadence-1.8.0 → qadence-1.9.1}/.github/ISSUE_TEMPLATE/new-feature.yml +0 -0
- {qadence-1.8.0 → qadence-1.9.1}/.github/workflows/build_docs.yml +0 -0
- {qadence-1.8.0 → qadence-1.9.1}/.github/workflows/lint.yml +0 -0
- {qadence-1.8.0 → qadence-1.9.1}/.github/workflows/test_all.yml +0 -0
- {qadence-1.8.0 → qadence-1.9.1}/.github/workflows/test_examples.yml +0 -0
- {qadence-1.8.0 → qadence-1.9.1}/.github/workflows/test_fast.yml +0 -0
- {qadence-1.8.0 → qadence-1.9.1}/.gitignore +0 -0
- {qadence-1.8.0 → qadence-1.9.1}/.pre-commit-config.yaml +0 -0
- {qadence-1.8.0 → qadence-1.9.1}/LICENSE +0 -0
- {qadence-1.8.0 → qadence-1.9.1}/MANIFEST.in +0 -0
- {qadence-1.8.0 → qadence-1.9.1}/README.md +0 -0
- {qadence-1.8.0 → qadence-1.9.1}/qadence/analog/__init__.py +0 -0
- {qadence-1.8.0 → qadence-1.9.1}/qadence/analog/addressing.py +0 -0
- {qadence-1.8.0 → qadence-1.9.1}/qadence/analog/constants.py +0 -0
- {qadence-1.8.0 → qadence-1.9.1}/qadence/analog/device.py +0 -0
- {qadence-1.8.0 → qadence-1.9.1}/qadence/analog/hamiltonian_terms.py +0 -0
- {qadence-1.8.0 → qadence-1.9.1}/qadence/backend.py +0 -0
- {qadence-1.8.0 → qadence-1.9.1}/qadence/backends/__init__.py +0 -0
- {qadence-1.8.0 → qadence-1.9.1}/qadence/backends/api.py +0 -0
- {qadence-1.8.0 → qadence-1.9.1}/qadence/backends/horqrux/__init__.py +0 -0
- {qadence-1.8.0 → qadence-1.9.1}/qadence/backends/horqrux/backend.py +0 -0
- {qadence-1.8.0 → qadence-1.9.1}/qadence/backends/horqrux/config.py +0 -0
- {qadence-1.8.0 → qadence-1.9.1}/qadence/backends/horqrux/convert_ops.py +0 -0
- {qadence-1.8.0 → qadence-1.9.1}/qadence/backends/jax_utils.py +0 -0
- {qadence-1.8.0 → qadence-1.9.1}/qadence/backends/pulser/__init__.py +0 -0
- {qadence-1.8.0 → qadence-1.9.1}/qadence/backends/pulser/channels.py +0 -0
- {qadence-1.8.0 → qadence-1.9.1}/qadence/backends/pulser/cloud.py +0 -0
- {qadence-1.8.0 → qadence-1.9.1}/qadence/backends/pulser/config.py +0 -0
- {qadence-1.8.0 → qadence-1.9.1}/qadence/backends/pulser/convert_ops.py +0 -0
- {qadence-1.8.0 → qadence-1.9.1}/qadence/backends/pulser/devices.py +0 -0
- {qadence-1.8.0 → qadence-1.9.1}/qadence/backends/pulser/pulses.py +0 -0
- {qadence-1.8.0 → qadence-1.9.1}/qadence/backends/pulser/waveforms.py +0 -0
- {qadence-1.8.0 → qadence-1.9.1}/qadence/backends/pyqtorch/__init__.py +0 -0
- {qadence-1.8.0 → qadence-1.9.1}/qadence/backends/utils.py +0 -0
- {qadence-1.8.0 → qadence-1.9.1}/qadence/blocks/__init__.py +0 -0
- {qadence-1.8.0 → qadence-1.9.1}/qadence/blocks/abstract.py +0 -0
- {qadence-1.8.0 → qadence-1.9.1}/qadence/blocks/analog.py +0 -0
- {qadence-1.8.0 → qadence-1.9.1}/qadence/blocks/block_to_tensor.py +0 -0
- {qadence-1.8.0 → qadence-1.9.1}/qadence/blocks/composite.py +0 -0
- {qadence-1.8.0 → qadence-1.9.1}/qadence/blocks/embedding.py +0 -0
- {qadence-1.8.0 → qadence-1.9.1}/qadence/blocks/manipulate.py +0 -0
- {qadence-1.8.0 → qadence-1.9.1}/qadence/blocks/matrix.py +0 -0
- {qadence-1.8.0 → qadence-1.9.1}/qadence/blocks/utils.py +0 -0
- {qadence-1.8.0 → qadence-1.9.1}/qadence/circuit.py +0 -0
- {qadence-1.8.0 → qadence-1.9.1}/qadence/constructors/__init__.py +0 -0
- {qadence-1.8.0 → qadence-1.9.1}/qadence/constructors/ansatze.py +0 -0
- {qadence-1.8.0 → qadence-1.9.1}/qadence/constructors/daqc/__init__.py +0 -0
- {qadence-1.8.0 → qadence-1.9.1}/qadence/constructors/daqc/daqc.py +0 -0
- {qadence-1.8.0 → qadence-1.9.1}/qadence/constructors/daqc/gen_parser.py +0 -0
- {qadence-1.8.0 → qadence-1.9.1}/qadence/constructors/daqc/utils.py +0 -0
- {qadence-1.8.0 → qadence-1.9.1}/qadence/constructors/feature_maps.py +0 -0
- {qadence-1.8.0 → qadence-1.9.1}/qadence/constructors/hamiltonians.py +0 -0
- {qadence-1.8.0 → qadence-1.9.1}/qadence/constructors/iia.py +0 -0
- {qadence-1.8.0 → qadence-1.9.1}/qadence/constructors/qft.py +0 -0
- {qadence-1.8.0 → qadence-1.9.1}/qadence/constructors/rydberg_feature_maps.py +0 -0
- {qadence-1.8.0 → qadence-1.9.1}/qadence/constructors/rydberg_hea.py +0 -0
- {qadence-1.8.0 → qadence-1.9.1}/qadence/constructors/utils.py +0 -0
- {qadence-1.8.0 → qadence-1.9.1}/qadence/decompose.py +0 -0
- {qadence-1.8.0 → qadence-1.9.1}/qadence/divergences.py +0 -0
- {qadence-1.8.0 → qadence-1.9.1}/qadence/draw/__init__.py +0 -0
- {qadence-1.8.0 → qadence-1.9.1}/qadence/draw/assets/dark/measurement.png +0 -0
- {qadence-1.8.0 → qadence-1.9.1}/qadence/draw/assets/dark/measurement.svg +0 -0
- {qadence-1.8.0 → qadence-1.9.1}/qadence/draw/assets/light/measurement.png +0 -0
- {qadence-1.8.0 → qadence-1.9.1}/qadence/draw/assets/light/measurement.svg +0 -0
- {qadence-1.8.0 → qadence-1.9.1}/qadence/draw/themes.py +0 -0
- {qadence-1.8.0 → qadence-1.9.1}/qadence/draw/utils.py +0 -0
- {qadence-1.8.0 → qadence-1.9.1}/qadence/draw/vizbackend.py +0 -0
- {qadence-1.8.0 → qadence-1.9.1}/qadence/engines/__init__.py +0 -0
- {qadence-1.8.0 → qadence-1.9.1}/qadence/engines/differentiable_backend.py +0 -0
- {qadence-1.8.0 → qadence-1.9.1}/qadence/engines/jax/__init__.py +0 -0
- {qadence-1.8.0 → qadence-1.9.1}/qadence/engines/jax/differentiable_backend.py +0 -0
- {qadence-1.8.0 → qadence-1.9.1}/qadence/engines/jax/differentiable_expectation.py +0 -0
- {qadence-1.8.0 → qadence-1.9.1}/qadence/engines/torch/__init__.py +0 -0
- {qadence-1.8.0 → qadence-1.9.1}/qadence/engines/torch/differentiable_backend.py +0 -0
- {qadence-1.8.0 → qadence-1.9.1}/qadence/engines/torch/differentiable_expectation.py +0 -0
- {qadence-1.8.0 → qadence-1.9.1}/qadence/exceptions/__init__.py +0 -0
- {qadence-1.8.0 → qadence-1.9.1}/qadence/exceptions/exceptions.py +0 -0
- {qadence-1.8.0 → qadence-1.9.1}/qadence/extensions.py +0 -0
- {qadence-1.8.0 → qadence-1.9.1}/qadence/libs.py +0 -0
- {qadence-1.8.0 → qadence-1.9.1}/qadence/logger.py +0 -0
- {qadence-1.8.0 → qadence-1.9.1}/qadence/measurements/__init__.py +0 -0
- {qadence-1.8.0 → qadence-1.9.1}/qadence/measurements/protocols.py +0 -0
- {qadence-1.8.0 → qadence-1.9.1}/qadence/measurements/samples.py +0 -0
- {qadence-1.8.0 → qadence-1.9.1}/qadence/measurements/tomography.py +0 -0
- {qadence-1.8.0 → qadence-1.9.1}/qadence/mitigations/__init__.py +0 -0
- {qadence-1.8.0 → qadence-1.9.1}/qadence/mitigations/analog_zne.py +0 -0
- {qadence-1.8.0 → qadence-1.9.1}/qadence/mitigations/protocols.py +0 -0
- {qadence-1.8.0 → qadence-1.9.1}/qadence/ml_tools/constructors.py +0 -0
- {qadence-1.8.0 → qadence-1.9.1}/qadence/ml_tools/models.py +0 -0
- {qadence-1.8.0 → qadence-1.9.1}/qadence/ml_tools/parameters.py +0 -0
- {qadence-1.8.0 → qadence-1.9.1}/qadence/ml_tools/tensors.py +0 -0
- {qadence-1.8.0 → qadence-1.9.1}/qadence/ml_tools/utils.py +0 -0
- {qadence-1.8.0 → qadence-1.9.1}/qadence/operations/__init__.py +0 -0
- {qadence-1.8.0 → qadence-1.9.1}/qadence/operations/analog.py +0 -0
- {qadence-1.8.0 → qadence-1.9.1}/qadence/operations/control_ops.py +0 -0
- {qadence-1.8.0 → qadence-1.9.1}/qadence/operations/parametric.py +0 -0
- {qadence-1.8.0 → qadence-1.9.1}/qadence/operations/primitive.py +0 -0
- {qadence-1.8.0 → qadence-1.9.1}/qadence/overlap.py +0 -0
- {qadence-1.8.0 → qadence-1.9.1}/qadence/parameters.py +0 -0
- {qadence-1.8.0 → qadence-1.9.1}/qadence/protocols.py +0 -0
- {qadence-1.8.0 → qadence-1.9.1}/qadence/py.typed +0 -0
- {qadence-1.8.0 → qadence-1.9.1}/qadence/qubit_support.py +0 -0
- {qadence-1.8.0 → qadence-1.9.1}/qadence/register.py +0 -0
- {qadence-1.8.0 → qadence-1.9.1}/qadence/serial_expr_grammar.peg +0 -0
- {qadence-1.8.0 → qadence-1.9.1}/qadence/serialization.py +0 -0
- {qadence-1.8.0 → qadence-1.9.1}/qadence/states.py +0 -0
- {qadence-1.8.0 → qadence-1.9.1}/qadence/transpile/__init__.py +0 -0
- {qadence-1.8.0 → qadence-1.9.1}/qadence/transpile/apply_fn.py +0 -0
- {qadence-1.8.0 → qadence-1.9.1}/qadence/transpile/block.py +0 -0
- {qadence-1.8.0 → qadence-1.9.1}/qadence/transpile/circuit.py +0 -0
- {qadence-1.8.0 → qadence-1.9.1}/qadence/transpile/digitalize.py +0 -0
- {qadence-1.8.0 → qadence-1.9.1}/qadence/transpile/flatten.py +0 -0
- {qadence-1.8.0 → qadence-1.9.1}/qadence/transpile/invert.py +0 -0
- {qadence-1.8.0 → qadence-1.9.1}/qadence/transpile/transpile.py +0 -0
- {qadence-1.8.0 → qadence-1.9.1}/qadence/utils.py +0 -0
- {qadence-1.8.0 → qadence-1.9.1}/renovate.json +0 -0
- {qadence-1.8.0 → qadence-1.9.1}/setup.py +0 -0
@@ -1,10 +1,9 @@
|
|
1
1
|
Metadata-Version: 2.3
|
2
2
|
Name: qadence
|
3
|
-
Version: 1.
|
3
|
+
Version: 1.9.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>, Smit Chaudhary <smit.chaudhary@pasqal.com>, Ignacio Fernández Graña <ignacio.fernandez-grana@pasqal.com>, Charles Moussa <charles.moussa@pasqal.com>, Giorgio Tosti Balducci <giorgio.tosti-balducci@pasqal.com>, Daniele Cucurachi <daniele.cucurachi@pasqal.com>
|
6
6
|
License: Apache 2.0
|
7
|
-
License-File: LICENSE
|
8
7
|
Classifier: License :: OSI Approved :: Apache Software License
|
9
8
|
Classifier: Programming Language :: Python
|
10
9
|
Classifier: Programming Language :: Python :: 3
|
@@ -22,7 +21,7 @@ Requires-Dist: matplotlib
|
|
22
21
|
Requires-Dist: nevergrad
|
23
22
|
Requires-Dist: numpy
|
24
23
|
Requires-Dist: openfermion
|
25
|
-
Requires-Dist: pyqtorch==1.
|
24
|
+
Requires-Dist: pyqtorch==1.6.0
|
26
25
|
Requires-Dist: pyyaml
|
27
26
|
Requires-Dist: rich
|
28
27
|
Requires-Dist: scipy
|
@@ -54,7 +53,7 @@ Requires-Dist: mlflow; extra == 'mlflow'
|
|
54
53
|
Provides-Extra: protocols
|
55
54
|
Requires-Dist: qadence-protocols; extra == 'protocols'
|
56
55
|
Provides-Extra: pulser
|
57
|
-
Requires-Dist: pasqal-cloud==0.12.
|
56
|
+
Requires-Dist: pasqal-cloud==0.12.5; extra == 'pulser'
|
58
57
|
Requires-Dist: pulser-core==1.1.1; extra == 'pulser'
|
59
58
|
Requires-Dist: pulser-simulation==1.1.1; extra == 'pulser'
|
60
59
|
Provides-Extra: visualization
|
@@ -16,11 +16,11 @@ nav:
|
|
16
16
|
- Contents:
|
17
17
|
- Block system: content/block_system.md
|
18
18
|
- Parametric programs: content/parameters.md
|
19
|
-
- Time-dependent generators: content/time_dependent.md
|
20
19
|
- Quantum models: content/quantummodels.md
|
21
20
|
- Quantum registers: content/register.md
|
22
21
|
- State initialization: content/state_init.md
|
23
22
|
- Arbitrary Hamiltonians: content/hamiltonians.md
|
23
|
+
- Time-dependent generators: content/time_dependent.md
|
24
24
|
- QML Constructors: content/qml_constructors.md
|
25
25
|
- Wavefunction overlaps: content/overlap.md
|
26
26
|
- Backends: content/backends.md
|
@@ -42,7 +42,9 @@ nav:
|
|
42
42
|
|
43
43
|
- Variational quantum algorithms:
|
44
44
|
- tutorials/qml/index.md
|
45
|
-
- Training
|
45
|
+
- Training: tutorials/qml/ml_tools/trainer.md
|
46
|
+
- Training Callbacks: tutorials/qml/ml_tools/callbacks.md
|
47
|
+
- Data and Configurations: tutorials/qml/ml_tools/data_and_config.md
|
46
48
|
- Configuring a QNN: tutorials/qml/config_qnn.md
|
47
49
|
- Quantum circuit learning: tutorials/qml/qcl.md
|
48
50
|
- Solving MaxCut with QAOA: tutorials/qml/qaoa.md
|
@@ -26,7 +26,7 @@ authors = [
|
|
26
26
|
]
|
27
27
|
requires-python = ">=3.9"
|
28
28
|
license = { text = "Apache 2.0" }
|
29
|
-
version = "1.
|
29
|
+
version = "1.9.1"
|
30
30
|
classifiers = [
|
31
31
|
"License :: OSI Approved :: Apache Software License",
|
32
32
|
"Programming Language :: Python",
|
@@ -50,7 +50,7 @@ dependencies = [
|
|
50
50
|
"jsonschema",
|
51
51
|
"nevergrad",
|
52
52
|
"scipy",
|
53
|
-
"pyqtorch==1.
|
53
|
+
"pyqtorch==1.6.0",
|
54
54
|
"pyyaml",
|
55
55
|
"matplotlib",
|
56
56
|
"Arpeggio==2.0.2",
|
@@ -64,7 +64,7 @@ allow-ambiguous-features = true
|
|
64
64
|
pulser = [
|
65
65
|
"pulser-core==1.1.1",
|
66
66
|
"pulser-simulation==1.1.1",
|
67
|
-
"pasqal-cloud==0.12.
|
67
|
+
"pasqal-cloud==0.12.5",
|
68
68
|
]
|
69
69
|
visualization = [
|
70
70
|
"graphviz",
|
@@ -34,7 +34,7 @@ logger.setLevel(LOG_LEVEL)
|
|
34
34
|
[
|
35
35
|
h.setLevel(LOG_LEVEL) # type: ignore[func-returns-value]
|
36
36
|
for h in logger.handlers
|
37
|
-
if h.get_name() == "console"
|
37
|
+
if h.get_name() == "console" or h.get_name() == "richconsole"
|
38
38
|
]
|
39
39
|
logger.debug(f"Qadence logger successfully setup with log level {LOG_LEVEL}")
|
40
40
|
|
@@ -78,9 +78,8 @@ def _build_rot_ham_evo(
|
|
78
78
|
if block.add_pattern and h_addr is not None:
|
79
79
|
h_block += h_addr
|
80
80
|
duration = block.parameters.duration
|
81
|
-
h_norm = block.parameters.h_norm
|
82
81
|
h_block += h_drive
|
83
|
-
return HamEvo(h_block
|
82
|
+
return HamEvo(h_block, duration / 1000)
|
84
83
|
|
85
84
|
|
86
85
|
def _analog_to_hevo(
|
@@ -36,7 +36,11 @@ def general_psr(spectrum: Tensor, n_eqs: int | None = None, shift_prefac: float
|
|
36
36
|
sorted_unique_spectral_gaps = torch.tensor(list(sorted_unique_spectral_gaps)[:n_eqs])
|
37
37
|
|
38
38
|
if n_eqs == 1:
|
39
|
-
return
|
39
|
+
return partial(
|
40
|
+
single_gap_psr,
|
41
|
+
spectral_gap=sorted_unique_spectral_gaps,
|
42
|
+
shift=shift_prefac * torch.tensor([PI / 2], dtype=torch.get_default_dtype()),
|
43
|
+
)
|
40
44
|
else:
|
41
45
|
return partial(
|
42
46
|
multi_gap_psr,
|
@@ -110,7 +114,9 @@ def multi_gap_psr(
|
|
110
114
|
batch_size = max(t.size(0) for t in param_dict.values())
|
111
115
|
|
112
116
|
# get shift values
|
113
|
-
shifts = shift_prefac * torch.linspace(
|
117
|
+
shifts = shift_prefac * torch.linspace(
|
118
|
+
PI / 2 - PI / 4, PI / 2 + PI / 5, n_eqs
|
119
|
+
) # breaking the symmetry of sampling range around PI/2
|
114
120
|
device = torch.device("cpu")
|
115
121
|
try:
|
116
122
|
device = [v.device for v in param_dict.values()][0]
|
@@ -25,7 +25,6 @@ from qadence.measurements import Measurements
|
|
25
25
|
from qadence.mitigations import Mitigations
|
26
26
|
from qadence.mitigations.protocols import apply_mitigation
|
27
27
|
from qadence.noise import NoiseHandler
|
28
|
-
from qadence.noise.protocols import apply_readout_noise
|
29
28
|
from qadence.overlap import overlap_exact
|
30
29
|
from qadence.register import Register
|
31
30
|
from qadence.transpile import transpile
|
@@ -311,8 +310,6 @@ class Backend(BackendInterface):
|
|
311
310
|
from qadence.transpile import invert_endianness
|
312
311
|
|
313
312
|
samples = invert_endianness(samples)
|
314
|
-
if noise is not None:
|
315
|
-
samples = apply_readout_noise(noise=noise, samples=samples)
|
316
313
|
if mitigation is not None:
|
317
314
|
logger.warning(
|
318
315
|
"Mitigation protocol is deprecated. Use qadence-protocols instead.",
|
@@ -354,27 +351,14 @@ class Backend(BackendInterface):
|
|
354
351
|
noise=noise,
|
355
352
|
)
|
356
353
|
support = sorted(list(circuit.abstract.register.support))
|
357
|
-
|
358
|
-
|
359
|
-
|
360
|
-
|
361
|
-
obs.native(
|
362
|
-
dm.squeeze(), param_values, qubit_support=support, noise=noise
|
363
|
-
)
|
364
|
-
for dm in dms
|
365
|
-
]
|
366
|
-
for obs in observable
|
367
|
-
]
|
368
|
-
res = torch.stack(
|
369
|
-
[torch.transpose(torch.stack(res), 0, -1) for res in res_list]
|
370
|
-
)
|
371
|
-
|
372
|
-
else:
|
373
|
-
res_list = [
|
374
|
-
obs.native(dms, param_values, qubit_support=support) for obs in observable
|
354
|
+
res_list = [
|
355
|
+
[
|
356
|
+
obs.native(dm.squeeze(), param_values, qubit_support=support, noise=noise)
|
357
|
+
for dm in dms
|
375
358
|
]
|
376
|
-
|
377
|
-
|
359
|
+
for obs in observable
|
360
|
+
]
|
361
|
+
res = torch.stack([torch.transpose(torch.stack(res), 0, -1) for res in res_list])
|
378
362
|
return res.real
|
379
363
|
elif mitigation is not None:
|
380
364
|
logger.warning(
|
@@ -23,22 +23,62 @@ from qadence.circuit import QuantumCircuit
|
|
23
23
|
from qadence.measurements import Measurements
|
24
24
|
from qadence.mitigations.protocols import Mitigations, apply_mitigation
|
25
25
|
from qadence.noise import NoiseHandler
|
26
|
-
from qadence.noise.protocols import apply_readout_noise
|
27
26
|
from qadence.transpile import (
|
28
27
|
chain_single_qubit_ops,
|
29
28
|
flatten,
|
30
29
|
invert_endianness,
|
31
30
|
scale_primitive_blocks_only,
|
31
|
+
set_noise,
|
32
32
|
transpile,
|
33
33
|
)
|
34
34
|
from qadence.types import BackendName, Endianness, Engine
|
35
35
|
|
36
36
|
from .config import Configuration, default_passes
|
37
|
-
from .convert_ops import convert_block
|
37
|
+
from .convert_ops import convert_block, convert_readout_noise
|
38
38
|
|
39
39
|
logger = getLogger(__name__)
|
40
40
|
|
41
41
|
|
42
|
+
def set_noise_abstract_to_native(circuit: ConvertedCircuit, config: Configuration) -> None:
|
43
|
+
"""Set noise in native blocks from the abstract ones with noise.
|
44
|
+
|
45
|
+
Args:
|
46
|
+
circuit (ConvertedCircuit): Input converted circuit.
|
47
|
+
"""
|
48
|
+
ops = convert_block(circuit.abstract.block, n_qubits=circuit.native.n_qubits, config=config)
|
49
|
+
circuit.native = pyq.QuantumCircuit(circuit.native.n_qubits, ops, circuit.native.readout_noise)
|
50
|
+
|
51
|
+
|
52
|
+
def set_readout_noise(circuit: ConvertedCircuit, noise: NoiseHandler) -> None:
|
53
|
+
"""Set readout noise in place in native.
|
54
|
+
|
55
|
+
Args:
|
56
|
+
circuit (ConvertedCircuit): Input converted circuit.
|
57
|
+
noise (NoiseHandler | None): Noise.
|
58
|
+
"""
|
59
|
+
readout = convert_readout_noise(circuit.abstract.n_qubits, noise)
|
60
|
+
if readout:
|
61
|
+
circuit.native.readout_noise = readout
|
62
|
+
|
63
|
+
|
64
|
+
def set_block_and_readout_noises(
|
65
|
+
circuit: ConvertedCircuit, noise: NoiseHandler | None, config: Configuration
|
66
|
+
) -> None:
|
67
|
+
"""Add noise on blocks and readout on circuit.
|
68
|
+
|
69
|
+
We first start by adding noise to the abstract blocks. Then we do a conversion to their
|
70
|
+
native representation. Finally, we add readout.
|
71
|
+
|
72
|
+
Args:
|
73
|
+
circuit (ConvertedCircuit): Input circuit.
|
74
|
+
noise (NoiseHandler | None): Noise to add.
|
75
|
+
"""
|
76
|
+
if noise:
|
77
|
+
set_noise(circuit, noise)
|
78
|
+
set_noise_abstract_to_native(circuit, config)
|
79
|
+
set_readout_noise(circuit, noise)
|
80
|
+
|
81
|
+
|
42
82
|
@dataclass(frozen=True, eq=True)
|
43
83
|
class Backend(BackendInterface):
|
44
84
|
"""PyQTorch backend."""
|
@@ -56,6 +96,17 @@ class Backend(BackendInterface):
|
|
56
96
|
logger.debug("Initialised")
|
57
97
|
|
58
98
|
def circuit(self, circuit: QuantumCircuit) -> ConvertedCircuit:
|
99
|
+
"""Return the converted circuit.
|
100
|
+
|
101
|
+
Note that to get a representation with noise, noise
|
102
|
+
should be passed within the config.
|
103
|
+
|
104
|
+
Args:
|
105
|
+
circuit (QuantumCircuit): Original circuit
|
106
|
+
|
107
|
+
Returns:
|
108
|
+
ConvertedCircuit: ConvertedCircuit instance for backend.
|
109
|
+
"""
|
59
110
|
passes = self.config.transpilation_passes
|
60
111
|
if passes is None:
|
61
112
|
passes = default_passes(self.config)
|
@@ -63,9 +114,30 @@ class Backend(BackendInterface):
|
|
63
114
|
original_circ = circuit
|
64
115
|
if len(passes) > 0:
|
65
116
|
circuit = transpile(*passes)(circuit)
|
117
|
+
# Setting noise in the circuit.
|
118
|
+
if self.config.noise:
|
119
|
+
set_noise(circuit, self.config.noise)
|
66
120
|
|
67
121
|
ops = convert_block(circuit.block, n_qubits=circuit.n_qubits, config=self.config)
|
68
|
-
|
122
|
+
readout_noise = (
|
123
|
+
convert_readout_noise(circuit.n_qubits, self.config.noise)
|
124
|
+
if self.config.noise
|
125
|
+
else None
|
126
|
+
)
|
127
|
+
if self.config.dropout_probability == 0:
|
128
|
+
native = pyq.QuantumCircuit(
|
129
|
+
circuit.n_qubits,
|
130
|
+
ops,
|
131
|
+
readout_noise,
|
132
|
+
)
|
133
|
+
else:
|
134
|
+
native = pyq.DropoutQuantumCircuit(
|
135
|
+
circuit.n_qubits,
|
136
|
+
ops,
|
137
|
+
readout_noise,
|
138
|
+
dropout_prob=self.config.dropout_probability,
|
139
|
+
dropout_mode=self.config.dropout_mode,
|
140
|
+
)
|
69
141
|
return ConvertedCircuit(native=native, abstract=circuit, original=original_circ)
|
70
142
|
|
71
143
|
def observable(self, observable: AbstractBlock, n_qubits: int) -> ConvertedObservable:
|
@@ -116,6 +188,7 @@ class Backend(BackendInterface):
|
|
116
188
|
noise: NoiseHandler | None = None,
|
117
189
|
endianness: Endianness = Endianness.BIG,
|
118
190
|
) -> Tensor:
|
191
|
+
set_block_and_readout_noises(circuit, noise, self.config)
|
119
192
|
state = self.run(
|
120
193
|
circuit,
|
121
194
|
param_values=param_values,
|
@@ -152,6 +225,9 @@ class Backend(BackendInterface):
|
|
152
225
|
"Looping expectation does not make sense with batched initial state. "
|
153
226
|
"Define your initial state with `batch_size=1`"
|
154
227
|
)
|
228
|
+
|
229
|
+
set_block_and_readout_noises(circuit, noise, self.config)
|
230
|
+
|
155
231
|
list_expvals = []
|
156
232
|
observables = observable if isinstance(observable, list) else [observable]
|
157
233
|
for vals in to_list_of_dicts(param_values):
|
@@ -206,12 +282,11 @@ class Backend(BackendInterface):
|
|
206
282
|
elif state is not None and pyqify_state:
|
207
283
|
n_qubits = circuit.abstract.n_qubits
|
208
284
|
state = pyqify(state, n_qubits) if pyqify_state else state
|
285
|
+
set_block_and_readout_noises(circuit, noise, self.config)
|
209
286
|
samples: list[Counter] = circuit.native.sample(
|
210
287
|
state=state, values=param_values, n_shots=n_shots
|
211
288
|
)
|
212
289
|
samples = invert_endianness(samples) if endianness != Endianness.BIG else samples
|
213
|
-
if noise is not None:
|
214
|
-
samples = apply_readout_noise(noise=noise, samples=samples)
|
215
290
|
if mitigation is not None:
|
216
291
|
logger.warning(
|
217
292
|
"Mitigation protocol is deprecated. Use qadence-protocols instead.",
|
@@ -4,17 +4,16 @@ from dataclasses import dataclass
|
|
4
4
|
from logging import getLogger
|
5
5
|
from typing import Callable
|
6
6
|
|
7
|
-
from pyqtorch.utils import SolverType
|
8
|
-
|
9
7
|
from qadence.analog import add_background_hamiltonian
|
10
8
|
from qadence.backend import BackendConfiguration
|
9
|
+
from qadence.noise import NoiseHandler
|
11
10
|
from qadence.transpile import (
|
12
11
|
blockfn_to_circfn,
|
13
12
|
chain_single_qubit_ops,
|
14
13
|
flatten,
|
15
14
|
scale_primitive_blocks_only,
|
16
15
|
)
|
17
|
-
from qadence.types import AlgoHEvo
|
16
|
+
from qadence.types import AlgoHEvo, DropoutMode, SolverType
|
18
17
|
|
19
18
|
logger = getLogger(__name__)
|
20
19
|
|
@@ -63,3 +62,11 @@ class Configuration(BackendConfiguration):
|
|
63
62
|
|
64
63
|
Loop over the batch of parameters to only allocate a single wavefunction at any given time.
|
65
64
|
"""
|
65
|
+
|
66
|
+
noise: NoiseHandler | None = None
|
67
|
+
"""NoiseHandler containing readout noise applied in backend."""
|
68
|
+
|
69
|
+
dropout_probability: float = 0.0
|
70
|
+
"""Quantum dropout probability (0 means no dropout)."""
|
71
|
+
dropout_mode: DropoutMode = DropoutMode.ROTATIONAL
|
72
|
+
"""Type of quantum dropout to perform."""
|
@@ -175,8 +175,23 @@ def sympy_to_pyq(expr: sympy.Expr) -> ConcretizedCallable | Tensor:
|
|
175
175
|
|
176
176
|
|
177
177
|
def convert_block(
|
178
|
-
block: AbstractBlock,
|
178
|
+
block: AbstractBlock,
|
179
|
+
n_qubits: int = None,
|
180
|
+
config: Configuration = None,
|
179
181
|
) -> Sequence[Module | Tensor | str | sympy.Expr]:
|
182
|
+
"""Convert block to native Pyqtorch representation.
|
183
|
+
|
184
|
+
Args:
|
185
|
+
block (AbstractBlock): Block to convert.
|
186
|
+
n_qubits (int, optional): Number of qubits. Defaults to None.
|
187
|
+
config (Configuration, optional): Backend configuration instance. Defaults to None.
|
188
|
+
|
189
|
+
Raises:
|
190
|
+
NotImplementedError: For non supported blocks.
|
191
|
+
|
192
|
+
Returns:
|
193
|
+
Sequence[Module | Tensor | str | sympy.Expr]: List of native operations.
|
194
|
+
"""
|
180
195
|
if isinstance(block, (Tensor, str, sympy.Expr)): # case for hamevo generators
|
181
196
|
if isinstance(block, Tensor):
|
182
197
|
block = block.permute(1, 2, 0) # put batch size in the back
|
@@ -208,8 +223,10 @@ def convert_block(
|
|
208
223
|
return [pyq.Scale(pyq.Sequence(scaled_ops), param)]
|
209
224
|
|
210
225
|
elif isinstance(block, TimeEvolutionBlock):
|
226
|
+
duration = block.duration # type: ignore [attr-defined]
|
211
227
|
if getattr(block.generator, "is_time_dependent", False):
|
212
228
|
config._use_gate_params = False
|
229
|
+
duration = config.get_param_name(block)[1]
|
213
230
|
generator = convert_block(block.generator, config=config)[0] # type: ignore [arg-type]
|
214
231
|
elif isinstance(block.generator, sympy.Basic):
|
215
232
|
generator = config.get_param_name(block)[1]
|
@@ -228,12 +245,26 @@ def convert_block(
|
|
228
245
|
generator = convert_block(block.generator, n_qubits, config)[0] # type: ignore[arg-type]
|
229
246
|
time_param = config.get_param_name(block)[0]
|
230
247
|
|
248
|
+
# convert noise operators here
|
249
|
+
noise_operators: list = [
|
250
|
+
convert_block(noise_block, config=config)[0] for noise_block in block.noise_operators
|
251
|
+
]
|
252
|
+
if len(noise_operators) > 0:
|
253
|
+
# squeeze batch size for noise operators
|
254
|
+
noise_operators = [
|
255
|
+
pyq_op.tensor(full_support=qubit_support).squeeze(-1) for pyq_op in noise_operators
|
256
|
+
]
|
257
|
+
|
231
258
|
return [
|
232
259
|
pyq.HamiltonianEvolution(
|
233
260
|
qubit_support=qubit_support,
|
234
261
|
generator=generator,
|
235
262
|
time=time_param,
|
236
263
|
cache_length=0,
|
264
|
+
duration=duration,
|
265
|
+
solver=config.ode_solver,
|
266
|
+
steps=config.n_steps_hevo,
|
267
|
+
noise_operators=noise_operators,
|
237
268
|
)
|
238
269
|
]
|
239
270
|
|
@@ -320,7 +351,16 @@ def convert_block(
|
|
320
351
|
)
|
321
352
|
|
322
353
|
|
323
|
-
def convert_digital_noise(noise: NoiseHandler) -> pyq.noise.NoiseProtocol:
|
354
|
+
def convert_digital_noise(noise: NoiseHandler) -> pyq.noise.NoiseProtocol | None:
|
355
|
+
"""Convert the digital noise into pyqtorch NoiseProtocol.
|
356
|
+
|
357
|
+
Args:
|
358
|
+
noise (NoiseHandler): Noise to convert.
|
359
|
+
|
360
|
+
Returns:
|
361
|
+
pyq.noise.NoiseProtocol | None: Pyqtorch native noise protocol
|
362
|
+
if there are any digital noise protocols.
|
363
|
+
"""
|
324
364
|
digital_part = noise.filter(NoiseProtocol.DIGITAL)
|
325
365
|
if digital_part is None:
|
326
366
|
return None
|
@@ -330,3 +370,24 @@ def convert_digital_noise(noise: NoiseHandler) -> pyq.noise.NoiseProtocol:
|
|
330
370
|
for proto, option in zip(digital_part.protocol, digital_part.options)
|
331
371
|
]
|
332
372
|
)
|
373
|
+
|
374
|
+
|
375
|
+
def convert_readout_noise(n_qubits: int, noise: NoiseHandler) -> pyq.noise.ReadoutNoise | None:
|
376
|
+
"""Convert the readout noise into pyqtorch ReadoutNoise.
|
377
|
+
|
378
|
+
Args:
|
379
|
+
n_qubits (int): Number of qubits
|
380
|
+
noise (NoiseHandler): Noise to convert.
|
381
|
+
|
382
|
+
Returns:
|
383
|
+
pyq.noise.ReadoutNoise | None: Pyqtorch native ReadoutNoise instance
|
384
|
+
if readout is is noise.
|
385
|
+
"""
|
386
|
+
readout_part = noise.filter(NoiseProtocol.READOUT)
|
387
|
+
if readout_part is None:
|
388
|
+
return None
|
389
|
+
|
390
|
+
if readout_part.protocol[0] == NoiseProtocol.READOUT.INDEPENDENT:
|
391
|
+
return pyq.noise.ReadoutNoise(n_qubits, **readout_part.options[0])
|
392
|
+
else:
|
393
|
+
return pyq.noise.CorrelatedReadoutNoise(**readout_part.options[0])
|
@@ -248,8 +248,6 @@ def _(
|
|
248
248
|
configuration: Union[BackendConfiguration, dict, None] = None,
|
249
249
|
) -> Tensor:
|
250
250
|
observable = observable if isinstance(observable, list) else [observable]
|
251
|
-
if backend == BackendName.PYQTORCH:
|
252
|
-
diff_mode = DiffMode.AD
|
253
251
|
bknd = backend_factory(backend, diff_mode=diff_mode, configuration=configuration)
|
254
252
|
conv = bknd.convert(circuit, observable)
|
255
253
|
|
@@ -4,11 +4,17 @@ formatters:
|
|
4
4
|
base:
|
5
5
|
format: "%(levelname) -5s %(asctime)s - %(name)s: %(message)s"
|
6
6
|
datefmt: "%Y-%m-%d %H:%M:%S"
|
7
|
+
empty:
|
8
|
+
format: "%(message)s" # Rich formatter for cleaner output
|
9
|
+
datefmt: "%Y-%m-%d %H:%M:%S"
|
7
10
|
handlers:
|
8
11
|
console:
|
9
12
|
class: logging.StreamHandler
|
10
13
|
formatter: base
|
11
14
|
stream: ext://sys.stderr
|
15
|
+
richconsole:
|
16
|
+
class: rich.logging.RichHandler
|
17
|
+
formatter: empty
|
12
18
|
loggers:
|
13
19
|
qadence:
|
14
20
|
level: INFO
|
@@ -22,3 +28,7 @@ loggers:
|
|
22
28
|
level: INFO
|
23
29
|
handlers: [console]
|
24
30
|
propagate: yes
|
31
|
+
ml_tools:
|
32
|
+
level: INFO
|
33
|
+
handlers: [richconsole]
|
34
|
+
propagate: false
|