qadence 1.1.1__py3-none-any.whl → 1.2.1__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/analog/__init__.py +4 -2
- qadence/analog/addressing.py +167 -0
- qadence/analog/constants.py +59 -0
- qadence/analog/device.py +82 -0
- qadence/analog/hamiltonian_terms.py +101 -0
- qadence/analog/parse_analog.py +120 -0
- qadence/backend.py +42 -12
- qadence/backends/__init__.py +1 -2
- qadence/backends/api.py +27 -9
- qadence/backends/braket/backend.py +3 -2
- qadence/backends/horqrux/__init__.py +5 -0
- qadence/backends/horqrux/backend.py +216 -0
- qadence/backends/horqrux/config.py +26 -0
- qadence/backends/horqrux/convert_ops.py +273 -0
- qadence/backends/jax_utils.py +45 -0
- qadence/backends/pulser/__init__.py +0 -1
- qadence/backends/pulser/backend.py +31 -15
- qadence/backends/pulser/config.py +19 -10
- qadence/backends/pulser/devices.py +57 -63
- qadence/backends/pulser/pulses.py +70 -12
- qadence/backends/pyqtorch/backend.py +4 -4
- qadence/backends/pyqtorch/config.py +18 -12
- qadence/backends/pyqtorch/convert_ops.py +15 -7
- qadence/backends/utils.py +5 -9
- qadence/blocks/abstract.py +5 -1
- qadence/blocks/analog.py +18 -9
- qadence/blocks/block_to_tensor.py +11 -0
- qadence/blocks/embedding.py +46 -24
- qadence/blocks/primitive.py +81 -9
- qadence/blocks/utils.py +20 -1
- qadence/circuit.py +3 -9
- qadence/constructors/__init__.py +4 -0
- qadence/constructors/feature_maps.py +84 -60
- qadence/constructors/hamiltonians.py +27 -98
- qadence/constructors/rydberg_feature_maps.py +113 -0
- qadence/divergences.py +12 -0
- qadence/engines/__init__.py +0 -0
- qadence/engines/differentiable_backend.py +152 -0
- qadence/engines/jax/__init__.py +8 -0
- qadence/engines/jax/differentiable_backend.py +73 -0
- qadence/engines/jax/differentiable_expectation.py +94 -0
- qadence/engines/torch/__init__.py +4 -0
- qadence/engines/torch/differentiable_backend.py +85 -0
- qadence/extensions.py +21 -9
- qadence/finitediff.py +47 -0
- qadence/mitigations/readout.py +92 -25
- qadence/ml_tools/models.py +10 -3
- qadence/models/qnn.py +88 -23
- qadence/models/quantum_model.py +13 -2
- qadence/operations.py +55 -70
- qadence/parameters.py +24 -13
- qadence/register.py +91 -43
- qadence/transpile/__init__.py +1 -0
- qadence/transpile/apply_fn.py +40 -0
- qadence/types.py +32 -2
- qadence/utils.py +35 -0
- {qadence-1.1.1.dist-info → qadence-1.2.1.dist-info}/METADATA +22 -3
- {qadence-1.1.1.dist-info → qadence-1.2.1.dist-info}/RECORD +62 -44
- {qadence-1.1.1.dist-info → qadence-1.2.1.dist-info}/WHEEL +1 -1
- qadence/analog/interaction.py +0 -198
- qadence/analog/utils.py +0 -132
- /qadence/{backends/pytorch_wrapper.py → engines/torch/differentiable_expectation.py} +0 -0
- {qadence-1.1.1.dist-info → qadence-1.2.1.dist-info}/licenses/LICENSE +0 -0
qadence/analog/interaction.py
DELETED
@@ -1,198 +0,0 @@
|
|
1
|
-
from __future__ import annotations
|
2
|
-
|
3
|
-
from copy import deepcopy
|
4
|
-
from functools import singledispatch
|
5
|
-
from itertools import product
|
6
|
-
from typing import Any, Callable, Union, overload
|
7
|
-
|
8
|
-
import torch
|
9
|
-
|
10
|
-
from qadence.analog.utils import ising_interaction, rot_generator, xy_interaction
|
11
|
-
from qadence.blocks.abstract import AbstractBlock
|
12
|
-
from qadence.blocks.analog import (
|
13
|
-
AnalogBlock,
|
14
|
-
AnalogChain,
|
15
|
-
AnalogKron,
|
16
|
-
ConstantAnalogRotation,
|
17
|
-
Interaction,
|
18
|
-
WaitBlock,
|
19
|
-
)
|
20
|
-
from qadence.blocks.composite import CompositeBlock
|
21
|
-
from qadence.blocks.primitive import PrimitiveBlock, ScaleBlock
|
22
|
-
from qadence.blocks.utils import _construct, add, chain, kron
|
23
|
-
from qadence.circuit import QuantumCircuit
|
24
|
-
from qadence.operations import HamEvo, I, wait
|
25
|
-
from qadence.qubit_support import QubitSupport
|
26
|
-
from qadence.register import Register
|
27
|
-
from qadence.transpile.transpile import blockfn_to_circfn
|
28
|
-
|
29
|
-
INTERACTIONS = {Interaction.NN: ising_interaction, Interaction.XY: xy_interaction}
|
30
|
-
|
31
|
-
|
32
|
-
@overload
|
33
|
-
def add_interaction(circuit: QuantumCircuit, **kwargs: Any) -> QuantumCircuit:
|
34
|
-
...
|
35
|
-
|
36
|
-
|
37
|
-
@overload
|
38
|
-
def add_interaction(block: AbstractBlock, **kwargs: Any) -> AbstractBlock:
|
39
|
-
...
|
40
|
-
|
41
|
-
|
42
|
-
@overload
|
43
|
-
def add_interaction(register: Register, block: AbstractBlock, **kwargs: Any) -> AbstractBlock:
|
44
|
-
...
|
45
|
-
|
46
|
-
|
47
|
-
@singledispatch
|
48
|
-
def add_interaction(
|
49
|
-
x: Register | QuantumCircuit | AbstractBlock,
|
50
|
-
*args: Any,
|
51
|
-
interaction: Interaction | Callable = Interaction.NN,
|
52
|
-
) -> QuantumCircuit | AbstractBlock:
|
53
|
-
"""Turns blocks or circuits into (a chain of) `HamEvo` blocks.
|
54
|
-
|
55
|
-
This includes a chosen interaction term.
|
56
|
-
|
57
|
-
This is a `@singledipatch`ed function which can be called in three ways:
|
58
|
-
|
59
|
-
* With a `QuantumCircuit` which contains all necessary information: `add_interaction(circuit)`
|
60
|
-
* With a `Register` and an `AbstractBlock`: `add_interaction(reg, block)`
|
61
|
-
* With an `AbstractBlock` only: `add_interaction(block)`
|
62
|
-
|
63
|
-
See the section about [analog blocks](/digital_analog_qc/analog-basics.md) for
|
64
|
-
detailed information about how which types of blocks are translated.
|
65
|
-
|
66
|
-
Arguments:
|
67
|
-
x: Circuit or block to be emulated. See the examples on which argument
|
68
|
-
combinations are accepted.
|
69
|
-
interaction: Type of interaction that is added. Can also be a function that accepts a
|
70
|
-
register and a list of edges that define which qubits interact (see the examples).
|
71
|
-
|
72
|
-
Examples:
|
73
|
-
```python exec="on" source="material-block" result="json"
|
74
|
-
from qadence import QuantumCircuit, AnalogRX, add_interaction
|
75
|
-
|
76
|
-
c = QuantumCircuit(2, AnalogRX(2.0))
|
77
|
-
e = add_interaction(c)
|
78
|
-
print(str(e.block.generator)) # markdown-exec: hide
|
79
|
-
```
|
80
|
-
You can also use `add_interaction` directly on a block, but you have to provide either
|
81
|
-
the `Register` or define a non-global qubit support.
|
82
|
-
```python exec="on" source="material-block" result="json"
|
83
|
-
from qadence import AnalogRX, Register, add_interaction
|
84
|
-
|
85
|
-
b = AnalogRX(2.0)
|
86
|
-
r = Register(1)
|
87
|
-
e = add_interaction(r, b)
|
88
|
-
print(e.generator) # markdown-exec: hide
|
89
|
-
|
90
|
-
# or provide only the block with local qubit support
|
91
|
-
# in this case the register is created via `Register(b.n_qubits)`
|
92
|
-
e = add_interaction(AnalogRX(2.0, qubit_support=(0,)))
|
93
|
-
print(e.generator)
|
94
|
-
```
|
95
|
-
You can specify a custom `interaction` function which has to accept a `Register` and a list
|
96
|
-
of `edges: list[tuple[int, int]]`:
|
97
|
-
```python exec="on" source="material-block" result="json"
|
98
|
-
from qadence import AnalogRX, Register, add_interaction
|
99
|
-
from qadence.analog.utils import ising_interaction
|
100
|
-
|
101
|
-
def int_fn(r: Register, pairs: list[tuple[int, int]]) -> AbstractBlock:
|
102
|
-
# do either something completely custom
|
103
|
-
# ...
|
104
|
-
# or e.g. change the default kwargs to `ising_interaction`
|
105
|
-
return ising_interaction(r, pairs, rydberg_level=70)
|
106
|
-
|
107
|
-
b = AnalogRX(2.0)
|
108
|
-
r = Register(1)
|
109
|
-
e = add_interaction(r, b, interaction=int_fn)
|
110
|
-
```
|
111
|
-
"""
|
112
|
-
raise ValueError(f"`add_interaction` is not implemented for {type(x)}")
|
113
|
-
|
114
|
-
|
115
|
-
@add_interaction.register # type: ignore[attr-defined]
|
116
|
-
def _(circuit: QuantumCircuit, **kwargs: Any) -> QuantumCircuit:
|
117
|
-
reg = circuit.register
|
118
|
-
return blockfn_to_circfn(lambda b: add_interaction(reg, b, **kwargs))(circuit)
|
119
|
-
|
120
|
-
|
121
|
-
@add_interaction.register # type: ignore[attr-defined]
|
122
|
-
def _(block: AbstractBlock, **kwargs: Any) -> AbstractBlock:
|
123
|
-
return add_interaction(Register(block.n_qubits), block, **kwargs)
|
124
|
-
|
125
|
-
|
126
|
-
@add_interaction.register # type: ignore[attr-defined]
|
127
|
-
def _(
|
128
|
-
register: Register,
|
129
|
-
block: AbstractBlock,
|
130
|
-
interaction: Union[Interaction, Callable] = Interaction.NN,
|
131
|
-
) -> AbstractBlock:
|
132
|
-
try:
|
133
|
-
fn = interaction if callable(interaction) else INTERACTIONS[Interaction(interaction)]
|
134
|
-
except KeyError:
|
135
|
-
raise KeyError(
|
136
|
-
"Function `add_interaction` only supports NN and XY, or a custom callable function."
|
137
|
-
)
|
138
|
-
return _add_interaction(block, register, fn) # type: ignore[arg-type]
|
139
|
-
|
140
|
-
|
141
|
-
@singledispatch
|
142
|
-
def _add_interaction(b: AbstractBlock, r: Register, interaction: Callable) -> AbstractBlock:
|
143
|
-
raise NotImplementedError(f"Cannot emulate {type(b)}")
|
144
|
-
|
145
|
-
|
146
|
-
@_add_interaction.register
|
147
|
-
def _(b: CompositeBlock, r: Register, i: Callable) -> AbstractBlock:
|
148
|
-
return _construct(type(b), tuple(map(lambda b: _add_interaction(b, r, i), b.blocks)))
|
149
|
-
|
150
|
-
|
151
|
-
@_add_interaction.register
|
152
|
-
def _(block: ScaleBlock, register: Register, interaction: Callable) -> AbstractBlock:
|
153
|
-
if isinstance(block.block, AnalogBlock):
|
154
|
-
raise NotImplementedError("Scaling emulated analog blocks is not implemented.")
|
155
|
-
return block
|
156
|
-
|
157
|
-
|
158
|
-
@_add_interaction.register
|
159
|
-
def _(block: PrimitiveBlock, register: Register, interaction: Callable) -> AbstractBlock:
|
160
|
-
return block
|
161
|
-
|
162
|
-
|
163
|
-
@_add_interaction.register
|
164
|
-
def _(block: WaitBlock, register: Register, interaction: Callable) -> AbstractBlock:
|
165
|
-
duration = block.parameters.duration
|
166
|
-
|
167
|
-
support = tuple(range(register.n_qubits))
|
168
|
-
assert support == block.qubit_support if not block.qubit_support.is_global else True
|
169
|
-
pairs = list(filter(lambda x: x[0] < x[1], product(support, support)))
|
170
|
-
|
171
|
-
return HamEvo(interaction(register, pairs), duration / 1000) if len(pairs) else I(0)
|
172
|
-
|
173
|
-
|
174
|
-
@_add_interaction.register
|
175
|
-
def _(block: ConstantAnalogRotation, register: Register, interaction: Callable) -> AbstractBlock:
|
176
|
-
# convert "global" to indexed qubit suppport so that we can re-use `kron` dispatched function
|
177
|
-
b = deepcopy(block)
|
178
|
-
b.qubit_support = QubitSupport(*range(register.n_qubits))
|
179
|
-
return _add_interaction(kron(b), register, interaction)
|
180
|
-
|
181
|
-
|
182
|
-
@_add_interaction.register
|
183
|
-
def _(block: AnalogKron, register: Register, interaction: Callable) -> AbstractBlock:
|
184
|
-
from qadence import block_to_tensor
|
185
|
-
|
186
|
-
w_block = wait(duration=block.duration, qubit_support=block.qubit_support)
|
187
|
-
i_terms = add_interaction(register, w_block, interaction=interaction)
|
188
|
-
|
189
|
-
generator = add(rot_generator(b) for b in block.blocks if isinstance(b, ConstantAnalogRotation))
|
190
|
-
generator = generator if i_terms == I(0) else generator + i_terms.generator # type: ignore[attr-defined] # noqa: E501
|
191
|
-
|
192
|
-
norm = torch.norm(block_to_tensor(generator)).item()
|
193
|
-
return HamEvo(generator / norm, norm * block.duration / 1000)
|
194
|
-
|
195
|
-
|
196
|
-
@_add_interaction.register
|
197
|
-
def _(block: AnalogChain, register: Register, interaction: Callable) -> AbstractBlock:
|
198
|
-
return chain(add_interaction(register, b, interaction=interaction) for b in block.blocks)
|
qadence/analog/utils.py
DELETED
@@ -1,132 +0,0 @@
|
|
1
|
-
from __future__ import annotations
|
2
|
-
|
3
|
-
from math import dist as euclidean_distance
|
4
|
-
|
5
|
-
from sympy import cos, sin
|
6
|
-
|
7
|
-
from qadence.blocks.abstract import AbstractBlock
|
8
|
-
from qadence.blocks.analog import (
|
9
|
-
ConstantAnalogRotation,
|
10
|
-
)
|
11
|
-
from qadence.blocks.utils import add, kron
|
12
|
-
from qadence.operations import N, X, Y
|
13
|
-
from qadence.register import Register
|
14
|
-
|
15
|
-
# Ising coupling coefficient depending on the Rydberg level
|
16
|
-
# Include a normalization to the Planck constant hbar
|
17
|
-
# In units of [rad . µm^6 / µs]
|
18
|
-
|
19
|
-
C6_DICT = {
|
20
|
-
50: 96120.72,
|
21
|
-
51: 122241.6,
|
22
|
-
52: 154693.02,
|
23
|
-
53: 194740.36,
|
24
|
-
54: 243973.91,
|
25
|
-
55: 304495.01,
|
26
|
-
56: 378305.98,
|
27
|
-
57: 468027.05,
|
28
|
-
58: 576714.85,
|
29
|
-
59: 707911.38,
|
30
|
-
60: 865723.02,
|
31
|
-
61: 1054903.11,
|
32
|
-
62: 1281042.11,
|
33
|
-
63: 1550531.15,
|
34
|
-
64: 1870621.31,
|
35
|
-
65: 2249728.57,
|
36
|
-
66: 2697498.69,
|
37
|
-
67: 3224987.51,
|
38
|
-
68: 3844734.37,
|
39
|
-
69: 4571053.32,
|
40
|
-
70: 5420158.53,
|
41
|
-
71: 6410399.4,
|
42
|
-
72: 7562637.31,
|
43
|
-
73: 8900342.14,
|
44
|
-
74: 10449989.62,
|
45
|
-
75: 12241414.53,
|
46
|
-
76: 14308028.03,
|
47
|
-
77: 16687329.94,
|
48
|
-
78: 19421333.62,
|
49
|
-
79: 22557029.94,
|
50
|
-
80: 26146720.74,
|
51
|
-
81: 30248886.65,
|
52
|
-
82: 34928448.69,
|
53
|
-
83: 40257623.67,
|
54
|
-
84: 46316557.88,
|
55
|
-
85: 53194043.52,
|
56
|
-
86: 60988354.64,
|
57
|
-
87: 69808179.15,
|
58
|
-
88: 79773468.88,
|
59
|
-
89: 91016513.07,
|
60
|
-
90: 103677784.57,
|
61
|
-
91: 117933293.96,
|
62
|
-
92: 133943541.9,
|
63
|
-
93: 151907135.94,
|
64
|
-
94: 172036137.34,
|
65
|
-
95: 194562889.89,
|
66
|
-
96: 219741590.56,
|
67
|
-
97: 247850178.91,
|
68
|
-
98: 279192193.77,
|
69
|
-
99: 314098829.39,
|
70
|
-
100: 352931119.11,
|
71
|
-
}
|
72
|
-
|
73
|
-
|
74
|
-
def _qubitposition(register: Register, i: int) -> tuple[int, int]:
|
75
|
-
(x, y) = list(register.coords.values())[i]
|
76
|
-
return (x, y)
|
77
|
-
|
78
|
-
|
79
|
-
def ising_interaction(
|
80
|
-
register: Register, pairs: list[tuple[int, int]], rydberg_level: int = 60
|
81
|
-
) -> AbstractBlock:
|
82
|
-
"""
|
83
|
-
Computes the Rydberg Ising interaction Hamiltonian for a register of qubits.
|
84
|
-
|
85
|
-
H_int = ∑_(j<i) (C_6 / R**6) * kron(N_i, N_j)
|
86
|
-
|
87
|
-
Args:
|
88
|
-
register: the register of qubits.
|
89
|
-
pairs: a list of all pairs of interacting qubits.
|
90
|
-
rydberg_level: determines the value of C_6
|
91
|
-
"""
|
92
|
-
c6 = C6_DICT[rydberg_level]
|
93
|
-
|
94
|
-
def term(i: int, j: int) -> AbstractBlock:
|
95
|
-
qi, qj = _qubitposition(register, i), _qubitposition(register, j)
|
96
|
-
rij = euclidean_distance(qi, qj)
|
97
|
-
return (c6 / rij**6) * kron(N(i), N(j))
|
98
|
-
|
99
|
-
return add(term(i, j) for (i, j) in pairs)
|
100
|
-
|
101
|
-
|
102
|
-
def xy_interaction(
|
103
|
-
register: Register, pairs: list[tuple[int, int]], c3: float = 3700.0
|
104
|
-
) -> AbstractBlock:
|
105
|
-
"""
|
106
|
-
Computes the Rydberg XY interaction Hamiltonian for a register of qubits.
|
107
|
-
|
108
|
-
H_int = ∑_(j<i) (C_3 / R**3) * (kron(X_i, X_j) + kron(Y_i, Y_j))
|
109
|
-
|
110
|
-
Args:
|
111
|
-
register: the register of qubits.
|
112
|
-
pairs: a list of all pairs of interacting qubits.
|
113
|
-
c3: the coefficient value of C_3 in units of [rad . µm^3 / µs]
|
114
|
-
"""
|
115
|
-
|
116
|
-
def term(i: int, j: int) -> AbstractBlock:
|
117
|
-
qi, qj = _qubitposition(register, i), _qubitposition(register, j)
|
118
|
-
rij = euclidean_distance(qi, qj)
|
119
|
-
return (c3 / rij**3) * (kron(X(i), X(j)) + kron(Y(i), Y(j)))
|
120
|
-
|
121
|
-
return add(term(i, j) for (i, j) in pairs)
|
122
|
-
|
123
|
-
|
124
|
-
def rot_generator(block: ConstantAnalogRotation) -> AbstractBlock:
|
125
|
-
omega = block.parameters.omega
|
126
|
-
delta = block.parameters.delta
|
127
|
-
phase = block.parameters.phase
|
128
|
-
support = block.qubit_support
|
129
|
-
|
130
|
-
x_terms = (omega / 2) * add(cos(phase) * X(i) - sin(phase) * Y(i) for i in support)
|
131
|
-
z_terms = delta * add(N(i) for i in support)
|
132
|
-
return x_terms - z_terms # type: ignore[no-any-return]
|
File without changes
|
File without changes
|