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.
Files changed (75) hide show
  1. qadence/__init__.py +1 -1
  2. qadence/analog/device.py +1 -1
  3. qadence/analog/parse_analog.py +1 -2
  4. qadence/backend.py +3 -3
  5. qadence/backends/gpsr.py +8 -2
  6. qadence/backends/horqrux/backend.py +3 -3
  7. qadence/backends/pulser/backend.py +21 -38
  8. qadence/backends/pulser/convert_ops.py +2 -2
  9. qadence/backends/pyqtorch/backend.py +85 -10
  10. qadence/backends/pyqtorch/config.py +10 -3
  11. qadence/backends/pyqtorch/convert_ops.py +245 -233
  12. qadence/backends/utils.py +9 -1
  13. qadence/blocks/abstract.py +1 -1
  14. qadence/blocks/embedding.py +21 -11
  15. qadence/blocks/matrix.py +3 -1
  16. qadence/blocks/primitive.py +37 -11
  17. qadence/circuit.py +1 -1
  18. qadence/constructors/__init__.py +2 -1
  19. qadence/constructors/ansatze.py +176 -0
  20. qadence/engines/differentiable_backend.py +3 -3
  21. qadence/engines/jax/differentiable_backend.py +2 -2
  22. qadence/engines/jax/differentiable_expectation.py +2 -2
  23. qadence/engines/torch/differentiable_backend.py +2 -2
  24. qadence/engines/torch/differentiable_expectation.py +2 -2
  25. qadence/execution.py +14 -16
  26. qadence/extensions.py +1 -1
  27. qadence/log_config.yaml +10 -0
  28. qadence/measurements/shadow.py +101 -133
  29. qadence/measurements/tomography.py +2 -2
  30. qadence/measurements/utils.py +4 -4
  31. qadence/mitigations/analog_zne.py +8 -7
  32. qadence/mitigations/protocols.py +2 -2
  33. qadence/mitigations/readout.py +14 -5
  34. qadence/ml_tools/__init__.py +4 -8
  35. qadence/ml_tools/callbacks/__init__.py +30 -0
  36. qadence/ml_tools/callbacks/callback.py +451 -0
  37. qadence/ml_tools/callbacks/callbackmanager.py +214 -0
  38. qadence/ml_tools/{saveload.py → callbacks/saveload.py} +11 -11
  39. qadence/ml_tools/callbacks/writer_registry.py +430 -0
  40. qadence/ml_tools/config.py +132 -258
  41. qadence/ml_tools/constructors.py +2 -2
  42. qadence/ml_tools/data.py +7 -3
  43. qadence/ml_tools/loss/__init__.py +10 -0
  44. qadence/ml_tools/loss/loss.py +87 -0
  45. qadence/ml_tools/models.py +7 -7
  46. qadence/ml_tools/optimize_step.py +45 -10
  47. qadence/ml_tools/stages.py +46 -0
  48. qadence/ml_tools/train_utils/__init__.py +7 -0
  49. qadence/ml_tools/train_utils/base_trainer.py +548 -0
  50. qadence/ml_tools/train_utils/config_manager.py +184 -0
  51. qadence/ml_tools/trainer.py +692 -0
  52. qadence/model.py +6 -6
  53. qadence/noise/__init__.py +2 -2
  54. qadence/noise/protocols.py +188 -36
  55. qadence/operations/control_ops.py +37 -22
  56. qadence/operations/ham_evo.py +88 -26
  57. qadence/operations/parametric.py +32 -10
  58. qadence/operations/primitive.py +61 -29
  59. qadence/overlap.py +0 -6
  60. qadence/parameters.py +3 -2
  61. qadence/transpile/__init__.py +2 -1
  62. qadence/transpile/noise.py +53 -0
  63. qadence/types.py +39 -3
  64. {qadence-1.7.8.dist-info → qadence-1.9.0.dist-info}/METADATA +5 -9
  65. {qadence-1.7.8.dist-info → qadence-1.9.0.dist-info}/RECORD +67 -63
  66. {qadence-1.7.8.dist-info → qadence-1.9.0.dist-info}/WHEEL +1 -1
  67. qadence/backends/braket/__init__.py +0 -4
  68. qadence/backends/braket/backend.py +0 -234
  69. qadence/backends/braket/config.py +0 -22
  70. qadence/backends/braket/convert_ops.py +0 -116
  71. qadence/ml_tools/printing.py +0 -153
  72. qadence/ml_tools/train_grad.py +0 -395
  73. qadence/ml_tools/train_no_grad.py +0 -199
  74. qadence/noise/readout.py +0 -218
  75. {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
@@ -49,7 +49,7 @@ class RydbergDevice:
49
49
  )
50
50
 
51
51
  def _to_dict(self) -> dict:
52
- device_dict = {}
52
+ device_dict = dict()
53
53
  for field in fields(self):
54
54
  if field.name != "pattern":
55
55
  device_dict[field.name] = getattr(self, field.name)
@@ -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 / h_norm, duration * h_norm / 1000)
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 Noise
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: Noise | None = None,
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: Noise | None = None,
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 single_gap_psr
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(PI / 2 - PI / 5, PI / 2 + PI / 5, n_eqs)
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 Noise
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: Noise | None = None,
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: Noise | None = None,
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 Noise
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: Noise | None = None,
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: 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
- noise_probs = noise.options.get("noise_probs", None)
245
- if noise_probs is None:
246
- KeyError("A `noise probs` option should be passed to the <class QuantumModel>.")
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
- sim_config = {"noise": noise.protocol, noise.protocol + "_rate": noise_prob}
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: Noise | None = None,
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: Noise | None = None,
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
- # TODO: There should be a better check for batched density matrices.
359
- if dms.size()[0] > 1:
360
- res_list = [
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
- res = torch.transpose(torch.stack(res_list), 0, 1)
378
- res = res if len(res.shape) > 0 else res.reshape(1)
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 Noise
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: Noise | None = None,
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 Noise
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
- native = pyq.QuantumCircuit(circuit.n_qubits, ops)
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: Noise | None = None,
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: Noise | None = None,
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: Noise | None = None,
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: Noise | None = None,
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."""