qadence 1.7.8__tar.gz → 1.8.0__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.7.8 → qadence-1.8.0}/PKG-INFO +5 -8
- {qadence-1.7.8 → qadence-1.8.0}/mkdocs.yml +1 -0
- {qadence-1.7.8 → qadence-1.8.0}/pyproject.toml +8 -9
- {qadence-1.7.8 → qadence-1.8.0}/qadence/analog/device.py +1 -1
- {qadence-1.7.8 → qadence-1.8.0}/qadence/backend.py +3 -3
- {qadence-1.7.8 → qadence-1.8.0}/qadence/backends/horqrux/backend.py +3 -3
- {qadence-1.7.8 → qadence-1.8.0}/qadence/backends/pulser/backend.py +16 -17
- {qadence-1.7.8 → qadence-1.8.0}/qadence/backends/pulser/convert_ops.py +2 -2
- {qadence-1.7.8 → qadence-1.8.0}/qadence/backends/pyqtorch/backend.py +7 -7
- qadence-1.8.0/qadence/backends/pyqtorch/convert_ops.py +332 -0
- {qadence-1.7.8 → qadence-1.8.0}/qadence/backends/utils.py +9 -1
- {qadence-1.7.8 → qadence-1.8.0}/qadence/blocks/abstract.py +1 -1
- {qadence-1.7.8 → qadence-1.8.0}/qadence/blocks/embedding.py +21 -11
- {qadence-1.7.8 → qadence-1.8.0}/qadence/blocks/matrix.py +3 -1
- {qadence-1.7.8 → qadence-1.8.0}/qadence/blocks/primitive.py +36 -11
- {qadence-1.7.8 → qadence-1.8.0}/qadence/circuit.py +1 -1
- {qadence-1.7.8 → qadence-1.8.0}/qadence/constructors/__init__.py +2 -1
- {qadence-1.7.8 → qadence-1.8.0}/qadence/constructors/ansatze.py +176 -0
- {qadence-1.7.8 → qadence-1.8.0}/qadence/engines/differentiable_backend.py +3 -3
- {qadence-1.7.8 → qadence-1.8.0}/qadence/engines/jax/differentiable_backend.py +2 -2
- {qadence-1.7.8 → qadence-1.8.0}/qadence/engines/jax/differentiable_expectation.py +2 -2
- {qadence-1.7.8 → qadence-1.8.0}/qadence/engines/torch/differentiable_backend.py +2 -2
- {qadence-1.7.8 → qadence-1.8.0}/qadence/engines/torch/differentiable_expectation.py +2 -2
- {qadence-1.7.8 → qadence-1.8.0}/qadence/execution.py +14 -14
- {qadence-1.7.8 → qadence-1.8.0}/qadence/extensions.py +1 -1
- {qadence-1.7.8 → qadence-1.8.0}/qadence/measurements/shadow.py +4 -5
- {qadence-1.7.8 → qadence-1.8.0}/qadence/measurements/tomography.py +2 -2
- {qadence-1.7.8 → qadence-1.8.0}/qadence/measurements/utils.py +2 -2
- {qadence-1.7.8 → qadence-1.8.0}/qadence/mitigations/analog_zne.py +8 -7
- {qadence-1.7.8 → qadence-1.8.0}/qadence/mitigations/protocols.py +2 -2
- {qadence-1.7.8 → qadence-1.8.0}/qadence/mitigations/readout.py +8 -5
- {qadence-1.7.8 → qadence-1.8.0}/qadence/ml_tools/constructors.py +2 -2
- {qadence-1.7.8 → qadence-1.8.0}/qadence/ml_tools/models.py +7 -7
- {qadence-1.7.8 → qadence-1.8.0}/qadence/ml_tools/printing.py +2 -1
- {qadence-1.7.8 → qadence-1.8.0}/qadence/model.py +5 -5
- qadence-1.8.0/qadence/noise/__init__.py +6 -0
- qadence-1.8.0/qadence/noise/protocols.py +241 -0
- {qadence-1.7.8 → qadence-1.8.0}/qadence/operations/control_ops.py +37 -22
- {qadence-1.7.8 → qadence-1.8.0}/qadence/operations/ham_evo.py +1 -0
- {qadence-1.7.8 → qadence-1.8.0}/qadence/operations/parametric.py +32 -10
- {qadence-1.7.8 → qadence-1.8.0}/qadence/operations/primitive.py +61 -29
- {qadence-1.7.8 → qadence-1.8.0}/qadence/overlap.py +0 -6
- {qadence-1.7.8 → qadence-1.8.0}/qadence/parameters.py +3 -2
- {qadence-1.7.8 → qadence-1.8.0}/qadence/transpile/__init__.py +2 -1
- qadence-1.8.0/qadence/transpile/noise.py +46 -0
- {qadence-1.7.8 → qadence-1.8.0}/qadence/types.py +26 -2
- {qadence-1.7.8 → qadence-1.8.0}/renovate.json +0 -2
- qadence-1.7.8/qadence/backends/braket/__init__.py +0 -4
- qadence-1.7.8/qadence/backends/braket/backend.py +0 -234
- qadence-1.7.8/qadence/backends/braket/config.py +0 -22
- qadence-1.7.8/qadence/backends/braket/convert_ops.py +0 -116
- qadence-1.7.8/qadence/backends/pyqtorch/convert_ops.py +0 -381
- qadence-1.7.8/qadence/noise/__init__.py +0 -6
- qadence-1.7.8/qadence/noise/protocols.py +0 -54
- {qadence-1.7.8 → qadence-1.8.0}/.coveragerc +0 -0
- {qadence-1.7.8 → qadence-1.8.0}/.github/ISSUE_TEMPLATE/bug-report.yml +0 -0
- {qadence-1.7.8 → qadence-1.8.0}/.github/ISSUE_TEMPLATE/config.yml +0 -0
- {qadence-1.7.8 → qadence-1.8.0}/.github/ISSUE_TEMPLATE/new-feature.yml +0 -0
- {qadence-1.7.8 → qadence-1.8.0}/.github/workflows/build_docs.yml +0 -0
- {qadence-1.7.8 → qadence-1.8.0}/.github/workflows/lint.yml +0 -0
- {qadence-1.7.8 → qadence-1.8.0}/.github/workflows/test_all.yml +0 -0
- {qadence-1.7.8 → qadence-1.8.0}/.github/workflows/test_examples.yml +0 -0
- {qadence-1.7.8 → qadence-1.8.0}/.github/workflows/test_fast.yml +0 -0
- {qadence-1.7.8 → qadence-1.8.0}/.gitignore +0 -0
- {qadence-1.7.8 → qadence-1.8.0}/.pre-commit-config.yaml +0 -0
- {qadence-1.7.8 → qadence-1.8.0}/LICENSE +0 -0
- {qadence-1.7.8 → qadence-1.8.0}/MANIFEST.in +0 -0
- {qadence-1.7.8 → qadence-1.8.0}/README.md +0 -0
- {qadence-1.7.8 → qadence-1.8.0}/qadence/__init__.py +0 -0
- {qadence-1.7.8 → qadence-1.8.0}/qadence/analog/__init__.py +0 -0
- {qadence-1.7.8 → qadence-1.8.0}/qadence/analog/addressing.py +0 -0
- {qadence-1.7.8 → qadence-1.8.0}/qadence/analog/constants.py +0 -0
- {qadence-1.7.8 → qadence-1.8.0}/qadence/analog/hamiltonian_terms.py +0 -0
- {qadence-1.7.8 → qadence-1.8.0}/qadence/analog/parse_analog.py +0 -0
- {qadence-1.7.8 → qadence-1.8.0}/qadence/backends/__init__.py +0 -0
- {qadence-1.7.8 → qadence-1.8.0}/qadence/backends/api.py +0 -0
- {qadence-1.7.8 → qadence-1.8.0}/qadence/backends/gpsr.py +0 -0
- {qadence-1.7.8 → qadence-1.8.0}/qadence/backends/horqrux/__init__.py +0 -0
- {qadence-1.7.8 → qadence-1.8.0}/qadence/backends/horqrux/config.py +0 -0
- {qadence-1.7.8 → qadence-1.8.0}/qadence/backends/horqrux/convert_ops.py +0 -0
- {qadence-1.7.8 → qadence-1.8.0}/qadence/backends/jax_utils.py +0 -0
- {qadence-1.7.8 → qadence-1.8.0}/qadence/backends/pulser/__init__.py +0 -0
- {qadence-1.7.8 → qadence-1.8.0}/qadence/backends/pulser/channels.py +0 -0
- {qadence-1.7.8 → qadence-1.8.0}/qadence/backends/pulser/cloud.py +0 -0
- {qadence-1.7.8 → qadence-1.8.0}/qadence/backends/pulser/config.py +0 -0
- {qadence-1.7.8 → qadence-1.8.0}/qadence/backends/pulser/devices.py +0 -0
- {qadence-1.7.8 → qadence-1.8.0}/qadence/backends/pulser/pulses.py +0 -0
- {qadence-1.7.8 → qadence-1.8.0}/qadence/backends/pulser/waveforms.py +0 -0
- {qadence-1.7.8 → qadence-1.8.0}/qadence/backends/pyqtorch/__init__.py +0 -0
- {qadence-1.7.8 → qadence-1.8.0}/qadence/backends/pyqtorch/config.py +0 -0
- {qadence-1.7.8 → qadence-1.8.0}/qadence/blocks/__init__.py +0 -0
- {qadence-1.7.8 → qadence-1.8.0}/qadence/blocks/analog.py +0 -0
- {qadence-1.7.8 → qadence-1.8.0}/qadence/blocks/block_to_tensor.py +0 -0
- {qadence-1.7.8 → qadence-1.8.0}/qadence/blocks/composite.py +0 -0
- {qadence-1.7.8 → qadence-1.8.0}/qadence/blocks/manipulate.py +0 -0
- {qadence-1.7.8 → qadence-1.8.0}/qadence/blocks/utils.py +0 -0
- {qadence-1.7.8 → qadence-1.8.0}/qadence/constructors/daqc/__init__.py +0 -0
- {qadence-1.7.8 → qadence-1.8.0}/qadence/constructors/daqc/daqc.py +0 -0
- {qadence-1.7.8 → qadence-1.8.0}/qadence/constructors/daqc/gen_parser.py +0 -0
- {qadence-1.7.8 → qadence-1.8.0}/qadence/constructors/daqc/utils.py +0 -0
- {qadence-1.7.8 → qadence-1.8.0}/qadence/constructors/feature_maps.py +0 -0
- {qadence-1.7.8 → qadence-1.8.0}/qadence/constructors/hamiltonians.py +0 -0
- {qadence-1.7.8 → qadence-1.8.0}/qadence/constructors/iia.py +0 -0
- {qadence-1.7.8 → qadence-1.8.0}/qadence/constructors/qft.py +0 -0
- {qadence-1.7.8 → qadence-1.8.0}/qadence/constructors/rydberg_feature_maps.py +0 -0
- {qadence-1.7.8 → qadence-1.8.0}/qadence/constructors/rydberg_hea.py +0 -0
- {qadence-1.7.8 → qadence-1.8.0}/qadence/constructors/utils.py +0 -0
- {qadence-1.7.8 → qadence-1.8.0}/qadence/decompose.py +0 -0
- {qadence-1.7.8 → qadence-1.8.0}/qadence/divergences.py +0 -0
- {qadence-1.7.8 → qadence-1.8.0}/qadence/draw/__init__.py +0 -0
- {qadence-1.7.8 → qadence-1.8.0}/qadence/draw/assets/dark/measurement.png +0 -0
- {qadence-1.7.8 → qadence-1.8.0}/qadence/draw/assets/dark/measurement.svg +0 -0
- {qadence-1.7.8 → qadence-1.8.0}/qadence/draw/assets/light/measurement.png +0 -0
- {qadence-1.7.8 → qadence-1.8.0}/qadence/draw/assets/light/measurement.svg +0 -0
- {qadence-1.7.8 → qadence-1.8.0}/qadence/draw/themes.py +0 -0
- {qadence-1.7.8 → qadence-1.8.0}/qadence/draw/utils.py +0 -0
- {qadence-1.7.8 → qadence-1.8.0}/qadence/draw/vizbackend.py +0 -0
- {qadence-1.7.8 → qadence-1.8.0}/qadence/engines/__init__.py +0 -0
- {qadence-1.7.8 → qadence-1.8.0}/qadence/engines/jax/__init__.py +0 -0
- {qadence-1.7.8 → qadence-1.8.0}/qadence/engines/torch/__init__.py +0 -0
- {qadence-1.7.8 → qadence-1.8.0}/qadence/exceptions/__init__.py +0 -0
- {qadence-1.7.8 → qadence-1.8.0}/qadence/exceptions/exceptions.py +0 -0
- {qadence-1.7.8 → qadence-1.8.0}/qadence/libs.py +0 -0
- {qadence-1.7.8 → qadence-1.8.0}/qadence/log_config.yaml +0 -0
- {qadence-1.7.8 → qadence-1.8.0}/qadence/logger.py +0 -0
- {qadence-1.7.8 → qadence-1.8.0}/qadence/measurements/__init__.py +0 -0
- {qadence-1.7.8 → qadence-1.8.0}/qadence/measurements/protocols.py +0 -0
- {qadence-1.7.8 → qadence-1.8.0}/qadence/measurements/samples.py +0 -0
- {qadence-1.7.8 → qadence-1.8.0}/qadence/mitigations/__init__.py +0 -0
- {qadence-1.7.8 → qadence-1.8.0}/qadence/ml_tools/__init__.py +0 -0
- {qadence-1.7.8 → qadence-1.8.0}/qadence/ml_tools/config.py +0 -0
- {qadence-1.7.8 → qadence-1.8.0}/qadence/ml_tools/data.py +0 -0
- {qadence-1.7.8 → qadence-1.8.0}/qadence/ml_tools/optimize_step.py +0 -0
- {qadence-1.7.8 → qadence-1.8.0}/qadence/ml_tools/parameters.py +0 -0
- {qadence-1.7.8 → qadence-1.8.0}/qadence/ml_tools/saveload.py +0 -0
- {qadence-1.7.8 → qadence-1.8.0}/qadence/ml_tools/tensors.py +0 -0
- {qadence-1.7.8 → qadence-1.8.0}/qadence/ml_tools/train_grad.py +0 -0
- {qadence-1.7.8 → qadence-1.8.0}/qadence/ml_tools/train_no_grad.py +0 -0
- {qadence-1.7.8 → qadence-1.8.0}/qadence/ml_tools/utils.py +0 -0
- {qadence-1.7.8 → qadence-1.8.0}/qadence/noise/readout.py +0 -0
- {qadence-1.7.8 → qadence-1.8.0}/qadence/operations/__init__.py +0 -0
- {qadence-1.7.8 → qadence-1.8.0}/qadence/operations/analog.py +0 -0
- {qadence-1.7.8 → qadence-1.8.0}/qadence/protocols.py +0 -0
- {qadence-1.7.8 → qadence-1.8.0}/qadence/py.typed +0 -0
- {qadence-1.7.8 → qadence-1.8.0}/qadence/qubit_support.py +0 -0
- {qadence-1.7.8 → qadence-1.8.0}/qadence/register.py +0 -0
- {qadence-1.7.8 → qadence-1.8.0}/qadence/serial_expr_grammar.peg +0 -0
- {qadence-1.7.8 → qadence-1.8.0}/qadence/serialization.py +0 -0
- {qadence-1.7.8 → qadence-1.8.0}/qadence/states.py +0 -0
- {qadence-1.7.8 → qadence-1.8.0}/qadence/transpile/apply_fn.py +0 -0
- {qadence-1.7.8 → qadence-1.8.0}/qadence/transpile/block.py +0 -0
- {qadence-1.7.8 → qadence-1.8.0}/qadence/transpile/circuit.py +0 -0
- {qadence-1.7.8 → qadence-1.8.0}/qadence/transpile/digitalize.py +0 -0
- {qadence-1.7.8 → qadence-1.8.0}/qadence/transpile/flatten.py +0 -0
- {qadence-1.7.8 → qadence-1.8.0}/qadence/transpile/invert.py +0 -0
- {qadence-1.7.8 → qadence-1.8.0}/qadence/transpile/transpile.py +0 -0
- {qadence-1.7.8 → qadence-1.8.0}/qadence/utils.py +0 -0
- {qadence-1.7.8 → qadence-1.8.0}/setup.py +0 -0
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.3
|
2
2
|
Name: qadence
|
3
|
-
Version: 1.
|
3
|
+
Version: 1.8.0
|
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
|
@@ -22,7 +22,7 @@ Requires-Dist: matplotlib
|
|
22
22
|
Requires-Dist: nevergrad
|
23
23
|
Requires-Dist: numpy
|
24
24
|
Requires-Dist: openfermion
|
25
|
-
Requires-Dist: pyqtorch==1.
|
25
|
+
Requires-Dist: pyqtorch==1.5.1
|
26
26
|
Requires-Dist: pyyaml
|
27
27
|
Requires-Dist: rich
|
28
28
|
Requires-Dist: scipy
|
@@ -31,14 +31,11 @@ Requires-Dist: sympytorch>=0.1.2
|
|
31
31
|
Requires-Dist: tensorboard>=2.12.0
|
32
32
|
Requires-Dist: torch
|
33
33
|
Provides-Extra: all
|
34
|
-
Requires-Dist: braket; extra == 'all'
|
35
34
|
Requires-Dist: libs; extra == 'all'
|
36
35
|
Requires-Dist: mlflow; extra == 'all'
|
37
36
|
Requires-Dist: protocols; extra == 'all'
|
38
37
|
Requires-Dist: pulser; extra == 'all'
|
39
38
|
Requires-Dist: visualization; extra == 'all'
|
40
|
-
Provides-Extra: braket
|
41
|
-
Requires-Dist: amazon-braket-sdk<1.71.2; extra == 'braket'
|
42
39
|
Provides-Extra: dlprof
|
43
40
|
Requires-Dist: nvidia-dlprof[pytorch]; extra == 'dlprof'
|
44
41
|
Requires-Dist: nvidia-pyindex; extra == 'dlprof'
|
@@ -57,9 +54,9 @@ Requires-Dist: mlflow; extra == 'mlflow'
|
|
57
54
|
Provides-Extra: protocols
|
58
55
|
Requires-Dist: qadence-protocols; extra == 'protocols'
|
59
56
|
Provides-Extra: pulser
|
60
|
-
Requires-Dist: pasqal-cloud==0.12.
|
61
|
-
Requires-Dist: pulser-core==
|
62
|
-
Requires-Dist: pulser-simulation==
|
57
|
+
Requires-Dist: pasqal-cloud==0.12.4; extra == 'pulser'
|
58
|
+
Requires-Dist: pulser-core==1.1.1; extra == 'pulser'
|
59
|
+
Requires-Dist: pulser-simulation==1.1.1; extra == 'pulser'
|
63
60
|
Provides-Extra: visualization
|
64
61
|
Requires-Dist: graphviz; extra == 'visualization'
|
65
62
|
Description-Content-Type: text/markdown
|
@@ -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.8.0"
|
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.5.1",
|
54
54
|
"pyyaml",
|
55
55
|
"matplotlib",
|
56
56
|
"Arpeggio==2.0.2",
|
@@ -62,11 +62,10 @@ allow-ambiguous-features = true
|
|
62
62
|
|
63
63
|
[project.optional-dependencies]
|
64
64
|
pulser = [
|
65
|
-
"pulser-core==
|
66
|
-
"pulser-simulation==
|
67
|
-
"pasqal-cloud==0.12.
|
65
|
+
"pulser-core==1.1.1",
|
66
|
+
"pulser-simulation==1.1.1",
|
67
|
+
"pasqal-cloud==0.12.4",
|
68
68
|
]
|
69
|
-
braket = ["amazon-braket-sdk<1.71.2"]
|
70
69
|
visualization = [
|
71
70
|
"graphviz",
|
72
71
|
# FIXME: will be needed once we support latex labels
|
@@ -86,7 +85,7 @@ protocols = ["qadence-protocols"]
|
|
86
85
|
libs = ["qadence-libs"]
|
87
86
|
dlprof = ["nvidia-pyindex", "nvidia-dlprof[pytorch]"]
|
88
87
|
mlflow = ["mlflow"]
|
89
|
-
all = ["pulser", "
|
88
|
+
all = ["pulser", "visualization", "protocols", "libs", "mlflow"]
|
90
89
|
|
91
90
|
|
92
91
|
[tool.hatch.envs.default]
|
@@ -105,7 +104,7 @@ dependencies = [
|
|
105
104
|
"ruff",
|
106
105
|
"pydocstringformatter",
|
107
106
|
]
|
108
|
-
features = ["pulser", "
|
107
|
+
features = ["pulser", "visualization", "horqrux", "mlflow"]
|
109
108
|
|
110
109
|
[tool.hatch.envs.default.scripts]
|
111
110
|
test = "pytest -n auto --cov-report lcov --cov-config=pyproject.toml --cov=qadence --cov=tests --ignore=./tests/test_examples.py {args}"
|
@@ -143,7 +142,7 @@ dependencies = [
|
|
143
142
|
"markdown-exec",
|
144
143
|
"mike",
|
145
144
|
]
|
146
|
-
features = ["pulser", "
|
145
|
+
features = ["pulser", "horqrux", "visualization", "mlflow"]
|
147
146
|
|
148
147
|
[tool.hatch.envs.docs.scripts]
|
149
148
|
build = "mkdocs build --clean --strict"
|
@@ -23,7 +23,7 @@ from qadence.blocks.analog import ConstantAnalogRotation, InteractionBlock
|
|
23
23
|
from qadence.circuit import QuantumCircuit
|
24
24
|
from qadence.measurements import Measurements
|
25
25
|
from qadence.mitigations import Mitigations
|
26
|
-
from qadence.noise import
|
26
|
+
from qadence.noise import NoiseHandler
|
27
27
|
from qadence.parameters import stringify
|
28
28
|
from qadence.types import ArrayLike, BackendName, DiffMode, Endianness, Engine, ParamDictType
|
29
29
|
|
@@ -240,7 +240,7 @@ class Backend(ABC):
|
|
240
240
|
param_values: dict[str, Tensor] = {},
|
241
241
|
n_shots: int = 1000,
|
242
242
|
state: ArrayLike | None = None,
|
243
|
-
noise:
|
243
|
+
noise: NoiseHandler | None = None,
|
244
244
|
mitigation: Mitigations | None = None,
|
245
245
|
endianness: Endianness = Endianness.BIG,
|
246
246
|
) -> list[Counter]:
|
@@ -290,7 +290,7 @@ class Backend(ABC):
|
|
290
290
|
param_values: ParamDictType = {},
|
291
291
|
state: ArrayLike | None = None,
|
292
292
|
measurement: Measurements | None = None,
|
293
|
-
noise:
|
293
|
+
noise: NoiseHandler | None = None,
|
294
294
|
mitigation: Mitigations | None = None,
|
295
295
|
endianness: Endianness = Endianness.BIG,
|
296
296
|
) -> ArrayLike:
|
@@ -21,7 +21,7 @@ from qadence.blocks import AbstractBlock
|
|
21
21
|
from qadence.circuit import QuantumCircuit
|
22
22
|
from qadence.measurements import Measurements
|
23
23
|
from qadence.mitigations import Mitigations
|
24
|
-
from qadence.noise import
|
24
|
+
from qadence.noise import NoiseHandler
|
25
25
|
from qadence.transpile import flatten, scale_primitive_blocks_only, transpile
|
26
26
|
from qadence.types import BackendName, Endianness, Engine, ParamDictType
|
27
27
|
from qadence.utils import int_to_basis
|
@@ -114,7 +114,7 @@ class Backend(BackendInterface):
|
|
114
114
|
param_values: ParamDictType = {},
|
115
115
|
state: ArrayLike | None = None,
|
116
116
|
measurement: Measurements | None = None,
|
117
|
-
noise:
|
117
|
+
noise: NoiseHandler | None = None,
|
118
118
|
mitigation: Mitigations | None = None,
|
119
119
|
endianness: Endianness = Endianness.BIG,
|
120
120
|
) -> ArrayLike:
|
@@ -163,7 +163,7 @@ class Backend(BackendInterface):
|
|
163
163
|
param_values: ParamDictType = {},
|
164
164
|
n_shots: int = 1,
|
165
165
|
state: ArrayLike | None = None,
|
166
|
-
noise:
|
166
|
+
noise: NoiseHandler | None = None,
|
167
167
|
mitigation: Mitigations | None = None,
|
168
168
|
endianness: Endianness = Endianness.BIG,
|
169
169
|
) -> list[Counter]:
|
@@ -24,12 +24,12 @@ from qadence.circuit import QuantumCircuit
|
|
24
24
|
from qadence.measurements import Measurements
|
25
25
|
from qadence.mitigations import Mitigations
|
26
26
|
from qadence.mitigations.protocols import apply_mitigation
|
27
|
-
from qadence.noise import
|
28
|
-
from qadence.noise.protocols import
|
27
|
+
from qadence.noise import NoiseHandler
|
28
|
+
from qadence.noise.protocols import apply_readout_noise
|
29
29
|
from qadence.overlap import overlap_exact
|
30
30
|
from qadence.register import Register
|
31
31
|
from qadence.transpile import transpile
|
32
|
-
from qadence.types import BackendName, DeviceType, Endianness, Engine
|
32
|
+
from qadence.types import BackendName, DeviceType, Endianness, Engine, NoiseProtocol
|
33
33
|
|
34
34
|
from .channels import GLOBAL_CHANNEL, LOCAL_CHANNEL
|
35
35
|
from .cloud import get_client
|
@@ -187,7 +187,7 @@ class Backend(BackendInterface):
|
|
187
187
|
param_values: dict[str, Tensor] = {},
|
188
188
|
state: Tensor | None = None,
|
189
189
|
endianness: Endianness = Endianness.BIG,
|
190
|
-
noise:
|
190
|
+
noise: NoiseHandler | None = None,
|
191
191
|
) -> Tensor:
|
192
192
|
vals = to_list_of_dicts(param_values)
|
193
193
|
|
@@ -235,27 +235,26 @@ class Backend(BackendInterface):
|
|
235
235
|
def _run_noisy(
|
236
236
|
self,
|
237
237
|
circuit: ConvertedCircuit,
|
238
|
-
noise:
|
238
|
+
noise: NoiseHandler,
|
239
239
|
param_values: dict[str, Tensor] = dict(),
|
240
240
|
state: Tensor | None = None,
|
241
241
|
endianness: Endianness = Endianness.BIG,
|
242
242
|
) -> Tensor:
|
243
243
|
vals = to_list_of_dicts(param_values)
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
if not (isinstance(noise_probs, float) or isinstance(noise_probs, Iterable)):
|
248
|
-
KeyError(
|
249
|
-
"A single or a range of noise probabilities"
|
250
|
-
" should be passed. Got {type(noise_probs)}."
|
251
|
-
)
|
244
|
+
if not isinstance(noise.protocol[-1], NoiseProtocol.ANALOG):
|
245
|
+
raise TypeError("Noise must be of type `NoiseProtocol.ANALOG`.")
|
246
|
+
noise_probs = noise.options[-1].get("noise_probs", None)
|
252
247
|
|
253
248
|
def run_noisy_sim(noise_prob: float) -> Tensor:
|
254
249
|
batched_dm = np.zeros(
|
255
250
|
(len(vals), 2**circuit.abstract.n_qubits, 2**circuit.abstract.n_qubits),
|
256
251
|
dtype=np.complex128,
|
257
252
|
)
|
258
|
-
|
253
|
+
# pulser requires lower letters
|
254
|
+
sim_config = {
|
255
|
+
"noise": noise.protocol[-1].lower(),
|
256
|
+
noise.protocol[-1].lower() + "_rate": noise_prob,
|
257
|
+
}
|
259
258
|
self.config.sim_config = SimConfig(**sim_config)
|
260
259
|
|
261
260
|
for i, param_values_el in enumerate(vals):
|
@@ -289,7 +288,7 @@ class Backend(BackendInterface):
|
|
289
288
|
param_values: dict[str, Tensor] = {},
|
290
289
|
n_shots: int = 1,
|
291
290
|
state: Tensor | None = None,
|
292
|
-
noise:
|
291
|
+
noise: NoiseHandler | None = None,
|
293
292
|
mitigation: Mitigations | None = None,
|
294
293
|
endianness: Endianness = Endianness.BIG,
|
295
294
|
) -> list[Counter]:
|
@@ -313,7 +312,7 @@ class Backend(BackendInterface):
|
|
313
312
|
|
314
313
|
samples = invert_endianness(samples)
|
315
314
|
if noise is not None:
|
316
|
-
samples =
|
315
|
+
samples = apply_readout_noise(noise=noise, samples=samples)
|
317
316
|
if mitigation is not None:
|
318
317
|
logger.warning(
|
319
318
|
"Mitigation protocol is deprecated. Use qadence-protocols instead.",
|
@@ -329,7 +328,7 @@ class Backend(BackendInterface):
|
|
329
328
|
param_values: dict[str, Tensor] = {},
|
330
329
|
state: Tensor | None = None,
|
331
330
|
measurement: Measurements | None = None,
|
332
|
-
noise:
|
331
|
+
noise: NoiseHandler | None = None,
|
333
332
|
mitigation: Mitigations | None = None,
|
334
333
|
endianness: Endianness = Endianness.BIG,
|
335
334
|
) -> Tensor:
|
@@ -5,7 +5,7 @@ from typing import Sequence
|
|
5
5
|
import torch
|
6
6
|
from torch.nn import Module
|
7
7
|
|
8
|
-
from qadence import
|
8
|
+
from qadence import NoiseHandler
|
9
9
|
from qadence.blocks import (
|
10
10
|
AbstractBlock,
|
11
11
|
)
|
@@ -40,7 +40,7 @@ class PulserObservable(Module):
|
|
40
40
|
state: torch.Tensor,
|
41
41
|
values: dict[str, torch.Tensor] = dict(),
|
42
42
|
qubit_support: tuple | None = None,
|
43
|
-
noise:
|
43
|
+
noise: NoiseHandler | None = None,
|
44
44
|
endianness: Endianness = Endianness.BIG,
|
45
45
|
) -> torch.Tensor:
|
46
46
|
if not self.block.is_parametric:
|
@@ -22,8 +22,8 @@ from qadence.blocks import AbstractBlock
|
|
22
22
|
from qadence.circuit import QuantumCircuit
|
23
23
|
from qadence.measurements import Measurements
|
24
24
|
from qadence.mitigations.protocols import Mitigations, apply_mitigation
|
25
|
-
from qadence.noise import
|
26
|
-
from qadence.noise.protocols import
|
25
|
+
from qadence.noise import NoiseHandler
|
26
|
+
from qadence.noise.protocols import apply_readout_noise
|
27
27
|
from qadence.transpile import (
|
28
28
|
chain_single_qubit_ops,
|
29
29
|
flatten,
|
@@ -113,7 +113,7 @@ class Backend(BackendInterface):
|
|
113
113
|
param_values: dict[str, Tensor] = {},
|
114
114
|
state: Tensor | None = None,
|
115
115
|
measurement: Measurements | None = None,
|
116
|
-
noise:
|
116
|
+
noise: NoiseHandler | None = None,
|
117
117
|
endianness: Endianness = Endianness.BIG,
|
118
118
|
) -> Tensor:
|
119
119
|
state = self.run(
|
@@ -138,7 +138,7 @@ class Backend(BackendInterface):
|
|
138
138
|
param_values: dict[str, Tensor] = {},
|
139
139
|
state: Tensor | None = None,
|
140
140
|
measurement: Measurements | None = None,
|
141
|
-
noise:
|
141
|
+
noise: NoiseHandler | None = None,
|
142
142
|
endianness: Endianness = Endianness.BIG,
|
143
143
|
) -> Tensor:
|
144
144
|
if state is None:
|
@@ -169,7 +169,7 @@ class Backend(BackendInterface):
|
|
169
169
|
param_values: dict[str, Tensor] = {},
|
170
170
|
state: Tensor | None = None,
|
171
171
|
measurement: Measurements | None = None,
|
172
|
-
noise:
|
172
|
+
noise: NoiseHandler | None = None,
|
173
173
|
mitigation: Mitigations | None = None,
|
174
174
|
endianness: Endianness = Endianness.BIG,
|
175
175
|
) -> Tensor:
|
@@ -196,7 +196,7 @@ class Backend(BackendInterface):
|
|
196
196
|
param_values: dict[str, Tensor] = {},
|
197
197
|
n_shots: int = 1,
|
198
198
|
state: Tensor | None = None,
|
199
|
-
noise:
|
199
|
+
noise: NoiseHandler | None = None,
|
200
200
|
mitigation: Mitigations | None = None,
|
201
201
|
endianness: Endianness = Endianness.BIG,
|
202
202
|
pyqify_state: bool = True,
|
@@ -211,7 +211,7 @@ class Backend(BackendInterface):
|
|
211
211
|
)
|
212
212
|
samples = invert_endianness(samples) if endianness != Endianness.BIG else samples
|
213
213
|
if noise is not None:
|
214
|
-
samples =
|
214
|
+
samples = apply_readout_noise(noise=noise, samples=samples)
|
215
215
|
if mitigation is not None:
|
216
216
|
logger.warning(
|
217
217
|
"Mitigation protocol is deprecated. Use qadence-protocols instead.",
|
@@ -0,0 +1,332 @@
|
|
1
|
+
from __future__ import annotations
|
2
|
+
|
3
|
+
import re
|
4
|
+
from functools import partial, reduce
|
5
|
+
from itertools import chain as flatten
|
6
|
+
from typing import Any, Callable, Sequence
|
7
|
+
|
8
|
+
import pyqtorch as pyq
|
9
|
+
import sympy
|
10
|
+
import torch
|
11
|
+
from pyqtorch.embed import ConcretizedCallable
|
12
|
+
from torch import (
|
13
|
+
Tensor,
|
14
|
+
cdouble,
|
15
|
+
complex64,
|
16
|
+
float64,
|
17
|
+
tensor,
|
18
|
+
)
|
19
|
+
from torch.nn import Module
|
20
|
+
|
21
|
+
from qadence.blocks import (
|
22
|
+
AbstractBlock,
|
23
|
+
AddBlock,
|
24
|
+
ChainBlock,
|
25
|
+
CompositeBlock,
|
26
|
+
MatrixBlock,
|
27
|
+
ParametricBlock,
|
28
|
+
PrimitiveBlock,
|
29
|
+
ScaleBlock,
|
30
|
+
TimeEvolutionBlock,
|
31
|
+
)
|
32
|
+
from qadence.blocks.primitive import ProjectorBlock
|
33
|
+
from qadence.noise import NoiseHandler
|
34
|
+
from qadence.operations import (
|
35
|
+
U,
|
36
|
+
multi_qubit_gateset,
|
37
|
+
non_unitary_gateset,
|
38
|
+
single_qubit_gateset,
|
39
|
+
three_qubit_gateset,
|
40
|
+
two_qubit_gateset,
|
41
|
+
)
|
42
|
+
from qadence.types import NoiseProtocol, OpName
|
43
|
+
|
44
|
+
from .config import Configuration
|
45
|
+
|
46
|
+
SYMPY_TO_PYQ_MAPPING = {
|
47
|
+
sympy.Pow: "pow",
|
48
|
+
sympy.cos: "cos",
|
49
|
+
sympy.Add: "add",
|
50
|
+
sympy.Mul: "mul",
|
51
|
+
sympy.sin: "sin",
|
52
|
+
sympy.log: "log",
|
53
|
+
sympy.tan: "tan",
|
54
|
+
sympy.tanh: "tanh",
|
55
|
+
sympy.Heaviside: "hs",
|
56
|
+
sympy.Abs: "abs",
|
57
|
+
sympy.exp: "exp",
|
58
|
+
sympy.acos: "acos",
|
59
|
+
sympy.asin: "asin",
|
60
|
+
sympy.atan: "atan",
|
61
|
+
}
|
62
|
+
|
63
|
+
|
64
|
+
# Tdagger is not supported currently
|
65
|
+
supported_gates = list(set(OpName.list()) - set([OpName.TDAGGER]))
|
66
|
+
"""The set of supported gates.
|
67
|
+
|
68
|
+
Tdagger is currently not supported.
|
69
|
+
"""
|
70
|
+
|
71
|
+
|
72
|
+
def is_single_qubit_chain(block: AbstractBlock) -> bool:
|
73
|
+
return (
|
74
|
+
isinstance(block, (ChainBlock))
|
75
|
+
and block.n_supports == 1
|
76
|
+
and all([isinstance(b, (ParametricBlock, PrimitiveBlock)) for b in block])
|
77
|
+
and not any([isinstance(b, (ScaleBlock, U)) for b in block])
|
78
|
+
)
|
79
|
+
|
80
|
+
|
81
|
+
def extract_parameter(block: ScaleBlock | ParametricBlock, config: Configuration) -> str | Tensor:
|
82
|
+
"""Extract the parameter as string or its tensor value.
|
83
|
+
|
84
|
+
Args:
|
85
|
+
block (ScaleBlock | ParametricBlock): Block to extract parameter from.
|
86
|
+
config (Configuration): Configuration instance.
|
87
|
+
|
88
|
+
Returns:
|
89
|
+
str | Tensor: Parameter value or symbol.
|
90
|
+
"""
|
91
|
+
if not block.is_parametric:
|
92
|
+
tensor_val = tensor([block.parameters.parameter], dtype=complex64)
|
93
|
+
return (
|
94
|
+
tensor([block.parameters.parameter], dtype=float64)
|
95
|
+
if torch.all(tensor_val.imag == 0)
|
96
|
+
else tensor_val
|
97
|
+
)
|
98
|
+
|
99
|
+
return config.get_param_name(block)[0]
|
100
|
+
|
101
|
+
|
102
|
+
def replace_underscore_floats(s: str) -> str:
|
103
|
+
"""Replace underscores with periods for all floats in given string.
|
104
|
+
|
105
|
+
Needed for correct parsing of string by sympy parser.
|
106
|
+
|
107
|
+
Args:
|
108
|
+
s (str): string expression
|
109
|
+
|
110
|
+
Returns:
|
111
|
+
str: transformed string expression
|
112
|
+
"""
|
113
|
+
|
114
|
+
# Regular expression to match floats written with underscores instead of dots
|
115
|
+
float_with_underscore_pattern = r"""
|
116
|
+
(?<!\w) # Negative lookbehind to ensure not part of a word
|
117
|
+
-? # Optional negative sign
|
118
|
+
\d+ # One or more digits (before underscore)
|
119
|
+
_ # The underscore acting as decimal separator
|
120
|
+
\d+ # One or more digits (after underscore)
|
121
|
+
([eE][-+]?\d+)? # Optional exponent part for scientific notation
|
122
|
+
(?!\w) # Negative lookahead to ensure not part of a word
|
123
|
+
"""
|
124
|
+
|
125
|
+
# Function to replace the underscore with a dot
|
126
|
+
def underscore_to_dot(match: re.Match) -> Any:
|
127
|
+
return match.group(0).replace("_", ".")
|
128
|
+
|
129
|
+
# Compile the regular expression
|
130
|
+
pattern = re.compile(float_with_underscore_pattern, re.VERBOSE)
|
131
|
+
|
132
|
+
return pattern.sub(underscore_to_dot, s)
|
133
|
+
|
134
|
+
|
135
|
+
def sympy_to_pyq(expr: sympy.Expr) -> ConcretizedCallable | Tensor:
|
136
|
+
"""Convert sympy expression to pyqtorch ConcretizedCallable object.
|
137
|
+
|
138
|
+
Args:
|
139
|
+
expr (sympy.Expr): sympy expression
|
140
|
+
|
141
|
+
Returns:
|
142
|
+
ConcretizedCallable: expression encoded as ConcretizedCallable
|
143
|
+
"""
|
144
|
+
|
145
|
+
# base case - independent argument
|
146
|
+
if len(expr.args) == 0:
|
147
|
+
try:
|
148
|
+
res = torch.as_tensor(float(expr))
|
149
|
+
except Exception as e:
|
150
|
+
res = str(expr)
|
151
|
+
|
152
|
+
if "/" in res: # Found a rational
|
153
|
+
res = torch.as_tensor(float(sympy.Rational(res).evalf()))
|
154
|
+
return res
|
155
|
+
|
156
|
+
# Recursively iterate through current function arguments
|
157
|
+
all_results = []
|
158
|
+
for arg in expr.args:
|
159
|
+
res = sympy_to_pyq(arg)
|
160
|
+
all_results.append(res)
|
161
|
+
|
162
|
+
# deal with multi-argument (>2) sympy functions: converting to nested
|
163
|
+
# ConcretizedCallable objects
|
164
|
+
if len(all_results) > 2:
|
165
|
+
|
166
|
+
def fn(x: str | ConcretizedCallable, y: str | ConcretizedCallable) -> Callable:
|
167
|
+
return partial(ConcretizedCallable, call_name=SYMPY_TO_PYQ_MAPPING[expr.func])( # type: ignore [no-any-return]
|
168
|
+
abstract_args=[x, y]
|
169
|
+
)
|
170
|
+
|
171
|
+
concretized_callable = reduce(fn, all_results)
|
172
|
+
else:
|
173
|
+
concretized_callable = ConcretizedCallable(SYMPY_TO_PYQ_MAPPING[expr.func], all_results)
|
174
|
+
return concretized_callable
|
175
|
+
|
176
|
+
|
177
|
+
def convert_block(
|
178
|
+
block: AbstractBlock, n_qubits: int = None, config: Configuration = None
|
179
|
+
) -> Sequence[Module | Tensor | str | sympy.Expr]:
|
180
|
+
if isinstance(block, (Tensor, str, sympy.Expr)): # case for hamevo generators
|
181
|
+
if isinstance(block, Tensor):
|
182
|
+
block = block.permute(1, 2, 0) # put batch size in the back
|
183
|
+
return [block]
|
184
|
+
qubit_support = block.qubit_support
|
185
|
+
if n_qubits is None:
|
186
|
+
n_qubits = max(qubit_support) + 1
|
187
|
+
|
188
|
+
if config is None:
|
189
|
+
config = Configuration()
|
190
|
+
|
191
|
+
noise: NoiseHandler | None = None
|
192
|
+
if hasattr(block, "noise") and block.noise:
|
193
|
+
noise = convert_digital_noise(block.noise)
|
194
|
+
|
195
|
+
if isinstance(block, ScaleBlock):
|
196
|
+
scaled_ops = convert_block(block.block, n_qubits, config)
|
197
|
+
scale = extract_parameter(block, config=config)
|
198
|
+
|
199
|
+
# replace underscore by dot when underscore is between two numbers in string
|
200
|
+
if isinstance(scale, str):
|
201
|
+
scale = replace_underscore_floats(scale)
|
202
|
+
|
203
|
+
if isinstance(scale, str) and not config._use_gate_params:
|
204
|
+
param = sympy_to_pyq(sympy.parse_expr(scale))
|
205
|
+
else:
|
206
|
+
param = scale
|
207
|
+
|
208
|
+
return [pyq.Scale(pyq.Sequence(scaled_ops), param)]
|
209
|
+
|
210
|
+
elif isinstance(block, TimeEvolutionBlock):
|
211
|
+
if getattr(block.generator, "is_time_dependent", False):
|
212
|
+
config._use_gate_params = False
|
213
|
+
generator = convert_block(block.generator, config=config)[0] # type: ignore [arg-type]
|
214
|
+
elif isinstance(block.generator, sympy.Basic):
|
215
|
+
generator = config.get_param_name(block)[1]
|
216
|
+
|
217
|
+
elif isinstance(block.generator, Tensor):
|
218
|
+
m = block.generator.to(dtype=cdouble)
|
219
|
+
generator = convert_block(
|
220
|
+
MatrixBlock(
|
221
|
+
m,
|
222
|
+
qubit_support=qubit_support,
|
223
|
+
check_unitary=False,
|
224
|
+
check_hermitian=True,
|
225
|
+
)
|
226
|
+
)[0]
|
227
|
+
else:
|
228
|
+
generator = convert_block(block.generator, n_qubits, config)[0] # type: ignore[arg-type]
|
229
|
+
time_param = config.get_param_name(block)[0]
|
230
|
+
|
231
|
+
return [
|
232
|
+
pyq.HamiltonianEvolution(
|
233
|
+
qubit_support=qubit_support,
|
234
|
+
generator=generator,
|
235
|
+
time=time_param,
|
236
|
+
cache_length=0,
|
237
|
+
)
|
238
|
+
]
|
239
|
+
|
240
|
+
elif isinstance(block, MatrixBlock):
|
241
|
+
return [pyq.primitives.Primitive(block.matrix, block.qubit_support, noise=noise)]
|
242
|
+
elif isinstance(block, CompositeBlock):
|
243
|
+
ops = list(flatten(*(convert_block(b, n_qubits, config) for b in block.blocks)))
|
244
|
+
if isinstance(block, AddBlock):
|
245
|
+
return [pyq.Add(ops)] # add
|
246
|
+
elif is_single_qubit_chain(block) and config.use_single_qubit_composition:
|
247
|
+
return [pyq.Merge(ops)] # for chains of single qubit ops on the same qubit
|
248
|
+
else:
|
249
|
+
return [pyq.Sequence(ops)] # for kron and chain
|
250
|
+
elif isinstance(block, tuple(non_unitary_gateset)):
|
251
|
+
if isinstance(block, ProjectorBlock):
|
252
|
+
projector = getattr(pyq, block.name)
|
253
|
+
if block.name == OpName.N:
|
254
|
+
return [projector(target=qubit_support, noise=noise)]
|
255
|
+
else:
|
256
|
+
return [
|
257
|
+
projector(
|
258
|
+
qubit_support=qubit_support,
|
259
|
+
ket=block.ket,
|
260
|
+
bra=block.bra,
|
261
|
+
noise=noise,
|
262
|
+
)
|
263
|
+
]
|
264
|
+
else:
|
265
|
+
return [getattr(pyq, block.name)(qubit_support[0])]
|
266
|
+
elif isinstance(block, tuple(single_qubit_gateset)):
|
267
|
+
pyq_cls = getattr(pyq, block.name)
|
268
|
+
if isinstance(block, ParametricBlock):
|
269
|
+
if isinstance(block, U):
|
270
|
+
op = pyq_cls(
|
271
|
+
qubit_support[0],
|
272
|
+
*config.get_param_name(block),
|
273
|
+
noise=noise,
|
274
|
+
)
|
275
|
+
else:
|
276
|
+
param = extract_parameter(block, config)
|
277
|
+
op = pyq_cls(qubit_support[0], param, noise=noise)
|
278
|
+
else:
|
279
|
+
op = pyq_cls(qubit_support[0], noise=noise) # type: ignore [attr-defined]
|
280
|
+
return [op]
|
281
|
+
elif isinstance(block, tuple(two_qubit_gateset)):
|
282
|
+
pyq_cls = getattr(pyq, block.name)
|
283
|
+
if isinstance(block, ParametricBlock):
|
284
|
+
op = pyq_cls(
|
285
|
+
qubit_support[0],
|
286
|
+
qubit_support[1],
|
287
|
+
extract_parameter(block, config),
|
288
|
+
noise=noise,
|
289
|
+
)
|
290
|
+
else:
|
291
|
+
op = pyq_cls(
|
292
|
+
qubit_support[0], qubit_support[1], noise=noise # type: ignore [attr-defined]
|
293
|
+
)
|
294
|
+
return [op]
|
295
|
+
elif isinstance(block, tuple(three_qubit_gateset) + tuple(multi_qubit_gateset)):
|
296
|
+
block_name = block.name[1:] if block.name.startswith("M") else block.name
|
297
|
+
pyq_cls = getattr(pyq, block_name)
|
298
|
+
if isinstance(block, ParametricBlock):
|
299
|
+
op = pyq_cls(
|
300
|
+
qubit_support[:-1],
|
301
|
+
qubit_support[-1],
|
302
|
+
extract_parameter(block, config),
|
303
|
+
noise=noise,
|
304
|
+
)
|
305
|
+
else:
|
306
|
+
if "CSWAP" in block_name:
|
307
|
+
op = pyq_cls(
|
308
|
+
qubit_support[:-2], qubit_support[-2:], noise=noise # type: ignore [attr-defined]
|
309
|
+
)
|
310
|
+
else:
|
311
|
+
op = pyq_cls(
|
312
|
+
qubit_support[:-1], qubit_support[-1], noise=noise # type: ignore [attr-defined]
|
313
|
+
)
|
314
|
+
return [op]
|
315
|
+
else:
|
316
|
+
raise NotImplementedError(
|
317
|
+
f"Non supported operation of type {type(block)}. "
|
318
|
+
"In case you are trying to run an `AnalogBlock`, make sure you "
|
319
|
+
"specify the `device_specs` in your `Register` first."
|
320
|
+
)
|
321
|
+
|
322
|
+
|
323
|
+
def convert_digital_noise(noise: NoiseHandler) -> pyq.noise.NoiseProtocol:
|
324
|
+
digital_part = noise.filter(NoiseProtocol.DIGITAL)
|
325
|
+
if digital_part is None:
|
326
|
+
return None
|
327
|
+
return pyq.noise.NoiseProtocol(
|
328
|
+
[
|
329
|
+
pyq.noise.NoiseProtocol(proto, option.get("error_probability"))
|
330
|
+
for proto, option in zip(digital_part.protocol, digital_part.options)
|
331
|
+
]
|
332
|
+
)
|