qadence 1.7.8__py3-none-any.whl → 1.9.0__py3-none-any.whl
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/__init__.py +1 -1
- qadence/analog/device.py +1 -1
- qadence/analog/parse_analog.py +1 -2
- qadence/backend.py +3 -3
- qadence/backends/gpsr.py +8 -2
- qadence/backends/horqrux/backend.py +3 -3
- qadence/backends/pulser/backend.py +21 -38
- qadence/backends/pulser/convert_ops.py +2 -2
- qadence/backends/pyqtorch/backend.py +85 -10
- qadence/backends/pyqtorch/config.py +10 -3
- qadence/backends/pyqtorch/convert_ops.py +245 -233
- qadence/backends/utils.py +9 -1
- qadence/blocks/abstract.py +1 -1
- qadence/blocks/embedding.py +21 -11
- qadence/blocks/matrix.py +3 -1
- qadence/blocks/primitive.py +37 -11
- qadence/circuit.py +1 -1
- qadence/constructors/__init__.py +2 -1
- qadence/constructors/ansatze.py +176 -0
- qadence/engines/differentiable_backend.py +3 -3
- qadence/engines/jax/differentiable_backend.py +2 -2
- qadence/engines/jax/differentiable_expectation.py +2 -2
- qadence/engines/torch/differentiable_backend.py +2 -2
- qadence/engines/torch/differentiable_expectation.py +2 -2
- qadence/execution.py +14 -16
- qadence/extensions.py +1 -1
- qadence/log_config.yaml +10 -0
- qadence/measurements/shadow.py +101 -133
- qadence/measurements/tomography.py +2 -2
- qadence/measurements/utils.py +4 -4
- qadence/mitigations/analog_zne.py +8 -7
- qadence/mitigations/protocols.py +2 -2
- qadence/mitigations/readout.py +14 -5
- qadence/ml_tools/__init__.py +4 -8
- qadence/ml_tools/callbacks/__init__.py +30 -0
- qadence/ml_tools/callbacks/callback.py +451 -0
- qadence/ml_tools/callbacks/callbackmanager.py +214 -0
- qadence/ml_tools/{saveload.py → callbacks/saveload.py} +11 -11
- qadence/ml_tools/callbacks/writer_registry.py +430 -0
- qadence/ml_tools/config.py +132 -258
- qadence/ml_tools/constructors.py +2 -2
- qadence/ml_tools/data.py +7 -3
- qadence/ml_tools/loss/__init__.py +10 -0
- qadence/ml_tools/loss/loss.py +87 -0
- qadence/ml_tools/models.py +7 -7
- qadence/ml_tools/optimize_step.py +45 -10
- qadence/ml_tools/stages.py +46 -0
- qadence/ml_tools/train_utils/__init__.py +7 -0
- qadence/ml_tools/train_utils/base_trainer.py +548 -0
- qadence/ml_tools/train_utils/config_manager.py +184 -0
- qadence/ml_tools/trainer.py +692 -0
- qadence/model.py +6 -6
- qadence/noise/__init__.py +2 -2
- qadence/noise/protocols.py +188 -36
- qadence/operations/control_ops.py +37 -22
- qadence/operations/ham_evo.py +88 -26
- qadence/operations/parametric.py +32 -10
- qadence/operations/primitive.py +61 -29
- qadence/overlap.py +0 -6
- qadence/parameters.py +3 -2
- qadence/transpile/__init__.py +2 -1
- qadence/transpile/noise.py +53 -0
- qadence/types.py +39 -3
- {qadence-1.7.8.dist-info → qadence-1.9.0.dist-info}/METADATA +5 -9
- {qadence-1.7.8.dist-info → qadence-1.9.0.dist-info}/RECORD +67 -63
- {qadence-1.7.8.dist-info → qadence-1.9.0.dist-info}/WHEEL +1 -1
- qadence/backends/braket/__init__.py +0 -4
- qadence/backends/braket/backend.py +0 -234
- qadence/backends/braket/config.py +0 -22
- qadence/backends/braket/convert_ops.py +0 -116
- qadence/ml_tools/printing.py +0 -153
- qadence/ml_tools/train_grad.py +0 -395
- qadence/ml_tools/train_no_grad.py +0 -199
- qadence/noise/readout.py +0 -218
- {qadence-1.7.8.dist-info → qadence-1.9.0.dist-info}/licenses/LICENSE +0 -0
qadence/__init__.py
CHANGED
@@ -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
|
|
qadence/analog/device.py
CHANGED
qadence/analog/parse_analog.py
CHANGED
@@ -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(
|
qadence/backend.py
CHANGED
@@ -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:
|
qadence/backends/gpsr.py
CHANGED
@@ -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]
|
@@ -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,11 @@ 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 apply_noise
|
27
|
+
from qadence.noise import NoiseHandler
|
29
28
|
from qadence.overlap import overlap_exact
|
30
29
|
from qadence.register import Register
|
31
30
|
from qadence.transpile import transpile
|
32
|
-
from qadence.types import BackendName, DeviceType, Endianness, Engine
|
31
|
+
from qadence.types import BackendName, DeviceType, Endianness, Engine, NoiseProtocol
|
33
32
|
|
34
33
|
from .channels import GLOBAL_CHANNEL, LOCAL_CHANNEL
|
35
34
|
from .cloud import get_client
|
@@ -187,7 +186,7 @@ class Backend(BackendInterface):
|
|
187
186
|
param_values: dict[str, Tensor] = {},
|
188
187
|
state: Tensor | None = None,
|
189
188
|
endianness: Endianness = Endianness.BIG,
|
190
|
-
noise:
|
189
|
+
noise: NoiseHandler | None = None,
|
191
190
|
) -> Tensor:
|
192
191
|
vals = to_list_of_dicts(param_values)
|
193
192
|
|
@@ -235,27 +234,26 @@ class Backend(BackendInterface):
|
|
235
234
|
def _run_noisy(
|
236
235
|
self,
|
237
236
|
circuit: ConvertedCircuit,
|
238
|
-
noise:
|
237
|
+
noise: NoiseHandler,
|
239
238
|
param_values: dict[str, Tensor] = dict(),
|
240
239
|
state: Tensor | None = None,
|
241
240
|
endianness: Endianness = Endianness.BIG,
|
242
241
|
) -> Tensor:
|
243
242
|
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
|
-
)
|
243
|
+
if not isinstance(noise.protocol[-1], NoiseProtocol.ANALOG):
|
244
|
+
raise TypeError("Noise must be of type `NoiseProtocol.ANALOG`.")
|
245
|
+
noise_probs = noise.options[-1].get("noise_probs", None)
|
252
246
|
|
253
247
|
def run_noisy_sim(noise_prob: float) -> Tensor:
|
254
248
|
batched_dm = np.zeros(
|
255
249
|
(len(vals), 2**circuit.abstract.n_qubits, 2**circuit.abstract.n_qubits),
|
256
250
|
dtype=np.complex128,
|
257
251
|
)
|
258
|
-
|
252
|
+
# pulser requires lower letters
|
253
|
+
sim_config = {
|
254
|
+
"noise": noise.protocol[-1].lower(),
|
255
|
+
noise.protocol[-1].lower() + "_rate": noise_prob,
|
256
|
+
}
|
259
257
|
self.config.sim_config = SimConfig(**sim_config)
|
260
258
|
|
261
259
|
for i, param_values_el in enumerate(vals):
|
@@ -289,7 +287,7 @@ class Backend(BackendInterface):
|
|
289
287
|
param_values: dict[str, Tensor] = {},
|
290
288
|
n_shots: int = 1,
|
291
289
|
state: Tensor | None = None,
|
292
|
-
noise:
|
290
|
+
noise: NoiseHandler | None = None,
|
293
291
|
mitigation: Mitigations | None = None,
|
294
292
|
endianness: Endianness = Endianness.BIG,
|
295
293
|
) -> list[Counter]:
|
@@ -312,8 +310,6 @@ class Backend(BackendInterface):
|
|
312
310
|
from qadence.transpile import invert_endianness
|
313
311
|
|
314
312
|
samples = invert_endianness(samples)
|
315
|
-
if noise is not None:
|
316
|
-
samples = apply_noise(noise=noise, samples=samples)
|
317
313
|
if mitigation is not None:
|
318
314
|
logger.warning(
|
319
315
|
"Mitigation protocol is deprecated. Use qadence-protocols instead.",
|
@@ -329,7 +325,7 @@ class Backend(BackendInterface):
|
|
329
325
|
param_values: dict[str, Tensor] = {},
|
330
326
|
state: Tensor | None = None,
|
331
327
|
measurement: Measurements | None = None,
|
332
|
-
noise:
|
328
|
+
noise: NoiseHandler | None = None,
|
333
329
|
mitigation: Mitigations | None = None,
|
334
330
|
endianness: Endianness = Endianness.BIG,
|
335
331
|
) -> Tensor:
|
@@ -355,27 +351,14 @@ class Backend(BackendInterface):
|
|
355
351
|
noise=noise,
|
356
352
|
)
|
357
353
|
support = sorted(list(circuit.abstract.register.support))
|
358
|
-
|
359
|
-
|
360
|
-
|
361
|
-
|
362
|
-
obs.native(
|
363
|
-
dm.squeeze(), param_values, qubit_support=support, noise=noise
|
364
|
-
)
|
365
|
-
for dm in dms
|
366
|
-
]
|
367
|
-
for obs in observable
|
368
|
-
]
|
369
|
-
res = torch.stack(
|
370
|
-
[torch.transpose(torch.stack(res), 0, -1) for res in res_list]
|
371
|
-
)
|
372
|
-
|
373
|
-
else:
|
374
|
-
res_list = [
|
375
|
-
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
|
376
358
|
]
|
377
|
-
|
378
|
-
|
359
|
+
for obs in observable
|
360
|
+
]
|
361
|
+
res = torch.stack([torch.transpose(torch.stack(res), 0, -1) for res in res_list])
|
379
362
|
return res.real
|
380
363
|
elif mitigation is not None:
|
381
364
|
logger.warning(
|
@@ -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,23 +22,63 @@ 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 apply_noise
|
25
|
+
from qadence.noise import NoiseHandler
|
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:
|
@@ -113,9 +185,10 @@ class Backend(BackendInterface):
|
|
113
185
|
param_values: dict[str, Tensor] = {},
|
114
186
|
state: Tensor | None = None,
|
115
187
|
measurement: Measurements | None = None,
|
116
|
-
noise:
|
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,
|
@@ -138,7 +211,7 @@ class Backend(BackendInterface):
|
|
138
211
|
param_values: dict[str, Tensor] = {},
|
139
212
|
state: Tensor | None = None,
|
140
213
|
measurement: Measurements | None = None,
|
141
|
-
noise:
|
214
|
+
noise: NoiseHandler | None = None,
|
142
215
|
endianness: Endianness = Endianness.BIG,
|
143
216
|
) -> Tensor:
|
144
217
|
if state is None:
|
@@ -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):
|
@@ -169,7 +245,7 @@ class Backend(BackendInterface):
|
|
169
245
|
param_values: dict[str, Tensor] = {},
|
170
246
|
state: Tensor | None = None,
|
171
247
|
measurement: Measurements | None = None,
|
172
|
-
noise:
|
248
|
+
noise: NoiseHandler | None = None,
|
173
249
|
mitigation: Mitigations | None = None,
|
174
250
|
endianness: Endianness = Endianness.BIG,
|
175
251
|
) -> Tensor:
|
@@ -196,7 +272,7 @@ class Backend(BackendInterface):
|
|
196
272
|
param_values: dict[str, Tensor] = {},
|
197
273
|
n_shots: int = 1,
|
198
274
|
state: Tensor | None = None,
|
199
|
-
noise:
|
275
|
+
noise: NoiseHandler | None = None,
|
200
276
|
mitigation: Mitigations | None = None,
|
201
277
|
endianness: Endianness = Endianness.BIG,
|
202
278
|
pyqify_state: bool = True,
|
@@ -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_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."""
|