cirq-core 1.6.0.dev20250423233500__py3-none-any.whl → 1.6.0.dev20250425004112__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.
Potentially problematic release.
This version of cirq-core might be problematic. Click here for more details.
- cirq/_version.py +1 -1
- cirq/_version_test.py +1 -1
- cirq/ops/dense_pauli_string.py +28 -28
- cirq/ops/diagonal_gate.py +12 -14
- cirq/ops/eigen_gate.py +8 -5
- cirq/ops/fourier_transform.py +8 -12
- cirq/ops/fsim_gate.py +38 -37
- cirq/ops/gate_operation.py +25 -27
- cirq/ops/gateset.py +7 -5
- cirq/ops/global_phase_op.py +11 -11
- cirq/ops/greedy_qubit_manager.py +9 -7
- cirq/ops/identity.py +8 -6
- cirq/ops/kraus_channel.py +7 -4
- cirq/ops/linear_combinations.py +36 -34
- cirq/ops/matrix_gates.py +10 -10
- cirq/ops/measure_util.py +6 -4
- cirq/ops/measurement_gate.py +12 -12
- cirq/ops/mixed_unitary_channel.py +7 -4
- cirq/ops/named_qubit.py +8 -5
- cirq/ops/op_tree.py +4 -2
- cirq/ops/parallel_gate.py +11 -13
- cirq/ops/parity_gates.py +15 -17
- cirq/ops/pauli_gates.py +20 -17
- cirq/ops/pauli_interaction_gate.py +10 -14
- cirq/ops/pauli_measurement_gate.py +20 -20
- cirq/ops/pauli_string.py +76 -79
- cirq/ops/pauli_string_phasor.py +30 -30
- cirq/ops/pauli_string_raw_types.py +6 -4
- cirq/ops/pauli_sum_exponential.py +11 -11
- cirq/ops/permutation_gate.py +5 -3
- cirq/ops/phased_iswap_gate.py +8 -8
- cirq/ops/phased_x_gate.py +8 -9
- cirq/ops/phased_x_z_gate.py +15 -13
- cirq/ops/qid_util.py +6 -4
- cirq/ops/qubit_manager.py +9 -7
- cirq/ops/random_gate_channel.py +9 -7
- cirq/ops/raw_types.py +70 -72
- cirq/ops/raw_types_test.py +10 -6
- cirq/ops/state_preparation_channel.py +4 -4
- cirq/ops/swap_gates.py +7 -9
- cirq/ops/three_qubit_gates.py +22 -28
- cirq/ops/two_qubit_diagonal_gate.py +8 -8
- cirq/ops/uniform_superposition_gate.py +3 -1
- cirq/ops/wait_gate.py +12 -9
- cirq/protocols/act_on_protocol.py +6 -4
- cirq/protocols/act_on_protocol_test.py +8 -5
- cirq/protocols/apply_unitary_protocol.py +10 -8
- cirq/protocols/circuit_diagram_info_protocol.py +10 -8
- cirq/protocols/control_key_protocol.py +5 -3
- cirq/protocols/decompose_protocol.py +25 -22
- cirq/protocols/decompose_protocol_test.py +5 -2
- cirq/protocols/inverse_protocol.py +10 -8
- {cirq_core-1.6.0.dev20250423233500.dist-info → cirq_core-1.6.0.dev20250425004112.dist-info}/METADATA +1 -1
- {cirq_core-1.6.0.dev20250423233500.dist-info → cirq_core-1.6.0.dev20250425004112.dist-info}/RECORD +57 -57
- {cirq_core-1.6.0.dev20250423233500.dist-info → cirq_core-1.6.0.dev20250425004112.dist-info}/WHEEL +0 -0
- {cirq_core-1.6.0.dev20250423233500.dist-info → cirq_core-1.6.0.dev20250425004112.dist-info}/licenses/LICENSE +0 -0
- {cirq_core-1.6.0.dev20250423233500.dist-info → cirq_core-1.6.0.dev20250425004112.dist-info}/top_level.txt +0 -0
cirq/_version.py
CHANGED
cirq/_version_test.py
CHANGED
cirq/ops/dense_pauli_string.py
CHANGED
|
@@ -12,6 +12,8 @@
|
|
|
12
12
|
# See the License for the specific language governing permissions and
|
|
13
13
|
# limitations under the License.
|
|
14
14
|
|
|
15
|
+
from __future__ import annotations
|
|
16
|
+
|
|
15
17
|
import abc
|
|
16
18
|
import numbers
|
|
17
19
|
from types import NotImplementedType
|
|
@@ -45,7 +47,7 @@ if TYPE_CHECKING:
|
|
|
45
47
|
|
|
46
48
|
# Order is important! Index equals numeric value.
|
|
47
49
|
PAULI_CHARS = 'IXYZ'
|
|
48
|
-
PAULI_GATES: List[Union[
|
|
50
|
+
PAULI_GATES: List[Union[cirq.Pauli, cirq.IdentityGate]] = [
|
|
49
51
|
identity.I,
|
|
50
52
|
pauli_gates.X,
|
|
51
53
|
pauli_gates.Y,
|
|
@@ -84,9 +86,9 @@ class BaseDensePauliString(raw_types.Gate, metaclass=abc.ABCMeta):
|
|
|
84
86
|
|
|
85
87
|
def __init__(
|
|
86
88
|
self,
|
|
87
|
-
pauli_mask: Union[Iterable[
|
|
89
|
+
pauli_mask: Union[Iterable[cirq.PAULI_GATE_LIKE], np.ndarray],
|
|
88
90
|
*,
|
|
89
|
-
coefficient:
|
|
91
|
+
coefficient: cirq.TParamValComplex = 1,
|
|
90
92
|
):
|
|
91
93
|
"""Initializes a new dense pauli string.
|
|
92
94
|
|
|
@@ -116,7 +118,7 @@ class BaseDensePauliString(raw_types.Gate, metaclass=abc.ABCMeta):
|
|
|
116
118
|
return self._pauli_mask
|
|
117
119
|
|
|
118
120
|
@property
|
|
119
|
-
def coefficient(self) ->
|
|
121
|
+
def coefficient(self) -> cirq.TParamValComplex:
|
|
120
122
|
"""A complex coefficient or symbol."""
|
|
121
123
|
return self._coefficient
|
|
122
124
|
|
|
@@ -129,7 +131,7 @@ class BaseDensePauliString(raw_types.Gate, metaclass=abc.ABCMeta):
|
|
|
129
131
|
return self.coefficient, tuple(PAULI_CHARS[p] for p in self.pauli_mask)
|
|
130
132
|
|
|
131
133
|
@classmethod
|
|
132
|
-
def one_hot(cls, *, index: int, length: int, pauli:
|
|
134
|
+
def one_hot(cls, *, index: int, length: int, pauli: cirq.PAULI_GATE_LIKE) -> Self:
|
|
133
135
|
"""Creates a dense pauli string with only one non-identity Pauli.
|
|
134
136
|
|
|
135
137
|
Args:
|
|
@@ -179,9 +181,7 @@ class BaseDensePauliString(raw_types.Gate, metaclass=abc.ABCMeta):
|
|
|
179
181
|
decomposed_ops = cast(Iterable['cirq.OP_TREE'], self._decompose_(qubits))
|
|
180
182
|
return protocols.apply_unitaries(decomposed_ops, qubits, args)
|
|
181
183
|
|
|
182
|
-
def _decompose_(
|
|
183
|
-
self, qubits: Sequence['cirq.Qid']
|
|
184
|
-
) -> Union[NotImplementedType, 'cirq.OP_TREE']:
|
|
184
|
+
def _decompose_(self, qubits: Sequence[cirq.Qid]) -> Union[NotImplementedType, cirq.OP_TREE]:
|
|
185
185
|
if not self._has_unitary_():
|
|
186
186
|
return NotImplemented
|
|
187
187
|
result = [PAULI_GATES[p].on(q) for p, q in zip(self.pauli_mask, qubits) if p]
|
|
@@ -195,7 +195,7 @@ class BaseDensePauliString(raw_types.Gate, metaclass=abc.ABCMeta):
|
|
|
195
195
|
def _parameter_names_(self) -> AbstractSet[str]:
|
|
196
196
|
return protocols.parameter_names(self.coefficient)
|
|
197
197
|
|
|
198
|
-
def _resolve_parameters_(self, resolver:
|
|
198
|
+
def _resolve_parameters_(self, resolver: cirq.ParamResolver, recursive: bool) -> Self:
|
|
199
199
|
return self.copy(
|
|
200
200
|
coefficient=protocols.resolve_parameters(self.coefficient, resolver, recursive)
|
|
201
201
|
)
|
|
@@ -218,7 +218,7 @@ class BaseDensePauliString(raw_types.Gate, metaclass=abc.ABCMeta):
|
|
|
218
218
|
return NotImplemented
|
|
219
219
|
|
|
220
220
|
@overload
|
|
221
|
-
def __getitem__(self, item: int) -> Union[
|
|
221
|
+
def __getitem__(self, item: int) -> Union[cirq.Pauli, cirq.IdentityGate]:
|
|
222
222
|
pass
|
|
223
223
|
|
|
224
224
|
@overload
|
|
@@ -234,7 +234,7 @@ class BaseDensePauliString(raw_types.Gate, metaclass=abc.ABCMeta):
|
|
|
234
234
|
|
|
235
235
|
raise TypeError(f'indices must be integers or slices, not {type(item)}')
|
|
236
236
|
|
|
237
|
-
def __iter__(self) -> Iterator[Union[
|
|
237
|
+
def __iter__(self) -> Iterator[Union[cirq.Pauli, cirq.IdentityGate]]:
|
|
238
238
|
for i in range(len(self)):
|
|
239
239
|
yield self[i]
|
|
240
240
|
|
|
@@ -301,7 +301,7 @@ class BaseDensePauliString(raw_types.Gate, metaclass=abc.ABCMeta):
|
|
|
301
301
|
|
|
302
302
|
return NotImplemented
|
|
303
303
|
|
|
304
|
-
def tensor_product(self, other:
|
|
304
|
+
def tensor_product(self, other: BaseDensePauliString) -> Self:
|
|
305
305
|
"""Concatenates dense pauli strings and multiplies their coefficients.
|
|
306
306
|
|
|
307
307
|
Args:
|
|
@@ -323,10 +323,10 @@ class BaseDensePauliString(raw_types.Gate, metaclass=abc.ABCMeta):
|
|
|
323
323
|
pauli_mask=self.pauli_mask,
|
|
324
324
|
)
|
|
325
325
|
|
|
326
|
-
def on(self, *qubits:
|
|
326
|
+
def on(self, *qubits: cirq.Qid) -> cirq.PauliString:
|
|
327
327
|
return self.sparse(qubits)
|
|
328
328
|
|
|
329
|
-
def sparse(self, qubits: Optional[Sequence[
|
|
329
|
+
def sparse(self, qubits: Optional[Sequence[cirq.Qid]] = None) -> cirq.PauliString:
|
|
330
330
|
"""A `cirq.PauliString` version of this dense pauli string.
|
|
331
331
|
|
|
332
332
|
Args:
|
|
@@ -390,11 +390,11 @@ class BaseDensePauliString(raw_types.Gate, metaclass=abc.ABCMeta):
|
|
|
390
390
|
|
|
391
391
|
return NotImplemented
|
|
392
392
|
|
|
393
|
-
def frozen(self) ->
|
|
393
|
+
def frozen(self) -> DensePauliString:
|
|
394
394
|
"""A `cirq.DensePauliString` with the same contents."""
|
|
395
395
|
return DensePauliString(coefficient=self.coefficient, pauli_mask=self.pauli_mask)
|
|
396
396
|
|
|
397
|
-
def mutable_copy(self) ->
|
|
397
|
+
def mutable_copy(self) -> MutableDensePauliString:
|
|
398
398
|
"""A `cirq.MutableDensePauliString` with the same contents."""
|
|
399
399
|
return MutableDensePauliString(
|
|
400
400
|
coefficient=self.coefficient, pauli_mask=np.copy(self.pauli_mask)
|
|
@@ -403,7 +403,7 @@ class BaseDensePauliString(raw_types.Gate, metaclass=abc.ABCMeta):
|
|
|
403
403
|
@abc.abstractmethod
|
|
404
404
|
def copy(
|
|
405
405
|
self,
|
|
406
|
-
coefficient: Optional[
|
|
406
|
+
coefficient: Optional[cirq.TParamValComplex] = None,
|
|
407
407
|
pauli_mask: Union[None, str, Iterable[int], np.ndarray] = None,
|
|
408
408
|
) -> Self:
|
|
409
409
|
"""Returns a copy with possibly modified contents.
|
|
@@ -454,14 +454,14 @@ class DensePauliString(BaseDensePauliString):
|
|
|
454
454
|
dense pauli strings, see `cirq.MutableDensePauliString`.
|
|
455
455
|
"""
|
|
456
456
|
|
|
457
|
-
def frozen(self) ->
|
|
457
|
+
def frozen(self) -> DensePauliString:
|
|
458
458
|
return self
|
|
459
459
|
|
|
460
460
|
def copy(
|
|
461
461
|
self,
|
|
462
|
-
coefficient: Optional[
|
|
462
|
+
coefficient: Optional[cirq.TParamValComplex] = None,
|
|
463
463
|
pauli_mask: Union[None, str, Iterable[int], np.ndarray] = None,
|
|
464
|
-
) ->
|
|
464
|
+
) -> DensePauliString:
|
|
465
465
|
if pauli_mask is None and (coefficient is None or coefficient == self.coefficient):
|
|
466
466
|
return self
|
|
467
467
|
return DensePauliString(
|
|
@@ -489,14 +489,14 @@ class MutableDensePauliString(BaseDensePauliString):
|
|
|
489
489
|
"""
|
|
490
490
|
|
|
491
491
|
@overload
|
|
492
|
-
def __setitem__(self, key: int, value:
|
|
492
|
+
def __setitem__(self, key: int, value: cirq.PAULI_GATE_LIKE) -> Self:
|
|
493
493
|
pass
|
|
494
494
|
|
|
495
495
|
@overload
|
|
496
496
|
def __setitem__(
|
|
497
497
|
self,
|
|
498
498
|
key: slice,
|
|
499
|
-
value: Union[Iterable[
|
|
499
|
+
value: Union[Iterable[cirq.PAULI_GATE_LIKE], np.ndarray, BaseDensePauliString],
|
|
500
500
|
) -> Self:
|
|
501
501
|
pass
|
|
502
502
|
|
|
@@ -559,9 +559,9 @@ class MutableDensePauliString(BaseDensePauliString):
|
|
|
559
559
|
|
|
560
560
|
def copy(
|
|
561
561
|
self,
|
|
562
|
-
coefficient: Optional[
|
|
562
|
+
coefficient: Optional[cirq.TParamValComplex] = None,
|
|
563
563
|
pauli_mask: Union[None, str, Iterable[int], np.ndarray] = None,
|
|
564
|
-
) ->
|
|
564
|
+
) -> MutableDensePauliString:
|
|
565
565
|
return MutableDensePauliString(
|
|
566
566
|
coefficient=self.coefficient if coefficient is None else coefficient,
|
|
567
567
|
pauli_mask=np.copy(self.pauli_mask) if pauli_mask is None else pauli_mask,
|
|
@@ -574,7 +574,7 @@ class MutableDensePauliString(BaseDensePauliString):
|
|
|
574
574
|
return self.coefficient, tuple(PAULI_CHARS[p] for p in self.pauli_mask)
|
|
575
575
|
|
|
576
576
|
@classmethod
|
|
577
|
-
def inline_gaussian_elimination(cls, rows:
|
|
577
|
+
def inline_gaussian_elimination(cls, rows: List[MutableDensePauliString]) -> None:
|
|
578
578
|
if not rows:
|
|
579
579
|
return
|
|
580
580
|
|
|
@@ -605,7 +605,7 @@ class MutableDensePauliString(BaseDensePauliString):
|
|
|
605
605
|
next_row += 1
|
|
606
606
|
|
|
607
607
|
|
|
608
|
-
def _pauli_index(val:
|
|
608
|
+
def _pauli_index(val: cirq.PAULI_GATE_LIKE) -> int:
|
|
609
609
|
m = pauli_string.PAULI_GATE_LIKE_TO_INDEX_MAP
|
|
610
610
|
if val not in m:
|
|
611
611
|
raise TypeError(
|
|
@@ -616,13 +616,13 @@ def _pauli_index(val: 'cirq.PAULI_GATE_LIKE') -> int:
|
|
|
616
616
|
return m[val]
|
|
617
617
|
|
|
618
618
|
|
|
619
|
-
def _as_pauli_mask(val: Union[Iterable[
|
|
619
|
+
def _as_pauli_mask(val: Union[Iterable[cirq.PAULI_GATE_LIKE], np.ndarray]) -> np.ndarray:
|
|
620
620
|
if isinstance(val, np.ndarray):
|
|
621
621
|
return np.asarray(val, dtype=np.uint8)
|
|
622
622
|
return np.array([_pauli_index(v) for v in val], dtype=np.uint8)
|
|
623
623
|
|
|
624
624
|
|
|
625
|
-
def _attempt_value_to_pauli_index(v:
|
|
625
|
+
def _attempt_value_to_pauli_index(v: cirq.Operation) -> Optional[Tuple[int, int]]:
|
|
626
626
|
if not isinstance(v, raw_types.Operation):
|
|
627
627
|
return None
|
|
628
628
|
|
cirq/ops/diagonal_gate.py
CHANGED
|
@@ -18,6 +18,8 @@ The gate is used to create a (2^n)x(2^n) matrix with the diagonal elements
|
|
|
18
18
|
passed as a list.
|
|
19
19
|
"""
|
|
20
20
|
|
|
21
|
+
from __future__ import annotations
|
|
22
|
+
|
|
21
23
|
from typing import (
|
|
22
24
|
AbstractSet,
|
|
23
25
|
Any,
|
|
@@ -81,7 +83,7 @@ class DiagonalGate(raw_types.Gate):
|
|
|
81
83
|
all phases.
|
|
82
84
|
"""
|
|
83
85
|
|
|
84
|
-
def __init__(self, diag_angles_radians: Sequence[
|
|
86
|
+
def __init__(self, diag_angles_radians: Sequence[cirq.TParamVal]) -> None:
|
|
85
87
|
r"""A n-qubit gate with only diagonal elements.
|
|
86
88
|
|
|
87
89
|
This gate's off-diagonal elements are zero and its on-diagonal
|
|
@@ -92,10 +94,10 @@ class DiagonalGate(raw_types.Gate):
|
|
|
92
94
|
If these values are $(x_0, x_1, \ldots , x_N)$ then the unitary
|
|
93
95
|
has diagonal values $(e^{i x_0}, e^{i x_1}, \ldots, e^{i x_N})$.
|
|
94
96
|
"""
|
|
95
|
-
self._diag_angles_radians: Tuple[
|
|
97
|
+
self._diag_angles_radians: Tuple[cirq.TParamVal, ...] = tuple(diag_angles_radians)
|
|
96
98
|
|
|
97
99
|
@property
|
|
98
|
-
def diag_angles_radians(self) -> Tuple[
|
|
100
|
+
def diag_angles_radians(self) -> Tuple[cirq.TParamVal, ...]:
|
|
99
101
|
return self._diag_angles_radians
|
|
100
102
|
|
|
101
103
|
def _num_qubits_(self):
|
|
@@ -109,9 +111,7 @@ class DiagonalGate(raw_types.Gate):
|
|
|
109
111
|
name for angle in self._diag_angles_radians for name in protocols.parameter_names(angle)
|
|
110
112
|
}
|
|
111
113
|
|
|
112
|
-
def _resolve_parameters_(
|
|
113
|
-
self, resolver: 'cirq.ParamResolver', recursive: bool
|
|
114
|
-
) -> 'DiagonalGate':
|
|
114
|
+
def _resolve_parameters_(self, resolver: cirq.ParamResolver, recursive: bool) -> DiagonalGate:
|
|
115
115
|
return DiagonalGate(
|
|
116
116
|
protocols.resolve_parameters(self._diag_angles_radians, resolver, recursive)
|
|
117
117
|
)
|
|
@@ -124,7 +124,7 @@ class DiagonalGate(raw_types.Gate):
|
|
|
124
124
|
return None
|
|
125
125
|
return np.diag([np.exp(1j * angle) for angle in self._diag_angles_radians])
|
|
126
126
|
|
|
127
|
-
def _apply_unitary_(self, args:
|
|
127
|
+
def _apply_unitary_(self, args: protocols.ApplyUnitaryArgs) -> np.ndarray:
|
|
128
128
|
if self._is_parameterized_():
|
|
129
129
|
return NotImplemented
|
|
130
130
|
for index, angle in enumerate(self._diag_angles_radians):
|
|
@@ -132,9 +132,7 @@ class DiagonalGate(raw_types.Gate):
|
|
|
132
132
|
args.target_tensor[subspace_index] *= np.exp(1j * angle)
|
|
133
133
|
return args.target_tensor
|
|
134
134
|
|
|
135
|
-
def _circuit_diagram_info_(
|
|
136
|
-
self, args: 'cirq.CircuitDiagramInfoArgs'
|
|
137
|
-
) -> 'cirq.CircuitDiagramInfo':
|
|
135
|
+
def _circuit_diagram_info_(self, args: cirq.CircuitDiagramInfoArgs) -> cirq.CircuitDiagramInfo:
|
|
138
136
|
rounded_angles = np.array(self._diag_angles_radians)
|
|
139
137
|
if args.precision is not None:
|
|
140
138
|
rounded_angles = rounded_angles.round(args.precision)
|
|
@@ -150,7 +148,7 @@ class DiagonalGate(raw_types.Gate):
|
|
|
150
148
|
[diag_str] + [f"#{i}" for i in range(2, self._num_qubits_() + 1)]
|
|
151
149
|
)
|
|
152
150
|
|
|
153
|
-
def __pow__(self, exponent: Any) ->
|
|
151
|
+
def __pow__(self, exponent: Any) -> DiagonalGate:
|
|
154
152
|
if not isinstance(exponent, (int, float, sympy.Basic)):
|
|
155
153
|
return NotImplemented
|
|
156
154
|
angles = []
|
|
@@ -163,8 +161,8 @@ class DiagonalGate(raw_types.Gate):
|
|
|
163
161
|
return tuple(self._diag_angles_radians)
|
|
164
162
|
|
|
165
163
|
def _decompose_for_basis(
|
|
166
|
-
self, index: int, bit_flip: int, theta:
|
|
167
|
-
) -> Iterator[Union[
|
|
164
|
+
self, index: int, bit_flip: int, theta: cirq.TParamVal, qubits: Sequence[cirq.Qid]
|
|
165
|
+
) -> Iterator[Union[cirq.ZPowGate, cirq.CXPowGate]]:
|
|
168
166
|
if index == 0:
|
|
169
167
|
return
|
|
170
168
|
largest_digit = self._num_qubits_() - (len(bin(index)) - 2)
|
|
@@ -175,7 +173,7 @@ class DiagonalGate(raw_types.Gate):
|
|
|
175
173
|
elif _flip_bit > largest_digit:
|
|
176
174
|
yield common_gates.CNOT(qubits[_flip_bit], qubits[largest_digit])
|
|
177
175
|
|
|
178
|
-
def _decompose_(self, qubits: Sequence[
|
|
176
|
+
def _decompose_(self, qubits: Sequence[cirq.Qid]) -> cirq.OP_TREE:
|
|
179
177
|
"""Decompose the n-qubit diagonal gates into CNOT and Rz gates.
|
|
180
178
|
|
|
181
179
|
A 3 qubits decomposition looks like
|
cirq/ops/eigen_gate.py
CHANGED
|
@@ -11,6 +11,9 @@
|
|
|
11
11
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
12
|
# See the License for the specific language governing permissions and
|
|
13
13
|
# limitations under the License.
|
|
14
|
+
|
|
15
|
+
from __future__ import annotations
|
|
16
|
+
|
|
14
17
|
import abc
|
|
15
18
|
import fractions
|
|
16
19
|
import math
|
|
@@ -131,7 +134,7 @@ class EigenGate(raw_types.Gate):
|
|
|
131
134
|
return self._global_shift
|
|
132
135
|
|
|
133
136
|
# virtual method
|
|
134
|
-
def _with_exponent(self, exponent: value.TParamVal) ->
|
|
137
|
+
def _with_exponent(self, exponent: value.TParamVal) -> EigenGate:
|
|
135
138
|
"""Return the same kind of gate, but with a different exponent.
|
|
136
139
|
|
|
137
140
|
Child classes should override this method if they have an __init__
|
|
@@ -144,7 +147,7 @@ class EigenGate(raw_types.Gate):
|
|
|
144
147
|
# pylint: enable=unexpected-keyword-arg
|
|
145
148
|
|
|
146
149
|
def _diagram_exponent(
|
|
147
|
-
self, args:
|
|
150
|
+
self, args: protocols.CircuitDiagramInfoArgs, *, ignore_global_phase: bool = True
|
|
148
151
|
):
|
|
149
152
|
"""The exponent to use in circuit diagrams.
|
|
150
153
|
|
|
@@ -199,7 +202,7 @@ class EigenGate(raw_types.Gate):
|
|
|
199
202
|
return result
|
|
200
203
|
|
|
201
204
|
def _format_exponent_as_angle(
|
|
202
|
-
self, args:
|
|
205
|
+
self, args: protocols.CircuitDiagramInfoArgs, order: int = 2
|
|
203
206
|
) -> str:
|
|
204
207
|
"""Returns string with exponent expressed as angle in radians.
|
|
205
208
|
|
|
@@ -297,7 +300,7 @@ class EigenGate(raw_types.Gate):
|
|
|
297
300
|
real_periods = [abs(2 / e) for e in exponents if e != 0]
|
|
298
301
|
return _approximate_common_period(real_periods)
|
|
299
302
|
|
|
300
|
-
def __pow__(self, exponent: Union[float, sympy.Symbol]) ->
|
|
303
|
+
def __pow__(self, exponent: Union[float, sympy.Symbol]) -> EigenGate:
|
|
301
304
|
new_exponent = protocols.mul(self._exponent, exponent, NotImplemented)
|
|
302
305
|
if new_exponent is NotImplemented:
|
|
303
306
|
return NotImplemented # pragma: no cover
|
|
@@ -344,7 +347,7 @@ class EigenGate(raw_types.Gate):
|
|
|
344
347
|
def _parameter_names_(self) -> AbstractSet[str]:
|
|
345
348
|
return protocols.parameter_names(self._exponent)
|
|
346
349
|
|
|
347
|
-
def _resolve_parameters_(self, resolver:
|
|
350
|
+
def _resolve_parameters_(self, resolver: cirq.ParamResolver, recursive: bool) -> EigenGate:
|
|
348
351
|
exponent = resolver.value_of(self._exponent, recursive)
|
|
349
352
|
if isinstance(exponent, numbers.Complex):
|
|
350
353
|
if isinstance(exponent, numbers.Real):
|
cirq/ops/fourier_transform.py
CHANGED
|
@@ -12,6 +12,8 @@
|
|
|
12
12
|
# See the License for the specific language governing permissions and
|
|
13
13
|
# limitations under the License.
|
|
14
14
|
|
|
15
|
+
from __future__ import annotations
|
|
16
|
+
|
|
15
17
|
from typing import AbstractSet, Any, Dict, Union
|
|
16
18
|
|
|
17
19
|
import numpy as np
|
|
@@ -87,9 +89,7 @@ class QuantumFourierTransformGate(raw_types.Gate):
|
|
|
87
89
|
f'without_reverse={self._without_reverse!r})'
|
|
88
90
|
)
|
|
89
91
|
|
|
90
|
-
def _circuit_diagram_info_(
|
|
91
|
-
self, args: 'cirq.CircuitDiagramInfoArgs'
|
|
92
|
-
) -> 'cirq.CircuitDiagramInfo':
|
|
92
|
+
def _circuit_diagram_info_(self, args: cirq.CircuitDiagramInfoArgs) -> cirq.CircuitDiagramInfo:
|
|
93
93
|
return cirq.CircuitDiagramInfo(
|
|
94
94
|
wire_symbols=(str(self),) + tuple(f'#{k+1}' for k in range(1, self._num_qubits)),
|
|
95
95
|
exponent_qubit_index=0,
|
|
@@ -133,7 +133,7 @@ class PhaseGradientGate(raw_types.Gate):
|
|
|
133
133
|
for i, q in enumerate(qubits):
|
|
134
134
|
yield cirq.Z(q) ** (self.exponent / 2**i)
|
|
135
135
|
|
|
136
|
-
def _apply_unitary_(self, args:
|
|
136
|
+
def _apply_unitary_(self, args: cirq.ApplyUnitaryArgs):
|
|
137
137
|
if isinstance(self.exponent, sympy.Basic):
|
|
138
138
|
return NotImplemented
|
|
139
139
|
|
|
@@ -167,8 +167,8 @@ class PhaseGradientGate(raw_types.Gate):
|
|
|
167
167
|
return cirq.parameter_names(self.exponent)
|
|
168
168
|
|
|
169
169
|
def _resolve_parameters_(
|
|
170
|
-
self, resolver:
|
|
171
|
-
) ->
|
|
170
|
+
self, resolver: cirq.ParamResolver, recursive: bool
|
|
171
|
+
) -> PhaseGradientGate:
|
|
172
172
|
new_exponent = cirq.resolve_parameters(self.exponent, resolver, recursive)
|
|
173
173
|
return PhaseGradientGate(num_qubits=self._num_qubits, exponent=new_exponent)
|
|
174
174
|
|
|
@@ -182,9 +182,7 @@ class PhaseGradientGate(raw_types.Gate):
|
|
|
182
182
|
f'exponent={_compat.proper_repr(self.exponent)})'
|
|
183
183
|
)
|
|
184
184
|
|
|
185
|
-
def _circuit_diagram_info_(
|
|
186
|
-
self, args: 'cirq.CircuitDiagramInfoArgs'
|
|
187
|
-
) -> 'cirq.CircuitDiagramInfo':
|
|
185
|
+
def _circuit_diagram_info_(self, args: cirq.CircuitDiagramInfoArgs) -> cirq.CircuitDiagramInfo:
|
|
188
186
|
return cirq.CircuitDiagramInfo(
|
|
189
187
|
wire_symbols=('Grad',) + tuple(f'#{k+1}' for k in range(1, self._num_qubits)),
|
|
190
188
|
exponent=self.exponent,
|
|
@@ -192,9 +190,7 @@ class PhaseGradientGate(raw_types.Gate):
|
|
|
192
190
|
)
|
|
193
191
|
|
|
194
192
|
|
|
195
|
-
def qft(
|
|
196
|
-
*qubits: 'cirq.Qid', without_reverse: bool = False, inverse: bool = False
|
|
197
|
-
) -> 'cirq.Operation':
|
|
193
|
+
def qft(*qubits: cirq.Qid, without_reverse: bool = False, inverse: bool = False) -> cirq.Operation:
|
|
198
194
|
"""The quantum Fourier transform.
|
|
199
195
|
|
|
200
196
|
Transforms a qubit register from the computational basis to the frequency
|
cirq/ops/fsim_gate.py
CHANGED
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
12
|
# See the License for the specific language governing permissions and
|
|
13
13
|
# limitations under the License.
|
|
14
|
+
|
|
14
15
|
"""Defines the fermionic simulation gate.
|
|
15
16
|
|
|
16
17
|
This is the family of two-qubit gates that preserve excitations (number of ON
|
|
@@ -21,6 +22,8 @@ context of chemistry the electron count is conserved over time. This property
|
|
|
21
22
|
applies more generally to fermions, thus the name of the gate.
|
|
22
23
|
"""
|
|
23
24
|
|
|
25
|
+
from __future__ import annotations
|
|
26
|
+
|
|
24
27
|
import cmath
|
|
25
28
|
import math
|
|
26
29
|
from typing import AbstractSet, Any, Dict, Iterator, Optional, Tuple
|
|
@@ -34,7 +37,7 @@ from cirq._compat import proper_repr
|
|
|
34
37
|
from cirq.ops import gate_features, raw_types
|
|
35
38
|
|
|
36
39
|
|
|
37
|
-
def _canonicalize(value:
|
|
40
|
+
def _canonicalize(value: cirq.TParamVal) -> cirq.TParamVal:
|
|
38
41
|
"""Assumes value is 2π-periodic and shifts it into [-π, π)."""
|
|
39
42
|
if protocols.is_parameterized(value):
|
|
40
43
|
return value
|
|
@@ -42,12 +45,12 @@ def _canonicalize(value: 'cirq.TParamVal') -> 'cirq.TParamVal':
|
|
|
42
45
|
return value - period * np.floor((value + np.pi) / period)
|
|
43
46
|
|
|
44
47
|
|
|
45
|
-
def _zero_mod_pi(param:
|
|
48
|
+
def _zero_mod_pi(param: cirq.TParamVal) -> bool:
|
|
46
49
|
"""Returns True iff param, assumed to be in [-pi, pi), is 0 (mod pi)."""
|
|
47
50
|
return param in (0.0, -np.pi, -sympy.pi)
|
|
48
51
|
|
|
49
52
|
|
|
50
|
-
def _half_pi_mod_pi(param:
|
|
53
|
+
def _half_pi_mod_pi(param: cirq.TParamVal) -> bool:
|
|
51
54
|
"""Returns True iff param, assumed to be in [-pi, pi), is pi/2 (mod pi)."""
|
|
52
55
|
return param in (-np.pi / 2, np.pi / 2, -sympy.pi / 2, sympy.pi / 2)
|
|
53
56
|
|
|
@@ -90,7 +93,7 @@ class FSimGate(gate_features.InterchangeableQubitsGate, raw_types.Gate):
|
|
|
90
93
|
FSimGate(θ, φ) = ISWAP**(-2θ/π) CZPowGate(exponent=-φ/π)
|
|
91
94
|
"""
|
|
92
95
|
|
|
93
|
-
def __init__(self, theta:
|
|
96
|
+
def __init__(self, theta: cirq.TParamVal, phi: cirq.TParamVal) -> None:
|
|
94
97
|
"""Inits FSimGate.
|
|
95
98
|
|
|
96
99
|
Args:
|
|
@@ -106,11 +109,11 @@ class FSimGate(gate_features.InterchangeableQubitsGate, raw_types.Gate):
|
|
|
106
109
|
self._phi = _canonicalize(phi)
|
|
107
110
|
|
|
108
111
|
@property
|
|
109
|
-
def theta(self) ->
|
|
112
|
+
def theta(self) -> cirq.TParamVal:
|
|
110
113
|
return self._theta
|
|
111
114
|
|
|
112
115
|
@property
|
|
113
|
-
def phi(self) ->
|
|
116
|
+
def phi(self) -> cirq.TParamVal:
|
|
114
117
|
return self._phi
|
|
115
118
|
|
|
116
119
|
def _num_qubits_(self) -> int:
|
|
@@ -162,15 +165,13 @@ class FSimGate(gate_features.InterchangeableQubitsGate, raw_types.Gate):
|
|
|
162
165
|
}
|
|
163
166
|
)
|
|
164
167
|
|
|
165
|
-
def _resolve_parameters_(
|
|
166
|
-
self, resolver: 'cirq.ParamResolver', recursive: bool
|
|
167
|
-
) -> 'cirq.FSimGate':
|
|
168
|
+
def _resolve_parameters_(self, resolver: cirq.ParamResolver, recursive: bool) -> cirq.FSimGate:
|
|
168
169
|
return FSimGate(
|
|
169
170
|
protocols.resolve_parameters(self.theta, resolver, recursive),
|
|
170
171
|
protocols.resolve_parameters(self.phi, resolver, recursive),
|
|
171
172
|
)
|
|
172
173
|
|
|
173
|
-
def _apply_unitary_(self, args:
|
|
174
|
+
def _apply_unitary_(self, args: cirq.ApplyUnitaryArgs) -> Optional[np.ndarray]:
|
|
174
175
|
if cirq.is_parameterized(self):
|
|
175
176
|
return None
|
|
176
177
|
if self.theta != 0:
|
|
@@ -187,7 +188,7 @@ class FSimGate(gate_features.InterchangeableQubitsGate, raw_types.Gate):
|
|
|
187
188
|
out[ii] *= cmath.exp(-1j * self.phi)
|
|
188
189
|
return out
|
|
189
190
|
|
|
190
|
-
def _decompose_(self, qubits) -> Iterator[
|
|
191
|
+
def _decompose_(self, qubits) -> Iterator[cirq.OP_TREE]:
|
|
191
192
|
a, b = qubits
|
|
192
193
|
xx = cirq.XXPowGate(exponent=self.theta / np.pi, global_shift=-0.5)
|
|
193
194
|
yy = cirq.YYPowGate(exponent=self.theta / np.pi, global_shift=-0.5)
|
|
@@ -195,12 +196,12 @@ class FSimGate(gate_features.InterchangeableQubitsGate, raw_types.Gate):
|
|
|
195
196
|
yield yy(a, b)
|
|
196
197
|
yield cirq.CZ(a, b) ** (-self.phi / np.pi)
|
|
197
198
|
|
|
198
|
-
def _circuit_diagram_info_(self, args:
|
|
199
|
+
def _circuit_diagram_info_(self, args: cirq.CircuitDiagramInfoArgs) -> Tuple[str, ...]:
|
|
199
200
|
t = args.format_radians(self.theta)
|
|
200
201
|
p = args.format_radians(self.phi)
|
|
201
202
|
return f'FSim({t}, {p})', f'FSim({t}, {p})'
|
|
202
203
|
|
|
203
|
-
def __pow__(self, power) ->
|
|
204
|
+
def __pow__(self, power) -> FSimGate:
|
|
204
205
|
return FSimGate(cirq.mul(self.theta, power), cirq.mul(self.phi, power))
|
|
205
206
|
|
|
206
207
|
def __repr__(self) -> str:
|
|
@@ -275,11 +276,11 @@ class PhasedFSimGate(gate_features.InterchangeableQubitsGate, raw_types.Gate):
|
|
|
275
276
|
|
|
276
277
|
def __init__(
|
|
277
278
|
self,
|
|
278
|
-
theta:
|
|
279
|
-
zeta:
|
|
280
|
-
chi:
|
|
281
|
-
gamma:
|
|
282
|
-
phi:
|
|
279
|
+
theta: cirq.TParamVal,
|
|
280
|
+
zeta: cirq.TParamVal = 0.0,
|
|
281
|
+
chi: cirq.TParamVal = 0.0,
|
|
282
|
+
gamma: cirq.TParamVal = 0.0,
|
|
283
|
+
phi: cirq.TParamVal = 0.0,
|
|
283
284
|
) -> None:
|
|
284
285
|
"""Inits PhasedFSimGate.
|
|
285
286
|
|
|
@@ -302,32 +303,32 @@ class PhasedFSimGate(gate_features.InterchangeableQubitsGate, raw_types.Gate):
|
|
|
302
303
|
self._phi = _canonicalize(phi)
|
|
303
304
|
|
|
304
305
|
@property
|
|
305
|
-
def theta(self) ->
|
|
306
|
+
def theta(self) -> cirq.TParamVal:
|
|
306
307
|
return self._theta
|
|
307
308
|
|
|
308
309
|
@property
|
|
309
|
-
def zeta(self) ->
|
|
310
|
+
def zeta(self) -> cirq.TParamVal:
|
|
310
311
|
return self._zeta
|
|
311
312
|
|
|
312
313
|
@property
|
|
313
|
-
def chi(self) ->
|
|
314
|
+
def chi(self) -> cirq.TParamVal:
|
|
314
315
|
return self._chi
|
|
315
316
|
|
|
316
317
|
@property
|
|
317
|
-
def gamma(self) ->
|
|
318
|
+
def gamma(self) -> cirq.TParamVal:
|
|
318
319
|
return self._gamma
|
|
319
320
|
|
|
320
321
|
@property
|
|
321
|
-
def phi(self) ->
|
|
322
|
+
def phi(self) -> cirq.TParamVal:
|
|
322
323
|
return self._phi
|
|
323
324
|
|
|
324
325
|
@staticmethod
|
|
325
326
|
def from_fsim_rz(
|
|
326
|
-
theta:
|
|
327
|
-
phi:
|
|
328
|
-
rz_angles_before: Tuple[
|
|
329
|
-
rz_angles_after: Tuple[
|
|
330
|
-
) ->
|
|
327
|
+
theta: cirq.TParamVal,
|
|
328
|
+
phi: cirq.TParamVal,
|
|
329
|
+
rz_angles_before: Tuple[cirq.TParamVal, cirq.TParamVal],
|
|
330
|
+
rz_angles_after: Tuple[cirq.TParamVal, cirq.TParamVal],
|
|
331
|
+
) -> PhasedFSimGate:
|
|
331
332
|
"""Creates PhasedFSimGate using an alternate parametrization.
|
|
332
333
|
|
|
333
334
|
Args:
|
|
@@ -348,7 +349,7 @@ class PhasedFSimGate(gate_features.InterchangeableQubitsGate, raw_types.Gate):
|
|
|
348
349
|
return PhasedFSimGate(theta, zeta, chi, gamma, phi)
|
|
349
350
|
|
|
350
351
|
@staticmethod
|
|
351
|
-
def from_matrix(u: np.ndarray) -> Optional[
|
|
352
|
+
def from_matrix(u: np.ndarray) -> Optional[PhasedFSimGate]:
|
|
352
353
|
"""Contruct a PhasedFSimGate from unitary.
|
|
353
354
|
|
|
354
355
|
Args:
|
|
@@ -387,14 +388,14 @@ class PhasedFSimGate(gate_features.InterchangeableQubitsGate, raw_types.Gate):
|
|
|
387
388
|
return None
|
|
388
389
|
|
|
389
390
|
@property
|
|
390
|
-
def rz_angles_before(self) -> Tuple[
|
|
391
|
+
def rz_angles_before(self) -> Tuple[cirq.TParamVal, cirq.TParamVal]:
|
|
391
392
|
"""Returns 2-tuple of phase angles applied to qubits before FSimGate."""
|
|
392
393
|
b0 = (-self.gamma + self.zeta + self.chi) / 2.0
|
|
393
394
|
b1 = (-self.gamma - self.zeta - self.chi) / 2.0
|
|
394
395
|
return b0, b1
|
|
395
396
|
|
|
396
397
|
@property
|
|
397
|
-
def rz_angles_after(self) -> Tuple[
|
|
398
|
+
def rz_angles_after(self) -> Tuple[cirq.TParamVal, cirq.TParamVal]:
|
|
398
399
|
"""Returns 2-tuple of phase angles applied to qubits after FSimGate."""
|
|
399
400
|
a0 = (-self.gamma + self.zeta - self.chi) / 2.0
|
|
400
401
|
a1 = (-self.gamma - self.zeta + self.chi) / 2.0
|
|
@@ -456,8 +457,8 @@ class PhasedFSimGate(gate_features.InterchangeableQubitsGate, raw_types.Gate):
|
|
|
456
457
|
# fmt: on
|
|
457
458
|
|
|
458
459
|
def _resolve_parameters_(
|
|
459
|
-
self, resolver:
|
|
460
|
-
) ->
|
|
460
|
+
self, resolver: cirq.ParamResolver, recursive: bool
|
|
461
|
+
) -> cirq.PhasedFSimGate:
|
|
461
462
|
return PhasedFSimGate(
|
|
462
463
|
protocols.resolve_parameters(self.theta, resolver, recursive),
|
|
463
464
|
protocols.resolve_parameters(self.zeta, resolver, recursive),
|
|
@@ -466,7 +467,7 @@ class PhasedFSimGate(gate_features.InterchangeableQubitsGate, raw_types.Gate):
|
|
|
466
467
|
protocols.resolve_parameters(self.phi, resolver, recursive),
|
|
467
468
|
)
|
|
468
469
|
|
|
469
|
-
def _apply_unitary_(self, args:
|
|
470
|
+
def _apply_unitary_(self, args: cirq.ApplyUnitaryArgs) -> Optional[np.ndarray]:
|
|
470
471
|
if cirq.is_parameterized(self):
|
|
471
472
|
return None
|
|
472
473
|
oi = args.subspace_index(0b01)
|
|
@@ -491,7 +492,7 @@ class PhasedFSimGate(gate_features.InterchangeableQubitsGate, raw_types.Gate):
|
|
|
491
492
|
out[ii] *= f * f
|
|
492
493
|
return out
|
|
493
494
|
|
|
494
|
-
def _decompose_(self, qubits) -> Iterator[
|
|
495
|
+
def _decompose_(self, qubits) -> Iterator[cirq.OP_TREE]:
|
|
495
496
|
"""Decomposes self into Z rotations and FSimGate.
|
|
496
497
|
|
|
497
498
|
Note that Z rotations returned by this method have unusual global phase
|
|
@@ -500,7 +501,7 @@ class PhasedFSimGate(gate_features.InterchangeableQubitsGate, raw_types.Gate):
|
|
|
500
501
|
makes the top left element of the matrix equal to 1.
|
|
501
502
|
"""
|
|
502
503
|
|
|
503
|
-
def to_exponent(angle_rads:
|
|
504
|
+
def to_exponent(angle_rads: cirq.TParamVal) -> cirq.TParamVal:
|
|
504
505
|
"""Divides angle_rads by symbolic or numerical pi."""
|
|
505
506
|
pi = sympy.pi if protocols.is_parameterized(angle_rads) else np.pi
|
|
506
507
|
return angle_rads / pi
|
|
@@ -514,7 +515,7 @@ class PhasedFSimGate(gate_features.InterchangeableQubitsGate, raw_types.Gate):
|
|
|
514
515
|
yield cirq.Z(q0) ** to_exponent(after[0])
|
|
515
516
|
yield cirq.Z(q1) ** to_exponent(after[1])
|
|
516
517
|
|
|
517
|
-
def _circuit_diagram_info_(self, args:
|
|
518
|
+
def _circuit_diagram_info_(self, args: cirq.CircuitDiagramInfoArgs) -> Tuple[str, ...]:
|
|
518
519
|
theta = args.format_radians(self.theta)
|
|
519
520
|
zeta = args.format_radians(self.zeta)
|
|
520
521
|
chi = args.format_radians(self.chi)
|