qadence 1.9.2__py3-none-any.whl → 1.10.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/backends/api.py +3 -3
- qadence/backends/horqrux/convert_ops.py +3 -1
- qadence/blocks/embedding.py +7 -6
- qadence/blocks/utils.py +5 -3
- qadence/constructors/__init__.py +5 -4
- qadence/constructors/ala.py +270 -0
- qadence/constructors/{ansatze.py → hea.py} +76 -195
- qadence/constructors/iia.py +31 -0
- qadence/extensions.py +4 -8
- qadence/measurements/shadow.py +30 -10
- qadence/ml_tools/constructors.py +8 -6
- qadence/ml_tools/trainer.py +6 -4
- qadence/operations/control_ops.py +3 -9
- qadence/pasqal_cloud_connection.py +235 -0
- qadence/transpile/digitalize.py +4 -4
- qadence/transpile/flatten.py +4 -4
- qadence/transpile/invert.py +6 -12
- qadence/transpile/transpile.py +2 -4
- {qadence-1.9.2.dist-info → qadence-1.10.0.dist-info}/METADATA +2 -2
- {qadence-1.9.2.dist-info → qadence-1.10.0.dist-info}/RECORD +22 -20
- {qadence-1.9.2.dist-info → qadence-1.10.0.dist-info}/WHEEL +0 -0
- {qadence-1.9.2.dist-info → qadence-1.10.0.dist-info}/licenses/LICENSE +0 -0
@@ -4,11 +4,10 @@ import itertools
|
|
4
4
|
from typing import Any, Type, Union
|
5
5
|
|
6
6
|
from qadence.blocks import AbstractBlock, block_is_qubit_hamiltonian, chain, kron, tag
|
7
|
+
from qadence.constructors.hamiltonians import hamiltonian_factory
|
7
8
|
from qadence.operations import CNOT, CPHASE, CRX, CRY, CRZ, CZ, RX, RY, HamEvo
|
8
9
|
from qadence.types import Interaction, Strategy
|
9
10
|
|
10
|
-
from .hamiltonians import hamiltonian_factory
|
11
|
-
|
12
11
|
DigitalEntanglers = Union[CNOT, CZ, CRZ, CRY, CRX]
|
13
12
|
|
14
13
|
|
@@ -16,7 +15,7 @@ def hea(
|
|
16
15
|
n_qubits: int,
|
17
16
|
depth: int = 1,
|
18
17
|
param_prefix: str = "theta",
|
19
|
-
support: tuple[int, ...] = None,
|
18
|
+
support: tuple[int, ...] | None = None,
|
20
19
|
strategy: Strategy = Strategy.DIGITAL,
|
21
20
|
**strategy_args: Any,
|
22
21
|
) -> AbstractBlock:
|
@@ -24,11 +23,11 @@ def hea(
|
|
24
23
|
Factory function for the Hardware Efficient Ansatz (HEA).
|
25
24
|
|
26
25
|
Args:
|
27
|
-
n_qubits: number of qubits in the
|
26
|
+
n_qubits: number of qubits in the circuit
|
28
27
|
depth: number of layers of the HEA
|
29
28
|
param_prefix: the base name of the variational parameters
|
30
|
-
support: qubit
|
31
|
-
strategy: Strategy.
|
29
|
+
support: qubit indices where the HEA is applied
|
30
|
+
strategy: Strategy for the ansatz. One of the Strategy variants.
|
32
31
|
**strategy_args: see below
|
33
32
|
|
34
33
|
Keyword Arguments:
|
@@ -42,10 +41,13 @@ def hea(
|
|
42
41
|
- Digital: 2-qubit entangling operation. Supports CNOT, CZ,
|
43
42
|
CRX, CRY, CRZ, CPHASE. Controlled rotations will have variational
|
44
43
|
parameters on the rotation angles.
|
45
|
-
-
|
44
|
+
- SDAQC | Analog: Hamiltonian generator for the
|
46
45
|
analog entangling layer. Defaults to global ZZ Hamiltonian.
|
47
46
|
Time parameter is considered variational.
|
48
47
|
|
48
|
+
Returns:
|
49
|
+
The Hardware Efficient Ansatz (HEA) circuit.
|
50
|
+
|
49
51
|
Examples:
|
50
52
|
```python exec="on" source="material-block" result="json"
|
51
53
|
from qadence import RZ, RX
|
@@ -97,10 +99,21 @@ def _rotations_digital(
|
|
97
99
|
n_qubits: int,
|
98
100
|
depth: int,
|
99
101
|
param_prefix: str = "theta",
|
100
|
-
support: tuple[int, ...] = None,
|
102
|
+
support: tuple[int, ...] | None = None,
|
101
103
|
operations: list[Type[AbstractBlock]] = [RX, RY, RX],
|
102
104
|
) -> list[AbstractBlock]:
|
103
|
-
"""Creates the layers of single qubit rotations in an HEA.
|
105
|
+
"""Creates the layers of single qubit rotations in an HEA.
|
106
|
+
|
107
|
+
Args:
|
108
|
+
n_qubits: The number of qubits in the HEA.
|
109
|
+
depth: The number of layers of rotations.
|
110
|
+
param_prefix: The prefix for the parameter names.
|
111
|
+
support: The qubits to apply the rotations to.
|
112
|
+
operations: The operations to apply the rotations with.
|
113
|
+
|
114
|
+
Returns:
|
115
|
+
A list of digital rotation layers in the HEA.
|
116
|
+
"""
|
104
117
|
if support is None:
|
105
118
|
support = tuple(range(n_qubits))
|
106
119
|
iterator = itertools.count()
|
@@ -123,23 +136,50 @@ def _entangler(
|
|
123
136
|
param_str: str,
|
124
137
|
op: Type[DigitalEntanglers] = CNOT,
|
125
138
|
) -> AbstractBlock:
|
139
|
+
"""
|
140
|
+
Create a 2-qubit operation for the digital HEA.
|
141
|
+
|
142
|
+
Args:
|
143
|
+
control (int): control qubit index
|
144
|
+
target (int): target qubit index
|
145
|
+
param_str (str): base for naming the variational parameter if parametric block
|
146
|
+
op (Type[DigitalEntanglers]): 2-qubit operation (CNOT, CZ, CRX, CRY, CRZ or CPHASE)
|
147
|
+
|
148
|
+
Returns:
|
149
|
+
The 2-qubit digital entangler for the HEA.
|
150
|
+
"""
|
126
151
|
if op in [CNOT, CZ]:
|
127
152
|
return op(control, target) # type: ignore
|
128
153
|
elif op in [CRZ, CRY, CRX, CPHASE]:
|
129
154
|
return op(control, target, param_str) # type: ignore
|
130
155
|
else:
|
131
|
-
raise ValueError("Provided entangler not accepted for digital
|
156
|
+
raise ValueError("Provided entangler not accepted for digital ansatz")
|
132
157
|
|
133
158
|
|
134
159
|
def _entanglers_digital(
|
135
160
|
n_qubits: int,
|
136
161
|
depth: int,
|
137
162
|
param_prefix: str = "theta",
|
138
|
-
support: tuple[int, ...] = None,
|
163
|
+
support: tuple[int, ...] | None = None,
|
139
164
|
periodic: bool = False,
|
140
165
|
entangler: Type[DigitalEntanglers] = CNOT,
|
141
166
|
) -> list[AbstractBlock]:
|
142
|
-
"""Creates the layers of digital entangling operations in an HEA.
|
167
|
+
"""Creates the layers of digital entangling operations in an HEA.
|
168
|
+
|
169
|
+
Args:
|
170
|
+
n_qubits (int): number of qubits in the block.
|
171
|
+
depth (int): number of layers of the HEA.
|
172
|
+
param_prefix (str): the base name of the variational parameters
|
173
|
+
support (tuple): qubit indices where the HEA is applied.
|
174
|
+
periodic (bool): if the qubits should be linked periodically.
|
175
|
+
periodic=False is not supported in emu-c.
|
176
|
+
entangler (AbstractBlock): 2-qubit entangling operation.
|
177
|
+
Supports CNOT, CZ, CRX, CRY, CRZ. Controlld rotations
|
178
|
+
will have variational parameters on the rotation angles.
|
179
|
+
|
180
|
+
Returns:
|
181
|
+
The entanglers for the digital Hardware Efficient Ansatz (HEA).
|
182
|
+
"""
|
143
183
|
if support is None:
|
144
184
|
support = tuple(range(n_qubits))
|
145
185
|
iterator = itertools.count()
|
@@ -179,26 +219,29 @@ def hea_digital(
|
|
179
219
|
n_qubits: int,
|
180
220
|
depth: int = 1,
|
181
221
|
param_prefix: str = "theta",
|
222
|
+
support: tuple[int, ...] | None = None,
|
182
223
|
periodic: bool = False,
|
183
224
|
operations: list[type[AbstractBlock]] = [RX, RY, RX],
|
184
|
-
support: tuple[int, ...] = None,
|
185
225
|
entangler: Type[DigitalEntanglers] = CNOT,
|
186
226
|
) -> AbstractBlock:
|
187
227
|
"""
|
188
228
|
Construct the Digital Hardware Efficient Ansatz (HEA).
|
189
229
|
|
190
230
|
Args:
|
191
|
-
n_qubits (int): number of qubits in the
|
231
|
+
n_qubits (int): number of qubits in the cricuit.
|
192
232
|
depth (int): number of layers of the HEA.
|
193
233
|
param_prefix (str): the base name of the variational parameters
|
234
|
+
support (tuple): qubit indices where the HEA is applied.
|
194
235
|
periodic (bool): if the qubits should be linked periodically.
|
195
236
|
periodic=False is not supported in emu-c.
|
196
237
|
operations (list): list of operations to cycle through in the
|
197
238
|
digital single-qubit rotations of each layer.
|
198
|
-
support (tuple): qubit indexes where the HEA is applied.
|
199
239
|
entangler (AbstractBlock): 2-qubit entangling operation.
|
200
240
|
Supports CNOT, CZ, CRX, CRY, CRZ. Controlld rotations
|
201
241
|
will have variational parameters on the rotation angles.
|
242
|
+
|
243
|
+
Returns:
|
244
|
+
The digital Hardware Efficient Ansatz (HEA) circuit.
|
202
245
|
"""
|
203
246
|
try:
|
204
247
|
if entangler not in [CNOT, CZ, CRX, CRY, CRZ, CPHASE]:
|
@@ -242,15 +285,26 @@ def _entanglers_analog(
|
|
242
285
|
param_prefix: str = "theta",
|
243
286
|
entangler: AbstractBlock | None = None,
|
244
287
|
) -> list[AbstractBlock]:
|
245
|
-
|
288
|
+
"""
|
289
|
+
Creates the entanglers for the sDAQC.
|
290
|
+
|
291
|
+
Args:
|
292
|
+
depth: The number of layers of entanglers.
|
293
|
+
param_prefix: The prefix for the parameter names.
|
294
|
+
entangler: The entangler to use.
|
295
|
+
|
296
|
+
Returns:
|
297
|
+
A list of analog entanglers for sDAQC HEA.
|
298
|
+
"""
|
299
|
+
return [HamEvo(entangler, param_prefix + f"_t_{d}") for d in range(depth)] # type: ignore
|
246
300
|
|
247
301
|
|
248
302
|
def hea_sDAQC(
|
249
303
|
n_qubits: int,
|
250
304
|
depth: int = 1,
|
251
305
|
param_prefix: str = "theta",
|
306
|
+
support: tuple[int, ...] | None = None,
|
252
307
|
operations: list[type[AbstractBlock]] = [RX, RY, RX],
|
253
|
-
support: tuple[int, ...] = None,
|
254
308
|
entangler: AbstractBlock | None = None,
|
255
309
|
) -> AbstractBlock:
|
256
310
|
"""
|
@@ -259,15 +313,18 @@ def hea_sDAQC(
|
|
259
313
|
It uses step-wise digital-analog computation.
|
260
314
|
|
261
315
|
Args:
|
262
|
-
n_qubits (int): number of qubits in the
|
316
|
+
n_qubits (int): number of qubits in the circuit.
|
263
317
|
depth (int): number of layers of the HEA.
|
264
318
|
param_prefix (str): the base name of the variational parameters
|
319
|
+
support (tuple): qubit indices where the HEA is applied.
|
265
320
|
operations (list): list of operations to cycle through in the
|
266
321
|
digital single-qubit rotations of each layer.
|
267
|
-
support (tuple): qubit indexes where the HEA is applied.
|
268
322
|
entangler (AbstractBlock): Hamiltonian generator for the
|
269
323
|
analog entangling layer. Defaults to global ZZ Hamiltonian.
|
270
324
|
Time parameter is considered variational.
|
325
|
+
|
326
|
+
Returns:
|
327
|
+
The step-wise digital-analog Hardware Efficient Ansatz (sDA HEA) circuit.
|
271
328
|
"""
|
272
329
|
|
273
330
|
# TODO: Add qubit support
|
@@ -320,179 +377,3 @@ def hea_bDAQC(*args: Any, **kwargs: Any) -> Any:
|
|
320
377
|
|
321
378
|
def hea_analog(*args: Any, **kwargs: Any) -> Any:
|
322
379
|
raise NotImplementedError
|
323
|
-
|
324
|
-
|
325
|
-
def alt(
|
326
|
-
n_qubits: int,
|
327
|
-
m_block_qubits: int,
|
328
|
-
depth: int = 1,
|
329
|
-
param_prefix: str = "theta",
|
330
|
-
support: tuple[int, ...] = None,
|
331
|
-
strategy: Strategy = Strategy.DIGITAL,
|
332
|
-
**strategy_args: Any,
|
333
|
-
) -> AbstractBlock:
|
334
|
-
"""
|
335
|
-
Factory function for the alternating layer ansatz (alt).
|
336
|
-
|
337
|
-
Args:
|
338
|
-
n_qubits: number of qubits in the block
|
339
|
-
m_block_qubits: number of qubits in the local entangling block
|
340
|
-
depth: number of layers of the alt
|
341
|
-
param_prefix: the base name of the variational parameters
|
342
|
-
support: qubit indexes where the alt is applied
|
343
|
-
strategy: Strategy.Digital or Strategy.DigitalAnalog
|
344
|
-
**strategy_args: see below
|
345
|
-
|
346
|
-
Keyword Arguments:
|
347
|
-
operations (list): list of operations to cycle through in the
|
348
|
-
digital single-qubit rotations of each layer. Valid for
|
349
|
-
Digital .
|
350
|
-
entangler (AbstractBlock):
|
351
|
-
- Digital: 2-qubit entangling operation. Supports CNOT, CZ,
|
352
|
-
CRX, CRY, CRZ, CPHASE. Controlled rotations will have variational
|
353
|
-
parameters on the rotation angles.
|
354
|
-
"""
|
355
|
-
|
356
|
-
if support is None:
|
357
|
-
support = tuple(range(n_qubits))
|
358
|
-
|
359
|
-
alt_func_dict = {
|
360
|
-
Strategy.DIGITAL: alt_digital,
|
361
|
-
Strategy.SDAQC: alt_sDAQC,
|
362
|
-
Strategy.BDAQC: alt_bDAQC,
|
363
|
-
Strategy.ANALOG: alt_analog,
|
364
|
-
}
|
365
|
-
|
366
|
-
try:
|
367
|
-
alt_func = alt_func_dict[strategy]
|
368
|
-
except KeyError:
|
369
|
-
raise KeyError(f"Strategy {strategy} not recognized.")
|
370
|
-
|
371
|
-
hea_block: AbstractBlock = alt_func(
|
372
|
-
n_qubits=n_qubits,
|
373
|
-
m_block_qubits=m_block_qubits,
|
374
|
-
depth=depth,
|
375
|
-
param_prefix=param_prefix,
|
376
|
-
support=support,
|
377
|
-
**strategy_args,
|
378
|
-
) # type: ignore
|
379
|
-
|
380
|
-
return hea_block
|
381
|
-
|
382
|
-
|
383
|
-
#################
|
384
|
-
## DIGITAL ALT ##
|
385
|
-
#################
|
386
|
-
|
387
|
-
|
388
|
-
def _entanglers_block_digital(
|
389
|
-
n_qubits: int,
|
390
|
-
m_block_qubits: int,
|
391
|
-
depth: int,
|
392
|
-
param_prefix: str = "theta",
|
393
|
-
support: tuple[int, ...] = None,
|
394
|
-
entangler: Type[DigitalEntanglers] = CNOT,
|
395
|
-
) -> list[AbstractBlock]:
|
396
|
-
if support is None:
|
397
|
-
support = tuple(range(n_qubits))
|
398
|
-
iterator = itertools.count()
|
399
|
-
ent_list: list[AbstractBlock] = []
|
400
|
-
|
401
|
-
for d in range(depth):
|
402
|
-
start_i = 0 if not d % 2 else -m_block_qubits // 2
|
403
|
-
ents = [
|
404
|
-
kron(
|
405
|
-
_entangler(
|
406
|
-
control=support[i + j],
|
407
|
-
target=support[i + j + 1],
|
408
|
-
param_str=param_prefix + f"_ent_{next(iterator)}",
|
409
|
-
op=entangler,
|
410
|
-
)
|
411
|
-
for j in range(start_j, m_block_qubits, 2)
|
412
|
-
for i in range(start_i, n_qubits, m_block_qubits)
|
413
|
-
if i + j + 1 < n_qubits and j + 1 < m_block_qubits and i + j >= 0
|
414
|
-
)
|
415
|
-
for start_j in [i for i in range(2) if m_block_qubits > 2 or i == 0]
|
416
|
-
]
|
417
|
-
|
418
|
-
ent_list.append(chain(*ents))
|
419
|
-
return ent_list
|
420
|
-
|
421
|
-
|
422
|
-
def alt_digital(
|
423
|
-
n_qubits: int,
|
424
|
-
m_block_qubits: int,
|
425
|
-
depth: int = 1,
|
426
|
-
support: tuple[int, ...] = None,
|
427
|
-
param_prefix: str = "theta",
|
428
|
-
operations: list[type[AbstractBlock]] = [RX, RY],
|
429
|
-
entangler: Type[DigitalEntanglers] = CNOT,
|
430
|
-
) -> AbstractBlock:
|
431
|
-
"""
|
432
|
-
Construct the digital alternating layer ansatz (ALT).
|
433
|
-
|
434
|
-
Args:
|
435
|
-
n_qubits (int): number of qubits in the ansatz.
|
436
|
-
m_block_qubits (int): number of qubits in the local entangling block.
|
437
|
-
depth (int): number of layers of the ALT.
|
438
|
-
param_prefix (str): the base name of the variational parameters
|
439
|
-
operations (list): list of operations to cycle through in the
|
440
|
-
digital single-qubit rotations of each layer.
|
441
|
-
support (tuple): qubit indexes where the ALT is applied.
|
442
|
-
entangler (AbstractBlock): 2-qubit entangling operation.
|
443
|
-
Supports CNOT, CZ, CRX, CRY, CRZ. Controlld rotations
|
444
|
-
will have variational parameters on the rotation angles.
|
445
|
-
"""
|
446
|
-
|
447
|
-
try:
|
448
|
-
if entangler not in [CNOT, CZ, CRX, CRY, CRZ, CPHASE]:
|
449
|
-
raise ValueError(
|
450
|
-
"Please provide a valid two-qubit entangler operation for digital ALT."
|
451
|
-
)
|
452
|
-
except TypeError:
|
453
|
-
raise ValueError("Please provide a valid two-qubit entangler operation for digital ALT.")
|
454
|
-
|
455
|
-
rot_list = _rotations_digital(
|
456
|
-
n_qubits=n_qubits,
|
457
|
-
depth=depth,
|
458
|
-
support=support,
|
459
|
-
param_prefix=param_prefix,
|
460
|
-
operations=operations,
|
461
|
-
)
|
462
|
-
|
463
|
-
ent_list = _entanglers_block_digital(
|
464
|
-
n_qubits,
|
465
|
-
m_block_qubits,
|
466
|
-
param_prefix=param_prefix + "_ent",
|
467
|
-
depth=depth,
|
468
|
-
support=support,
|
469
|
-
entangler=entangler,
|
470
|
-
)
|
471
|
-
|
472
|
-
layers = []
|
473
|
-
for d in range(depth):
|
474
|
-
layers.append(rot_list[d])
|
475
|
-
layers.append(ent_list[d])
|
476
|
-
|
477
|
-
return tag(chain(*layers), "ALT")
|
478
|
-
|
479
|
-
|
480
|
-
#################
|
481
|
-
## sdaqc ALT ##
|
482
|
-
#################
|
483
|
-
def alt_sDAQC(*args: Any, **kwargs: Any) -> Any:
|
484
|
-
raise NotImplementedError
|
485
|
-
|
486
|
-
|
487
|
-
#################
|
488
|
-
## bdaqc ALT ##
|
489
|
-
#################
|
490
|
-
def alt_bDAQC(*args: Any, **kwargs: Any) -> Any:
|
491
|
-
raise NotImplementedError
|
492
|
-
|
493
|
-
|
494
|
-
#################
|
495
|
-
## analog ALT ##
|
496
|
-
#################
|
497
|
-
def alt_analog(*args: Any, **kwargs: Any) -> Any:
|
498
|
-
raise NotImplementedError
|
qadence/constructors/iia.py
CHANGED
@@ -32,6 +32,16 @@ def _entangler_analog(
|
|
32
32
|
param_str: str,
|
33
33
|
generator: AbstractBlock | None = None,
|
34
34
|
) -> AbstractBlock:
|
35
|
+
"""
|
36
|
+
Creates the analog entangler for identity initialized ansatz.
|
37
|
+
|
38
|
+
Args:
|
39
|
+
param_str: The parameter string.
|
40
|
+
generator: The Hamiltonian generator for the analog entangler.
|
41
|
+
|
42
|
+
Returns:
|
43
|
+
The analog entangler for the identity initialized ansatz.
|
44
|
+
"""
|
35
45
|
param = Parameter(name=param_str, value=0.0, trainable=True)
|
36
46
|
return HamEvo(generator=generator, parameter=param)
|
37
47
|
|
@@ -44,6 +54,21 @@ def _rotations(
|
|
44
54
|
values: list[float | torch.Tensor],
|
45
55
|
ops: list[type[AbstractBlock]] = [RX, RY],
|
46
56
|
) -> list[KronBlock]:
|
57
|
+
"""
|
58
|
+
Creates the digital rotation layers for the identity initialized ansatz.
|
59
|
+
|
60
|
+
Args:
|
61
|
+
n_qubits: The number of qubits in the identity initialized ansatz.
|
62
|
+
layer: The layer number.
|
63
|
+
side: The side of the a single layer the rotations are applied to.
|
64
|
+
Either 'left' or 'right'.
|
65
|
+
param_str: The parameter string.
|
66
|
+
values: The values of the rotation angles.
|
67
|
+
ops: The operations to apply the rotations with.
|
68
|
+
|
69
|
+
Returns:
|
70
|
+
The digital rotation layers for the identity initialized ansatz.
|
71
|
+
"""
|
47
72
|
if side == "left":
|
48
73
|
idx = lambda x: x # noqa: E731
|
49
74
|
elif side == "right":
|
@@ -106,6 +131,9 @@ def identity_initialized_ansatz(
|
|
106
131
|
Time parameter is considered variational.
|
107
132
|
Defaults to a global NN Hamiltonain.
|
108
133
|
periodic (bool): if the qubits should be linked periodically. Valid only for digital.
|
134
|
+
|
135
|
+
Returns:
|
136
|
+
The identity initialized ansatz circuit.
|
109
137
|
"""
|
110
138
|
initialized_layers = []
|
111
139
|
for layer in range(depth):
|
@@ -212,3 +240,6 @@ def identity_initialized_ansatz(
|
|
212
240
|
initialized_layers.append(tag(chain(*krons), tag=f"BPMA-{layer}"))
|
213
241
|
|
214
242
|
return chain(*initialized_layers)
|
243
|
+
|
244
|
+
|
245
|
+
iia = identity_initialized_ansatz
|
qadence/extensions.py
CHANGED
@@ -15,20 +15,16 @@ EngineClsType = TypeVar("EngineClsType", bound=DifferentiableBackend)
|
|
15
15
|
logger = getLogger(__name__)
|
16
16
|
|
17
17
|
|
18
|
-
class ConfigNotFoundError(ModuleNotFoundError):
|
19
|
-
...
|
18
|
+
class ConfigNotFoundError(ModuleNotFoundError): ...
|
20
19
|
|
21
20
|
|
22
|
-
class BackendNotFoundError(ModuleNotFoundError):
|
23
|
-
...
|
21
|
+
class BackendNotFoundError(ModuleNotFoundError): ...
|
24
22
|
|
25
23
|
|
26
|
-
class EngineNotFoundError(ModuleNotFoundError):
|
27
|
-
...
|
24
|
+
class EngineNotFoundError(ModuleNotFoundError): ...
|
28
25
|
|
29
26
|
|
30
|
-
class SupportedGatesNotFoundError(ModuleNotFoundError):
|
31
|
-
...
|
27
|
+
class SupportedGatesNotFoundError(ModuleNotFoundError): ...
|
32
28
|
|
33
29
|
|
34
30
|
def import_config(backend_name: str | BackendName) -> BackendConfiguration:
|
qadence/measurements/shadow.py
CHANGED
@@ -6,7 +6,7 @@ from torch import Tensor
|
|
6
6
|
|
7
7
|
from qadence.backend import Backend
|
8
8
|
from qadence.backends.pyqtorch import Backend as PyQBackend
|
9
|
-
from qadence.blocks import AbstractBlock, KronBlock,
|
9
|
+
from qadence.blocks import AbstractBlock, KronBlock, kron
|
10
10
|
from qadence.blocks.block_to_tensor import HMAT, IMAT, SDAGMAT
|
11
11
|
from qadence.blocks.composite import CompositeBlock
|
12
12
|
from qadence.blocks.primitive import PrimitiveBlock
|
@@ -16,7 +16,7 @@ from qadence.engines.differentiable_backend import DifferentiableBackend
|
|
16
16
|
from qadence.measurements.utils import get_qubit_indices_for_op
|
17
17
|
from qadence.noise import NoiseHandler
|
18
18
|
from qadence.operations import H, I, SDagger, X, Y, Z
|
19
|
-
from qadence.types import Endianness
|
19
|
+
from qadence.types import BackendName, Endianness
|
20
20
|
|
21
21
|
pauli_gates = [X, Y, Z]
|
22
22
|
pauli_rotations = [
|
@@ -134,20 +134,40 @@ def classical_shadow(
|
|
134
134
|
shadow: list = list()
|
135
135
|
all_rotations = extract_operators(unitary_ids, circuit.n_qubits)
|
136
136
|
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
137
|
+
initial_state = state
|
138
|
+
backend_name = backend.name if hasattr(backend, "name") else backend.backend.name
|
139
|
+
if backend_name == BackendName.PYQTORCH:
|
140
|
+
# run the initial circuit without rotations
|
141
|
+
# to save computation time
|
142
|
+
conv_circ = backend.circuit(circuit)
|
143
|
+
initial_state = backend.run(
|
144
|
+
circuit=conv_circ,
|
145
|
+
param_values=param_values,
|
146
|
+
state=state,
|
147
|
+
endianness=endianness,
|
148
|
+
)
|
149
|
+
all_rotations = [
|
150
|
+
QuantumCircuit(circuit.n_qubits, rots) if rots else QuantumCircuit(circuit.n_qubits)
|
151
|
+
for rots in all_rotations
|
152
|
+
]
|
153
|
+
else:
|
154
|
+
all_rotations = [
|
155
|
+
(
|
156
|
+
QuantumCircuit(circuit.n_qubits, circuit.block, rots)
|
157
|
+
if rots
|
158
|
+
else QuantumCircuit(circuit.n_qubits, circuit.block)
|
141
159
|
)
|
142
|
-
|
143
|
-
|
160
|
+
for rots in all_rotations
|
161
|
+
]
|
162
|
+
|
163
|
+
for i in range(shadow_size):
|
144
164
|
# Reverse endianness to get sample bitstrings in ILO.
|
145
|
-
conv_circ = backend.circuit(
|
165
|
+
conv_circ = backend.circuit(all_rotations[i])
|
146
166
|
batch_samples = backend.sample(
|
147
167
|
circuit=conv_circ,
|
148
168
|
param_values=param_values,
|
149
169
|
n_shots=1,
|
150
|
-
state=
|
170
|
+
state=initial_state,
|
151
171
|
noise=noise,
|
152
172
|
endianness=endianness,
|
153
173
|
)
|
qadence/ml_tools/constructors.py
CHANGED
@@ -13,13 +13,13 @@ from qadence.constructors import (
|
|
13
13
|
analog_feature_map,
|
14
14
|
feature_map,
|
15
15
|
hamiltonian_factory,
|
16
|
-
|
16
|
+
iia,
|
17
17
|
rydberg_feature_map,
|
18
18
|
rydberg_hea,
|
19
19
|
rydberg_tower_feature_map,
|
20
20
|
)
|
21
|
-
from qadence.constructors.ansatze import hea_digital, hea_sDAQC
|
22
21
|
from qadence.constructors.hamiltonians import ObservableConfig, TDetuning
|
22
|
+
from qadence.constructors.hea import hea_digital, hea_sDAQC
|
23
23
|
from qadence.measurements import Measurements
|
24
24
|
from qadence.noise import NoiseHandler
|
25
25
|
from qadence.operations import CNOT, RX, RY, I, N, Z
|
@@ -107,7 +107,8 @@ def _encode_features_series_digital(
|
|
107
107
|
)
|
108
108
|
|
109
109
|
support_arrays = {
|
110
|
-
key: support
|
110
|
+
key: support
|
111
|
+
for key, support in zip(config.inputs, support_arrays_list) # type: ignore[union-attr, arg-type]
|
111
112
|
}
|
112
113
|
|
113
114
|
num_uploads = {key: value + 1 for key, value in config.num_repeats.items()} # type: ignore[union-attr]
|
@@ -163,7 +164,8 @@ def _encode_features_parallel_digital(
|
|
163
164
|
)
|
164
165
|
|
165
166
|
support_arrays = {
|
166
|
-
key: support
|
167
|
+
key: support
|
168
|
+
for key, support in zip(config.inputs, support_arrays_list) # type: ignore[union-attr, arg-type]
|
167
169
|
}
|
168
170
|
|
169
171
|
num_uploads = {key: value + 1 for key, value in config.num_repeats.items()} # type: ignore[union-attr]
|
@@ -412,7 +414,7 @@ def _create_iia_digital(
|
|
412
414
|
entangler = config.strategy_args.get("entangler", CNOT)
|
413
415
|
periodic = config.strategy_args.get("periodic", False)
|
414
416
|
|
415
|
-
return
|
417
|
+
return iia(
|
416
418
|
n_qubits=num_qubits,
|
417
419
|
depth=config.depth,
|
418
420
|
param_prefix=config.param_prefix,
|
@@ -441,7 +443,7 @@ def _create_iia_sdaqc(
|
|
441
443
|
entangler = config.strategy_args.get("entangler", CNOT)
|
442
444
|
periodic = config.strategy_args.get("periodic", False)
|
443
445
|
|
444
|
-
return
|
446
|
+
return iia(
|
445
447
|
n_qubits=num_qubits,
|
446
448
|
depth=config.depth,
|
447
449
|
param_prefix=config.param_prefix,
|
qadence/ml_tools/trainer.py
CHANGED
@@ -632,10 +632,12 @@ class Trainer(BaseTrainer):
|
|
632
632
|
|
633
633
|
def build_optimize_result(
|
634
634
|
self,
|
635
|
-
result:
|
636
|
-
|
637
|
-
|
638
|
-
|
635
|
+
result: (
|
636
|
+
None
|
637
|
+
| tuple[torch.Tensor, dict[Any, Any]]
|
638
|
+
| list[tuple[torch.Tensor, dict[Any, Any]]]
|
639
|
+
| list[list[tuple[torch.Tensor, dict[Any, Any]]]]
|
640
|
+
),
|
639
641
|
) -> None:
|
640
642
|
"""
|
641
643
|
Builds and stores the optimization result by calculating the average loss and metrics.
|
@@ -119,9 +119,7 @@ class MCRX(ParametricControlBlock):
|
|
119
119
|
|
120
120
|
@property
|
121
121
|
def eigenvalues_generator(self) -> Tensor:
|
122
|
-
return torch.cat(
|
123
|
-
(torch.zeros(2**self.n_qubits - 2), torch.tensor([1, -1], dtype=cdouble))
|
124
|
-
)
|
122
|
+
return torch.cat((torch.zeros(2**self.n_qubits - 2), torch.tensor([1, -1], dtype=cdouble)))
|
125
123
|
|
126
124
|
@property
|
127
125
|
def eigenvalues(self) -> Tensor:
|
@@ -164,9 +162,7 @@ class MCRY(ParametricControlBlock):
|
|
164
162
|
|
165
163
|
@property
|
166
164
|
def eigenvalues_generator(self) -> Tensor:
|
167
|
-
return torch.cat(
|
168
|
-
(torch.zeros(2**self.n_qubits - 2), torch.tensor([1, -1], dtype=cdouble))
|
169
|
-
)
|
165
|
+
return torch.cat((torch.zeros(2**self.n_qubits - 2), torch.tensor([1, -1], dtype=cdouble)))
|
170
166
|
|
171
167
|
@property
|
172
168
|
def eigenvalues(self) -> Tensor:
|
@@ -205,9 +201,7 @@ class MCRZ(ParametricControlBlock):
|
|
205
201
|
|
206
202
|
@property
|
207
203
|
def eigenvalues_generator(self) -> Tensor:
|
208
|
-
return torch.cat(
|
209
|
-
(torch.zeros(2**self.n_qubits - 2), torch.tensor([1, -1], dtype=cdouble))
|
210
|
-
)
|
204
|
+
return torch.cat((torch.zeros(2**self.n_qubits - 2), torch.tensor([1, -1], dtype=cdouble)))
|
211
205
|
|
212
206
|
@property
|
213
207
|
def eigenvalues(self) -> Tensor:
|