qilisdk 0.1.3__py3-none-any.whl → 0.1.5__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.
- qilisdk/__init__.py +11 -2
- qilisdk/__init__.pyi +2 -3
- qilisdk/_logging.py +135 -0
- qilisdk/_optionals.py +5 -7
- qilisdk/analog/__init__.py +3 -18
- qilisdk/analog/exceptions.py +2 -4
- qilisdk/analog/hamiltonian.py +455 -110
- qilisdk/analog/linear_schedule.py +118 -0
- qilisdk/analog/schedule.py +272 -79
- qilisdk/backends/__init__.py +45 -0
- qilisdk/{digital/digital_algorithm.py → backends/__init__.pyi} +3 -5
- qilisdk/backends/backend.py +117 -0
- qilisdk/{extras/cuda → backends}/cuda_backend.py +153 -161
- qilisdk/backends/qutip_backend.py +492 -0
- qilisdk/common/__init__.py +48 -2
- qilisdk/common/algorithm.py +2 -1
- qilisdk/{extras/qaas/qaas_settings.py → common/exceptions.py} +12 -6
- qilisdk/common/model.py +1019 -1
- qilisdk/common/parameterizable.py +75 -0
- qilisdk/common/qtensor.py +666 -0
- qilisdk/common/result.py +2 -1
- qilisdk/common/variables.py +1931 -0
- qilisdk/{extras/cuda/cuda_analog_result.py → cost_functions/__init__.py} +3 -4
- qilisdk/cost_functions/cost_function.py +77 -0
- qilisdk/cost_functions/model_cost_function.py +145 -0
- qilisdk/cost_functions/observable_cost_function.py +109 -0
- qilisdk/digital/__init__.py +3 -22
- qilisdk/digital/ansatz.py +203 -160
- qilisdk/digital/circuit.py +81 -9
- qilisdk/digital/exceptions.py +12 -6
- qilisdk/digital/gates.py +228 -85
- qilisdk/{extras/qaas/qaas_analog_result.py → functionals/__init__.py} +14 -5
- qilisdk/functionals/functional.py +39 -0
- qilisdk/{extras/cuda/cuda_digital_result.py → functionals/functional_result.py} +3 -4
- qilisdk/functionals/sampling.py +81 -0
- qilisdk/functionals/sampling_result.py +92 -0
- qilisdk/functionals/time_evolution.py +98 -0
- qilisdk/functionals/time_evolution_result.py +84 -0
- qilisdk/functionals/variational_program.py +80 -0
- qilisdk/functionals/variational_program_result.py +69 -0
- qilisdk/logging_config.yaml +16 -0
- qilisdk/{common/backend.py → optimizers/__init__.py} +2 -1
- qilisdk/optimizers/optimizer.py +39 -0
- qilisdk/{common → optimizers}/optimizer_result.py +3 -12
- qilisdk/{common/optimizer.py → optimizers/scipy_optimizer.py} +10 -28
- qilisdk/settings.py +78 -0
- qilisdk/{extras → speqtrum}/__init__.py +7 -8
- qilisdk/{extras → speqtrum}/__init__.pyi +3 -3
- qilisdk/speqtrum/experiments/__init__.py +25 -0
- qilisdk/speqtrum/experiments/experiment_functional.py +124 -0
- qilisdk/speqtrum/experiments/experiment_result.py +231 -0
- qilisdk/{extras/qaas → speqtrum}/keyring.py +8 -4
- qilisdk/speqtrum/speqtrum.py +432 -0
- qilisdk/speqtrum/speqtrum_models.py +300 -0
- qilisdk/utils/__init__.py +0 -14
- qilisdk/utils/openqasm2.py +1 -1
- qilisdk/utils/serialization.py +1 -1
- qilisdk/utils/visualization/PlusJakartaSans-SemiBold.ttf +0 -0
- qilisdk/utils/visualization/__init__.py +24 -0
- qilisdk/utils/visualization/circuit_renderers.py +781 -0
- qilisdk/utils/visualization/schedule_renderers.py +161 -0
- qilisdk/utils/visualization/style.py +154 -0
- qilisdk/utils/visualization/themes.py +76 -0
- qilisdk/yaml.py +126 -0
- {qilisdk-0.1.3.dist-info → qilisdk-0.1.5.dist-info}/METADATA +180 -135
- qilisdk-0.1.5.dist-info/RECORD +69 -0
- qilisdk/analog/algorithms.py +0 -111
- qilisdk/analog/analog_backend.py +0 -43
- qilisdk/analog/analog_result.py +0 -114
- qilisdk/analog/quantum_objects.py +0 -533
- qilisdk/digital/digital_backend.py +0 -90
- qilisdk/digital/digital_result.py +0 -145
- qilisdk/digital/vqe.py +0 -166
- qilisdk/extras/cuda/__init__.py +0 -13
- qilisdk/extras/qaas/__init__.py +0 -13
- qilisdk/extras/qaas/models.py +0 -132
- qilisdk/extras/qaas/qaas_backend.py +0 -255
- qilisdk/extras/qaas/qaas_digital_result.py +0 -20
- qilisdk/extras/qaas/qaas_time_evolution_result.py +0 -20
- qilisdk/extras/qaas/qaas_vqe_result.py +0 -20
- qilisdk-0.1.3.dist-info/RECORD +0 -51
- {qilisdk-0.1.3.dist-info → qilisdk-0.1.5.dist-info}/WHEEL +0 -0
- {qilisdk-0.1.3.dist-info → qilisdk-0.1.5.dist-info}/licenses/LICENCE +0 -0
qilisdk/digital/gates.py
CHANGED
|
@@ -20,6 +20,8 @@ import numpy as np
|
|
|
20
20
|
from scipy.linalg import expm
|
|
21
21
|
from typing_extensions import Self
|
|
22
22
|
|
|
23
|
+
from qilisdk.common.parameterizable import Parameterizable
|
|
24
|
+
from qilisdk.common.variables import Parameter
|
|
23
25
|
from qilisdk.yaml import yaml
|
|
24
26
|
|
|
25
27
|
from .exceptions import (
|
|
@@ -32,7 +34,7 @@ from .exceptions import (
|
|
|
32
34
|
TBasicGate = TypeVar("TBasicGate", bound="BasicGate")
|
|
33
35
|
|
|
34
36
|
|
|
35
|
-
class Gate(ABC):
|
|
37
|
+
class Gate(Parameterizable, ABC):
|
|
36
38
|
"""
|
|
37
39
|
Represents a quantum gate that can be used in quantum circuits.
|
|
38
40
|
"""
|
|
@@ -103,54 +105,60 @@ class Gate(ABC):
|
|
|
103
105
|
return len(self.qubits)
|
|
104
106
|
|
|
105
107
|
@property
|
|
106
|
-
def
|
|
108
|
+
def nparameters(self) -> int:
|
|
107
109
|
"""
|
|
108
|
-
Retrieve
|
|
110
|
+
Retrieve the number of parameters for the gate.
|
|
109
111
|
|
|
110
112
|
Returns:
|
|
111
|
-
|
|
113
|
+
int: The count of parameters needed by the gate.
|
|
112
114
|
"""
|
|
113
|
-
return
|
|
115
|
+
return len(self.get_parameters())
|
|
114
116
|
|
|
115
117
|
@property
|
|
116
|
-
def
|
|
118
|
+
def is_parameterized(self) -> bool:
|
|
117
119
|
"""
|
|
118
|
-
|
|
120
|
+
Determine whether the gate requires parameters.
|
|
119
121
|
|
|
120
122
|
Returns:
|
|
121
|
-
|
|
123
|
+
bool: True if the gate is parameterized; otherwise, False.
|
|
122
124
|
"""
|
|
123
|
-
return
|
|
125
|
+
return self.nparameters != 0
|
|
124
126
|
|
|
125
127
|
@property
|
|
126
|
-
def
|
|
128
|
+
def parameters(self) -> dict[str, Parameter]:
|
|
129
|
+
"""Returns the raw parameter objects stored in the gate.
|
|
130
|
+
|
|
131
|
+
Returns:
|
|
132
|
+
dict[str, Parameter]: A dictionary mapping each Parameter object to its label.
|
|
127
133
|
"""
|
|
128
|
-
|
|
134
|
+
return {}
|
|
135
|
+
|
|
136
|
+
def get_parameters(self) -> dict[str, float]: # noqa: PLR6301
|
|
137
|
+
"""
|
|
138
|
+
Retrieve a mapping of parameter names to their corresponding values.
|
|
129
139
|
|
|
130
140
|
Returns:
|
|
131
|
-
|
|
141
|
+
dict[str, float]: A dictionary mapping each parameter name to its numeric value.
|
|
132
142
|
"""
|
|
133
|
-
return
|
|
143
|
+
return {}
|
|
134
144
|
|
|
135
|
-
|
|
136
|
-
def nparameters(self) -> int:
|
|
145
|
+
def get_parameter_names(self) -> list[str]:
|
|
137
146
|
"""
|
|
138
|
-
Retrieve the
|
|
147
|
+
Retrieve the symbolic names of the gate's parameters.
|
|
139
148
|
|
|
140
149
|
Returns:
|
|
141
|
-
|
|
150
|
+
list[str]: A list containing the names of the parameters.
|
|
142
151
|
"""
|
|
143
|
-
return
|
|
152
|
+
return list(self.get_parameters())
|
|
144
153
|
|
|
145
|
-
|
|
146
|
-
def is_parameterized(self) -> bool:
|
|
154
|
+
def get_parameter_values(self) -> list[float]:
|
|
147
155
|
"""
|
|
148
|
-
|
|
156
|
+
Retrieve the numerical values assigned to the gate's parameters.
|
|
149
157
|
|
|
150
158
|
Returns:
|
|
151
|
-
|
|
159
|
+
list[float]: A list containing the parameter values.
|
|
152
160
|
"""
|
|
153
|
-
return self.
|
|
161
|
+
return list(self.get_parameters().values())
|
|
154
162
|
|
|
155
163
|
def set_parameters(self, parameters: dict[str, float]) -> None:
|
|
156
164
|
"""
|
|
@@ -166,7 +174,7 @@ class Gate(ABC):
|
|
|
166
174
|
if not self.is_parameterized:
|
|
167
175
|
raise GateNotParameterizedError
|
|
168
176
|
|
|
169
|
-
if any(name not in self.
|
|
177
|
+
if any(name not in self.get_parameters() for name in parameters):
|
|
170
178
|
raise InvalidParameterNameError
|
|
171
179
|
|
|
172
180
|
def set_parameter_values(self, values: list[float]) -> None:
|
|
@@ -183,26 +191,34 @@ class Gate(ABC):
|
|
|
183
191
|
if not self.is_parameterized:
|
|
184
192
|
raise GateNotParameterizedError
|
|
185
193
|
|
|
186
|
-
if len(values) != len(self.
|
|
194
|
+
if len(values) != len(self.get_parameters()):
|
|
187
195
|
raise ParametersNotEqualError
|
|
188
196
|
|
|
197
|
+
def get_parameter_bounds(self) -> dict[str, tuple[float, float]]: # noqa: PLR6301
|
|
198
|
+
return {}
|
|
199
|
+
|
|
200
|
+
def set_parameter_bounds(self, ranges: dict[str, tuple[float, float]]) -> None:
|
|
201
|
+
if not self.is_parameterized:
|
|
202
|
+
raise GateNotParameterizedError
|
|
203
|
+
|
|
189
204
|
def __repr__(self) -> str:
|
|
190
205
|
qubits_str = f"({self.qubits[0]})" if self.nqubits == 1 else str(self.qubits)
|
|
191
206
|
return f"{self.name}{qubits_str}"
|
|
192
207
|
|
|
193
208
|
|
|
209
|
+
@yaml.register_class
|
|
194
210
|
class BasicGate(Gate):
|
|
195
211
|
"""
|
|
196
212
|
Represents a quantum gate that can be used in quantum circuits.
|
|
197
213
|
"""
|
|
198
214
|
|
|
199
|
-
def __init__(self, target_qubits: tuple[int, ...], parameters: dict[str,
|
|
215
|
+
def __init__(self, target_qubits: tuple[int, ...], parameters: dict[str, Parameter] = {}) -> None:
|
|
200
216
|
# Check for duplicate integers in target_qubits.
|
|
201
217
|
if len(target_qubits) != len(set(target_qubits)):
|
|
202
218
|
raise ValueError("Duplicate target qubits found.")
|
|
203
219
|
|
|
204
220
|
self._target_qubits: tuple[int, ...] = target_qubits
|
|
205
|
-
self._parameters: dict[str,
|
|
221
|
+
self._parameters: dict[str, Parameter] = parameters
|
|
206
222
|
self._matrix: np.ndarray = self._generate_matrix()
|
|
207
223
|
|
|
208
224
|
@property
|
|
@@ -214,22 +230,38 @@ class BasicGate(Gate):
|
|
|
214
230
|
return self._target_qubits
|
|
215
231
|
|
|
216
232
|
@property
|
|
217
|
-
def parameters(self) -> dict[str,
|
|
218
|
-
return
|
|
233
|
+
def parameters(self) -> dict[str, Parameter]:
|
|
234
|
+
return self._parameters
|
|
235
|
+
|
|
236
|
+
def get_parameters(self) -> dict[str, float]:
|
|
237
|
+
return {k: v.value for k, v in self._parameters.items()}
|
|
219
238
|
|
|
220
239
|
def set_parameters(self, parameters: dict[str, float]) -> None:
|
|
221
240
|
super().set_parameters(parameters=parameters)
|
|
222
|
-
|
|
241
|
+
for k, v in parameters.items():
|
|
242
|
+
self._parameters[k].set_value(v)
|
|
223
243
|
self._matrix = self._generate_matrix()
|
|
224
244
|
|
|
225
245
|
def set_parameter_values(self, values: list[float]) -> None:
|
|
226
246
|
super().set_parameter_values(values=values)
|
|
227
247
|
|
|
228
|
-
for key, value in zip(self.
|
|
229
|
-
self._parameters[key]
|
|
248
|
+
for key, value in zip(self.get_parameters(), values):
|
|
249
|
+
self._parameters[key].set_value(value)
|
|
230
250
|
|
|
231
251
|
self._matrix = self._generate_matrix()
|
|
232
252
|
|
|
253
|
+
def get_parameter_bounds(self) -> dict[str, tuple[float, float]]:
|
|
254
|
+
return {k: v.bounds for k, v in self._parameters.items()}
|
|
255
|
+
|
|
256
|
+
def set_parameter_bounds(self, ranges: dict[str, tuple[float, float]]) -> None:
|
|
257
|
+
super().set_parameter_bounds(ranges=ranges)
|
|
258
|
+
for label, bound in ranges.items():
|
|
259
|
+
if label not in self._parameters:
|
|
260
|
+
raise ValueError(
|
|
261
|
+
f"The provided parameter label {label} is not defined in the list of parameters in this object."
|
|
262
|
+
)
|
|
263
|
+
self._parameters[label].set_bounds(bound[0], bound[1])
|
|
264
|
+
|
|
233
265
|
def controlled(self: Self, *control_qubits: int) -> Controlled[Self]:
|
|
234
266
|
"""
|
|
235
267
|
Creates a controlled version of this unitary gate.
|
|
@@ -293,18 +325,6 @@ class Modified(Gate, Generic[TBasicGate]):
|
|
|
293
325
|
def target_qubits(self) -> tuple[int, ...]:
|
|
294
326
|
return self._basic_gate.target_qubits
|
|
295
327
|
|
|
296
|
-
@property
|
|
297
|
-
def parameters(self) -> dict[str, float]:
|
|
298
|
-
return self._basic_gate.parameters
|
|
299
|
-
|
|
300
|
-
@property
|
|
301
|
-
def parameter_names(self) -> list[str]:
|
|
302
|
-
return self._basic_gate.parameter_names
|
|
303
|
-
|
|
304
|
-
@property
|
|
305
|
-
def parameter_values(self) -> list[float]:
|
|
306
|
-
return self._basic_gate.parameter_values
|
|
307
|
-
|
|
308
328
|
@property
|
|
309
329
|
def nparameters(self) -> int:
|
|
310
330
|
return self._basic_gate.nparameters
|
|
@@ -313,6 +333,19 @@ class Modified(Gate, Generic[TBasicGate]):
|
|
|
313
333
|
def is_parameterized(self) -> bool:
|
|
314
334
|
return self._basic_gate.is_parameterized
|
|
315
335
|
|
|
336
|
+
@property
|
|
337
|
+
def parameters(self) -> dict[str, Parameter]:
|
|
338
|
+
return self._basic_gate.parameters
|
|
339
|
+
|
|
340
|
+
def get_parameters(self) -> dict[str, float]:
|
|
341
|
+
return self._basic_gate.get_parameters()
|
|
342
|
+
|
|
343
|
+
def get_parameter_names(self) -> list[str]:
|
|
344
|
+
return self._basic_gate.get_parameter_names()
|
|
345
|
+
|
|
346
|
+
def get_parameter_values(self) -> list[float]:
|
|
347
|
+
return self._basic_gate.get_parameter_values()
|
|
348
|
+
|
|
316
349
|
def set_parameters(self, parameters: dict[str, float]) -> None:
|
|
317
350
|
self._basic_gate.set_parameters(parameters=parameters)
|
|
318
351
|
self._matrix = self._generate_matrix()
|
|
@@ -321,6 +354,12 @@ class Modified(Gate, Generic[TBasicGate]):
|
|
|
321
354
|
self._basic_gate.set_parameter_values(values=values)
|
|
322
355
|
self._matrix = self._generate_matrix()
|
|
323
356
|
|
|
357
|
+
def get_parameter_bounds(self) -> dict[str, tuple[float, float]]:
|
|
358
|
+
return self._basic_gate.get_parameter_bounds()
|
|
359
|
+
|
|
360
|
+
def set_parameter_bounds(self, ranges: dict[str, tuple[float, float]]) -> None:
|
|
361
|
+
self._basic_gate.set_parameter_bounds(ranges)
|
|
362
|
+
|
|
324
363
|
@abstractmethod
|
|
325
364
|
def _generate_matrix(self) -> np.ndarray: ...
|
|
326
365
|
|
|
@@ -450,14 +489,48 @@ class M(Gate):
|
|
|
450
489
|
return self._target_qubits
|
|
451
490
|
|
|
452
491
|
|
|
492
|
+
@yaml.register_class
|
|
493
|
+
class I(BasicGate):
|
|
494
|
+
"""
|
|
495
|
+
The Identity gate.
|
|
496
|
+
|
|
497
|
+
The associated matrix is:
|
|
498
|
+
|
|
499
|
+
.. code-block:: text
|
|
500
|
+
|
|
501
|
+
[[1, 0],
|
|
502
|
+
[0, 1]]
|
|
503
|
+
|
|
504
|
+
"""
|
|
505
|
+
|
|
506
|
+
def __init__(self, qubit: int) -> None:
|
|
507
|
+
"""
|
|
508
|
+
Initialize a Pauli-X gate.
|
|
509
|
+
|
|
510
|
+
Args:
|
|
511
|
+
qubit (int): The target qubit index for the X gate.
|
|
512
|
+
"""
|
|
513
|
+
super().__init__(target_qubits=(qubit,))
|
|
514
|
+
|
|
515
|
+
@property
|
|
516
|
+
def name(self) -> str:
|
|
517
|
+
return "I"
|
|
518
|
+
|
|
519
|
+
def _generate_matrix(self) -> np.ndarray: # noqa: PLR6301
|
|
520
|
+
return np.array([[1, 0], [0, 1]], dtype=complex)
|
|
521
|
+
|
|
522
|
+
|
|
453
523
|
@yaml.register_class
|
|
454
524
|
class X(BasicGate):
|
|
455
525
|
"""
|
|
456
526
|
The Pauli-X gate.
|
|
457
527
|
|
|
458
528
|
The associated matrix is:
|
|
459
|
-
|
|
460
|
-
|
|
529
|
+
|
|
530
|
+
.. code-block:: text
|
|
531
|
+
|
|
532
|
+
[[0, 1],
|
|
533
|
+
[1, 0]]
|
|
461
534
|
|
|
462
535
|
This is a pi radians rotation around the X-axis in the Bloch sphere.
|
|
463
536
|
"""
|
|
@@ -487,8 +560,9 @@ class Y(BasicGate):
|
|
|
487
560
|
The associated matrix is:
|
|
488
561
|
|
|
489
562
|
.. code-block:: text
|
|
490
|
-
|
|
491
|
-
|
|
563
|
+
|
|
564
|
+
[[ 0, -i ],
|
|
565
|
+
[ i, 0 ]]
|
|
492
566
|
|
|
493
567
|
This is a pi radians rotation around the Y-axis in the Bloch sphere.
|
|
494
568
|
"""
|
|
@@ -518,8 +592,9 @@ class Z(BasicGate):
|
|
|
518
592
|
The associated matrix is:
|
|
519
593
|
|
|
520
594
|
.. code-block:: text
|
|
595
|
+
|
|
521
596
|
[[1, 0],
|
|
522
|
-
|
|
597
|
+
[0, -1]]
|
|
523
598
|
|
|
524
599
|
This is a pi radians rotation around the Z-axis in the Bloch sphere.
|
|
525
600
|
"""
|
|
@@ -549,8 +624,9 @@ class H(BasicGate):
|
|
|
549
624
|
The associated matrix is:
|
|
550
625
|
|
|
551
626
|
.. code-block:: text
|
|
552
|
-
|
|
553
|
-
|
|
627
|
+
|
|
628
|
+
[[1/sqrt(2), 1/sqrt(2)],
|
|
629
|
+
[1/sqrt(2), -1/sqrt(2)]]
|
|
554
630
|
|
|
555
631
|
This is a pi radians rotation around the (X+Z)-axis in the Bloch sphere.
|
|
556
632
|
"""
|
|
@@ -580,6 +656,7 @@ class S(BasicGate):
|
|
|
580
656
|
The associated matrix is:
|
|
581
657
|
|
|
582
658
|
.. code-block:: text
|
|
659
|
+
|
|
583
660
|
[[1, 0],
|
|
584
661
|
[0, i]]
|
|
585
662
|
|
|
@@ -611,6 +688,7 @@ class T(BasicGate):
|
|
|
611
688
|
The associated matrix is:
|
|
612
689
|
|
|
613
690
|
.. code-block:: text
|
|
691
|
+
|
|
614
692
|
[[1, 0],
|
|
615
693
|
[0, exp(i*pi/4)]]
|
|
616
694
|
|
|
@@ -642,6 +720,7 @@ class RX(BasicGate):
|
|
|
642
720
|
The associated matrix is:
|
|
643
721
|
|
|
644
722
|
.. code-block:: text
|
|
723
|
+
|
|
645
724
|
[[cos(theta/2), -i*sin(theta/2)],
|
|
646
725
|
[-i*sin(theta/2), cos(theta/2)]]
|
|
647
726
|
|
|
@@ -651,7 +730,7 @@ class RX(BasicGate):
|
|
|
651
730
|
|
|
652
731
|
PARAMETER_NAMES: ClassVar[list[str]] = ["theta"]
|
|
653
732
|
|
|
654
|
-
def __init__(self, qubit: int, *, theta: float) -> None:
|
|
733
|
+
def __init__(self, qubit: int, *, theta: float | Parameter) -> None:
|
|
655
734
|
"""
|
|
656
735
|
Initialize an RX gate.
|
|
657
736
|
|
|
@@ -659,7 +738,10 @@ class RX(BasicGate):
|
|
|
659
738
|
qubit (int): The target qubit index for the rotation.
|
|
660
739
|
theta (float): The rotation angle (polar) in radians.
|
|
661
740
|
"""
|
|
662
|
-
super().__init__(
|
|
741
|
+
super().__init__(
|
|
742
|
+
target_qubits=(qubit,),
|
|
743
|
+
parameters={"theta": theta if isinstance(theta, Parameter) else Parameter("theta", theta)},
|
|
744
|
+
)
|
|
663
745
|
|
|
664
746
|
@property
|
|
665
747
|
def name(self) -> str:
|
|
@@ -667,10 +749,10 @@ class RX(BasicGate):
|
|
|
667
749
|
|
|
668
750
|
@property
|
|
669
751
|
def theta(self) -> float:
|
|
670
|
-
return self.
|
|
752
|
+
return self.get_parameters()["theta"]
|
|
671
753
|
|
|
672
754
|
def _generate_matrix(self) -> np.ndarray:
|
|
673
|
-
theta = self.
|
|
755
|
+
theta = self.theta
|
|
674
756
|
cos_half = np.cos(theta / 2)
|
|
675
757
|
sin_half = np.sin(theta / 2)
|
|
676
758
|
return np.array([[cos_half, -1j * sin_half], [-1j * sin_half, cos_half]], dtype=complex)
|
|
@@ -684,6 +766,7 @@ class RY(BasicGate):
|
|
|
684
766
|
The associated matrix is:
|
|
685
767
|
|
|
686
768
|
.. code-block:: text
|
|
769
|
+
|
|
687
770
|
[[cos(theta/2), -sin(theta/2)],
|
|
688
771
|
[sin(theta/2), cos(theta/2)]]
|
|
689
772
|
|
|
@@ -693,7 +776,7 @@ class RY(BasicGate):
|
|
|
693
776
|
|
|
694
777
|
PARAMETER_NAMES: ClassVar[list[str]] = ["theta"]
|
|
695
778
|
|
|
696
|
-
def __init__(self, qubit: int, *, theta: float) -> None:
|
|
779
|
+
def __init__(self, qubit: int, *, theta: float | Parameter) -> None:
|
|
697
780
|
"""
|
|
698
781
|
Initialize an RY gate.
|
|
699
782
|
|
|
@@ -701,7 +784,10 @@ class RY(BasicGate):
|
|
|
701
784
|
qubit (int): The target qubit index for the rotation.
|
|
702
785
|
theta (float): The rotation angle (polar) in radians.
|
|
703
786
|
"""
|
|
704
|
-
super().__init__(
|
|
787
|
+
super().__init__(
|
|
788
|
+
target_qubits=(qubit,),
|
|
789
|
+
parameters={"theta": theta if isinstance(theta, Parameter) else Parameter("theta", theta)},
|
|
790
|
+
)
|
|
705
791
|
|
|
706
792
|
@property
|
|
707
793
|
def name(self) -> str:
|
|
@@ -709,10 +795,10 @@ class RY(BasicGate):
|
|
|
709
795
|
|
|
710
796
|
@property
|
|
711
797
|
def theta(self) -> float:
|
|
712
|
-
return self.
|
|
798
|
+
return self.get_parameters()["theta"]
|
|
713
799
|
|
|
714
800
|
def _generate_matrix(self) -> np.ndarray:
|
|
715
|
-
theta = self.
|
|
801
|
+
theta = self.theta
|
|
716
802
|
cos_half = np.cos(theta / 2)
|
|
717
803
|
sin_half = np.sin(theta / 2)
|
|
718
804
|
return np.array([[cos_half, -sin_half], [sin_half, cos_half]], dtype=complex)
|
|
@@ -726,6 +812,7 @@ class RZ(BasicGate):
|
|
|
726
812
|
The associated matrix is:
|
|
727
813
|
|
|
728
814
|
.. code-block:: text
|
|
815
|
+
|
|
729
816
|
[[exp(-i*phi/2), 0],
|
|
730
817
|
[0, exp(i*phi/2)]]
|
|
731
818
|
|
|
@@ -743,7 +830,7 @@ class RZ(BasicGate):
|
|
|
743
830
|
|
|
744
831
|
PARAMETER_NAMES: ClassVar[list[str]] = ["phi"]
|
|
745
832
|
|
|
746
|
-
def __init__(self, qubit: int, *, phi: float) -> None:
|
|
833
|
+
def __init__(self, qubit: int, *, phi: float | Parameter) -> None:
|
|
747
834
|
"""
|
|
748
835
|
Initialize an RZ gate.
|
|
749
836
|
|
|
@@ -751,21 +838,22 @@ class RZ(BasicGate):
|
|
|
751
838
|
qubit (int): The target qubit index for the rotation.
|
|
752
839
|
phi (float): The rotation angle (azimuthal) in radians.
|
|
753
840
|
"""
|
|
754
|
-
super().__init__(
|
|
841
|
+
super().__init__(
|
|
842
|
+
target_qubits=(qubit,),
|
|
843
|
+
parameters={"phi": phi if isinstance(phi, Parameter) else Parameter("phi", phi)},
|
|
844
|
+
)
|
|
755
845
|
|
|
756
846
|
@property
|
|
757
847
|
def name(self) -> str:
|
|
758
848
|
return "RZ"
|
|
759
849
|
|
|
760
850
|
@property
|
|
761
|
-
def
|
|
762
|
-
return self.
|
|
851
|
+
def phi(self) -> float:
|
|
852
|
+
return self.get_parameters()["phi"]
|
|
763
853
|
|
|
764
854
|
def _generate_matrix(self) -> np.ndarray:
|
|
765
|
-
phi = self.
|
|
766
|
-
|
|
767
|
-
sin_half = np.sin(phi / 2)
|
|
768
|
-
return np.array([[cos_half, -sin_half], [sin_half, cos_half]], dtype=complex)
|
|
855
|
+
phi = self.phi
|
|
856
|
+
return np.array([[np.exp(-0.5j * phi), 0.0], [0.0, np.exp(0.5j * phi)]], dtype=complex)
|
|
769
857
|
|
|
770
858
|
|
|
771
859
|
@yaml.register_class
|
|
@@ -776,6 +864,7 @@ class U1(BasicGate):
|
|
|
776
864
|
The associated matrix is:
|
|
777
865
|
|
|
778
866
|
.. code-block:: text
|
|
867
|
+
|
|
779
868
|
[[1, 0],
|
|
780
869
|
[0, exp(i*phi)]]
|
|
781
870
|
|
|
@@ -790,7 +879,7 @@ class U1(BasicGate):
|
|
|
790
879
|
|
|
791
880
|
PARAMETER_NAMES: ClassVar[list[str]] = ["phi"]
|
|
792
881
|
|
|
793
|
-
def __init__(self, qubit: int, *, phi: float) -> None:
|
|
882
|
+
def __init__(self, qubit: int, *, phi: float | Parameter) -> None:
|
|
794
883
|
"""
|
|
795
884
|
Initialize a U1 gate.
|
|
796
885
|
|
|
@@ -798,7 +887,10 @@ class U1(BasicGate):
|
|
|
798
887
|
qubit (int): The target qubit index for the U1 gate.
|
|
799
888
|
phi (float): The phase to add, or equivalently the rotation angle (azimuthal) in radians.
|
|
800
889
|
"""
|
|
801
|
-
super().__init__(
|
|
890
|
+
super().__init__(
|
|
891
|
+
target_qubits=(qubit,),
|
|
892
|
+
parameters={"phi": phi if isinstance(phi, Parameter) else Parameter("phi", phi)},
|
|
893
|
+
)
|
|
802
894
|
|
|
803
895
|
@property
|
|
804
896
|
def name(self) -> str:
|
|
@@ -806,10 +898,10 @@ class U1(BasicGate):
|
|
|
806
898
|
|
|
807
899
|
@property
|
|
808
900
|
def phi(self) -> float:
|
|
809
|
-
return self.
|
|
901
|
+
return self.get_parameters()["phi"]
|
|
810
902
|
|
|
811
903
|
def _generate_matrix(self) -> np.ndarray:
|
|
812
|
-
phi = self.
|
|
904
|
+
phi = self.phi
|
|
813
905
|
return np.array([[1, 0], [0, np.exp(1j * phi)]], dtype=complex)
|
|
814
906
|
|
|
815
907
|
|
|
@@ -821,6 +913,7 @@ class U2(BasicGate):
|
|
|
821
913
|
The associated matrix is:
|
|
822
914
|
|
|
823
915
|
.. code-block:: text
|
|
916
|
+
|
|
824
917
|
1/sqrt(2)*[[1, -exp(i*gamma)],
|
|
825
918
|
[exp(i*phi), exp(i*(phi+gamma))]]
|
|
826
919
|
|
|
@@ -838,7 +931,7 @@ class U2(BasicGate):
|
|
|
838
931
|
|
|
839
932
|
PARAMETER_NAMES: ClassVar[list[str]] = ["phi", "gamma"]
|
|
840
933
|
|
|
841
|
-
def __init__(self, qubit: int, *, phi: float, gamma: float) -> None:
|
|
934
|
+
def __init__(self, qubit: int, *, phi: float | Parameter, gamma: float | Parameter) -> None:
|
|
842
935
|
"""
|
|
843
936
|
Initialize a U2 gate.
|
|
844
937
|
|
|
@@ -847,7 +940,13 @@ class U2(BasicGate):
|
|
|
847
940
|
phi (float): The first phase parameter, or equivalently the first rotation angle (azimuthal) in radians.
|
|
848
941
|
gamma (float): The second phase parameter, or equivalently the second rotation angle (azimuthal) in radians..
|
|
849
942
|
"""
|
|
850
|
-
super().__init__(
|
|
943
|
+
super().__init__(
|
|
944
|
+
target_qubits=(qubit,),
|
|
945
|
+
parameters={
|
|
946
|
+
"phi": phi if isinstance(phi, Parameter) else Parameter("phi", phi),
|
|
947
|
+
"gamma": gamma if isinstance(gamma, Parameter) else Parameter("gamma", gamma),
|
|
948
|
+
},
|
|
949
|
+
)
|
|
851
950
|
|
|
852
951
|
@property
|
|
853
952
|
def name(self) -> str:
|
|
@@ -855,15 +954,15 @@ class U2(BasicGate):
|
|
|
855
954
|
|
|
856
955
|
@property
|
|
857
956
|
def phi(self) -> float:
|
|
858
|
-
return self.
|
|
957
|
+
return self.get_parameters()["phi"]
|
|
859
958
|
|
|
860
959
|
@property
|
|
861
960
|
def gamma(self) -> float:
|
|
862
|
-
return self.
|
|
961
|
+
return self.get_parameters()["gamma"]
|
|
863
962
|
|
|
864
963
|
def _generate_matrix(self) -> np.ndarray:
|
|
865
|
-
phi = self.
|
|
866
|
-
gamma = self.
|
|
964
|
+
phi = self.phi
|
|
965
|
+
gamma = self.gamma
|
|
867
966
|
return (1 / np.sqrt(2)) * np.array(
|
|
868
967
|
[
|
|
869
968
|
[1, -np.exp(1j * gamma)],
|
|
@@ -881,6 +980,7 @@ class U3(BasicGate):
|
|
|
881
980
|
The associated matrix is:
|
|
882
981
|
|
|
883
982
|
.. code-block:: text
|
|
983
|
+
|
|
884
984
|
[[cos(theta/2), -exp(i*gamma/2*sin(theta/2))],
|
|
885
985
|
[exp(i*phi/2)*sin(theta/2), exp(i*(phi+gamma))*cos(theta/2)]]
|
|
886
986
|
|
|
@@ -899,7 +999,9 @@ class U3(BasicGate):
|
|
|
899
999
|
|
|
900
1000
|
PARAMETER_NAMES: ClassVar[list[str]] = ["theta", "phi", "gamma"]
|
|
901
1001
|
|
|
902
|
-
def __init__(
|
|
1002
|
+
def __init__(
|
|
1003
|
+
self, qubit: int, *, theta: float | Parameter, phi: float | Parameter, gamma: float | Parameter
|
|
1004
|
+
) -> None:
|
|
903
1005
|
"""
|
|
904
1006
|
Initialize a U3 gate.
|
|
905
1007
|
|
|
@@ -909,7 +1011,14 @@ class U3(BasicGate):
|
|
|
909
1011
|
phi (float): The first phase parameter, or equivalently the first rotation angle (azimuthal) in radians.
|
|
910
1012
|
gamma (float): The second phase parameter, or equivalently the second rotation angle (azimuthal) in radians.
|
|
911
1013
|
"""
|
|
912
|
-
super().__init__(
|
|
1014
|
+
super().__init__(
|
|
1015
|
+
target_qubits=(qubit,),
|
|
1016
|
+
parameters={
|
|
1017
|
+
"theta": theta if isinstance(theta, Parameter) else Parameter("theta", theta),
|
|
1018
|
+
"phi": phi if isinstance(phi, Parameter) else Parameter("phi", phi),
|
|
1019
|
+
"gamma": gamma if isinstance(gamma, Parameter) else Parameter("gamma", gamma),
|
|
1020
|
+
},
|
|
1021
|
+
)
|
|
913
1022
|
|
|
914
1023
|
@property
|
|
915
1024
|
def name(self) -> str:
|
|
@@ -917,20 +1026,20 @@ class U3(BasicGate):
|
|
|
917
1026
|
|
|
918
1027
|
@property
|
|
919
1028
|
def theta(self) -> float:
|
|
920
|
-
return self.
|
|
1029
|
+
return self.get_parameters()["theta"]
|
|
921
1030
|
|
|
922
1031
|
@property
|
|
923
1032
|
def phi(self) -> float:
|
|
924
|
-
return self.
|
|
1033
|
+
return self.get_parameters()["phi"]
|
|
925
1034
|
|
|
926
1035
|
@property
|
|
927
1036
|
def gamma(self) -> float:
|
|
928
|
-
return self.
|
|
1037
|
+
return self.get_parameters()["gamma"]
|
|
929
1038
|
|
|
930
1039
|
def _generate_matrix(self) -> np.ndarray:
|
|
931
|
-
theta = self.
|
|
932
|
-
phi = self.
|
|
933
|
-
gamma = self.
|
|
1040
|
+
theta = self.theta
|
|
1041
|
+
phi = self.phi
|
|
1042
|
+
gamma = self.gamma
|
|
934
1043
|
return np.array(
|
|
935
1044
|
[
|
|
936
1045
|
[np.cos(theta / 2), -np.exp(1j * gamma) * np.sin(theta / 2)],
|
|
@@ -948,6 +1057,7 @@ class CNOT(Controlled[X]):
|
|
|
948
1057
|
The associated matrix is:
|
|
949
1058
|
|
|
950
1059
|
.. code-block:: text
|
|
1060
|
+
|
|
951
1061
|
[[1, 0, 0, 0],
|
|
952
1062
|
[0, 1, 0, 0],
|
|
953
1063
|
[0, 0, 0, 1],
|
|
@@ -973,6 +1083,7 @@ class CZ(Controlled[Z]):
|
|
|
973
1083
|
The associated matrix is:
|
|
974
1084
|
|
|
975
1085
|
.. code-block:: text
|
|
1086
|
+
|
|
976
1087
|
[[1, 0, 0, 0],
|
|
977
1088
|
[0, 1, 0, 0],
|
|
978
1089
|
[0, 0, 1, 0],
|
|
@@ -987,3 +1098,35 @@ class CZ(Controlled[Z]):
|
|
|
987
1098
|
|
|
988
1099
|
def __init__(self, control: int, target: int) -> None:
|
|
989
1100
|
super().__init__(control, basic_gate=Z(target))
|
|
1101
|
+
|
|
1102
|
+
|
|
1103
|
+
@yaml.register_class
|
|
1104
|
+
class SWAP(BasicGate):
|
|
1105
|
+
"""
|
|
1106
|
+
The SWAP gate.
|
|
1107
|
+
|
|
1108
|
+
The associated matrix is:
|
|
1109
|
+
|
|
1110
|
+
.. code-block:: text
|
|
1111
|
+
|
|
1112
|
+
[[1, 0, 0, 0],
|
|
1113
|
+
[0, 0, 1, 0],
|
|
1114
|
+
[0, 1, 0, 0],
|
|
1115
|
+
[0, 0, 0, 1]]
|
|
1116
|
+
|
|
1117
|
+
"""
|
|
1118
|
+
|
|
1119
|
+
def __init__(self, qubit_a: int, qubit_b: int) -> None:
|
|
1120
|
+
"""
|
|
1121
|
+
Args:
|
|
1122
|
+
qubit_a (int): First qubit to swap with.
|
|
1123
|
+
qubit_b (int): Second qubit to swap with.
|
|
1124
|
+
"""
|
|
1125
|
+
super().__init__(target_qubits=(qubit_a, qubit_b))
|
|
1126
|
+
|
|
1127
|
+
@property
|
|
1128
|
+
def name(self) -> str:
|
|
1129
|
+
return "SWAP"
|
|
1130
|
+
|
|
1131
|
+
def _generate_matrix(self) -> np.ndarray: # noqa: PLR6301
|
|
1132
|
+
return np.array([[1, 0, 0, 0], [0, 0, 1, 0], [0, 1, 0, 0], [0, 0, 0, 1]], dtype=complex)
|
|
@@ -12,9 +12,18 @@
|
|
|
12
12
|
# See the License for the specific language governing permissions and
|
|
13
13
|
# limitations under the License.
|
|
14
14
|
|
|
15
|
-
from
|
|
16
|
-
from
|
|
15
|
+
from .sampling import Sampling
|
|
16
|
+
from .sampling_result import SamplingResult
|
|
17
|
+
from .time_evolution import TimeEvolution
|
|
18
|
+
from .time_evolution_result import TimeEvolutionResult
|
|
19
|
+
from .variational_program import VariationalProgram
|
|
20
|
+
from .variational_program_result import VariationalProgramResult
|
|
17
21
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
22
|
+
__all__ = [
|
|
23
|
+
"Sampling",
|
|
24
|
+
"SamplingResult",
|
|
25
|
+
"TimeEvolution",
|
|
26
|
+
"TimeEvolutionResult",
|
|
27
|
+
"VariationalProgram",
|
|
28
|
+
"VariationalProgramResult",
|
|
29
|
+
]
|