qadence 1.4.0__py3-none-any.whl → 1.5.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 -0
- qadence/backends/pulser/backend.py +1 -1
- qadence/backends/pulser/config.py +3 -0
- qadence/backends/pyqtorch/backend.py +25 -22
- qadence/backends/pyqtorch/convert_ops.py +25 -10
- qadence/backends/utils.py +3 -2
- qadence/constructors/ansatze.py +5 -0
- qadence/constructors/feature_maps.py +4 -0
- qadence/engines/torch/differentiable_expectation.py +4 -164
- qadence/extensions.py +1 -0
- qadence/libs.py +15 -0
- qadence/measurements/protocols.py +2 -2
- qadence/measurements/samples.py +38 -0
- qadence/measurements/tomography.py +2 -112
- qadence/measurements/utils.py +180 -0
- qadence/ml_tools/data.py +11 -11
- qadence/ml_tools/models.py +8 -8
- qadence/ml_tools/optimize_step.py +2 -1
- qadence/ml_tools/train_grad.py +4 -2
- qadence/models/quantum_model.py +12 -7
- qadence/operations/analog.py +1 -0
- {qadence-1.4.0.dist-info → qadence-1.5.0.dist-info}/METADATA +22 -8
- {qadence-1.4.0.dist-info → qadence-1.5.0.dist-info}/RECORD +25 -22
- {qadence-1.4.0.dist-info → qadence-1.5.0.dist-info}/WHEEL +1 -1
- {qadence-1.4.0.dist-info → qadence-1.5.0.dist-info}/licenses/LICENSE +0 -0
qadence/__init__.py
CHANGED
@@ -32,6 +32,7 @@ DEFAULT_FLOAT_DTYPE = torchfloat64
|
|
32
32
|
DEFAULT_COMPLEX_DTYPE = cdouble
|
33
33
|
set_default_dtype(DEFAULT_FLOAT_DTYPE)
|
34
34
|
|
35
|
+
|
35
36
|
"""Fetch the functions defined in the __all__ of each sub-module.
|
36
37
|
|
37
38
|
Import to the qadence name space. Make sure each added submodule has the respective definition:
|
@@ -71,7 +71,7 @@ def make_sequence(circ: QuantumCircuit, config: Configuration) -> Sequence:
|
|
71
71
|
)
|
72
72
|
|
73
73
|
########
|
74
|
-
# FIXME: Remove the block below in V1.
|
74
|
+
# FIXME: Remove the block below in V1.5.0
|
75
75
|
if config.spacing is not None:
|
76
76
|
logger.warning(
|
77
77
|
"Passing register spacing in the backend configuration is deprecated. "
|
@@ -30,6 +30,7 @@ class Configuration(BackendConfiguration):
|
|
30
30
|
|
31
31
|
FIXME: This is deprecated, the device_type is now controlled in the
|
32
32
|
Qadence Device, as detailed in the documentation.
|
33
|
+
FIXME: Remove in v1.5.0
|
33
34
|
"""
|
34
35
|
|
35
36
|
sampling_rate: float = 1.0
|
@@ -44,6 +45,7 @@ class Configuration(BackendConfiguration):
|
|
44
45
|
|
45
46
|
FIXME: This is deprecated, spacing is now controlled in the Register,
|
46
47
|
as detailed in the register tutorial.
|
48
|
+
FIXME: Remove in v1.5.0
|
47
49
|
"""
|
48
50
|
|
49
51
|
method_solv: str = "adams"
|
@@ -89,6 +91,7 @@ class Configuration(BackendConfiguration):
|
|
89
91
|
|
90
92
|
FIXME: This is deprecated, the interaction is now controlled in the
|
91
93
|
Qadence Device, as detailed in the documentation.
|
94
|
+
FIXME: Remove in v1.5.0
|
92
95
|
"""
|
93
96
|
|
94
97
|
# configuration for cloud simulations
|
@@ -151,7 +151,9 @@ class Backend(BackendInterface):
|
|
151
151
|
if state is None:
|
152
152
|
from qadence.states import zero_state
|
153
153
|
|
154
|
-
state = zero_state(circuit.abstract.n_qubits, batch_size=1)
|
154
|
+
state = zero_state(circuit.abstract.n_qubits, batch_size=1).to(
|
155
|
+
dtype=circuit.native.dtype
|
156
|
+
)
|
155
157
|
if state.size(0) != 1:
|
156
158
|
raise ValueError(
|
157
159
|
"Looping expectation does not make sense with batched initial state. "
|
@@ -222,28 +224,29 @@ class Backend(BackendInterface):
|
|
222
224
|
}
|
223
225
|
)
|
224
226
|
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
_probs
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
if noise is not None:
|
239
|
-
samples = apply_noise(noise=noise, samples=samples)
|
240
|
-
if mitigation is not None:
|
241
|
-
logger.warning(
|
242
|
-
"Mitigation protocol is deprecated. Use qadence-protocols instead.",
|
227
|
+
with torch.no_grad():
|
228
|
+
wf = self.run(circuit=circuit, param_values=param_values, state=state)
|
229
|
+
probs = torch.abs(torch.pow(wf, 2))
|
230
|
+
samples = list(
|
231
|
+
map(
|
232
|
+
lambda _probs: _sample(
|
233
|
+
_probs=_probs,
|
234
|
+
n_shots=n_shots,
|
235
|
+
endianness=endianness,
|
236
|
+
n_qubits=circuit.abstract.n_qubits,
|
237
|
+
),
|
238
|
+
probs,
|
239
|
+
)
|
243
240
|
)
|
244
|
-
|
245
|
-
|
246
|
-
|
241
|
+
if noise is not None:
|
242
|
+
samples = apply_noise(noise=noise, samples=samples)
|
243
|
+
if mitigation is not None:
|
244
|
+
logger.warning(
|
245
|
+
"Mitigation protocol is deprecated. Use qadence-protocols instead.",
|
246
|
+
)
|
247
|
+
assert noise
|
248
|
+
samples = apply_mitigation(noise=noise, mitigation=mitigation, samples=samples)
|
249
|
+
return samples
|
247
250
|
|
248
251
|
def assign_parameters(self, circuit: ConvertedCircuit, param_values: dict[str, Tensor]) -> Any:
|
249
252
|
raise NotImplementedError
|
@@ -4,7 +4,7 @@ from functools import reduce
|
|
4
4
|
from itertools import chain as flatten
|
5
5
|
from math import prod
|
6
6
|
from operator import add
|
7
|
-
from typing import Sequence, Tuple
|
7
|
+
from typing import Any, Sequence, Tuple
|
8
8
|
|
9
9
|
import pyqtorch as pyq
|
10
10
|
import sympy
|
@@ -26,6 +26,7 @@ from torch import (
|
|
26
26
|
transpose,
|
27
27
|
)
|
28
28
|
from torch import device as torch_device
|
29
|
+
from torch import dtype as torch_dtype
|
29
30
|
from torch.nn import Module
|
30
31
|
|
31
32
|
from qadence.backends.utils import (
|
@@ -178,6 +179,7 @@ class PyQMatrixBlock(Module):
|
|
178
179
|
self.register_buffer("mat", block.matrix.unsqueeze(2))
|
179
180
|
self.mat: Tensor
|
180
181
|
self._device: torch_device = self.mat.device
|
182
|
+
self._dtype: torch_dtype = self.mat.dtype
|
181
183
|
|
182
184
|
def forward(self, state: Tensor, _: dict[str, Tensor] = None) -> Tensor:
|
183
185
|
return apply_operator(state, self.mat, self.qubits, self.n_qubits)
|
@@ -186,9 +188,10 @@ class PyQMatrixBlock(Module):
|
|
186
188
|
def device(self) -> torch_device:
|
187
189
|
return self._device
|
188
190
|
|
189
|
-
def to(self,
|
190
|
-
self.mat = self.mat.to(
|
191
|
-
self._device = device
|
191
|
+
def to(self, *args: Any, **kwargs: Any) -> PyQMatrixBlock:
|
192
|
+
self.mat = self.mat.to(*args, **kwargs)
|
193
|
+
self._device = self.mat.device
|
194
|
+
self._dtype = self.mat.dtype
|
192
195
|
return self
|
193
196
|
|
194
197
|
|
@@ -262,6 +265,7 @@ class PyQObservable(Module):
|
|
262
265
|
)
|
263
266
|
self._forward = lambda self, state, values: self.operation(state, values)
|
264
267
|
self._device = self.operation.device
|
268
|
+
self._dtype = self.operation.dtype
|
265
269
|
|
266
270
|
def run(self, state: Tensor, values: dict[str, Tensor]) -> Tensor:
|
267
271
|
return self._forward(self, state, values)
|
@@ -273,9 +277,14 @@ class PyQObservable(Module):
|
|
273
277
|
def device(self) -> torch_device:
|
274
278
|
return self._device
|
275
279
|
|
276
|
-
|
277
|
-
|
278
|
-
self.
|
280
|
+
@property
|
281
|
+
def dtype(self) -> torch_dtype:
|
282
|
+
return self._dtype
|
283
|
+
|
284
|
+
def to(self, *args: Any, **kwargs: Any) -> PyQObservable:
|
285
|
+
self.operation = self.operation.to(*args, **kwargs)
|
286
|
+
self._device = self.operation.device
|
287
|
+
self._dtype = self.operation.dtype
|
279
288
|
return self
|
280
289
|
|
281
290
|
|
@@ -338,6 +347,7 @@ class PyQHamiltonianEvolution(Module):
|
|
338
347
|
self._device: torch_device = (
|
339
348
|
self.hmat.device if hasattr(self, "hmat") else torch_device("cpu")
|
340
349
|
)
|
350
|
+
self._dtype: torch_dtype = self.hmat.dtype if hasattr(self, "hmat") else cdouble
|
341
351
|
|
342
352
|
def _unitary(self, hamiltonian: Tensor, time_evolution: Tensor) -> Tensor:
|
343
353
|
self.batch_size = max(hamiltonian.size()[2], len(time_evolution))
|
@@ -419,10 +429,15 @@ class PyQHamiltonianEvolution(Module):
|
|
419
429
|
def device(self) -> torch_device:
|
420
430
|
return self._device
|
421
431
|
|
422
|
-
|
432
|
+
@property
|
433
|
+
def dtype(self) -> torch_dtype:
|
434
|
+
return self._dtype
|
435
|
+
|
436
|
+
def to(self, *args: Any, **kwargs: Any) -> PyQHamiltonianEvolution:
|
423
437
|
if hasattr(self, "hmat"):
|
424
|
-
self.hmat = self.hmat.to(
|
425
|
-
|
438
|
+
self.hmat = self.hmat.to(*args, **kwargs)
|
439
|
+
self._device = self.hmat.device
|
440
|
+
self._dtype = self.hmat.dtype
|
426
441
|
return self
|
427
442
|
|
428
443
|
|
qadence/backends/utils.py
CHANGED
@@ -13,6 +13,7 @@ from pyqtorch.parametric import Parametric as PyQParametric
|
|
13
13
|
from torch import (
|
14
14
|
Tensor,
|
15
15
|
cat,
|
16
|
+
complex64,
|
16
17
|
complex128,
|
17
18
|
mean,
|
18
19
|
no_grad,
|
@@ -129,8 +130,8 @@ def is_pyq_shape(state: Tensor, n_qubits: int) -> bool:
|
|
129
130
|
|
130
131
|
def validate_state(state: Tensor, n_qubits: int) -> None:
|
131
132
|
"""Check if a custom initial state conforms to the qadence or the pyqtorch format."""
|
132
|
-
if state.dtype
|
133
|
-
raise TypeError(f"Expected
|
133
|
+
if state.dtype not in [complex128, complex64]:
|
134
|
+
raise TypeError(f"Expected complex dtype, got {state.dtype}")
|
134
135
|
elif len(state.size()) < 2:
|
135
136
|
raise ValueError(f"Invalid state shape. Got {state.shape}")
|
136
137
|
elif not is_qadence_shape(state, n_qubits) and not is_pyq_shape(state, n_qubits):
|
qadence/constructors/ansatze.py
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
from __future__ import annotations
|
2
2
|
|
3
3
|
import itertools
|
4
|
+
import warnings
|
4
5
|
from typing import Any, Optional, Type, Union
|
5
6
|
|
6
7
|
from qadence.blocks import AbstractBlock, block_is_qubit_hamiltonian, chain, kron, tag
|
@@ -328,6 +329,7 @@ def hea_analog(*args: Any, **kwargs: Any) -> Any:
|
|
328
329
|
#########
|
329
330
|
|
330
331
|
|
332
|
+
# FIXME: Remove in v1.5.0
|
331
333
|
def build_qnn(
|
332
334
|
n_qubits: int,
|
333
335
|
n_features: int,
|
@@ -360,6 +362,9 @@ def build_qnn(
|
|
360
362
|
Returns:
|
361
363
|
A list of Abstract blocks to be used for constructing a quantum circuit
|
362
364
|
"""
|
365
|
+
|
366
|
+
warnings.warn("Function build_qnn is deprecated and will be removed in v1.5.0.", FutureWarning)
|
367
|
+
|
363
368
|
depth = n_qubits if depth is None else depth
|
364
369
|
|
365
370
|
idx_fms = build_idx_fms(basis, fm_pauli, fm_strategy, n_features, n_qubits, spectrum)
|
@@ -35,6 +35,7 @@ RS_FUNC_DICT = {
|
|
35
35
|
}
|
36
36
|
|
37
37
|
|
38
|
+
# FIXME: Remove in v1.5.0
|
38
39
|
def backwards_compatibility(
|
39
40
|
fm_type: BasisSet | Callable | str,
|
40
41
|
reupload_scaling: ReuploadScaling | Callable | str,
|
@@ -224,6 +225,7 @@ def feature_map(
|
|
224
225
|
return fm
|
225
226
|
|
226
227
|
|
228
|
+
# FIXME: Remove in v1.5.0
|
227
229
|
def fourier_feature_map(
|
228
230
|
n_qubits: int, support: tuple[int, ...] = None, param: str = "phi", op: RotationTypes = RX
|
229
231
|
) -> AbstractBlock:
|
@@ -241,6 +243,7 @@ def fourier_feature_map(
|
|
241
243
|
return fm
|
242
244
|
|
243
245
|
|
246
|
+
# FIXME: Remove in v1.5.0
|
244
247
|
def chebyshev_feature_map(
|
245
248
|
n_qubits: int, support: tuple[int, ...] = None, param: str = "phi", op: RotationTypes = RX
|
246
249
|
) -> AbstractBlock:
|
@@ -259,6 +262,7 @@ def chebyshev_feature_map(
|
|
259
262
|
return fm
|
260
263
|
|
261
264
|
|
265
|
+
# FIXME: Remove in v1.5.0
|
262
266
|
def tower_feature_map(
|
263
267
|
n_qubits: int, support: tuple[int, ...] = None, param: str = "phi", op: RotationTypes = RX
|
264
268
|
) -> AbstractBlock:
|
@@ -1,6 +1,6 @@
|
|
1
1
|
from __future__ import annotations
|
2
2
|
|
3
|
-
from collections import
|
3
|
+
from collections import OrderedDict
|
4
4
|
from dataclasses import dataclass
|
5
5
|
from functools import partial
|
6
6
|
from typing import Any, Callable, Sequence
|
@@ -8,22 +8,19 @@ from typing import Any, Callable, Sequence
|
|
8
8
|
import torch
|
9
9
|
from torch import Tensor
|
10
10
|
from torch.autograd import Function
|
11
|
-
from torch.nn import Module
|
12
11
|
|
13
12
|
from qadence.backend import Backend as QuantumBackend
|
14
|
-
from qadence.backend import
|
13
|
+
from qadence.backend import ConvertedCircuit, ConvertedObservable
|
15
14
|
from qadence.backends.adjoint import AdjointExpectation
|
16
15
|
from qadence.backends.utils import infer_batchsize, is_pyq_shape, param_dict, pyqify, validate_state
|
17
16
|
from qadence.blocks.abstract import AbstractBlock
|
18
|
-
from qadence.blocks.
|
19
|
-
from qadence.blocks.utils import uuid_to_block, uuid_to_eigen
|
17
|
+
from qadence.blocks.utils import uuid_to_eigen
|
20
18
|
from qadence.circuit import QuantumCircuit
|
21
|
-
from qadence.extensions import get_gpsr_fns
|
22
19
|
from qadence.measurements import Measurements
|
23
20
|
from qadence.mitigations import Mitigations
|
24
21
|
from qadence.ml_tools import promote_to_tensor
|
25
22
|
from qadence.noise import Noise
|
26
|
-
from qadence.types import
|
23
|
+
from qadence.types import Endianness
|
27
24
|
|
28
25
|
|
29
26
|
class PSRExpectation(Function):
|
@@ -232,160 +229,3 @@ class DifferentiableExpectation:
|
|
232
229
|
# Since they are constants their gradients are 0.
|
233
230
|
param_to_psr[param_id] = lambda x: torch.tensor([0.0], requires_grad=False)
|
234
231
|
return param_to_psr
|
235
|
-
|
236
|
-
|
237
|
-
class DifferentiableBackend(Module):
|
238
|
-
"""A class to abstract the operations done by the autodiff engine.
|
239
|
-
|
240
|
-
Arguments:
|
241
|
-
backend: An instance of the QuantumBackend type perform execution.
|
242
|
-
diff_mode: A differentiable mode supported by the differentiation engine.
|
243
|
-
**psr_args: Arguments that will be passed on to `DifferentiableExpectation`.
|
244
|
-
"""
|
245
|
-
|
246
|
-
def __init__(
|
247
|
-
self,
|
248
|
-
backend: QuantumBackend,
|
249
|
-
diff_mode: DiffMode = DiffMode.AD,
|
250
|
-
**psr_args: int | float | None,
|
251
|
-
) -> None:
|
252
|
-
super().__init__()
|
253
|
-
|
254
|
-
self.backend = backend
|
255
|
-
self.diff_mode = diff_mode
|
256
|
-
self.psr_args = psr_args
|
257
|
-
# TODO: Add differentiable overlap calculation
|
258
|
-
self._overlap: Callable = None # type: ignore [assignment]
|
259
|
-
|
260
|
-
def run(
|
261
|
-
self,
|
262
|
-
circuit: ConvertedCircuit,
|
263
|
-
param_values: dict = {},
|
264
|
-
state: Tensor | None = None,
|
265
|
-
endianness: Endianness = Endianness.BIG,
|
266
|
-
) -> Tensor:
|
267
|
-
"""Run on the underlying backend."""
|
268
|
-
return self.backend.run(
|
269
|
-
circuit=circuit, param_values=param_values, state=state, endianness=endianness
|
270
|
-
)
|
271
|
-
|
272
|
-
def expectation(
|
273
|
-
self,
|
274
|
-
circuit: ConvertedCircuit,
|
275
|
-
observable: list[ConvertedObservable] | ConvertedObservable,
|
276
|
-
param_values: dict[str, Tensor] = {},
|
277
|
-
state: Tensor | None = None,
|
278
|
-
measurement: Measurements | None = None,
|
279
|
-
noise: Noise | None = None,
|
280
|
-
mitigation: Mitigations | None = None,
|
281
|
-
endianness: Endianness = Endianness.BIG,
|
282
|
-
) -> Tensor:
|
283
|
-
"""Compute the expectation value of a given observable.
|
284
|
-
|
285
|
-
Arguments:
|
286
|
-
circuit: A backend native quantum circuit to be executed.
|
287
|
-
observable: A backend native observable to compute the expectation value from.
|
288
|
-
param_values: A dict of values for symbolic substitution.
|
289
|
-
state: An initial state.
|
290
|
-
measurement: A shot-based measurement protocol.
|
291
|
-
endianness: Endianness of the state.
|
292
|
-
|
293
|
-
Returns:
|
294
|
-
A tensor of expectation values.
|
295
|
-
"""
|
296
|
-
observable = observable if isinstance(observable, list) else [observable]
|
297
|
-
differentiable_expectation = DifferentiableExpectation(
|
298
|
-
backend=self.backend,
|
299
|
-
circuit=circuit,
|
300
|
-
observable=observable,
|
301
|
-
param_values=param_values,
|
302
|
-
state=state,
|
303
|
-
measurement=measurement,
|
304
|
-
noise=noise,
|
305
|
-
mitigation=mitigation,
|
306
|
-
endianness=endianness,
|
307
|
-
)
|
308
|
-
|
309
|
-
if self.diff_mode == DiffMode.AD:
|
310
|
-
expectation = differentiable_expectation.ad
|
311
|
-
elif self.diff_mode == DiffMode.ADJOINT:
|
312
|
-
expectation = differentiable_expectation.adjoint
|
313
|
-
else:
|
314
|
-
try:
|
315
|
-
fns = get_gpsr_fns()
|
316
|
-
psr_fn = fns[self.diff_mode]
|
317
|
-
except KeyError:
|
318
|
-
raise ValueError(f"{self.diff_mode} differentiation mode is not supported")
|
319
|
-
expectation = partial(differentiable_expectation.psr, psr_fn=psr_fn, **self.psr_args)
|
320
|
-
return expectation()
|
321
|
-
|
322
|
-
def sample(
|
323
|
-
self,
|
324
|
-
circuit: ConvertedCircuit,
|
325
|
-
param_values: dict[str, Tensor],
|
326
|
-
n_shots: int = 1,
|
327
|
-
state: Tensor | None = None,
|
328
|
-
noise: Noise | None = None,
|
329
|
-
mitigation: Mitigations | None = None,
|
330
|
-
endianness: Endianness = Endianness.BIG,
|
331
|
-
) -> list[Counter]:
|
332
|
-
"""Sample bitstring from the registered circuit.
|
333
|
-
|
334
|
-
Arguments:
|
335
|
-
circuit: A backend native quantum circuit to be executed.
|
336
|
-
param_values: The values of the parameters after embedding
|
337
|
-
n_shots: The number of shots. Defaults to 1.
|
338
|
-
state: Initial state.
|
339
|
-
noise: A noise model to use.
|
340
|
-
mitigation: A mitigation protocol to apply to noisy samples.
|
341
|
-
endianness: Endianness of the resulting bitstrings.
|
342
|
-
|
343
|
-
Returns:
|
344
|
-
An iterable with all the sampled bitstrings
|
345
|
-
"""
|
346
|
-
with torch.no_grad():
|
347
|
-
return self.backend.sample(
|
348
|
-
circuit=circuit,
|
349
|
-
param_values=param_values,
|
350
|
-
n_shots=n_shots,
|
351
|
-
state=state,
|
352
|
-
noise=noise,
|
353
|
-
mitigation=mitigation,
|
354
|
-
endianness=endianness,
|
355
|
-
)
|
356
|
-
|
357
|
-
def circuit(self, circuit: QuantumCircuit) -> ConvertedCircuit:
|
358
|
-
parametrized_blocks = list(uuid_to_block(circuit.block).values())
|
359
|
-
non_prim_blocks = filter(lambda b: not isinstance(b, PrimitiveBlock), parametrized_blocks)
|
360
|
-
if len(list(non_prim_blocks)) > 0:
|
361
|
-
raise ValueError(
|
362
|
-
"The circuit contains non-primitive blocks that are currently not supported by the "
|
363
|
-
"PSR differentiable mode."
|
364
|
-
)
|
365
|
-
return self.backend.circuit(circuit)
|
366
|
-
|
367
|
-
def observable(self, observable: AbstractBlock, n_qubits: int) -> ConvertedObservable:
|
368
|
-
if observable is not None and observable.is_parametric:
|
369
|
-
raise ValueError("PSR cannot be applied to a parametric observable.")
|
370
|
-
return self.backend.observable(observable, n_qubits)
|
371
|
-
|
372
|
-
def convert(
|
373
|
-
self,
|
374
|
-
circuit: QuantumCircuit,
|
375
|
-
observable: list[AbstractBlock] | AbstractBlock | None = None,
|
376
|
-
) -> Converted:
|
377
|
-
if self.diff_mode != DiffMode.AD and observable is not None:
|
378
|
-
msg = (
|
379
|
-
f"Differentiation mode '{self.diff_mode}' does not support parametric observables."
|
380
|
-
)
|
381
|
-
if isinstance(observable, list):
|
382
|
-
for obs in observable:
|
383
|
-
if obs.is_parametric:
|
384
|
-
raise ValueError(msg)
|
385
|
-
else:
|
386
|
-
if observable.is_parametric:
|
387
|
-
raise ValueError(msg)
|
388
|
-
return self.backend.convert(circuit, observable)
|
389
|
-
|
390
|
-
def assign_parameters(self, circuit: ConvertedCircuit, param_values: dict[str, Tensor]) -> Any:
|
391
|
-
return self.backend.assign_parameters(circuit, param_values)
|
qadence/extensions.py
CHANGED
@@ -79,6 +79,7 @@ def _validate_diff_mode(backend: Backend, diff_mode: DiffMode) -> None:
|
|
79
79
|
|
80
80
|
def _validate_backend_config(backend: Backend) -> None:
|
81
81
|
if backend.config.use_gradient_checkpointing:
|
82
|
+
# FIXME: Remove in v1.5.0
|
82
83
|
msg = "use_gradient_checkpointing is deprecated."
|
83
84
|
import warnings
|
84
85
|
|
qadence/libs.py
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
from __future__ import annotations
|
2
|
+
|
3
|
+
import importlib
|
4
|
+
|
5
|
+
from qadence.logger import get_logger
|
6
|
+
|
7
|
+
logger = get_logger(__name__)
|
8
|
+
|
9
|
+
try:
|
10
|
+
module = importlib.import_module("qadence_libs.protocols")
|
11
|
+
available_libs = getattr(module, "available_libs")
|
12
|
+
except ModuleNotFoundError:
|
13
|
+
raise ModuleNotFoundError(
|
14
|
+
"The 'qadence_libs' module is not present." " Please install the 'qadence-libs' package."
|
15
|
+
)
|
@@ -5,16 +5,16 @@ from dataclasses import dataclass
|
|
5
5
|
from typing import Callable, cast
|
6
6
|
|
7
7
|
PROTOCOL_TO_MODULE = {
|
8
|
-
"tomography": "qadence.measurements.tomography",
|
9
8
|
"shadow": "qadence.measurements.shadow",
|
9
|
+
"tomography": "qadence.measurements.tomography",
|
10
10
|
}
|
11
11
|
|
12
12
|
|
13
13
|
# TODO: make this a StrEnum to keep consistency with the rest of the interface
|
14
14
|
@dataclass
|
15
15
|
class Measurements:
|
16
|
-
TOMOGRAPHY = "tomography"
|
17
16
|
SHADOW = "shadow"
|
17
|
+
TOMOGRAPHY = "tomography"
|
18
18
|
|
19
19
|
def __init__(self, protocol: str, options: dict) -> None:
|
20
20
|
self.protocol: str = protocol
|
@@ -0,0 +1,38 @@
|
|
1
|
+
from __future__ import annotations
|
2
|
+
|
3
|
+
from collections import Counter
|
4
|
+
from typing import List
|
5
|
+
|
6
|
+
from torch import Tensor
|
7
|
+
|
8
|
+
from qadence.blocks import AbstractBlock
|
9
|
+
from qadence.blocks.utils import unroll_block_with_scaling
|
10
|
+
from qadence.measurements.utils import pauli_z_expectation
|
11
|
+
|
12
|
+
|
13
|
+
def compute_expectation(
|
14
|
+
observable: List[AbstractBlock],
|
15
|
+
samples: List[Counter],
|
16
|
+
) -> List[Tensor]:
|
17
|
+
"""Given a list of observables in Z basis, compute the expectation values against samples.
|
18
|
+
|
19
|
+
Args:
|
20
|
+
observables: A list of observables
|
21
|
+
to estimate the expectation values from.
|
22
|
+
samples: List of samples against which expectation value is to be computed
|
23
|
+
"""
|
24
|
+
|
25
|
+
if not isinstance(observable, list):
|
26
|
+
raise TypeError(
|
27
|
+
f"Observables must be of type <class 'List[AbstractBlock]'>. Got {type(observable)}."
|
28
|
+
)
|
29
|
+
|
30
|
+
expectation_vals = []
|
31
|
+
|
32
|
+
for obs in observable:
|
33
|
+
decomposition = unroll_block_with_scaling(obs)
|
34
|
+
if not obs._is_diag_pauli or obs.is_identity:
|
35
|
+
raise TypeError("observable provided is not in the Z basis")
|
36
|
+
expectation_vals.append(pauli_z_expectation(decomposition, samples))
|
37
|
+
|
38
|
+
return expectation_vals
|
@@ -1,129 +1,19 @@
|
|
1
1
|
from __future__ import annotations
|
2
2
|
|
3
|
-
from collections import Counter
|
4
|
-
from functools import reduce
|
5
|
-
|
6
|
-
import numpy as np
|
7
3
|
import torch
|
8
4
|
from torch import Tensor
|
9
5
|
|
10
6
|
from qadence.backend import Backend
|
11
7
|
from qadence.backends.pyqtorch import Backend as PyQBackend
|
12
|
-
from qadence.blocks import AbstractBlock
|
8
|
+
from qadence.blocks import AbstractBlock
|
13
9
|
from qadence.blocks.utils import unroll_block_with_scaling
|
14
10
|
from qadence.circuit import QuantumCircuit
|
15
11
|
from qadence.engines.differentiable_backend import DifferentiableBackend
|
12
|
+
from qadence.measurements.utils import iterate_pauli_decomposition
|
16
13
|
from qadence.noise import Noise
|
17
|
-
from qadence.operations import H, SDagger, X, Y, Z
|
18
|
-
from qadence.parameters import evaluate
|
19
14
|
from qadence.utils import Endianness
|
20
15
|
|
21
16
|
|
22
|
-
def get_qubit_indices_for_op(pauli_term: tuple, op: PrimitiveBlock | None = None) -> list[int]:
|
23
|
-
"""Get qubit indices for the given op in the Pauli term if any."""
|
24
|
-
indices = []
|
25
|
-
blocks = getattr(pauli_term[0], "blocks", None)
|
26
|
-
if blocks is not None:
|
27
|
-
for block in blocks:
|
28
|
-
if op is None:
|
29
|
-
indices.append(block.qubit_support[0])
|
30
|
-
if isinstance(block, type(op)):
|
31
|
-
indices.append(block.qubit_support[0])
|
32
|
-
else:
|
33
|
-
block = pauli_term[0]
|
34
|
-
if op is None:
|
35
|
-
indices.append(block.qubit_support[0])
|
36
|
-
if isinstance(block, type(op)):
|
37
|
-
indices.append(block.qubit_support[0])
|
38
|
-
return indices
|
39
|
-
|
40
|
-
|
41
|
-
def rotate(circuit: QuantumCircuit, pauli_term: tuple) -> QuantumCircuit:
|
42
|
-
"""Rotate circuit to measurement basis and return the qubit support."""
|
43
|
-
rotations = []
|
44
|
-
|
45
|
-
# Mypy expects concrete types. Although there definitely should be
|
46
|
-
# a better way to pass the operation type.
|
47
|
-
for op, gate in [(X(0), Z), (Y(0), SDagger)]:
|
48
|
-
qubit_indices = get_qubit_indices_for_op(pauli_term, op=op)
|
49
|
-
for index in qubit_indices:
|
50
|
-
rotations.append(gate(index) * H(index))
|
51
|
-
rotated_block = chain(circuit.block, *rotations)
|
52
|
-
return QuantumCircuit(circuit.register, rotated_block)
|
53
|
-
|
54
|
-
|
55
|
-
def get_counts(samples: list, support: list) -> list:
|
56
|
-
"""Marginalise the probablity mass function to the support."""
|
57
|
-
counts = []
|
58
|
-
for sample in samples:
|
59
|
-
sample_counts = []
|
60
|
-
for k, v in sample.items():
|
61
|
-
sample_counts.append(Counter({"".join([k[i] for i in support]): sample[k]}))
|
62
|
-
reduced_counts = reduce(lambda x, y: x + y, sample_counts)
|
63
|
-
counts.append(reduced_counts)
|
64
|
-
return counts
|
65
|
-
|
66
|
-
|
67
|
-
def empirical_average(samples: list, support: list) -> Tensor:
|
68
|
-
"""Compute the empirical average."""
|
69
|
-
counters = get_counts(samples, support)
|
70
|
-
expectations = []
|
71
|
-
n_shots = np.sum(list(counters[0].values()))
|
72
|
-
parity = -1
|
73
|
-
for counter in counters:
|
74
|
-
counter_exps = []
|
75
|
-
for bitstring, count in counter.items():
|
76
|
-
counter_exps.append(count * parity ** (np.sum([int(bit) for bit in bitstring])))
|
77
|
-
expectations.append(np.sum(counter_exps) / n_shots)
|
78
|
-
return torch.tensor(expectations)
|
79
|
-
|
80
|
-
|
81
|
-
def iterate_pauli_decomposition(
|
82
|
-
circuit: QuantumCircuit,
|
83
|
-
param_values: dict,
|
84
|
-
pauli_decomposition: list,
|
85
|
-
n_shots: int,
|
86
|
-
state: Tensor | None = None,
|
87
|
-
backend: Backend | DifferentiableBackend = PyQBackend(),
|
88
|
-
noise: Noise | None = None,
|
89
|
-
endianness: Endianness = Endianness.BIG,
|
90
|
-
) -> Tensor:
|
91
|
-
"""Estimate total expectation value by averaging all Pauli terms."""
|
92
|
-
|
93
|
-
estimated_values = []
|
94
|
-
|
95
|
-
for pauli_term in pauli_decomposition:
|
96
|
-
if pauli_term[0].is_identity:
|
97
|
-
estimated_values.append(evaluate(pauli_term[1], as_torch=True))
|
98
|
-
else:
|
99
|
-
# Get the full qubit support for the Pauli term.
|
100
|
-
# Note: duplicates must be kept here to allow for
|
101
|
-
# observables chaining multiple operations on the same qubit
|
102
|
-
# such as `b = chain(Z(0), Z(0))`
|
103
|
-
support = get_qubit_indices_for_op(pauli_term)
|
104
|
-
# Rotate the circuit according to the given observable term.
|
105
|
-
rotated_circuit = rotate(circuit=circuit, pauli_term=pauli_term)
|
106
|
-
# Use the low-level backend API to avoid embedding of parameters
|
107
|
-
# already performed at the higher QuantumModel level.
|
108
|
-
# Therefore, parameters passed here have already been embedded.
|
109
|
-
conv_circ = backend.circuit(rotated_circuit)
|
110
|
-
samples = backend.sample(
|
111
|
-
circuit=conv_circ,
|
112
|
-
param_values=param_values,
|
113
|
-
n_shots=n_shots,
|
114
|
-
state=state,
|
115
|
-
noise=noise,
|
116
|
-
endianness=endianness,
|
117
|
-
)
|
118
|
-
estim_values = empirical_average(samples=samples, support=support)
|
119
|
-
# TODO: support for parametric observables to be tested
|
120
|
-
estimated_values.append(estim_values * evaluate(pauli_term[1]))
|
121
|
-
res = torch.sum(torch.stack(estimated_values), axis=0)
|
122
|
-
# Allow for automatic differentiation.
|
123
|
-
res.requires_grad = True
|
124
|
-
return res
|
125
|
-
|
126
|
-
|
127
17
|
def compute_expectation(
|
128
18
|
circuit: QuantumCircuit,
|
129
19
|
observables: list[AbstractBlock],
|
@@ -0,0 +1,180 @@
|
|
1
|
+
from __future__ import annotations
|
2
|
+
|
3
|
+
from collections import Counter
|
4
|
+
from functools import reduce
|
5
|
+
from typing import Dict, List, Tuple
|
6
|
+
|
7
|
+
import numpy as np
|
8
|
+
import torch
|
9
|
+
from sympy import Basic
|
10
|
+
from torch import Tensor
|
11
|
+
|
12
|
+
from qadence.backend import Backend
|
13
|
+
from qadence.backends.pyqtorch import Backend as PyQBackend
|
14
|
+
from qadence.blocks import AbstractBlock, PrimitiveBlock, chain
|
15
|
+
from qadence.circuit import QuantumCircuit
|
16
|
+
from qadence.engines.differentiable_backend import DifferentiableBackend
|
17
|
+
from qadence.noise import Noise
|
18
|
+
from qadence.operations import H, SDagger, X, Y, Z
|
19
|
+
from qadence.parameters import evaluate
|
20
|
+
from qadence.utils import Endianness
|
21
|
+
|
22
|
+
|
23
|
+
def get_qubit_indices_for_op(
|
24
|
+
pauli_term: Tuple[AbstractBlock, Basic], op: PrimitiveBlock | None = None
|
25
|
+
) -> List[int]:
|
26
|
+
"""Get qubit indices for the given op in the Pauli term if any.
|
27
|
+
|
28
|
+
Args:
|
29
|
+
pauli_term: Tuple of a Pauli block and a parameter.
|
30
|
+
op: Tuple of Primitive blocks or None.
|
31
|
+
|
32
|
+
Returns: A list of integers representing qubit indices.
|
33
|
+
"""
|
34
|
+
blocks = getattr(pauli_term[0], "blocks", None)
|
35
|
+
blocks = blocks if blocks is not None else [pauli_term[0]]
|
36
|
+
indices = [
|
37
|
+
block.qubit_support[0] for block in blocks if (op is None) or (isinstance(block, type(op)))
|
38
|
+
]
|
39
|
+
return indices
|
40
|
+
|
41
|
+
|
42
|
+
def get_counts(samples: List, support: List[int]) -> List[Counter]:
|
43
|
+
"""Marginalise the probability mass function to the support.
|
44
|
+
|
45
|
+
Args:
|
46
|
+
samples: List of samples against which expectation value is to be computed.
|
47
|
+
support: A list of integers representing qubit indices.
|
48
|
+
|
49
|
+
Returns: A List[Counter] of bit strings.
|
50
|
+
"""
|
51
|
+
return [
|
52
|
+
reduce(
|
53
|
+
lambda x, y: x + y,
|
54
|
+
[Counter({"".join([k[i] for i in support]): sample[k]}) for k, v in sample.items()],
|
55
|
+
)
|
56
|
+
for sample in samples
|
57
|
+
]
|
58
|
+
|
59
|
+
|
60
|
+
def empirical_average(samples: List, support: List[int]) -> Tensor:
|
61
|
+
"""Compute the empirical average.
|
62
|
+
|
63
|
+
Args:
|
64
|
+
samples: List of samples against which expectation value is to be computed.
|
65
|
+
support: A list of integers representing qubit indices.
|
66
|
+
|
67
|
+
Returns: A torch.Tensor of the empirical average.
|
68
|
+
"""
|
69
|
+
PARITY = -1
|
70
|
+
counters = get_counts(samples, support)
|
71
|
+
n_shots = np.sum(list(counters[0].values()))
|
72
|
+
expectations = []
|
73
|
+
for counter in counters:
|
74
|
+
counter_exps = []
|
75
|
+
for bitstring, count in counter.items():
|
76
|
+
counter_exps.append(count * PARITY ** (np.sum([int(bit) for bit in bitstring])))
|
77
|
+
expectations.append(np.sum(counter_exps) / n_shots)
|
78
|
+
return torch.tensor(expectations)
|
79
|
+
|
80
|
+
|
81
|
+
def pauli_z_expectation(
|
82
|
+
pauli_decomposition: List[Tuple[AbstractBlock, Basic]],
|
83
|
+
samples: List[Counter],
|
84
|
+
) -> Tensor:
|
85
|
+
"""Estimate total expectation value from samples by averaging all Pauli terms.
|
86
|
+
|
87
|
+
Args:
|
88
|
+
pauli_decomposition: A list of Pauli decomposed terms.
|
89
|
+
samples: Samples of bit string as Counters.
|
90
|
+
|
91
|
+
Returns: A torch.Tensor of the total expectation.
|
92
|
+
"""
|
93
|
+
|
94
|
+
estimated_values = []
|
95
|
+
for pauli_term in pauli_decomposition:
|
96
|
+
support = get_qubit_indices_for_op(pauli_term)
|
97
|
+
estim_values = empirical_average(samples=samples, support=support)
|
98
|
+
# TODO: support for parametric observables to be tested
|
99
|
+
estimated_values.append(estim_values * evaluate(pauli_term[1]))
|
100
|
+
res = torch.sum(torch.stack(estimated_values), axis=0)
|
101
|
+
return res
|
102
|
+
|
103
|
+
|
104
|
+
def rotate(circuit: QuantumCircuit, pauli_term: Tuple[AbstractBlock, Basic]) -> QuantumCircuit:
|
105
|
+
"""Rotate circuit to measurement basis and return the qubit support.
|
106
|
+
|
107
|
+
Args:
|
108
|
+
circuit: The circuit that is executed.
|
109
|
+
pauli_term: Tuple of a Pauli term and a parameter.
|
110
|
+
|
111
|
+
Returns: Rotated QuantumCircuit.
|
112
|
+
"""
|
113
|
+
|
114
|
+
rotations = []
|
115
|
+
|
116
|
+
for op, gate in [(X(0), Z), (Y(0), SDagger)]:
|
117
|
+
qubit_indices = get_qubit_indices_for_op(pauli_term, op=op)
|
118
|
+
for index in qubit_indices:
|
119
|
+
rotations.append(gate(index) * H(index))
|
120
|
+
rotated_block = chain(circuit.block, *rotations)
|
121
|
+
return QuantumCircuit(circuit.register, rotated_block)
|
122
|
+
|
123
|
+
|
124
|
+
def iterate_pauli_decomposition(
|
125
|
+
circuit: QuantumCircuit,
|
126
|
+
param_values: Dict[str, Tensor],
|
127
|
+
pauli_decomposition: List[Tuple[AbstractBlock, Basic]],
|
128
|
+
n_shots: int,
|
129
|
+
state: Tensor | None = None,
|
130
|
+
backend: Backend | DifferentiableBackend = PyQBackend(),
|
131
|
+
noise: Noise | None = None,
|
132
|
+
endianness: Endianness = Endianness.BIG,
|
133
|
+
) -> Tensor:
|
134
|
+
"""Estimate total expectation value by averaging all Pauli terms.
|
135
|
+
|
136
|
+
Args:
|
137
|
+
circuit: The circuit that is executed.
|
138
|
+
param_values: Parameters of the circuit.
|
139
|
+
pauli_decomposition: A list of Pauli decomposed terms.
|
140
|
+
n_shots: Number of shots to sample.
|
141
|
+
state: Initial state.
|
142
|
+
backend: A backend for circuit execution.
|
143
|
+
noise: A noise model to use.
|
144
|
+
endianness: Endianness of the resulting bit strings.
|
145
|
+
|
146
|
+
Returns: A torch.Tensor of bit strings n_shots x n_qubits.
|
147
|
+
"""
|
148
|
+
|
149
|
+
estimated_values = []
|
150
|
+
|
151
|
+
for pauli_term in pauli_decomposition:
|
152
|
+
if pauli_term[0].is_identity:
|
153
|
+
estimated_values.append(evaluate(pauli_term[1], as_torch=True))
|
154
|
+
else:
|
155
|
+
# Get the full qubit support for the Pauli term.
|
156
|
+
# Note: duplicates must be kept here to allow for
|
157
|
+
# observables chaining multiple operations on the same qubit
|
158
|
+
# such as `b = chain(Z(0), Z(0))`
|
159
|
+
support = get_qubit_indices_for_op(pauli_term)
|
160
|
+
# Rotate the circuit according to the given observable term.
|
161
|
+
rotated_circuit = rotate(circuit=circuit, pauli_term=pauli_term)
|
162
|
+
# Use the low-level backend API to avoid embedding of parameters
|
163
|
+
# already performed at the higher QuantumModel level.
|
164
|
+
# Therefore, parameters passed here have already been embedded.
|
165
|
+
conv_circ = backend.circuit(rotated_circuit)
|
166
|
+
samples = backend.sample(
|
167
|
+
circuit=conv_circ,
|
168
|
+
param_values=param_values,
|
169
|
+
n_shots=n_shots,
|
170
|
+
state=state,
|
171
|
+
noise=noise,
|
172
|
+
endianness=endianness,
|
173
|
+
)
|
174
|
+
estim_values = empirical_average(samples=samples, support=support)
|
175
|
+
# TODO: support for parametric observables to be tested
|
176
|
+
estimated_values.append(estim_values * evaluate(pauli_term[1]))
|
177
|
+
res = torch.sum(torch.stack(estimated_values), axis=0)
|
178
|
+
# Allow for automatic differentiation.
|
179
|
+
res.requires_grad = True
|
180
|
+
return res
|
qadence/ml_tools/data.py
CHANGED
@@ -82,34 +82,34 @@ def to_dataloader(*tensors: Tensor, batch_size: int = 1, infinite: bool = False)
|
|
82
82
|
|
83
83
|
|
84
84
|
@singledispatch
|
85
|
-
def data_to_device(xs: Any,
|
85
|
+
def data_to_device(xs: Any, *args: Any, **kwargs: Any) -> Any:
|
86
86
|
"""Utility method to move arbitrary data to 'device'."""
|
87
|
-
raise ValueError(f"
|
87
|
+
raise ValueError(f"Unable to move {type(xs)} with input args: {args} and kwargs: {kwargs}.")
|
88
88
|
|
89
89
|
|
90
90
|
@data_to_device.register
|
91
|
-
def _(xs: None,
|
91
|
+
def _(xs: None, *args: Any, **kwargs: Any) -> None:
|
92
92
|
return xs
|
93
93
|
|
94
94
|
|
95
95
|
@data_to_device.register(Tensor)
|
96
|
-
def _(xs: Tensor,
|
97
|
-
return xs.to(
|
96
|
+
def _(xs: Tensor, *args: Any, **kwargs: Any) -> Tensor:
|
97
|
+
return xs.to(*args, **kwargs)
|
98
98
|
|
99
99
|
|
100
100
|
@data_to_device.register(list)
|
101
|
-
def _(xs: list,
|
102
|
-
return [data_to_device(x,
|
101
|
+
def _(xs: list, *args: Any, **kwargs: Any) -> list:
|
102
|
+
return [data_to_device(x, *args, **kwargs) for x in xs]
|
103
103
|
|
104
104
|
|
105
105
|
@data_to_device.register(dict)
|
106
|
-
def _(xs: dict,
|
107
|
-
return {key: data_to_device(val,
|
106
|
+
def _(xs: dict, *args: Any, **kwargs: Any) -> dict:
|
107
|
+
return {key: data_to_device(val, *args, **kwargs) for key, val in xs.items()}
|
108
108
|
|
109
109
|
|
110
110
|
@data_to_device.register(DataLoader)
|
111
|
-
def _(xs: DataLoader,
|
112
|
-
return DataLoader(data_to_device(xs.dataset,
|
111
|
+
def _(xs: DataLoader, *args: Any, **kwargs: Any) -> DataLoader:
|
112
|
+
return DataLoader(data_to_device(xs.dataset, *args, **kwargs))
|
113
113
|
|
114
114
|
|
115
115
|
@data_to_device.register(DictDataLoader)
|
qadence/ml_tools/models.py
CHANGED
@@ -286,15 +286,15 @@ class TransformedModule(torch.nn.Module):
|
|
286
286
|
output_shifting=torch.tensor(d["_output_shifting"]),
|
287
287
|
)
|
288
288
|
|
289
|
-
def to(self,
|
289
|
+
def to(self, *args: Any, **kwargs: Any) -> TransformedModule:
|
290
290
|
try:
|
291
|
-
self.model = self.model.to(
|
292
|
-
self._input_scaling = self._input_scaling.to(
|
293
|
-
self._input_shifting = self._input_shifting.to(
|
294
|
-
self._output_scaling = self._output_scaling.to(
|
295
|
-
self._output_shifting = self._output_shifting.to(
|
291
|
+
self.model = self.model.to(*args, **kwargs)
|
292
|
+
self._input_scaling = self._input_scaling.to(*args, **kwargs)
|
293
|
+
self._input_shifting = self._input_shifting.to(*args, **kwargs)
|
294
|
+
self._output_scaling = self._output_scaling.to(*args, **kwargs)
|
295
|
+
self._output_shifting = self._output_shifting.to(*args, **kwargs)
|
296
296
|
|
297
|
-
logger.debug(f"Moved {self} to
|
297
|
+
logger.debug(f"Moved {self} to {args}, {kwargs}.")
|
298
298
|
except Exception as e:
|
299
|
-
logger.warning(f"Unable to move {self} to
|
299
|
+
logger.warning(f"Unable to move {self} to {args}, {kwargs} due to {e}.")
|
300
300
|
return self
|
@@ -15,6 +15,7 @@ def optimize_step(
|
|
15
15
|
loss_fn: Callable,
|
16
16
|
xs: dict | list | torch.Tensor | None,
|
17
17
|
device: torch.device = None,
|
18
|
+
dtype: torch.dtype = None,
|
18
19
|
) -> tuple[torch.Tensor | float, dict | None]:
|
19
20
|
"""Default Torch optimize step with closure.
|
20
21
|
|
@@ -35,7 +36,7 @@ def optimize_step(
|
|
35
36
|
"""
|
36
37
|
|
37
38
|
loss, metrics = None, {}
|
38
|
-
xs_to_device = data_to_device(xs, device)
|
39
|
+
xs_to_device = data_to_device(xs, device=device, dtype=dtype)
|
39
40
|
|
40
41
|
def closure() -> Any:
|
41
42
|
# NOTE: We need the nonlocal as we can't return a metric dict and
|
qadence/ml_tools/train_grad.py
CHANGED
@@ -4,6 +4,7 @@ from typing import Callable, Union
|
|
4
4
|
|
5
5
|
from rich.progress import BarColumn, Progress, TaskProgressColumn, TextColumn, TimeRemainingColumn
|
6
6
|
from torch import device as torch_device
|
7
|
+
from torch import dtype as torch_dtype
|
7
8
|
from torch.nn import DataParallel, Module
|
8
9
|
from torch.optim import Optimizer
|
9
10
|
from torch.utils.data import DataLoader
|
@@ -28,6 +29,7 @@ def train(
|
|
28
29
|
device: torch_device = None,
|
29
30
|
optimize_step: Callable = optimize_step,
|
30
31
|
write_tensorboard: Callable = write_tensorboard,
|
32
|
+
dtype: torch_dtype = None,
|
31
33
|
) -> tuple[Module, Optimizer]:
|
32
34
|
"""Runs the training loop with gradient-based optimizer.
|
33
35
|
|
@@ -111,9 +113,9 @@ def train(
|
|
111
113
|
|
112
114
|
# Move model to device before optimizer is loaded
|
113
115
|
if isinstance(model, DataParallel):
|
114
|
-
model = model.module.to(device)
|
116
|
+
model = model.module.to(device=device, dtype=dtype)
|
115
117
|
else:
|
116
|
-
model = model.to(device)
|
118
|
+
model = model.to(device=device, dtype=dtype)
|
117
119
|
# load available checkpoint
|
118
120
|
init_iter = 0
|
119
121
|
if config.folder:
|
qadence/models/quantum_model.py
CHANGED
@@ -341,19 +341,24 @@ class QuantumModel(nn.Module):
|
|
341
341
|
params = self.embedding_fn(self._params, values)
|
342
342
|
return self.backend.assign_parameters(self._circuit, params)
|
343
343
|
|
344
|
-
def to(self,
|
344
|
+
def to(self, *args: Any, **kwargs: Any) -> QuantumModel:
|
345
345
|
try:
|
346
346
|
if isinstance(self._circuit.native, torch.nn.Module):
|
347
347
|
# Backends which are not torch-based cannot be moved to 'device'
|
348
|
-
self.
|
349
|
-
self._circuit.native = self._circuit.native.to(device)
|
348
|
+
self._circuit.native = self._circuit.native.to(*args, **kwargs)
|
350
349
|
if self._observable is not None:
|
351
350
|
if isinstance(self._observable, ConvertedObservable):
|
352
|
-
self._observable.native = self._observable.native.to(
|
351
|
+
self._observable.native = self._observable.native.to(*args, **kwargs)
|
353
352
|
elif isinstance(self._observable, list):
|
354
353
|
for obs in self._observable:
|
355
|
-
obs.native = obs.native.to(
|
356
|
-
|
354
|
+
obs.native = obs.native.to(*args, **kwargs)
|
355
|
+
self._params = self._params.to(
|
356
|
+
device=self._circuit.native.device,
|
357
|
+
dtype=torch.float64
|
358
|
+
if self._circuit.native.dtype == torch.cdouble
|
359
|
+
else torch.float32,
|
360
|
+
)
|
361
|
+
logger.debug(f"Moved {self} to {args}, {kwargs}.")
|
357
362
|
except Exception as e:
|
358
|
-
logger.warning(f"Unable to move {self} to
|
363
|
+
logger.warning(f"Unable to move {self} to {args}, {kwargs} due to {e}.")
|
359
364
|
return self
|
qadence/operations/analog.py
CHANGED
@@ -1,6 +1,6 @@
|
|
1
|
-
Metadata-Version: 2.
|
1
|
+
Metadata-Version: 2.3
|
2
2
|
Name: qadence
|
3
|
-
Version: 1.
|
3
|
+
Version: 1.5.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>
|
6
6
|
License: Apache 2.0
|
@@ -13,14 +13,14 @@ Classifier: Programming Language :: Python :: 3.10
|
|
13
13
|
Classifier: Programming Language :: Python :: 3.11
|
14
14
|
Classifier: Programming Language :: Python :: Implementation :: CPython
|
15
15
|
Classifier: Programming Language :: Python :: Implementation :: PyPy
|
16
|
-
Requires-Python: <3.
|
16
|
+
Requires-Python: <3.13,>=3.9
|
17
17
|
Requires-Dist: deepdiff
|
18
18
|
Requires-Dist: jsonschema
|
19
19
|
Requires-Dist: matplotlib
|
20
20
|
Requires-Dist: nevergrad
|
21
21
|
Requires-Dist: numpy
|
22
22
|
Requires-Dist: openfermion
|
23
|
-
Requires-Dist: pyqtorch==1.0
|
23
|
+
Requires-Dist: pyqtorch==1.1.0
|
24
24
|
Requires-Dist: rich
|
25
25
|
Requires-Dist: scipy
|
26
26
|
Requires-Dist: sympytorch>=0.1.2
|
@@ -29,10 +29,11 @@ Requires-Dist: torch
|
|
29
29
|
Provides-Extra: all
|
30
30
|
Requires-Dist: amazon-braket-sdk; extra == 'all'
|
31
31
|
Requires-Dist: graphviz; extra == 'all'
|
32
|
+
Requires-Dist: libs; extra == 'all'
|
32
33
|
Requires-Dist: protocols; extra == 'all'
|
33
34
|
Requires-Dist: pulser>=0.15.2; extra == 'all'
|
34
35
|
Provides-Extra: braket
|
35
|
-
Requires-Dist: amazon-braket-sdk; extra == 'braket'
|
36
|
+
Requires-Dist: amazon-braket-sdk==1.71.0; extra == 'braket'
|
36
37
|
Provides-Extra: horqrux
|
37
38
|
Requires-Dist: einops; extra == 'horqrux'
|
38
39
|
Requires-Dist: flax; extra == 'horqrux'
|
@@ -41,6 +42,8 @@ Requires-Dist: jax; extra == 'horqrux'
|
|
41
42
|
Requires-Dist: jaxopt; extra == 'horqrux'
|
42
43
|
Requires-Dist: optax; extra == 'horqrux'
|
43
44
|
Requires-Dist: sympy2jax; extra == 'horqrux'
|
45
|
+
Provides-Extra: libs
|
46
|
+
Requires-Dist: qadence-libs; extra == 'libs'
|
44
47
|
Provides-Extra: protocols
|
45
48
|
Requires-Dist: qadence-protocols; extra == 'protocols'
|
46
49
|
Provides-Extra: pulser
|
@@ -51,13 +54,15 @@ Requires-Dist: graphviz; extra == 'visualization'
|
|
51
54
|
Description-Content-Type: text/markdown
|
52
55
|
|
53
56
|
<picture>
|
54
|
-
<source media="(prefers-color-scheme: dark)" srcset="./docs/logo/qadence_logo_white.svg">
|
55
|
-
<source media="(prefers-color-scheme: light)" srcset="./docs/logo/qadence_logo.svg">
|
56
|
-
<img alt="Qadence logo" src="./docs/logo/qadence_logo.svg">
|
57
|
+
<source media="(prefers-color-scheme: dark)" srcset="./docs/assets/logo/qadence_logo_white.svg">
|
58
|
+
<source media="(prefers-color-scheme: light)" srcset="./docs/assets/logo/qadence_logo.svg">
|
59
|
+
<img alt="Qadence logo" src="./docs/assets/logo/qadence_logo.svg">
|
57
60
|
</picture>
|
58
61
|
|
59
62
|
**For a high-level overview of Qadence features, [check out our white paper](https://arxiv.org/abs/2401.09915).**
|
60
63
|
|
64
|
+
**For more detailed information, [check out the documentation](https://pasqal-io.github.io/qadence/latest/).**
|
65
|
+
|
61
66
|
**Qadence** is a Python package that provides a simple interface to build _**digital-analog quantum
|
62
67
|
programs**_ with tunable qubit interaction defined on _**arbitrary register topologies**_ realizable on neutral atom devices.
|
63
68
|
|
@@ -69,6 +74,13 @@ programs**_ with tunable qubit interaction defined on _**arbitrary register topo
|
|
69
74
|
|
70
75
|
## Feature highlights
|
71
76
|
|
77
|
+
<picture>
|
78
|
+
<source media="(prefers-color-scheme: dark)" srcset="./docs/assets/qadence_arch.svg">
|
79
|
+
<source media="(prefers-color-scheme: light)" srcset="./docs/assets/qadence_arch.svg">
|
80
|
+
<img alt="Qadence architecture" src="./docs/assets/qadence_arch.svg">
|
81
|
+
</picture>
|
82
|
+
|
83
|
+
|
72
84
|
* A [block-based system](docs/tutorials/getting_started.md) for composing _**complex digital-analog
|
73
85
|
programs**_ in a flexible and scalable manner, inspired by the Julia quantum SDK
|
74
86
|
[Yao.jl](https://github.com/QuantumBFS/Yao.jl) and functional programming concepts.
|
@@ -97,6 +109,8 @@ The default, pre-installed backend for Qadence is [PyQTorch](https://github.com/
|
|
97
109
|
* `pulser`: The [Pulser](https://github.com/pasqal-io/Pulser) backend for composing, simulating and executing pulse sequences for neutral-atom quantum devices.
|
98
110
|
* `braket`: The [Braket](https://github.com/amazon-braket/amazon-braket-sdk-python) backend, an open source library that provides a framework for interacting with quantum computing hardware devices through Amazon Braket.
|
99
111
|
* `visualization`: A visualization library to display quantum circuit diagrams.
|
112
|
+
* `protocols`: A collection of [protocols](https://github.com/pasqal-io/qadence-protocols) for error mitigation in Qadence.
|
113
|
+
* `libs`: A collection of [functionalities](https://github.com/pasqal-io/qadence-libs) for graph machine learning problems build on top of Qadence.
|
100
114
|
|
101
115
|
Qadence also supports a `JAX` engine which is currently supporting the [Horqrux](https://github.com/pasqal-io/horqrux) backend. `horqrux` is currently only available via the [low-level API](examples/backends/low_level/horqrux_backend.py).
|
102
116
|
|
@@ -1,11 +1,12 @@
|
|
1
|
-
qadence/__init__.py,sha256
|
1
|
+
qadence/__init__.py,sha256=-UKQQ_dYiaa7viishl2baAbxS82eS6dAoCnq_CLSmao,1708
|
2
2
|
qadence/backend.py,sha256=5sfXUTRts_13v6lajq1Wvy3u_eOCOeIYnTiaZV_NGFQ,15493
|
3
3
|
qadence/circuit.py,sha256=EGBPRRWlK-mcXaaAhJnp-hxVWQ8NxngGKbvhPqrEeKM,6892
|
4
4
|
qadence/decompose.py,sha256=_L0hI3SbYErXEDp-aXFeNk0JR9ffJ_JD_EnRJbJKT20,5230
|
5
5
|
qadence/divergences.py,sha256=JhpELhWSnuDvQxa9hJp_DE3EQg2Ban-Ta0mHZ_fVrHg,1832
|
6
6
|
qadence/execution.py,sha256=5_P5OSatiwEAu7aAkCLau5VcmtIZiC3VFIj5YYdwAbY,9287
|
7
|
-
qadence/extensions.py,sha256=
|
7
|
+
qadence/extensions.py,sha256=CgaUR3amh80g_zwxGaAjFvgI-JT_pmDiUMzzzVQP7zc,4582
|
8
8
|
qadence/finitediff.py,sha256=TijuaWUbX9VlbLyMYco6HkK9eCoRTVnKug4Ekd6mlTI,1592
|
9
|
+
qadence/libs.py,sha256=HetkKO8TCTlVCViQdVQJvxwBekrhd-y_iMox4UJMY1M,410
|
9
10
|
qadence/logger.py,sha256=mdTr52nL30ipPRwp11nIHKLEoB3hqs7J-Mric5KVfyM,912
|
10
11
|
qadence/overlap.py,sha256=3vsg0HLOO3X8LiVgvjSc5s-cs8Di4TpEA657LWZ5HEY,17294
|
11
12
|
qadence/parameters.py,sha256=svZ3L-Z4pzm2PkPDIlb-DWkwGOQLAm1eECCtu7nd3W0,12334
|
@@ -28,7 +29,7 @@ qadence/backends/adjoint.py,sha256=C2BdLUs2rdV9TiErkVlE0hoeLx_nK7up9mzIO-0vB2g,6
|
|
28
29
|
qadence/backends/api.py,sha256=6PoK4ydhi2tj9w0ePMQl1G4kEFROoWe3lrkrtQwWxkc,3224
|
29
30
|
qadence/backends/gpsr.py,sha256=227h5KPI_KStrwfP5zuwkzOqviRZmqa7ijIIhhawwPM,4341
|
30
31
|
qadence/backends/jax_utils.py,sha256=VfKhqCKknHDWZO21UFipWH_Lkiq175Z5GkP49gWjbyw,5038
|
31
|
-
qadence/backends/utils.py,sha256=
|
32
|
+
qadence/backends/utils.py,sha256=hnV9AXztMvAPcO8mv9UhdGMbS9albiMQBxlYPgLrD68,6490
|
32
33
|
qadence/backends/braket/__init__.py,sha256=eruyDZKMqkh1LE7eJ980vcrLJbia35uUX6krAP78clI,121
|
33
34
|
qadence/backends/braket/backend.py,sha256=PLW-NCNp_RqAQy149ASEOOvwPrLsFGjCKWuEmTnS5Qg,8730
|
34
35
|
qadence/backends/braket/config.py,sha256=b9aIdma0DRwC_3A6xUSLdXMCZe6z6kDcAgkp6MxcXIk,603
|
@@ -38,18 +39,18 @@ qadence/backends/horqrux/backend.py,sha256=qdThkUXbhDrsD1lAio2SFsxdYATxLVXoNsuXN
|
|
38
39
|
qadence/backends/horqrux/config.py,sha256=fPWFag1hmRhqj0T-fJOx5x8_C5UEZUXpdUnpOgX0Jpc,901
|
39
40
|
qadence/backends/horqrux/convert_ops.py,sha256=nzfYF0yjB7zwaHCEXWZUUYDfz38Yi22xF2zDRFaOwR0,8564
|
40
41
|
qadence/backends/pulser/__init__.py,sha256=capQ-eHqwtOeLf4mWsI0BIseAHhiLGie5cFD4-iVhUo,116
|
41
|
-
qadence/backends/pulser/backend.py,sha256=
|
42
|
+
qadence/backends/pulser/backend.py,sha256=3p9cB5QN60nzqhWvdLZol0t66PugaWqvWHdDEXgGRwM,13868
|
42
43
|
qadence/backends/pulser/channels.py,sha256=ZF0yEXUFHAmi3IdeXjzdTNGR5NzaRRFTiUpUGVg2sO4,329
|
43
44
|
qadence/backends/pulser/cloud.py,sha256=0uUluvbFV9sOuCPraE-9uiVtC3Q8QaDY1IJMDi8grDM,2057
|
44
|
-
qadence/backends/pulser/config.py,sha256=
|
45
|
+
qadence/backends/pulser/config.py,sha256=1qu_GhGTGcCpFoKctGt_IhKOKWiMcJIL2vHTFJg9I3E,3122
|
45
46
|
qadence/backends/pulser/convert_ops.py,sha256=0HGWe5kIwI1ZALHf2j68B8aBOhwFNZV-mDy1_6zsF5g,1227
|
46
47
|
qadence/backends/pulser/devices.py,sha256=DermLZNfmCB3SqteKVW4uhg4jp6ya1G6ptnXbBnJogI,2448
|
47
48
|
qadence/backends/pulser/pulses.py,sha256=DopdEZ8eeWK7wZxqJTBhqY0w5bEXu6fVK7rnZOb50ns,11893
|
48
49
|
qadence/backends/pulser/waveforms.py,sha256=0uz95b7rUaUUtN0tuHBZmJ0H6UBmfHST_59ozwsRCzg,2227
|
49
50
|
qadence/backends/pyqtorch/__init__.py,sha256=0OdVy6cq0oQggV48LO1WXdaZuSkDkz7OYNEPIkNAmfk,140
|
50
|
-
qadence/backends/pyqtorch/backend.py,sha256=
|
51
|
+
qadence/backends/pyqtorch/backend.py,sha256=hNo9nKxfJ3rFDEPjZOhfmbKUUVsNzTl0aRh9sgeKlqc,9763
|
51
52
|
qadence/backends/pyqtorch/config.py,sha256=f5BjWehCqm9do2OahNWrv2w55y3orkw0Wj2f6flwRaU,1907
|
52
|
-
qadence/backends/pyqtorch/convert_ops.py,sha256=
|
53
|
+
qadence/backends/pyqtorch/convert_ops.py,sha256=By_p1-Oem8MhHYP8jx5qdut9lhDWN0xc4B9YaP0MSxA,17512
|
53
54
|
qadence/blocks/__init__.py,sha256=H6jEA_CptkE-eoB4UfSbUiDszbxxhZwECV_TgoZWXoU,960
|
54
55
|
qadence/blocks/abstract.py,sha256=35RcVlNvD1BmBoJ8bbYJ3LrdU72wixt9ZmTbCtEwNus,11796
|
55
56
|
qadence/blocks/analog.py,sha256=ymnnlSVoW1XL05ZvnnHCqRTHuOXIEY_7E9M0PNKJZy4,10812
|
@@ -61,8 +62,8 @@ qadence/blocks/matrix.py,sha256=XQI6D4CWhCf3j-hvA0jRKOgprs0RA6su7OythCoH6Ls,3785
|
|
61
62
|
qadence/blocks/primitive.py,sha256=fC5ItpA-52LOiGPT1ERM4RshP6PQlkxlgR9p2J0Rgz4,16631
|
62
63
|
qadence/blocks/utils.py,sha256=lNWNCGpM4q_KilaiSGj1u8XJrilR5PdV92KZHZt6MEQ,16358
|
63
64
|
qadence/constructors/__init__.py,sha256=d4ndrNCTCDS_kUYeigGFQOUFSAMaPKL--_FcdZy7eQo,1152
|
64
|
-
qadence/constructors/ansatze.py,sha256=
|
65
|
-
qadence/constructors/feature_maps.py,sha256=
|
65
|
+
qadence/constructors/ansatze.py,sha256=8JoYvv7nYPgygIZpB227Zx7csPxg8SIR1tnYl0SzAb4,12170
|
66
|
+
qadence/constructors/feature_maps.py,sha256=Z8h_UDpG9wtpt72htZK6c0mV0YNwzSsH4rv2A_vRhNw,11566
|
66
67
|
qadence/constructors/hamiltonians.py,sha256=rEeMkMepQE5xe-siAfhIlgUE2aIGwk8SUdPLNTPHUnU,8860
|
67
68
|
qadence/constructors/iia.py,sha256=z-4AA9Oj-j2oZ0QDkLYNk4duS3UHY_98Qwt9VO_ZDDU,7001
|
68
69
|
qadence/constructors/qft.py,sha256=2LpgQ-z1HUxB3rqHzYsbjqpdU63gyuuaUVCbNEFbjo8,7688
|
@@ -88,37 +89,39 @@ qadence/engines/jax/differentiable_backend.py,sha256=W5rDA8wb-ECnFWoLj4dVugF9v1l
|
|
88
89
|
qadence/engines/jax/differentiable_expectation.py,sha256=XBYHT1XKRuZfKxTcNy8KJpSDPt-2PR4ZCanImCPI9OI,3677
|
89
90
|
qadence/engines/torch/__init__.py,sha256=iZFdD32ot0B0CVyC-f5dVViOBnqoalxa6M9Lj4WQuPE,160
|
90
91
|
qadence/engines/torch/differentiable_backend.py,sha256=AWthwvKE8pCOih4dZ3tXxQX4W1ps9mBcvo7n4V9V24Y,3553
|
91
|
-
qadence/engines/torch/differentiable_expectation.py,sha256=
|
92
|
+
qadence/engines/torch/differentiable_expectation.py,sha256=w_9infZDQRRU7sII8V0aklXrR73IOU0Bjf8C5neJLIY,9161
|
92
93
|
qadence/exceptions/__init__.py,sha256=BU6vWrI9mshzr1aTPm1Ticr_o_42GjTrWI4OZXhThsI,203
|
93
94
|
qadence/exceptions/exceptions.py,sha256=4j_VJpx2sZ2Mir5BJUWu4nwb131FY1ygO4q8-XlyfRc,190
|
94
95
|
qadence/measurements/__init__.py,sha256=RIjG9tVJMqhNzyj7maZI250Um0KgHl2PizDcKJag-JU,161
|
95
|
-
qadence/measurements/protocols.py,sha256=
|
96
|
+
qadence/measurements/protocols.py,sha256=mD50R9yPs5bIYH7Efd0BsR0503apiyrsZydi_Q6BJag,1161
|
97
|
+
qadence/measurements/samples.py,sha256=AVvszDwgfKnZ_ooATyTA3270vGeg1V3WO94jsfrTk-8,1200
|
96
98
|
qadence/measurements/shadow.py,sha256=ROMQFtV9LaUB2Q6pjcBY1qDAYjDUGq1FUFmI8WXTd0g,12550
|
97
|
-
qadence/measurements/tomography.py,sha256=
|
99
|
+
qadence/measurements/tomography.py,sha256=8fzXhYOu_DaMiUoZzLvpP03WhuwlZ3ldkWepLUHjWqM,2665
|
100
|
+
qadence/measurements/utils.py,sha256=CJmnSobzdeR4T4FuEpad7d-BSJ9W-wTaU9hRbveB6kY,6534
|
98
101
|
qadence/mitigations/__init__.py,sha256=RzaxYJftePFMloGhBVSixZ8fSe-ps_Jc-EyPm6xz-bs,159
|
99
102
|
qadence/mitigations/analog_zne.py,sha256=g0QkjSdF-N9Dv2N8Oza4sylnjUMid5ea-4NCT9Tcm3Y,7768
|
100
103
|
qadence/mitigations/protocols.py,sha256=Jq9MyLujfTyWmc7XVUGYVRUkJT1MmZw-GgmWpVjmX2Y,1608
|
101
104
|
qadence/mitigations/readout.py,sha256=HPfYmdjRlieUdOBMZTghFK4DRWfveM4KkDkEI0bMI0E,6262
|
102
105
|
qadence/ml_tools/__init__.py,sha256=_H5A_BWZRZVGoJszb9s8XRJnLnJxUNfYjuT9HT2yASo,786
|
103
106
|
qadence/ml_tools/config.py,sha256=X8dHyjq4D9-ITjs7UQo0vjJTcHkpbZC0gChH5eEN2G8,2356
|
104
|
-
qadence/ml_tools/data.py,sha256=
|
105
|
-
qadence/ml_tools/models.py,sha256=
|
106
|
-
qadence/ml_tools/optimize_step.py,sha256=
|
107
|
+
qadence/ml_tools/data.py,sha256=8ZUFjhQSp94w7icX7RzM2J39Yo7P_T-AgjcThBc8miI,4283
|
108
|
+
qadence/ml_tools/models.py,sha256=biUWnqXKmGMJfT-QObJ-cQ6770YIfOTz-o28EKPkM3Q,11736
|
109
|
+
qadence/ml_tools/optimize_step.py,sha256=ATXWmAqybJVK3QmAaDqVXB5mxjTo2MIi_e0a5WSPFpc,1800
|
107
110
|
qadence/ml_tools/parameters.py,sha256=gew2Kq_5-RgRpaTvs8eauVhgo0sTqqDQEV6WHFEiLGM,1301
|
108
111
|
qadence/ml_tools/printing.py,sha256=kwwD9yLVqezaqWX5OAsXr8GLdJUnGrY-t5SnoKHtl9g,707
|
109
112
|
qadence/ml_tools/saveload.py,sha256=Xi3o2bMsYueFPxrU6AXgDB0MHSev8gKLVhdqecPDBt8,4663
|
110
113
|
qadence/ml_tools/tensors.py,sha256=xZ9ZRzOqEaMgLUGWQf1najDmL6iLuN1ojCGVFs1Tm94,1337
|
111
|
-
qadence/ml_tools/train_grad.py,sha256=
|
114
|
+
qadence/ml_tools/train_grad.py,sha256=b_FxOkK3QoLAOwSowjkkMIjlBEDjoLcjeo3Vk_RHhkc,7399
|
112
115
|
qadence/ml_tools/train_no_grad.py,sha256=erwus-pUOg8q6WgoQsDW6MeH80wlRPBh69W1ZMHKoL8,4714
|
113
116
|
qadence/ml_tools/utils.py,sha256=_GZSN5Flk1nRFutkXih397Q3cWKdX0UP8c9CRXpUL7c,1654
|
114
117
|
qadence/models/__init__.py,sha256=0nZzAC2TGr8Yuf40-R7m2cSsr_BlNq_GsMOwaOYZLqM,193
|
115
118
|
qadence/models/qnn.py,sha256=gc_iC1GG6WJbeLaln9jy4yYp9fY0p8fkpKkKJpXJ3ck,10397
|
116
|
-
qadence/models/quantum_model.py,sha256=
|
119
|
+
qadence/models/quantum_model.py,sha256=ucExUBPBYWrC7mLF4SQbvHqjdXmkEi7-wIdXqpfaGew,14107
|
117
120
|
qadence/noise/__init__.py,sha256=r0nR8uEZeB1M9pI2UisjWq0bjw50fPFfVGzIMev923g,147
|
118
121
|
qadence/noise/protocols.py,sha256=-aZ06JvMnpxCeT5v5lI_RNPOLbb9Ju1Pi1AB6uAXxVE,1653
|
119
122
|
qadence/noise/readout.py,sha256=BqBIZbPXWqZaKi6EpBSpXXQ9NhQXdQ-YL6ZmwbSjgfE,6736
|
120
123
|
qadence/operations/__init__.py,sha256=6D2yNOJ78BgFBZpHpHYMUDzU2R1HovB-mwGgNq-Uwwk,1944
|
121
|
-
qadence/operations/analog.py,sha256=
|
124
|
+
qadence/operations/analog.py,sha256=FkwAtsL7M6EPk5_shCXqHXzJDr0MY3_mA9R5LbZKu8w,7782
|
122
125
|
qadence/operations/control_ops.py,sha256=6PVTFELkbvfvgczPbKw0QDin_CpDFzganIdJFaQJHjY,9492
|
123
126
|
qadence/operations/ham_evo.py,sha256=EhBz5ZgoWsP4PhR8DLvTdje8bl17oEBipBdSkpCTWV4,7400
|
124
127
|
qadence/operations/parametric.py,sha256=RVRTlKOd2_bKXwNorO3TYhZ88AFaEgGkxKYKzT_RuIA,4919
|
@@ -131,7 +134,7 @@ qadence/transpile/digitalize.py,sha256=iWRwYAYQsD2INHj0HNbGJriv_3fRCuBW1nDBrwtKS
|
|
131
134
|
qadence/transpile/flatten.py,sha256=EdhSG5WyF56nbnxINNLqrHgY84MRM1YFjT3fR4aph5Q,3427
|
132
135
|
qadence/transpile/invert.py,sha256=KAefHTG2AWr39aengVhXrzCtJPhrZC-ZnL6vYvmbnY0,4867
|
133
136
|
qadence/transpile/transpile.py,sha256=6MRRkk1OS279L1fwUQjazA6qlfpbd-T_EJMKT8hAhOU,2721
|
134
|
-
qadence-1.
|
135
|
-
qadence-1.
|
136
|
-
qadence-1.
|
137
|
-
qadence-1.
|
137
|
+
qadence-1.5.0.dist-info/METADATA,sha256=NgAwZRUkuLfgnTuo46gGAW1Pj8EmPCAvvPr3FbPi1Ww,8997
|
138
|
+
qadence-1.5.0.dist-info/WHEEL,sha256=uNdcs2TADwSd5pVaP0Z_kcjcvvTUklh2S7bxZMF8Uj0,87
|
139
|
+
qadence-1.5.0.dist-info/licenses/LICENSE,sha256=z8d0m5b2O9McPEK1xHG_dWgUBT6EfBDz6wA0F7xSPTA,11358
|
140
|
+
qadence-1.5.0.dist-info/RECORD,,
|
File without changes
|