qadence 1.7.7__py3-none-any.whl → 1.8.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/analog/device.py +1 -1
- qadence/backend.py +3 -3
- qadence/backends/horqrux/backend.py +3 -3
- qadence/backends/pulser/backend.py +16 -17
- qadence/backends/pulser/convert_ops.py +2 -2
- qadence/backends/pyqtorch/backend.py +7 -7
- qadence/backends/pyqtorch/convert_ops.py +191 -240
- qadence/backends/utils.py +9 -1
- qadence/blocks/abstract.py +1 -1
- qadence/blocks/embedding.py +21 -11
- qadence/blocks/matrix.py +3 -1
- qadence/blocks/primitive.py +36 -11
- qadence/circuit.py +1 -1
- qadence/constructors/__init__.py +2 -1
- qadence/constructors/ansatze.py +176 -0
- qadence/engines/differentiable_backend.py +3 -3
- qadence/engines/jax/differentiable_backend.py +2 -2
- qadence/engines/jax/differentiable_expectation.py +2 -2
- qadence/engines/torch/differentiable_backend.py +2 -2
- qadence/engines/torch/differentiable_expectation.py +2 -2
- qadence/execution.py +14 -14
- qadence/extensions.py +1 -1
- qadence/measurements/shadow.py +4 -5
- qadence/measurements/tomography.py +2 -2
- qadence/measurements/utils.py +2 -2
- qadence/mitigations/analog_zne.py +8 -7
- qadence/mitigations/protocols.py +2 -2
- qadence/mitigations/readout.py +8 -5
- qadence/ml_tools/config.py +14 -0
- qadence/ml_tools/constructors.py +9 -4
- qadence/ml_tools/models.py +7 -7
- qadence/ml_tools/printing.py +2 -1
- qadence/ml_tools/train_grad.py +39 -7
- qadence/model.py +5 -5
- qadence/noise/__init__.py +2 -2
- qadence/noise/protocols.py +216 -29
- qadence/operations/control_ops.py +37 -22
- qadence/operations/ham_evo.py +1 -0
- qadence/operations/parametric.py +32 -10
- qadence/operations/primitive.py +61 -29
- qadence/overlap.py +0 -6
- qadence/parameters.py +3 -2
- qadence/transpile/__init__.py +2 -1
- qadence/transpile/noise.py +46 -0
- qadence/types.py +26 -2
- {qadence-1.7.7.dist-info → qadence-1.8.0.dist-info}/METADATA +5 -8
- {qadence-1.7.7.dist-info → qadence-1.8.0.dist-info}/RECORD +49 -52
- qadence/backends/braket/__init__.py +0 -4
- qadence/backends/braket/backend.py +0 -234
- qadence/backends/braket/config.py +0 -22
- qadence/backends/braket/convert_ops.py +0 -116
- {qadence-1.7.7.dist-info → qadence-1.8.0.dist-info}/WHEEL +0 -0
- {qadence-1.7.7.dist-info → qadence-1.8.0.dist-info}/licenses/LICENSE +0 -0
@@ -18,6 +18,7 @@ from qadence.blocks.utils import (
|
|
18
18
|
chain,
|
19
19
|
kron,
|
20
20
|
)
|
21
|
+
from qadence.noise import NoiseHandler
|
21
22
|
from qadence.parameters import (
|
22
23
|
Parameter,
|
23
24
|
evaluate,
|
@@ -35,9 +36,9 @@ class CNOT(ControlBlock):
|
|
35
36
|
|
36
37
|
name = OpName.CNOT
|
37
38
|
|
38
|
-
def __init__(self, control: int, target: int) -> None:
|
39
|
+
def __init__(self, control: int, target: int, noise: NoiseHandler | None = None) -> None:
|
39
40
|
self.generator = kron(N(control), X(target) - I(target))
|
40
|
-
super().__init__((control,), X(target))
|
41
|
+
super().__init__((control,), X(target), noise=noise)
|
41
42
|
|
42
43
|
@property
|
43
44
|
def eigenvalues_generator(self) -> Tensor:
|
@@ -63,9 +64,11 @@ class CNOT(ControlBlock):
|
|
63
64
|
class MCZ(ControlBlock):
|
64
65
|
name = OpName.MCZ
|
65
66
|
|
66
|
-
def __init__(
|
67
|
+
def __init__(
|
68
|
+
self, control: tuple[int, ...], target: int, noise: NoiseHandler | None = None
|
69
|
+
) -> None:
|
67
70
|
self.generator = kron(*[N(qubit) for qubit in control], Z(target) - I(target))
|
68
|
-
super().__init__(control, Z(target))
|
71
|
+
super().__init__(control, Z(target), noise=noise)
|
69
72
|
|
70
73
|
@property
|
71
74
|
def eigenvalues_generator(self) -> Tensor:
|
@@ -93,8 +96,8 @@ class CZ(MCZ):
|
|
93
96
|
|
94
97
|
name = OpName.CZ
|
95
98
|
|
96
|
-
def __init__(self, control: int, target: int) -> None:
|
97
|
-
super().__init__((control,), target)
|
99
|
+
def __init__(self, control: int, target: int, noise: NoiseHandler | None = None) -> None:
|
100
|
+
super().__init__((control,), target, noise=noise)
|
98
101
|
|
99
102
|
|
100
103
|
class MCRX(ParametricControlBlock):
|
@@ -105,9 +108,10 @@ class MCRX(ParametricControlBlock):
|
|
105
108
|
control: tuple[int, ...],
|
106
109
|
target: int,
|
107
110
|
parameter: Parameter | TNumber | sympy.Expr | str,
|
111
|
+
noise: NoiseHandler | None = None,
|
108
112
|
) -> None:
|
109
113
|
self.generator = kron(*[N(qubit) for qubit in control], X(target))
|
110
|
-
super().__init__(control, RX(target, parameter))
|
114
|
+
super().__init__(control, RX(target, parameter), noise=noise)
|
111
115
|
|
112
116
|
@classmethod
|
113
117
|
def num_parameters(cls) -> int:
|
@@ -136,8 +140,9 @@ class CRX(MCRX):
|
|
136
140
|
control: int,
|
137
141
|
target: int,
|
138
142
|
parameter: Parameter | TNumber | sympy.Expr | str,
|
143
|
+
noise: NoiseHandler | None = None,
|
139
144
|
):
|
140
|
-
super().__init__((control,), target, parameter)
|
145
|
+
super().__init__((control,), target, parameter, noise=noise)
|
141
146
|
|
142
147
|
|
143
148
|
class MCRY(ParametricControlBlock):
|
@@ -148,9 +153,10 @@ class MCRY(ParametricControlBlock):
|
|
148
153
|
control: tuple[int, ...],
|
149
154
|
target: int,
|
150
155
|
parameter: Parameter | TNumber | sympy.Expr | str,
|
156
|
+
noise: NoiseHandler | None = None,
|
151
157
|
) -> None:
|
152
158
|
self.generator = kron(*[N(qubit) for qubit in control], Y(target))
|
153
|
-
super().__init__(control, RY(target, parameter))
|
159
|
+
super().__init__(control, RY(target, parameter), noise=noise)
|
154
160
|
|
155
161
|
@classmethod
|
156
162
|
def num_parameters(cls) -> int:
|
@@ -175,12 +181,9 @@ class CRY(MCRY):
|
|
175
181
|
name = OpName.CRY
|
176
182
|
|
177
183
|
def __init__(
|
178
|
-
self,
|
179
|
-
control: int,
|
180
|
-
target: int,
|
181
|
-
parameter: TParameter,
|
184
|
+
self, control: int, target: int, parameter: TParameter, noise: NoiseHandler | None = None
|
182
185
|
):
|
183
|
-
super().__init__((control,), target, parameter)
|
186
|
+
super().__init__((control,), target, parameter, noise=noise)
|
184
187
|
|
185
188
|
|
186
189
|
class MCRZ(ParametricControlBlock):
|
@@ -191,9 +194,10 @@ class MCRZ(ParametricControlBlock):
|
|
191
194
|
control: tuple[int, ...],
|
192
195
|
target: int,
|
193
196
|
parameter: Parameter | TNumber | sympy.Expr | str,
|
197
|
+
noise: NoiseHandler | None = None,
|
194
198
|
) -> None:
|
195
199
|
self.generator = kron(*[N(qubit) for qubit in control], Z(target))
|
196
|
-
super().__init__(control, RZ(target, parameter))
|
200
|
+
super().__init__(control, RZ(target, parameter), noise=noise)
|
197
201
|
|
198
202
|
@classmethod
|
199
203
|
def num_parameters(cls) -> int:
|
@@ -222,8 +226,9 @@ class CRZ(MCRZ):
|
|
222
226
|
control: int,
|
223
227
|
target: int,
|
224
228
|
parameter: Parameter | TNumber | sympy.Expr | str,
|
229
|
+
noise: NoiseHandler | None = None,
|
225
230
|
):
|
226
|
-
super().__init__((control,), target, parameter)
|
231
|
+
super().__init__((control,), target, parameter, noise=noise)
|
227
232
|
|
228
233
|
|
229
234
|
class MCPHASE(ParametricControlBlock):
|
@@ -234,9 +239,10 @@ class MCPHASE(ParametricControlBlock):
|
|
234
239
|
control: tuple[int, ...],
|
235
240
|
target: int,
|
236
241
|
parameter: Parameter | TNumber | sympy.Expr | str,
|
242
|
+
noise: NoiseHandler | None = None,
|
237
243
|
) -> None:
|
238
244
|
self.generator = kron(*[N(qubit) for qubit in control], Z(target) - I(target))
|
239
|
-
super().__init__(control, PHASE(target, parameter))
|
245
|
+
super().__init__(control, PHASE(target, parameter), noise=noise)
|
240
246
|
|
241
247
|
@classmethod
|
242
248
|
def num_parameters(cls) -> int:
|
@@ -276,8 +282,9 @@ class CPHASE(MCPHASE):
|
|
276
282
|
control: int,
|
277
283
|
target: int,
|
278
284
|
parameter: Parameter | TNumber | sympy.Expr | str,
|
285
|
+
noise: NoiseHandler | None = None,
|
279
286
|
):
|
280
|
-
super().__init__((control,), target, parameter)
|
287
|
+
super().__init__((control,), target, parameter, noise=noise)
|
281
288
|
|
282
289
|
|
283
290
|
class CSWAP(ControlBlock):
|
@@ -285,7 +292,13 @@ class CSWAP(ControlBlock):
|
|
285
292
|
|
286
293
|
name = OpName.CSWAP
|
287
294
|
|
288
|
-
def __init__(
|
295
|
+
def __init__(
|
296
|
+
self,
|
297
|
+
control: int | tuple[int, ...],
|
298
|
+
target1: int,
|
299
|
+
target2: int,
|
300
|
+
noise: NoiseHandler | None = None,
|
301
|
+
) -> None:
|
289
302
|
if isinstance(control, tuple):
|
290
303
|
control = control[0]
|
291
304
|
|
@@ -303,7 +316,7 @@ class CSWAP(ControlBlock):
|
|
303
316
|
+ kron(a00p, a21, a12)
|
304
317
|
)
|
305
318
|
self.generator = no_effect + swap_effect
|
306
|
-
super().__init__((control,), SWAP(target1, target2))
|
319
|
+
super().__init__((control,), SWAP(target1, target2), noise=noise)
|
307
320
|
|
308
321
|
@property
|
309
322
|
def eigenvalues_generator(self) -> Tensor:
|
@@ -321,9 +334,11 @@ class CSWAP(ControlBlock):
|
|
321
334
|
class Toffoli(ControlBlock):
|
322
335
|
name = OpName.TOFFOLI
|
323
336
|
|
324
|
-
def __init__(
|
337
|
+
def __init__(
|
338
|
+
self, control: tuple[int, ...], target: int, noise: NoiseHandler | None = None
|
339
|
+
) -> None:
|
325
340
|
self.generator = kron(*[N(qubit) for qubit in control], X(target) - I(target))
|
326
|
-
super().__init__(control, X(target))
|
341
|
+
super().__init__(control, X(target), noise=noise)
|
327
342
|
|
328
343
|
@property
|
329
344
|
def n_qubits(self) -> int:
|
qadence/operations/ham_evo.py
CHANGED
qadence/operations/parametric.py
CHANGED
@@ -15,6 +15,7 @@ from qadence.blocks.utils import (
|
|
15
15
|
add, # noqa
|
16
16
|
chain,
|
17
17
|
)
|
18
|
+
from qadence.noise import NoiseHandler
|
18
19
|
from qadence.parameters import (
|
19
20
|
Parameter,
|
20
21
|
ParamMap,
|
@@ -32,10 +33,15 @@ class PHASE(ParametricBlock):
|
|
32
33
|
|
33
34
|
name = OpName.PHASE
|
34
35
|
|
35
|
-
def __init__(
|
36
|
+
def __init__(
|
37
|
+
self,
|
38
|
+
target: int,
|
39
|
+
parameter: Parameter | TNumber | sympy.Expr | str,
|
40
|
+
noise: NoiseHandler | None = None,
|
41
|
+
) -> None:
|
36
42
|
self.parameters = ParamMap(parameter=parameter)
|
37
43
|
self.generator = I(target) - Z(target)
|
38
|
-
super().__init__((target,))
|
44
|
+
super().__init__((target,), noise=noise)
|
39
45
|
|
40
46
|
@classmethod
|
41
47
|
def num_parameters(cls) -> int:
|
@@ -56,13 +62,18 @@ class RX(ParametricBlock):
|
|
56
62
|
|
57
63
|
name = OpName.RX
|
58
64
|
|
59
|
-
def __init__(
|
65
|
+
def __init__(
|
66
|
+
self,
|
67
|
+
target: int,
|
68
|
+
parameter: Parameter | TParameter | ParamMap,
|
69
|
+
noise: NoiseHandler | None = None,
|
70
|
+
) -> None:
|
60
71
|
# TODO: should we give them more meaningful names? like 'angle'?
|
61
72
|
self.parameters = (
|
62
73
|
parameter if isinstance(parameter, ParamMap) else ParamMap(parameter=parameter)
|
63
74
|
)
|
64
75
|
self.generator = X(target)
|
65
|
-
super().__init__((target,))
|
76
|
+
super().__init__((target,), noise=noise)
|
66
77
|
|
67
78
|
@classmethod
|
68
79
|
def num_parameters(cls) -> int:
|
@@ -84,12 +95,17 @@ class RY(ParametricBlock):
|
|
84
95
|
|
85
96
|
name = OpName.RY
|
86
97
|
|
87
|
-
def __init__(
|
98
|
+
def __init__(
|
99
|
+
self,
|
100
|
+
target: int,
|
101
|
+
parameter: Parameter | TParameter | ParamMap,
|
102
|
+
noise: NoiseHandler | None = None,
|
103
|
+
) -> None:
|
88
104
|
self.parameters = (
|
89
105
|
parameter if isinstance(parameter, ParamMap) else ParamMap(parameter=parameter)
|
90
106
|
)
|
91
107
|
self.generator = Y(target)
|
92
|
-
super().__init__((target,))
|
108
|
+
super().__init__((target,), noise=noise)
|
93
109
|
|
94
110
|
@classmethod
|
95
111
|
def num_parameters(cls) -> int:
|
@@ -111,12 +127,17 @@ class RZ(ParametricBlock):
|
|
111
127
|
|
112
128
|
name = OpName.RZ
|
113
129
|
|
114
|
-
def __init__(
|
130
|
+
def __init__(
|
131
|
+
self,
|
132
|
+
target: int,
|
133
|
+
parameter: Parameter | TParameter | ParamMap,
|
134
|
+
noise: NoiseHandler | None = None,
|
135
|
+
) -> None:
|
115
136
|
self.parameters = (
|
116
137
|
parameter if isinstance(parameter, ParamMap) else ParamMap(parameter=parameter)
|
117
138
|
)
|
118
139
|
self.generator = Z(target)
|
119
|
-
super().__init__((target,))
|
140
|
+
super().__init__((target,), noise=noise)
|
120
141
|
|
121
142
|
@classmethod
|
122
143
|
def num_parameters(cls) -> int:
|
@@ -147,10 +168,11 @@ class U(ParametricBlock):
|
|
147
168
|
phi: Parameter | TParameter,
|
148
169
|
theta: Parameter | TParameter,
|
149
170
|
omega: Parameter | TParameter,
|
150
|
-
|
171
|
+
noise: NoiseHandler | None = None,
|
172
|
+
) -> None:
|
151
173
|
self.parameters = ParamMap(phi=phi, theta=theta, omega=omega)
|
152
174
|
self.generator = chain(Z(target), Y(target), Z(target))
|
153
|
-
super().__init__((target,))
|
175
|
+
super().__init__((target,), noise=noise)
|
154
176
|
|
155
177
|
@classmethod
|
156
178
|
def num_parameters(cls) -> int:
|
qadence/operations/primitive.py
CHANGED
@@ -18,6 +18,7 @@ from qadence.blocks.utils import (
|
|
18
18
|
chain,
|
19
19
|
kron,
|
20
20
|
)
|
21
|
+
from qadence.noise import NoiseHandler
|
21
22
|
from qadence.parameters import (
|
22
23
|
Parameter,
|
23
24
|
)
|
@@ -31,8 +32,8 @@ class X(PrimitiveBlock):
|
|
31
32
|
|
32
33
|
name = OpName.X
|
33
34
|
|
34
|
-
def __init__(self, target: int):
|
35
|
-
super().__init__((target,))
|
35
|
+
def __init__(self, target: int, noise: NoiseHandler | None = None) -> None:
|
36
|
+
super().__init__((target,), noise=noise)
|
36
37
|
|
37
38
|
@property
|
38
39
|
def generator(self) -> AbstractBlock:
|
@@ -52,8 +53,8 @@ class Y(PrimitiveBlock):
|
|
52
53
|
|
53
54
|
name = OpName.Y
|
54
55
|
|
55
|
-
def __init__(self, target: int):
|
56
|
-
super().__init__((target,))
|
56
|
+
def __init__(self, target: int, noise: NoiseHandler | None = None) -> None:
|
57
|
+
super().__init__((target,), noise=noise)
|
57
58
|
|
58
59
|
@property
|
59
60
|
def generator(self) -> AbstractBlock:
|
@@ -73,8 +74,8 @@ class Z(PrimitiveBlock):
|
|
73
74
|
|
74
75
|
name = OpName.Z
|
75
76
|
|
76
|
-
def __init__(self, target: int):
|
77
|
-
super().__init__((target,))
|
77
|
+
def __init__(self, target: int, noise: NoiseHandler | None = None) -> None:
|
78
|
+
super().__init__((target,), noise=noise)
|
78
79
|
|
79
80
|
@property
|
80
81
|
def generator(self) -> AbstractBlock:
|
@@ -94,8 +95,8 @@ class I(PrimitiveBlock):
|
|
94
95
|
|
95
96
|
name = OpName.I
|
96
97
|
|
97
|
-
def __init__(self, target: int):
|
98
|
-
super().__init__((target,))
|
98
|
+
def __init__(self, target: int, noise: NoiseHandler | None = None) -> None:
|
99
|
+
super().__init__((target,), noise=noise)
|
99
100
|
|
100
101
|
def __ixor__(self, other: AbstractBlock | int) -> AbstractBlock:
|
101
102
|
if not isinstance(other, AbstractBlock):
|
@@ -113,7 +114,7 @@ class I(PrimitiveBlock):
|
|
113
114
|
|
114
115
|
@property
|
115
116
|
def generator(self) -> AbstractBlock:
|
116
|
-
return I(
|
117
|
+
return I(self.qubit_support[0])
|
117
118
|
|
118
119
|
@property
|
119
120
|
def eigenvalues_generator(self) -> Tensor:
|
@@ -137,8 +138,9 @@ class Projector(ProjectorBlock):
|
|
137
138
|
ket: str,
|
138
139
|
bra: str,
|
139
140
|
qubit_support: int | tuple[int, ...],
|
140
|
-
|
141
|
-
|
141
|
+
noise: NoiseHandler | None = None,
|
142
|
+
) -> None:
|
143
|
+
super().__init__(ket=ket, bra=bra, qubit_support=qubit_support, noise=noise)
|
142
144
|
|
143
145
|
@property
|
144
146
|
def generator(self) -> None:
|
@@ -154,8 +156,13 @@ class N(Projector):
|
|
154
156
|
|
155
157
|
name = OpName.N
|
156
158
|
|
157
|
-
def __init__(
|
158
|
-
|
159
|
+
def __init__(
|
160
|
+
self,
|
161
|
+
target: int,
|
162
|
+
state: str = "1",
|
163
|
+
noise: NoiseHandler | None = None,
|
164
|
+
) -> None:
|
165
|
+
super().__init__(ket=state, bra=state, qubit_support=(target,), noise=noise)
|
159
166
|
|
160
167
|
@property
|
161
168
|
def generator(self) -> None:
|
@@ -175,9 +182,13 @@ class S(PrimitiveBlock):
|
|
175
182
|
|
176
183
|
name = OpName.S
|
177
184
|
|
178
|
-
def __init__(
|
185
|
+
def __init__(
|
186
|
+
self,
|
187
|
+
target: int,
|
188
|
+
noise: NoiseHandler | None = None,
|
189
|
+
) -> None:
|
179
190
|
self.generator = I(target) - Z(target)
|
180
|
-
super().__init__((target,))
|
191
|
+
super().__init__((target,), noise=noise)
|
181
192
|
|
182
193
|
@property
|
183
194
|
def eigenvalues_generator(self) -> Tensor:
|
@@ -188,7 +199,7 @@ class S(PrimitiveBlock):
|
|
188
199
|
return tensor([1, 1j], dtype=cdouble)
|
189
200
|
|
190
201
|
def dagger(self) -> SDagger:
|
191
|
-
return SDagger(
|
202
|
+
return SDagger(self.qubit_support[0])
|
192
203
|
|
193
204
|
|
194
205
|
class SDagger(PrimitiveBlock):
|
@@ -196,9 +207,13 @@ class SDagger(PrimitiveBlock):
|
|
196
207
|
|
197
208
|
name = OpName.SDAGGER
|
198
209
|
|
199
|
-
def __init__(
|
210
|
+
def __init__(
|
211
|
+
self,
|
212
|
+
target: int,
|
213
|
+
noise: NoiseHandler | None = None,
|
214
|
+
) -> None:
|
200
215
|
self.generator = I(target) - Z(target)
|
201
|
-
super().__init__((target,))
|
216
|
+
super().__init__((target,), noise=noise)
|
202
217
|
|
203
218
|
@property
|
204
219
|
def eigenvalues_generator(self) -> Tensor:
|
@@ -209,7 +224,7 @@ class SDagger(PrimitiveBlock):
|
|
209
224
|
return tensor([1, -1j], dtype=cdouble)
|
210
225
|
|
211
226
|
def dagger(self) -> S:
|
212
|
-
return S(
|
227
|
+
return S(self.qubit_support[0])
|
213
228
|
|
214
229
|
|
215
230
|
class H(PrimitiveBlock):
|
@@ -217,9 +232,13 @@ class H(PrimitiveBlock):
|
|
217
232
|
|
218
233
|
name = OpName.H
|
219
234
|
|
220
|
-
def __init__(
|
235
|
+
def __init__(
|
236
|
+
self,
|
237
|
+
target: int,
|
238
|
+
noise: NoiseHandler | None = None,
|
239
|
+
) -> None:
|
221
240
|
self.generator = (1 / np.sqrt(2)) * (X(target) + Z(target) - np.sqrt(2) * I(target))
|
222
|
-
super().__init__((target,))
|
241
|
+
super().__init__((target,), noise=noise)
|
223
242
|
|
224
243
|
@property
|
225
244
|
def eigenvalues_generator(self) -> Tensor:
|
@@ -275,9 +294,13 @@ class T(PrimitiveBlock):
|
|
275
294
|
|
276
295
|
name = OpName.T
|
277
296
|
|
278
|
-
def __init__(
|
297
|
+
def __init__(
|
298
|
+
self,
|
299
|
+
target: int,
|
300
|
+
noise: NoiseHandler | None = None,
|
301
|
+
) -> None:
|
279
302
|
self.generator = I(target) - Z(target)
|
280
|
-
super().__init__((target,))
|
303
|
+
super().__init__((target,), noise)
|
281
304
|
|
282
305
|
@property
|
283
306
|
def eigenvalues_generator(self) -> Tensor:
|
@@ -292,7 +315,7 @@ class T(PrimitiveBlock):
|
|
292
315
|
return 1
|
293
316
|
|
294
317
|
def dagger(self) -> TDagger:
|
295
|
-
return TDagger(
|
318
|
+
return TDagger(self.qubit_support[0])
|
296
319
|
|
297
320
|
|
298
321
|
class TDagger(PrimitiveBlock):
|
@@ -301,9 +324,13 @@ class TDagger(PrimitiveBlock):
|
|
301
324
|
# FIXME: this gate is not support by any backend
|
302
325
|
name = "T_dagger"
|
303
326
|
|
304
|
-
def __init__(
|
327
|
+
def __init__(
|
328
|
+
self,
|
329
|
+
target: int,
|
330
|
+
noise: NoiseHandler | None = None,
|
331
|
+
) -> None:
|
305
332
|
self.generator = I(target) - Z(target)
|
306
|
-
super().__init__((target,))
|
333
|
+
super().__init__((target,), noise)
|
307
334
|
|
308
335
|
@property
|
309
336
|
def eigenvalues_generator(self) -> Tensor:
|
@@ -318,7 +345,7 @@ class TDagger(PrimitiveBlock):
|
|
318
345
|
return 1
|
319
346
|
|
320
347
|
def dagger(self) -> T:
|
321
|
-
return T(
|
348
|
+
return T(self.qubit_support[0])
|
322
349
|
|
323
350
|
|
324
351
|
class SWAP(PrimitiveBlock):
|
@@ -326,7 +353,12 @@ class SWAP(PrimitiveBlock):
|
|
326
353
|
|
327
354
|
name = OpName.SWAP
|
328
355
|
|
329
|
-
def __init__(
|
356
|
+
def __init__(
|
357
|
+
self,
|
358
|
+
control: int,
|
359
|
+
target: int,
|
360
|
+
noise: NoiseHandler | None = None,
|
361
|
+
) -> None:
|
330
362
|
a11 = 0.5 * (Z(control) - I(control))
|
331
363
|
a22 = -0.5 * (Z(target) + I(target))
|
332
364
|
a12 = 0.5 * (chain(X(control), Z(control)) + X(control))
|
@@ -334,7 +366,7 @@ class SWAP(PrimitiveBlock):
|
|
334
366
|
self.generator = (
|
335
367
|
kron(-1.0 * a22, a11) + kron(-1.0 * a11, a22) + kron(a12, a21) + kron(a21, a12)
|
336
368
|
)
|
337
|
-
super().__init__((control, target))
|
369
|
+
super().__init__((control, target), noise=noise)
|
338
370
|
|
339
371
|
@property
|
340
372
|
def eigenvalues_generator(self) -> Tensor:
|
qadence/overlap.py
CHANGED
@@ -102,9 +102,6 @@ def _select_overlap_method(
|
|
102
102
|
return overlap
|
103
103
|
|
104
104
|
elif method == OverlapMethod.SWAP_TEST:
|
105
|
-
if backend == BackendName.BRAKET:
|
106
|
-
raise ValueError("SWAP test method is not supported by the Braket backend.")
|
107
|
-
|
108
105
|
n_qubits = bra_circuit.n_qubits
|
109
106
|
|
110
107
|
# shift qubit support of bra and ket circuit blocks
|
@@ -128,9 +125,6 @@ def _select_overlap_method(
|
|
128
125
|
return overlap
|
129
126
|
|
130
127
|
elif method == OverlapMethod.HADAMARD_TEST:
|
131
|
-
if backend == BackendName.BRAKET:
|
132
|
-
raise ValueError("Hadamard test method is not supported by the Braket backend.")
|
133
|
-
|
134
128
|
n_qubits = bra_circuit.n_qubits
|
135
129
|
|
136
130
|
# construct controlled bra and ket blocks
|
qadence/parameters.py
CHANGED
@@ -228,7 +228,7 @@ def sympy_to_numeric(expr: Basic) -> TNumber:
|
|
228
228
|
return float(expr)
|
229
229
|
|
230
230
|
|
231
|
-
def evaluate(expr: Expr, values: dict =
|
231
|
+
def evaluate(expr: Expr, values: dict | None = None, as_torch: bool = False) -> TNumber | Tensor:
|
232
232
|
"""
|
233
233
|
Arguments:
|
234
234
|
|
@@ -260,7 +260,8 @@ def evaluate(expr: Expr, values: dict = {}, as_torch: bool = False) -> TNumber |
|
|
260
260
|
"""
|
261
261
|
res: Basic
|
262
262
|
res_value: TNumber | Tensor
|
263
|
-
query: dict[Parameter, TNumber | Tensor] =
|
263
|
+
query: dict[Parameter, TNumber | Tensor] = dict()
|
264
|
+
values = values or dict()
|
264
265
|
if isinstance(expr, Array):
|
265
266
|
return Tensor(expr.tolist())
|
266
267
|
else:
|
qadence/transpile/__init__.py
CHANGED
@@ -12,6 +12,7 @@ from .circuit import fill_identities
|
|
12
12
|
from .digitalize import digitalize
|
13
13
|
from .flatten import flatten
|
14
14
|
from .invert import invert_endianness, reassign
|
15
|
+
from .noise import set_noise
|
15
16
|
from .transpile import blockfn_to_circfn, transpile
|
16
17
|
|
17
|
-
__all__ = ["set_trainable", "invert_endianness"]
|
18
|
+
__all__ = ["set_trainable", "invert_endianness", "set_noise"]
|
@@ -0,0 +1,46 @@
|
|
1
|
+
from __future__ import annotations
|
2
|
+
|
3
|
+
from qadence.blocks.abstract import AbstractBlock
|
4
|
+
from qadence.circuit import QuantumCircuit
|
5
|
+
from qadence.noise.protocols import NoiseHandler
|
6
|
+
|
7
|
+
from .apply_fn import apply_fn_to_blocks
|
8
|
+
|
9
|
+
|
10
|
+
def _set_noise(
|
11
|
+
block: AbstractBlock,
|
12
|
+
noise: NoiseHandler | None,
|
13
|
+
target_class: type[AbstractBlock] | None = None,
|
14
|
+
) -> AbstractBlock:
|
15
|
+
"""Changes the noise protocol of a given block in place."""
|
16
|
+
if target_class is not None:
|
17
|
+
if isinstance(block, target_class):
|
18
|
+
block._noise = noise # type: ignore [attr-defined]
|
19
|
+
else:
|
20
|
+
block._noise = noise # type: ignore [attr-defined]
|
21
|
+
|
22
|
+
return block
|
23
|
+
|
24
|
+
|
25
|
+
def set_noise(
|
26
|
+
circuit: QuantumCircuit | AbstractBlock,
|
27
|
+
noise: NoiseHandler | None,
|
28
|
+
target_class: AbstractBlock | None = None,
|
29
|
+
) -> QuantumCircuit | AbstractBlock:
|
30
|
+
"""
|
31
|
+
Parses a `QuantumCircuit` or `CompositeBlock` to add noise to specific gates.
|
32
|
+
|
33
|
+
Changes the input in place.
|
34
|
+
|
35
|
+
Arguments:
|
36
|
+
circuit: the circuit or block to parse.
|
37
|
+
noise: the NoiseHandler protocol to change to, or `None` to remove the noise.
|
38
|
+
target_class: optional class to selectively add noise to.
|
39
|
+
"""
|
40
|
+
is_circuit_input = isinstance(circuit, QuantumCircuit)
|
41
|
+
|
42
|
+
input_block: AbstractBlock = circuit.block if is_circuit_input else circuit # type: ignore
|
43
|
+
|
44
|
+
output_block = apply_fn_to_blocks(input_block, _set_noise, noise, target_class)
|
45
|
+
|
46
|
+
return circuit
|
qadence/types.py
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
from __future__ import annotations
|
2
2
|
|
3
3
|
import importlib
|
4
|
+
from dataclasses import dataclass
|
4
5
|
from enum import Enum
|
5
6
|
from typing import Callable, Iterable, Tuple, Union
|
6
7
|
|
@@ -8,6 +9,7 @@ import numpy as np
|
|
8
9
|
import sympy
|
9
10
|
from matplotlib.figure import Figure
|
10
11
|
from numpy.typing import ArrayLike
|
12
|
+
from pyqtorch.noise import NoiseType as DigitalNoise
|
11
13
|
from pyqtorch.utils import SolverType
|
12
14
|
from torch import Tensor, pi
|
13
15
|
from torch.nn import Module
|
@@ -26,6 +28,7 @@ TArray = Union[Iterable, Tensor, np.ndarray]
|
|
26
28
|
TGenerator = Union[Tensor, sympy.Array, sympy.Basic]
|
27
29
|
"""Union of torch tensors and numpy arrays."""
|
28
30
|
|
31
|
+
|
29
32
|
PI = pi
|
30
33
|
|
31
34
|
# Modules to be automatically added to the qadence namespace
|
@@ -51,6 +54,7 @@ __all__ = [
|
|
51
54
|
"SerializationFormat",
|
52
55
|
"PI",
|
53
56
|
"SolverType",
|
57
|
+
"NoiseProtocol",
|
54
58
|
] # type: ignore
|
55
59
|
|
56
60
|
|
@@ -221,8 +225,6 @@ class _BackendName(StrEnum):
|
|
221
225
|
|
222
226
|
PYQTORCH = "pyqtorch"
|
223
227
|
"""The Pyqtorch backend."""
|
224
|
-
BRAKET = "braket"
|
225
|
-
"""The Braket backend."""
|
226
228
|
PULSER = "pulser"
|
227
229
|
"""The Pulser backend."""
|
228
230
|
HORQRUX = "horqrux"
|
@@ -457,3 +459,25 @@ class ExperimentTrackingTool(StrEnum):
|
|
457
459
|
|
458
460
|
|
459
461
|
LoggablePlotFunction = Callable[[Module, int], tuple[str, Figure]]
|
462
|
+
|
463
|
+
|
464
|
+
class AnalogNoise(StrEnum):
|
465
|
+
"""Type of noise protocol."""
|
466
|
+
|
467
|
+
DEPOLARIZING = "Depolarizing"
|
468
|
+
DEPHASING = "Dephasing"
|
469
|
+
|
470
|
+
|
471
|
+
@dataclass
|
472
|
+
class NoiseProtocol:
|
473
|
+
"""Type of noise protocol."""
|
474
|
+
|
475
|
+
ANALOG = AnalogNoise
|
476
|
+
"""Noise applied in analog blocks."""
|
477
|
+
READOUT = "Readout"
|
478
|
+
"""Noise applied on outputs of quantum programs."""
|
479
|
+
DIGITAL = DigitalNoise
|
480
|
+
"""Noise applied to digital blocks."""
|
481
|
+
|
482
|
+
|
483
|
+
NoiseEnum = Union[DigitalNoise, AnalogNoise, str]
|