qadence 1.6.2__py3-none-any.whl → 1.7.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 +2 -2
- qadence/backends/gpsr.py +15 -3
- qadence/backends/pyqtorch/backend.py +28 -43
- qadence/backends/pyqtorch/convert_ops.py +44 -227
- qadence/backends/utils.py +45 -4
- qadence/blocks/matrix.py +2 -2
- qadence/blocks/primitive.py +1 -1
- qadence/constructors/__init__.py +2 -0
- qadence/constructors/hamiltonians.py +38 -1
- qadence/draw/utils.py +1 -1
- qadence/engines/torch/differentiable_expectation.py +1 -1
- qadence/ml_tools/__init__.py +11 -3
- qadence/ml_tools/config.py +277 -2
- qadence/ml_tools/constructors.py +774 -0
- qadence/ml_tools/models.py +338 -250
- qadence/ml_tools/saveload.py +6 -6
- qadence/ml_tools/train_grad.py +3 -7
- qadence/ml_tools/utils.py +2 -8
- qadence/{models/quantum_model.py → model.py} +14 -8
- qadence/overlap.py +1 -1
- qadence/serialization.py +6 -6
- qadence/types.py +42 -0
- {qadence-1.6.2.dist-info → qadence-1.7.0.dist-info}/METADATA +14 -3
- {qadence-1.6.2.dist-info → qadence-1.7.0.dist-info}/RECORD +26 -29
- qadence/backends/adjoint.py +0 -163
- qadence/finitediff.py +0 -47
- qadence/models/__init__.py +0 -7
- qadence/models/qnn.py +0 -265
- {qadence-1.6.2.dist-info → qadence-1.7.0.dist-info}/WHEEL +0 -0
- {qadence-1.6.2.dist-info → qadence-1.7.0.dist-info}/licenses/LICENSE +0 -0
qadence/ml_tools/saveload.py
CHANGED
@@ -55,8 +55,9 @@ def load_checkpoint(
|
|
55
55
|
def write_checkpoint(
|
56
56
|
folder: Path, model: Module, optimizer: Optimizer | NGOptimizer, iteration: int | str
|
57
57
|
) -> None:
|
58
|
-
from qadence
|
59
|
-
|
58
|
+
from qadence import QuantumModel
|
59
|
+
|
60
|
+
from .models import QNN
|
60
61
|
|
61
62
|
device = None
|
62
63
|
try:
|
@@ -81,7 +82,7 @@ def write_checkpoint(
|
|
81
82
|
try:
|
82
83
|
d = (
|
83
84
|
model._to_dict(save_params=True)
|
84
|
-
if isinstance(model, (QNN, QuantumModel))
|
85
|
+
if isinstance(model, (QNN, QuantumModel))
|
85
86
|
else model.state_dict()
|
86
87
|
)
|
87
88
|
torch.save((iteration, d), folder / model_checkpoint_name)
|
@@ -103,8 +104,7 @@ def write_checkpoint(
|
|
103
104
|
def load_model(
|
104
105
|
folder: Path, model: Module, model_ckpt_name: str | Path = "", *args: Any, **kwargs: Any
|
105
106
|
) -> tuple[Module, int]:
|
106
|
-
from qadence
|
107
|
-
from qadence.models import QNN, QuantumModel
|
107
|
+
from qadence import QNN, QuantumModel
|
108
108
|
|
109
109
|
iteration = 0
|
110
110
|
if model_ckpt_name == "":
|
@@ -112,7 +112,7 @@ def load_model(
|
|
112
112
|
|
113
113
|
try:
|
114
114
|
iteration, model_dict = torch.load(folder / model_ckpt_name, *args, **kwargs)
|
115
|
-
if isinstance(model, (QuantumModel, QNN
|
115
|
+
if isinstance(model, (QuantumModel, QNN)):
|
116
116
|
model._from_dict(model_dict, as_torch=True)
|
117
117
|
elif isinstance(model, Module):
|
118
118
|
model.load_state_dict(model_dict, strict=True)
|
qadence/ml_tools/train_grad.py
CHANGED
@@ -52,16 +52,12 @@ def train(
|
|
52
52
|
device: String defining device to train on, pass 'cuda' for GPU.
|
53
53
|
optimize_step: Customizable optimization callback which is called at every iteration.=
|
54
54
|
The function must have the signature `optimize_step(model,
|
55
|
-
optimizer, loss_fn, xs, device="cpu")
|
56
|
-
Apart from the default we already supply three other optimization
|
57
|
-
functions `optimize_step_evo`, `optimize_step_grad_norm`, and
|
58
|
-
`optimize_step_inv_dirichlet`. Learn more about how to use this in
|
59
|
-
the [Advancded features](../../tutorials/advanced) tutorial of the
|
60
|
-
documentation.
|
55
|
+
optimizer, loss_fn, xs, device="cpu")`.
|
61
56
|
write_tensorboard: Customizable tensorboard logging callback which is
|
62
57
|
called every `config.write_every` iterations. The function must have
|
63
58
|
the signature `write_tensorboard(writer, loss, metrics, iteration)`
|
64
59
|
(see the example below).
|
60
|
+
dtype: The dtype to use for the data.
|
65
61
|
|
66
62
|
Example:
|
67
63
|
```python exec="on" source="material-block"
|
@@ -70,7 +66,7 @@ def train(
|
|
70
66
|
from itertools import count
|
71
67
|
from qadence import Parameter, QuantumCircuit, Z
|
72
68
|
from qadence import hamiltonian_factory, hea, feature_map, chain
|
73
|
-
from qadence
|
69
|
+
from qadence import QNN
|
74
70
|
from qadence.ml_tools import TrainConfig, train_with_grad, to_dataloader
|
75
71
|
|
76
72
|
n_qubits = 2
|
qadence/ml_tools/utils.py
CHANGED
@@ -5,16 +5,15 @@ from typing import Any
|
|
5
5
|
|
6
6
|
from torch import Tensor, rand
|
7
7
|
|
8
|
+
from qadence import QNN, QuantumModel
|
8
9
|
from qadence.blocks import AbstractBlock, parameters
|
9
10
|
from qadence.circuit import QuantumCircuit
|
10
|
-
from qadence.ml_tools.models import TransformedModule
|
11
|
-
from qadence.models import QNN, QuantumModel
|
12
11
|
from qadence.parameters import Parameter, stringify
|
13
12
|
|
14
13
|
|
15
14
|
@singledispatch
|
16
15
|
def rand_featureparameters(
|
17
|
-
x: QuantumCircuit | AbstractBlock | QuantumModel | QNN
|
16
|
+
x: QuantumCircuit | AbstractBlock | QuantumModel | QNN, *args: Any
|
18
17
|
) -> dict[str, Tensor]:
|
19
18
|
raise NotImplementedError(f"Unable to generate random featureparameters for object {type(x)}.")
|
20
19
|
|
@@ -39,8 +38,3 @@ def _(qm: QuantumModel, batch_size: int = 1) -> dict[str, Tensor]:
|
|
39
38
|
@rand_featureparameters.register
|
40
39
|
def _(qnn: QNN, batch_size: int = 1) -> dict[str, Tensor]:
|
41
40
|
return rand_featureparameters(qnn._circuit.abstract, batch_size)
|
42
|
-
|
43
|
-
|
44
|
-
@rand_featureparameters.register
|
45
|
-
def _(tm: TransformedModule, batch_size: int = 1) -> dict[str, Tensor]:
|
46
|
-
return rand_featureparameters(tm.model, batch_size)
|
@@ -36,7 +36,7 @@ class QuantumModel(nn.Module):
|
|
36
36
|
|
37
37
|
This class should be used as base class for any new quantum model supported in the qadence
|
38
38
|
framework for information on the implementation of custom models see
|
39
|
-
[here](/advanced_tutorials/custom-models.md).
|
39
|
+
[here](../tutorials/advanced_tutorials/custom-models.md).
|
40
40
|
"""
|
41
41
|
|
42
42
|
backend: Backend | DifferentiableBackend
|
@@ -258,10 +258,10 @@ class QuantumModel(nn.Module):
|
|
258
258
|
"observable": abs_obs,
|
259
259
|
"backend": self._backend_name,
|
260
260
|
"diff_mode": self._diff_mode,
|
261
|
-
"measurement":
|
262
|
-
|
263
|
-
|
264
|
-
"noise": self._noise._to_dict() if self._noise is not None else
|
261
|
+
"measurement": (
|
262
|
+
self._measurement._to_dict() if self._measurement is not None else dict()
|
263
|
+
),
|
264
|
+
"noise": self._noise._to_dict() if self._noise is not None else dict(),
|
265
265
|
"backend_configuration": asdict(self.backend.backend.config), # type: ignore
|
266
266
|
}
|
267
267
|
param_dict_conv = {}
|
@@ -354,9 +354,11 @@ class QuantumModel(nn.Module):
|
|
354
354
|
obs.native = obs.native.to(*args, **kwargs)
|
355
355
|
self._params = self._params.to(
|
356
356
|
device=self._circuit.native.device,
|
357
|
-
dtype=
|
358
|
-
|
359
|
-
|
357
|
+
dtype=(
|
358
|
+
torch.float64
|
359
|
+
if self._circuit.native.dtype == torch.cdouble
|
360
|
+
else torch.float32
|
361
|
+
),
|
360
362
|
)
|
361
363
|
logger.debug(f"Moved {self} to {args}, {kwargs}.")
|
362
364
|
else:
|
@@ -372,3 +374,7 @@ class QuantumModel(nn.Module):
|
|
372
374
|
if self.backend.backend.name == "pyqtorch" # type: ignore[union-attr]
|
373
375
|
else torch.device("cpu")
|
374
376
|
)
|
377
|
+
|
378
|
+
|
379
|
+
# Modules to be automatically added to the qadence namespace
|
380
|
+
__all__ = ["QuantumModel"] # type: ignore
|
qadence/overlap.py
CHANGED
@@ -13,7 +13,7 @@ from qadence.blocks.utils import chain, kron, tag
|
|
13
13
|
from qadence.circuit import QuantumCircuit
|
14
14
|
from qadence.divergences import js_divergence
|
15
15
|
from qadence.measurements import Measurements
|
16
|
-
from qadence.
|
16
|
+
from qadence.model import QuantumModel
|
17
17
|
from qadence.operations import SWAP, H, I, S
|
18
18
|
from qadence.transpile import reassign
|
19
19
|
from qadence.types import BackendName, DiffMode, OverlapMethod
|
qadence/serialization.py
CHANGED
@@ -17,11 +17,10 @@ from arpeggio.cleanpeg import ParserPEG
|
|
17
17
|
from sympy import *
|
18
18
|
from sympy import core, srepr
|
19
19
|
|
20
|
-
from qadence import QuantumCircuit, operations, parameters
|
20
|
+
from qadence import QNN, QuantumCircuit, QuantumModel, operations, parameters
|
21
21
|
from qadence import blocks as qadenceblocks
|
22
22
|
from qadence.blocks import AbstractBlock
|
23
23
|
from qadence.blocks.utils import tag
|
24
|
-
from qadence.models import QuantumModel
|
25
24
|
from qadence.parameters import Parameter
|
26
25
|
from qadence.register import Register
|
27
26
|
from qadence.types import SerializationFormat
|
@@ -48,6 +47,7 @@ SUPPORTED_OBJECTS = [
|
|
48
47
|
AbstractBlock,
|
49
48
|
QuantumCircuit,
|
50
49
|
QuantumModel,
|
50
|
+
QNN,
|
51
51
|
Register,
|
52
52
|
core.Basic,
|
53
53
|
torch.nn.Module,
|
@@ -374,12 +374,12 @@ def save(
|
|
374
374
|
Same as serialize/deserialize but for storing/loading files.
|
375
375
|
|
376
376
|
Supported types:
|
377
|
-
AbstractBlock | QuantumCircuit | QuantumModel |
|
377
|
+
AbstractBlock | QuantumCircuit | QuantumModel | Register | torch.nn.Module
|
378
378
|
Saves a qadence object to a json/.pt.
|
379
379
|
|
380
380
|
Arguments:
|
381
381
|
obj (AbstractBlock | QuantumCircuit | QuantumModel | Register):
|
382
|
-
Either AbstractBlock, QuantumCircuit, QuantumModel,
|
382
|
+
Either AbstractBlock, QuantumCircuit, QuantumModel, Register.
|
383
383
|
file_name (str): The name of the file.
|
384
384
|
format (str): The type of file to save.
|
385
385
|
Returns:
|
@@ -431,14 +431,14 @@ def load(file_path: str | Path, map_location: str = "cpu") -> SUPPORTED_TYPES:
|
|
431
431
|
"""
|
432
432
|
Same as serialize/deserialize but for storing/loading files.
|
433
433
|
|
434
|
-
Supported types: AbstractBlock | QuantumCircuit | QuantumModel |
|
434
|
+
Supported types: AbstractBlock | QuantumCircuit | QuantumModel | Register
|
435
435
|
Loads a .json or .pt file to one of the supported types.
|
436
436
|
|
437
437
|
Arguments:
|
438
438
|
file_path (str): The name of the file.
|
439
439
|
map_location (str): In case of a .pt file, on which device to load the object (cpu,cuda).
|
440
440
|
Returns:
|
441
|
-
A object of type AbstractBlock, QuantumCircuit, QuantumModel,
|
441
|
+
A object of type AbstractBlock, QuantumCircuit, QuantumModel, Register.
|
442
442
|
|
443
443
|
Examples:
|
444
444
|
```python exec="on" source="material-block" result="json"
|
qadence/types.py
CHANGED
@@ -27,6 +27,7 @@ PI = pi
|
|
27
27
|
|
28
28
|
# Modules to be automatically added to the qadence namespace
|
29
29
|
__all__ = [
|
30
|
+
"AnsatzType",
|
30
31
|
"Endianness",
|
31
32
|
"Strategy",
|
32
33
|
"ResultType",
|
@@ -34,6 +35,7 @@ __all__ = [
|
|
34
35
|
"BackendName",
|
35
36
|
"StateGeneratorType",
|
36
37
|
"LTSOrder",
|
38
|
+
"MultivariateStrategy",
|
37
39
|
"ReuploadScaling",
|
38
40
|
"BasisSet",
|
39
41
|
"TensorType",
|
@@ -70,6 +72,8 @@ class Strategy(StrEnum):
|
|
70
72
|
"""Use the step-wise digital-analog QC paradigm."""
|
71
73
|
BDAQC = "bDAQC"
|
72
74
|
"""Use the banged digital-analog QC paradigm."""
|
75
|
+
RYDBERG = "Rydberg"
|
76
|
+
"""Use the Rydberg QC paradigm."""
|
73
77
|
|
74
78
|
|
75
79
|
class Endianness(StrEnum):
|
@@ -145,6 +149,24 @@ class ReuploadScaling(StrEnum):
|
|
145
149
|
"""Exponentially increasing scaling."""
|
146
150
|
|
147
151
|
|
152
|
+
class MultivariateStrategy(StrEnum):
|
153
|
+
"""Multivariate strategy for feature maps."""
|
154
|
+
|
155
|
+
PARALLEL = "parallel"
|
156
|
+
"""Parallel strategy."""
|
157
|
+
SERIES = "SERIES"
|
158
|
+
"""Serial strategy."""
|
159
|
+
|
160
|
+
|
161
|
+
class AnsatzType(StrEnum):
|
162
|
+
"""Ansatz types for variational circuits."""
|
163
|
+
|
164
|
+
HEA = "hea"
|
165
|
+
"""Hardware-efficient ansatz."""
|
166
|
+
IIA = "iia"
|
167
|
+
"""Identity-Initialised Ansatz."""
|
168
|
+
|
169
|
+
|
148
170
|
class _DiffMode(StrEnum):
|
149
171
|
"""Differentiation modes to choose from."""
|
150
172
|
|
@@ -401,3 +423,23 @@ class ReadOutOptimization(StrEnum):
|
|
401
423
|
|
402
424
|
ParamDictType = dict[str, ArrayLike]
|
403
425
|
DifferentiableExpression = Callable[..., ArrayLike]
|
426
|
+
|
427
|
+
|
428
|
+
class InputDiffMode(StrEnum):
|
429
|
+
"""Derivative modes w.r.t inputs of UFAs."""
|
430
|
+
|
431
|
+
AD = "ad"
|
432
|
+
"""Reverse automatic differentiation."""
|
433
|
+
FD = "fd"
|
434
|
+
"""Central finite differencing."""
|
435
|
+
|
436
|
+
|
437
|
+
class ObservableTransform:
|
438
|
+
"""Observable transformation type."""
|
439
|
+
|
440
|
+
SCALE = "scale"
|
441
|
+
"""Use the given values as scale and shift."""
|
442
|
+
RANGE = "range"
|
443
|
+
"""Use the given values as min and max."""
|
444
|
+
NONE = "none"
|
445
|
+
"""No transformation."""
|
@@ -1,8 +1,8 @@
|
|
1
1
|
Metadata-Version: 2.3
|
2
2
|
Name: qadence
|
3
|
-
Version: 1.
|
3
|
+
Version: 1.7.0
|
4
4
|
Summary: Pasqal interface for circuit-based quantum computing SDKs
|
5
|
-
Author-email: Aleksander Wennersteen <aleksander.wennersteen@pasqal.com>, Gert-Jan Both <gert-jan.both@pasqal.com>, Niklas Heim <niklas.heim@pasqal.com>, Mario Dagrada <mario.dagrada@pasqal.com>, Vincent Elfving <vincent.elfving@pasqal.com>, Dominik Seitz <dominik.seitz@pasqal.com>, Roland Guichard <roland.guichard@pasqal.com>, "Joao P. Moutinho" <joao.moutinho@pasqal.com>, Vytautas Abramavicius <vytautas.abramavicius@pasqal.com>, Gergana Velikova <gergana.velikova@pasqal.com>, Eduardo Maschio <eduardo.maschio@pasqal.com>
|
5
|
+
Author-email: Aleksander Wennersteen <aleksander.wennersteen@pasqal.com>, Gert-Jan Both <gert-jan.both@pasqal.com>, Niklas Heim <niklas.heim@pasqal.com>, Mario Dagrada <mario.dagrada@pasqal.com>, Vincent Elfving <vincent.elfving@pasqal.com>, Dominik Seitz <dominik.seitz@pasqal.com>, Roland Guichard <roland.guichard@pasqal.com>, "Joao P. Moutinho" <joao.moutinho@pasqal.com>, Vytautas Abramavicius <vytautas.abramavicius@pasqal.com>, Gergana Velikova <gergana.velikova@pasqal.com>, Eduardo Maschio <eduardo.maschio@pasqal.com>, Smit Chaudhary <smit.chaudhary@pasqal.com>
|
6
6
|
License: Apache 2.0
|
7
7
|
License-File: LICENSE
|
8
8
|
Classifier: License :: OSI Approved :: Apache Software License
|
@@ -22,7 +22,7 @@ Requires-Dist: matplotlib
|
|
22
22
|
Requires-Dist: nevergrad
|
23
23
|
Requires-Dist: numpy
|
24
24
|
Requires-Dist: openfermion
|
25
|
-
Requires-Dist: pyqtorch==1.1
|
25
|
+
Requires-Dist: pyqtorch==1.2.1
|
26
26
|
Requires-Dist: pyyaml
|
27
27
|
Requires-Dist: rich
|
28
28
|
Requires-Dist: scipy
|
@@ -149,6 +149,15 @@ brew install graphviz
|
|
149
149
|
conda install python-graphviz
|
150
150
|
```
|
151
151
|
|
152
|
+
On Windows Linux Subsystem (WSL2) it has been reported that in some cases "wslutilities" must be installed.
|
153
|
+
Please follow instructions [here](https://wslutiliti.es/wslu/install.html) for your flavour.
|
154
|
+
For example on Ubuntu 22.04 LTS and later you must run:
|
155
|
+
```
|
156
|
+
sudo add-apt-repository ppa:wslutilities/wslu
|
157
|
+
sudo apt update
|
158
|
+
sudo apt install wslu
|
159
|
+
```
|
160
|
+
|
152
161
|
## Contributing
|
153
162
|
|
154
163
|
Before making a contribution, please review our [code of conduct](docs/getting_started/CODE_OF_CONDUCT.md).
|
@@ -179,6 +188,8 @@ install it from source using `pip`:
|
|
179
188
|
python -m pip install -e .
|
180
189
|
```
|
181
190
|
|
191
|
+
Users also report problems running Hatch on Windows, we suggest using WSL2.
|
192
|
+
|
182
193
|
## Citation
|
183
194
|
|
184
195
|
If you use Qadence for a publication, we kindly ask you to cite our work using the following BibTex entry:
|
@@ -1,24 +1,24 @@
|
|
1
|
-
qadence/__init__.py,sha256=
|
1
|
+
qadence/__init__.py,sha256=0SFU1_XZ-3WlSU1rA4W1Y0edxpZLO_sNg-YnpjlD77w,2638
|
2
2
|
qadence/backend.py,sha256=TTzWEHEyOg7EH02IBiDkhE-Uwtj0fSLNMvQ48qtAcOk,14401
|
3
3
|
qadence/circuit.py,sha256=3lQdjj_srxgk6f5M3eh3kE-Qdov4FA9TZxZZb0E1_mI,6966
|
4
4
|
qadence/decompose.py,sha256=C4LYia_GcC9Rx3QO0ZLWTI9dN63a8WTEAXO0ZVQWuiE,5221
|
5
5
|
qadence/divergences.py,sha256=JhpELhWSnuDvQxa9hJp_DE3EQg2Ban-Ta0mHZ_fVrHg,1832
|
6
6
|
qadence/execution.py,sha256=5_P5OSatiwEAu7aAkCLau5VcmtIZiC3VFIj5YYdwAbY,9287
|
7
7
|
qadence/extensions.py,sha256=qly8STovIr_tB9yJSlIjkaYfKFY-1VLto-Zqq0RdLAw,4247
|
8
|
-
qadence/finitediff.py,sha256=TijuaWUbX9VlbLyMYco6HkK9eCoRTVnKug4Ekd6mlTI,1592
|
9
8
|
qadence/libs.py,sha256=HetkKO8TCTlVCViQdVQJvxwBekrhd-y_iMox4UJMY1M,410
|
10
9
|
qadence/log_config.yaml,sha256=WwSpxqMSXgPJ7wO_wh46UnFzXdgX9NVA4MbN3TcJFyE,485
|
11
10
|
qadence/logger.py,sha256=Hb76pK3VyQjVjJb4_NqFlOJgjYJVa8t7DHJFlzOM86M,407
|
12
|
-
qadence/
|
11
|
+
qadence/model.py,sha256=4ajqTcj1JNbVaaC_P59nRJ_XjHHatYNK25iioEL4UX8,14607
|
12
|
+
qadence/overlap.py,sha256=v3XP3g7BaMoTjR0GVTqg7IDtAfq_Njo1ZNTeyo8uYNA,17089
|
13
13
|
qadence/parameters.py,sha256=WdHCcLJ8tyRfBdaLAo89GwJboj6wLdfhdHdqPDLLAhM,12337
|
14
14
|
qadence/protocols.py,sha256=bcYTxSjgMPV-a-D6yv90jCpnGik8myzaNpFv9z1gzJ0,442
|
15
15
|
qadence/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
16
16
|
qadence/qubit_support.py,sha256=Nkn1Q01RVViTcggSIom7EFKdWpAuM4TMGwBZ5feCUxA,2120
|
17
17
|
qadence/register.py,sha256=cBMzwZ7GWZ5ieuFt0bpproEI6a2ncNwfjj7ic379zyg,10276
|
18
18
|
qadence/serial_expr_grammar.peg,sha256=z5ytL7do9kO8o4h-V5GrsDuLdso0KsRcMuIYURFfmAY,328
|
19
|
-
qadence/serialization.py,sha256=
|
19
|
+
qadence/serialization.py,sha256=qEET6Gu9u2aSibPve3bJrqDzK2_gO3RPDJjt4ZY8GbE,15596
|
20
20
|
qadence/states.py,sha256=5QIOBBYs8e2uLFiMa8iMYZ-MvWIFEqkZAjNYx0SyYPI,14843
|
21
|
-
qadence/types.py,sha256=
|
21
|
+
qadence/types.py,sha256=n9vkVejthNlsJQABX9i2FmjWMHsvneVjs4UVxSJz99Q,10673
|
22
22
|
qadence/utils.py,sha256=mTDI54uXsFXrKKFshmXFzDdoaeLMLlqA1MR2G061TSc,10092
|
23
23
|
qadence/analog/__init__.py,sha256=BCyS9R4KUjzUXN0Ax3b0eMo8ZAuSkGoJQVtZ4_pvAFs,279
|
24
24
|
qadence/analog/addressing.py,sha256=fu5-xW9lquEbagApNp23S_ET1kl0iDtZUrIYSVNmw9s,6435
|
@@ -27,11 +27,10 @@ qadence/analog/device.py,sha256=RmPXWxq77pJXzvV6CIVSUVxxy-oKd6SqoSnQESNLIqg,2412
|
|
27
27
|
qadence/analog/hamiltonian_terms.py,sha256=9LKidqqEMJTTdXeaxkxP_otTmcv9i4yeJ-JKCLOCK3Y,3421
|
28
28
|
qadence/analog/parse_analog.py,sha256=ppvMZtsKXOIkIehCgjbdmG9n232DIycSanyuyVth5Wg,4223
|
29
29
|
qadence/backends/__init__.py,sha256=ibm7wmZxuIoMYAQxgAx0MsfLYWOVHNWgLwyS1HjMuuI,215
|
30
|
-
qadence/backends/adjoint.py,sha256=0NF7dFwjYWF-p3IwVdKjm7GaX9TO2CvfJiWiVzwSqNI,6946
|
31
30
|
qadence/backends/api.py,sha256=6PoK4ydhi2tj9w0ePMQl1G4kEFROoWe3lrkrtQwWxkc,3224
|
32
|
-
qadence/backends/gpsr.py,sha256=
|
31
|
+
qadence/backends/gpsr.py,sha256=GxK3hkdE-uUwZJokPalzLDaF8sO9MLTN9oRBZ2uKrEM,4749
|
33
32
|
qadence/backends/jax_utils.py,sha256=VfKhqCKknHDWZO21UFipWH_Lkiq175Z5GkP49gWjbyw,5038
|
34
|
-
qadence/backends/utils.py,sha256=
|
33
|
+
qadence/backends/utils.py,sha256=vPEBkjyS_xtc3OtzdqA_qcEQwkNhTl0JsBoUAHrpZ4s,7978
|
35
34
|
qadence/backends/braket/__init__.py,sha256=eruyDZKMqkh1LE7eJ980vcrLJbia35uUX6krAP78clI,121
|
36
35
|
qadence/backends/braket/backend.py,sha256=WX5FG4WsrtdnG0at2DvIY0n_AFm44t4g5OIJ1e8r6fQ,8752
|
37
36
|
qadence/backends/braket/config.py,sha256=7cu22dmYdp48Fu760HPfxBHinaUnGmzx9MkE_EPhVN8,594
|
@@ -50,9 +49,9 @@ qadence/backends/pulser/devices.py,sha256=DermLZNfmCB3SqteKVW4uhg4jp6ya1G6ptnXbB
|
|
50
49
|
qadence/backends/pulser/pulses.py,sha256=F4fExIRAhLPMtVg1bhNtDihUYHxu5RExGjovk8-CQIo,11884
|
51
50
|
qadence/backends/pulser/waveforms.py,sha256=0uz95b7rUaUUtN0tuHBZmJ0H6UBmfHST_59ozwsRCzg,2227
|
52
51
|
qadence/backends/pyqtorch/__init__.py,sha256=0OdVy6cq0oQggV48LO1WXdaZuSkDkz7OYNEPIkNAmfk,140
|
53
|
-
qadence/backends/pyqtorch/backend.py,sha256=
|
52
|
+
qadence/backends/pyqtorch/backend.py,sha256=xAPJT--Lu_OW8GVeXc1weBFB5iEwJ6hihFGo8PRJXnk,9309
|
54
53
|
qadence/backends/pyqtorch/config.py,sha256=hhea1dDAeee7uDE1fiCh4lJRS0EMSc3mmbXn92HBdyA,1898
|
55
|
-
qadence/backends/pyqtorch/convert_ops.py,sha256=
|
54
|
+
qadence/backends/pyqtorch/convert_ops.py,sha256=R7FNJ5UgO7_SsUOMY6tSXeOfIpq3-eqFZwXakLvUiHU,11943
|
56
55
|
qadence/blocks/__init__.py,sha256=H6jEA_CptkE-eoB4UfSbUiDszbxxhZwECV_TgoZWXoU,960
|
57
56
|
qadence/blocks/abstract.py,sha256=35RcVlNvD1BmBoJ8bbYJ3LrdU72wixt9ZmTbCtEwNus,11796
|
58
57
|
qadence/blocks/analog.py,sha256=ymnnlSVoW1XL05ZvnnHCqRTHuOXIEY_7E9M0PNKJZy4,10812
|
@@ -60,13 +59,13 @@ qadence/blocks/block_to_tensor.py,sha256=Sg7YGKUoPUUHKvyB8Khztrk7UYnV5SD451_3I00
|
|
60
59
|
qadence/blocks/composite.py,sha256=z_lXRBVnh-DdvfZdv6T0ZEmVhlU76zBt72P_FGGa-PQ,8897
|
61
60
|
qadence/blocks/embedding.py,sha256=TQt620UIVaNYHP34tpK9slv-PFiLvTQRYw5Ez9RuImE,6513
|
62
61
|
qadence/blocks/manipulate.py,sha256=kPmzej7mnWFoqTJA2CkGulT7hcPha0GGPARC8rjZltg,2387
|
63
|
-
qadence/blocks/matrix.py,sha256=
|
64
|
-
qadence/blocks/primitive.py,sha256=
|
62
|
+
qadence/blocks/matrix.py,sha256=k6CC3zN2i6nd7_9S9u4fJAxy9wfkM287945GpArwOhY,3771
|
63
|
+
qadence/blocks/primitive.py,sha256=RoEA9_VCI_8o4yg_pMe5T38z3LD6IFz9qlCiF3iHmOo,16631
|
65
64
|
qadence/blocks/utils.py,sha256=iCJDi6HTYYaQQCoP3cdIKeCDuy8KQCxctrHN5QWXV-M,16349
|
66
|
-
qadence/constructors/__init__.py,sha256=
|
65
|
+
qadence/constructors/__init__.py,sha256=oEGuILUB8qEbSeaKV9Q-Tk-DAVx-U0wqn8VoSztVueg,984
|
67
66
|
qadence/constructors/ansatze.py,sha256=bTrcF2RsyA_Btmkk80tWxP1dn9fK_SXAQFueIuWkT-c,9660
|
68
67
|
qadence/constructors/feature_maps.py,sha256=BaAxFi6fSKwjsfFjqZ8T7lyZfjotcgH2OW3b0j67YVk,8644
|
69
|
-
qadence/constructors/hamiltonians.py,sha256=
|
68
|
+
qadence/constructors/hamiltonians.py,sha256=u9feuuLmgQ7tX0TcP8tsbCefvBSVjkY7k4fMT5vp12Q,10054
|
70
69
|
qadence/constructors/iia.py,sha256=z-4AA9Oj-j2oZ0QDkLYNk4duS3UHY_98Qwt9VO_ZDDU,7001
|
71
70
|
qadence/constructors/qft.py,sha256=2LpgQ-z1HUxB3rqHzYsbjqpdU63gyuuaUVCbNEFbjo8,7688
|
72
71
|
qadence/constructors/rydberg_feature_maps.py,sha256=RuXtuAhjpong78jpKUjZHdh4fOdHBnuht1ffoAMWdEE,4839
|
@@ -78,7 +77,7 @@ qadence/constructors/daqc/gen_parser.py,sha256=taZMJ9BNp672qXqsNSQ8RY71tN2gMV4Rb
|
|
78
77
|
qadence/constructors/daqc/utils.py,sha256=1T83veISoOXhJYUWXhfocbISpfIgsrKrdDHCMbskGoQ,1067
|
79
78
|
qadence/draw/__init__.py,sha256=A2lU7_CfCjwZCnMRojG5CsoWm-7aWKpUYGyaJ9qBZIQ,2319
|
80
79
|
qadence/draw/themes.py,sha256=VV4YtC8X3UI63AuJO2D0fLMTLbdDUjIyXQcKuDuIVmI,5533
|
81
|
-
qadence/draw/utils.py,sha256=
|
80
|
+
qadence/draw/utils.py,sha256=4Hk-vwGz6ZRLKYnV26r1g3zBvOONvlFiN4Kh6toUsI0,12107
|
82
81
|
qadence/draw/vizbackend.py,sha256=BKq1fjW7zgEhaIhrmi-i6XV9ZWY7NmlmdDo9-tfP0Hk,14997
|
83
82
|
qadence/draw/assets/dark/measurement.png,sha256=hSMhZZCFKHNO2tCpYTTSYIF-nsAfNalRunRUIyhygC0,502
|
84
83
|
qadence/draw/assets/dark/measurement.svg,sha256=6ALGjaCX3xZ1NqB6RW6yzOchzZV-j8ukW4aGhEWe4Lk,7282
|
@@ -91,7 +90,7 @@ qadence/engines/jax/differentiable_backend.py,sha256=W5rDA8wb-ECnFWoLj4dVugF9v1l
|
|
91
90
|
qadence/engines/jax/differentiable_expectation.py,sha256=XBYHT1XKRuZfKxTcNy8KJpSDPt-2PR4ZCanImCPI9OI,3677
|
92
91
|
qadence/engines/torch/__init__.py,sha256=iZFdD32ot0B0CVyC-f5dVViOBnqoalxa6M9Lj4WQuPE,160
|
93
92
|
qadence/engines/torch/differentiable_backend.py,sha256=AWthwvKE8pCOih4dZ3tXxQX4W1ps9mBcvo7n4V9V24Y,3553
|
94
|
-
qadence/engines/torch/differentiable_expectation.py,sha256=
|
93
|
+
qadence/engines/torch/differentiable_expectation.py,sha256=kAYl23Xq9MwkLm0MzmiIES-qUXc2zQsl9TuIF_c-qTE,9599
|
95
94
|
qadence/exceptions/__init__.py,sha256=BU6vWrI9mshzr1aTPm1Ticr_o_42GjTrWI4OZXhThsI,203
|
96
95
|
qadence/exceptions/exceptions.py,sha256=4j_VJpx2sZ2Mir5BJUWu4nwb131FY1ygO4q8-XlyfRc,190
|
97
96
|
qadence/measurements/__init__.py,sha256=RIjG9tVJMqhNzyj7maZI250Um0KgHl2PizDcKJag-JU,161
|
@@ -104,21 +103,19 @@ qadence/mitigations/__init__.py,sha256=RzaxYJftePFMloGhBVSixZ8fSe-ps_Jc-EyPm6xz-
|
|
104
103
|
qadence/mitigations/analog_zne.py,sha256=g0QkjSdF-N9Dv2N8Oza4sylnjUMid5ea-4NCT9Tcm3Y,7768
|
105
104
|
qadence/mitigations/protocols.py,sha256=Jq9MyLujfTyWmc7XVUGYVRUkJT1MmZw-GgmWpVjmX2Y,1608
|
106
105
|
qadence/mitigations/readout.py,sha256=HPfYmdjRlieUdOBMZTghFK4DRWfveM4KkDkEI0bMI0E,6262
|
107
|
-
qadence/ml_tools/__init__.py,sha256=
|
108
|
-
qadence/ml_tools/config.py,sha256=
|
106
|
+
qadence/ml_tools/__init__.py,sha256=HP4xjldkUZ9_WbZEDgpl31qoP9st5SBbC-DjI5pkx3k,1054
|
107
|
+
qadence/ml_tools/config.py,sha256=XIL_V3zmHaBWIRoUmaHjN2a3tjZV-o0ya2gTRzugVzg,14007
|
108
|
+
qadence/ml_tools/constructors.py,sha256=bEQuE4h3njZiXo8GHviu8krQ4sG9x2dNlBvspE8XtZc,26364
|
109
109
|
qadence/ml_tools/data.py,sha256=8ZUFjhQSp94w7icX7RzM2J39Yo7P_T-AgjcThBc8miI,4283
|
110
|
-
qadence/ml_tools/models.py,sha256=
|
110
|
+
qadence/ml_tools/models.py,sha256=UutQ_pd2mHmZ1DUncxEtw7asdFuhW3syDyH86xp4S5E,15298
|
111
111
|
qadence/ml_tools/optimize_step.py,sha256=ATXWmAqybJVK3QmAaDqVXB5mxjTo2MIi_e0a5WSPFpc,1800
|
112
112
|
qadence/ml_tools/parameters.py,sha256=gew2Kq_5-RgRpaTvs8eauVhgo0sTqqDQEV6WHFEiLGM,1301
|
113
113
|
qadence/ml_tools/printing.py,sha256=YK2zc9SOc5wiLnMxm3Q1gSwPAVW9Vy2Pcnjg9gP0aKU,694
|
114
|
-
qadence/ml_tools/saveload.py,sha256=
|
114
|
+
qadence/ml_tools/saveload.py,sha256=SAhXVN4dI13JUdr_xuD_4MRcSBw_oSnTPZml2Mqims4,4876
|
115
115
|
qadence/ml_tools/tensors.py,sha256=xZ9ZRzOqEaMgLUGWQf1najDmL6iLuN1ojCGVFs1Tm94,1337
|
116
|
-
qadence/ml_tools/train_grad.py,sha256=
|
116
|
+
qadence/ml_tools/train_grad.py,sha256=Bp2bJYDE_ojlu0lm79RNLKS8JLlBLzCyfH_wUtEo_lU,9185
|
117
117
|
qadence/ml_tools/train_no_grad.py,sha256=PrOfPwu6C-YqfFxnRkbeyOQzqSyjRrx4AZZd6C-1xRw,4705
|
118
|
-
qadence/ml_tools/utils.py,sha256=
|
119
|
-
qadence/models/__init__.py,sha256=0nZzAC2TGr8Yuf40-R7m2cSsr_BlNq_GsMOwaOYZLqM,193
|
120
|
-
qadence/models/qnn.py,sha256=gc_iC1GG6WJbeLaln9jy4yYp9fY0p8fkpKkKJpXJ3ck,10397
|
121
|
-
qadence/models/quantum_model.py,sha256=RcKdkWX0dQaYuJiZbJ1WUYpLKmlJLiUglWV0Gv0-DIo,14417
|
118
|
+
qadence/ml_tools/utils.py,sha256=PW8FyoV0mG_DtN1U8njTDV5qxZ0EK4mnFwMAsLBArfk,1410
|
122
119
|
qadence/noise/__init__.py,sha256=r0nR8uEZeB1M9pI2UisjWq0bjw50fPFfVGzIMev923g,147
|
123
120
|
qadence/noise/protocols.py,sha256=-aZ06JvMnpxCeT5v5lI_RNPOLbb9Ju1Pi1AB6uAXxVE,1653
|
124
121
|
qadence/noise/readout.py,sha256=UpUdxaGu09SmqKXn0O7RYfF7b7UcRZiNMfDlpY0weV0,6726
|
@@ -136,7 +133,7 @@ qadence/transpile/digitalize.py,sha256=iWRwYAYQsD2INHj0HNbGJriv_3fRCuBW1nDBrwtKS
|
|
136
133
|
qadence/transpile/flatten.py,sha256=EdhSG5WyF56nbnxINNLqrHgY84MRM1YFjT3fR4aph5Q,3427
|
137
134
|
qadence/transpile/invert.py,sha256=KAefHTG2AWr39aengVhXrzCtJPhrZC-ZnL6vYvmbnY0,4867
|
138
135
|
qadence/transpile/transpile.py,sha256=6MRRkk1OS279L1fwUQjazA6qlfpbd-T_EJMKT8hAhOU,2721
|
139
|
-
qadence-1.
|
140
|
-
qadence-1.
|
141
|
-
qadence-1.
|
142
|
-
qadence-1.
|
136
|
+
qadence-1.7.0.dist-info/METADATA,sha256=8c2Am0vveGaO_sjoun3ProUrJmWzGmI75V-_bRMo_18,9640
|
137
|
+
qadence-1.7.0.dist-info/WHEEL,sha256=zEMcRr9Kr03x1ozGwg5v9NQBKn3kndp6LSoSlVg-jhU,87
|
138
|
+
qadence-1.7.0.dist-info/licenses/LICENSE,sha256=z8d0m5b2O9McPEK1xHG_dWgUBT6EfBDz6wA0F7xSPTA,11358
|
139
|
+
qadence-1.7.0.dist-info/RECORD,,
|
qadence/backends/adjoint.py
DELETED
@@ -1,163 +0,0 @@
|
|
1
|
-
from __future__ import annotations
|
2
|
-
|
3
|
-
from typing import Any
|
4
|
-
|
5
|
-
from pyqtorch.apply import apply_operator
|
6
|
-
from pyqtorch.circuit import QuantumCircuit as PyQCircuit
|
7
|
-
from pyqtorch.parametric import Parametric as PyQParametric
|
8
|
-
from pyqtorch.primitive import Primitive as PyQPrimitive
|
9
|
-
from pyqtorch.utils import inner_prod, param_dict
|
10
|
-
from torch import Tensor, no_grad, zeros
|
11
|
-
from torch.autograd import Function
|
12
|
-
from torch.nn import Module
|
13
|
-
|
14
|
-
from qadence.backends.pyqtorch.convert_ops import PyQHamiltonianEvolution, ScalePyQOperation
|
15
|
-
from qadence.blocks.abstract import AbstractBlock
|
16
|
-
|
17
|
-
|
18
|
-
class AdjointExpectation(Function):
|
19
|
-
"""
|
20
|
-
The adjoint differentiation method (https://arxiv.org/pdf/2009.02823.pdf).
|
21
|
-
|
22
|
-
is able to perform a backward pass in O(P) time and maintaining
|
23
|
-
atmost 3 states where P is the number of parameters in a variational circuit.
|
24
|
-
|
25
|
-
Pseudo-code of the algorithm:
|
26
|
-
|
27
|
-
c: a variational circuit
|
28
|
-
c.gates = gate0,gate1,..gateN, where N denotes the last gate in c
|
29
|
-
o: a observable
|
30
|
-
state: an initial state
|
31
|
-
|
32
|
-
1. Forward pass.
|
33
|
-
for gate in c.gates: # We apply gate0, gate1 to gateN.
|
34
|
-
state = gate(state)
|
35
|
-
|
36
|
-
projected_state = o(state) # Apply the observable to the state.
|
37
|
-
expval = overlap(state, projected_state) # Compute the expected value.
|
38
|
-
|
39
|
-
2. Backward pass:
|
40
|
-
grads = []
|
41
|
-
for gate in reversed(c.gates): # Iterate through c.gates in "reverse", so gateN, gateN-1 etc.
|
42
|
-
state = dagger(gate)(state) # 'Undo' the gate by applying its dagger.
|
43
|
-
if gate is Parametric:
|
44
|
-
mu = jacobian(gate)(state) # Compute the jacobian of the gate w.r.t its parameter.
|
45
|
-
grads.append(2 * overlap(mu, projected_state) # Compute the gradient.
|
46
|
-
projected_state = dagger(gate)(projected_state) # 'Undo' the gate from the projected_state.
|
47
|
-
|
48
|
-
Current Limitations:
|
49
|
-
|
50
|
-
(1) The adjoint method is only available in the pyqtorch backend.
|
51
|
-
(2) Parametric observables are not supported.
|
52
|
-
(3) Multiple observables are not supported.
|
53
|
-
(4) Higher order derivatives are not natively supported.
|
54
|
-
(5) Only expectation values can be differentiated, not wave functions.
|
55
|
-
"""
|
56
|
-
|
57
|
-
@staticmethod
|
58
|
-
@no_grad()
|
59
|
-
def forward(
|
60
|
-
ctx: Any,
|
61
|
-
circuit: PyQCircuit,
|
62
|
-
observable: PyQCircuit,
|
63
|
-
state: Tensor,
|
64
|
-
param_names: list[str],
|
65
|
-
*param_values: Tensor,
|
66
|
-
) -> Tensor:
|
67
|
-
for param in param_values:
|
68
|
-
param = param.detach()
|
69
|
-
ctx.circuit = circuit
|
70
|
-
ctx.observable = observable
|
71
|
-
ctx.param_names = param_names
|
72
|
-
values = param_dict(param_names, param_values)
|
73
|
-
ctx.out_state = circuit.run(state, values)
|
74
|
-
ctx.projected_state = observable.run(ctx.out_state, values)
|
75
|
-
ctx.save_for_backward(*param_values)
|
76
|
-
return inner_prod(ctx.out_state, ctx.projected_state).real
|
77
|
-
|
78
|
-
@staticmethod
|
79
|
-
@no_grad()
|
80
|
-
def backward(ctx: Any, grad_out: Tensor) -> tuple:
|
81
|
-
param_values = ctx.saved_tensors
|
82
|
-
values = param_dict(ctx.param_names, param_values)
|
83
|
-
|
84
|
-
def _apply_adjoint(ctx: Any, op: Module) -> list:
|
85
|
-
grads: list = []
|
86
|
-
if isinstance(op, PyQHamiltonianEvolution):
|
87
|
-
generator = op.block.generator
|
88
|
-
time_param = values[op.param_names[0]]
|
89
|
-
ctx.out_state = apply_operator(ctx.out_state, op.dagger(values), op.qubit_support)
|
90
|
-
# A HamEvo can have a parametrized (1) time evolution and/or (2) generator.
|
91
|
-
if (
|
92
|
-
isinstance(generator, AbstractBlock)
|
93
|
-
and generator.is_parametric
|
94
|
-
and values[op.param_names[1]].requires_grad
|
95
|
-
):
|
96
|
-
# If the generator contains a trainable parameter, we compute its gradient.
|
97
|
-
mu = apply_operator(
|
98
|
-
ctx.out_state, op.jacobian_generator(values), op.qubit_support
|
99
|
-
)
|
100
|
-
grads.append(2 * inner_prod(ctx.projected_state, mu).real)
|
101
|
-
if time_param.requires_grad:
|
102
|
-
# If the time evolution is trainable, we compute its gradient.
|
103
|
-
mu = apply_operator(ctx.out_state, op.jacobian_time(values), op.qubit_support)
|
104
|
-
grads.append(2 * inner_prod(ctx.projected_state, mu).real)
|
105
|
-
ctx.projected_state = apply_operator(
|
106
|
-
ctx.projected_state, op.dagger(values), op.qubit_support
|
107
|
-
)
|
108
|
-
elif isinstance(op, ScalePyQOperation):
|
109
|
-
ctx.out_state = apply_operator(ctx.out_state, op.dagger(values), op.qubit_support)
|
110
|
-
scaled_pyq_op = op.operations[0]
|
111
|
-
if (
|
112
|
-
isinstance(scaled_pyq_op, PyQParametric)
|
113
|
-
and values[scaled_pyq_op.param_name].requires_grad
|
114
|
-
):
|
115
|
-
mu = apply_operator(
|
116
|
-
ctx.out_state,
|
117
|
-
scaled_pyq_op.jacobian(values),
|
118
|
-
scaled_pyq_op.qubit_support,
|
119
|
-
)
|
120
|
-
grads.append(2 * inner_prod(ctx.projected_state, mu).real)
|
121
|
-
|
122
|
-
if values[op.param_name].requires_grad:
|
123
|
-
grads.append(2 * -values[op.param_name])
|
124
|
-
ctx.projected_state = apply_operator(
|
125
|
-
ctx.projected_state, op.dagger(values), op.qubit_support
|
126
|
-
)
|
127
|
-
elif isinstance(op, PyQCircuit):
|
128
|
-
grads = [g for sub_op in op.operations[::-1] for g in _apply_adjoint(ctx, sub_op)]
|
129
|
-
elif isinstance(op, PyQPrimitive):
|
130
|
-
ctx.out_state = apply_operator(ctx.out_state, op.dagger(values), op.qubit_support)
|
131
|
-
if isinstance(op, PyQParametric) and values[op.param_name].requires_grad:
|
132
|
-
mu = apply_operator(
|
133
|
-
ctx.out_state,
|
134
|
-
op.jacobian(values),
|
135
|
-
op.qubit_support,
|
136
|
-
)
|
137
|
-
grads.append(2 * inner_prod(ctx.projected_state, mu).real)
|
138
|
-
ctx.projected_state = apply_operator(
|
139
|
-
ctx.projected_state, op.dagger(values), op.qubit_support
|
140
|
-
)
|
141
|
-
else:
|
142
|
-
raise TypeError(
|
143
|
-
f"AdjointExpectation does not support a backward pass for type {type(op)}."
|
144
|
-
)
|
145
|
-
|
146
|
-
return grads
|
147
|
-
|
148
|
-
grads = list(
|
149
|
-
reversed(
|
150
|
-
[
|
151
|
-
grad_out * g
|
152
|
-
for op in ctx.circuit.operations[::-1]
|
153
|
-
for g in _apply_adjoint(ctx, op)
|
154
|
-
]
|
155
|
-
)
|
156
|
-
)
|
157
|
-
num_grads = len(grads)
|
158
|
-
num_params = len(ctx.saved_tensors)
|
159
|
-
diff = num_params - num_grads
|
160
|
-
grads = grads + [zeros(1, device=ctx.circuit.device) for _ in range(diff)]
|
161
|
-
# Set observable grads to 0
|
162
|
-
ctx.save_for_backward(*grads)
|
163
|
-
return (None, None, None, None, *grads)
|