cirq-core 1.6.0.dev20250424231143__py3-none-any.whl → 1.6.0.dev20250428201230__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 +28 -24
- cirq/protocols/decompose_protocol_test.py +5 -2
- cirq/protocols/inverse_protocol.py +10 -8
- {cirq_core-1.6.0.dev20250424231143.dist-info → cirq_core-1.6.0.dev20250428201230.dist-info}/METADATA +1 -1
- {cirq_core-1.6.0.dev20250424231143.dist-info → cirq_core-1.6.0.dev20250428201230.dist-info}/RECORD +57 -57
- {cirq_core-1.6.0.dev20250424231143.dist-info → cirq_core-1.6.0.dev20250428201230.dist-info}/WHEEL +1 -1
- {cirq_core-1.6.0.dev20250424231143.dist-info → cirq_core-1.6.0.dev20250428201230.dist-info}/licenses/LICENSE +0 -0
- {cirq_core-1.6.0.dev20250424231143.dist-info → cirq_core-1.6.0.dev20250428201230.dist-info}/top_level.txt +0 -0
cirq/ops/linear_combinations.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 numbers
|
|
16
18
|
from collections import defaultdict
|
|
17
19
|
from typing import (
|
|
@@ -81,7 +83,7 @@ class LinearCombinationOfGates(value.LinearDict[raw_types.Gate]):
|
|
|
81
83
|
2 * cirq.X - 2 * cirq.Z
|
|
82
84
|
"""
|
|
83
85
|
|
|
84
|
-
def __init__(self, terms: Mapping[raw_types.Gate,
|
|
86
|
+
def __init__(self, terms: Mapping[raw_types.Gate, cirq.TParamValComplex]) -> None:
|
|
85
87
|
"""Initializes linear combination from a collection of terms.
|
|
86
88
|
|
|
87
89
|
Args:
|
|
@@ -97,38 +99,38 @@ class LinearCombinationOfGates(value.LinearDict[raw_types.Gate]):
|
|
|
97
99
|
any_gate = next(iter(self))
|
|
98
100
|
return any_gate.num_qubits()
|
|
99
101
|
|
|
100
|
-
def _is_compatible(self, gate:
|
|
102
|
+
def _is_compatible(self, gate: cirq.Gate) -> bool:
|
|
101
103
|
return self.num_qubits() is None or self.num_qubits() == gate.num_qubits()
|
|
102
104
|
|
|
103
105
|
def __add__(
|
|
104
|
-
self, other: Union[raw_types.Gate,
|
|
105
|
-
) ->
|
|
106
|
+
self, other: Union[raw_types.Gate, LinearCombinationOfGates]
|
|
107
|
+
) -> LinearCombinationOfGates:
|
|
106
108
|
if not isinstance(other, LinearCombinationOfGates):
|
|
107
109
|
other = other.wrap_in_linear_combination()
|
|
108
110
|
return super().__add__(other)
|
|
109
111
|
|
|
110
112
|
def __iadd__(
|
|
111
|
-
self, other: Union[raw_types.Gate,
|
|
112
|
-
) ->
|
|
113
|
+
self, other: Union[raw_types.Gate, LinearCombinationOfGates]
|
|
114
|
+
) -> LinearCombinationOfGates:
|
|
113
115
|
if not isinstance(other, LinearCombinationOfGates):
|
|
114
116
|
other = other.wrap_in_linear_combination()
|
|
115
117
|
return super().__iadd__(other)
|
|
116
118
|
|
|
117
119
|
def __sub__(
|
|
118
|
-
self, other: Union[raw_types.Gate,
|
|
119
|
-
) ->
|
|
120
|
+
self, other: Union[raw_types.Gate, LinearCombinationOfGates]
|
|
121
|
+
) -> LinearCombinationOfGates:
|
|
120
122
|
if not isinstance(other, LinearCombinationOfGates):
|
|
121
123
|
other = other.wrap_in_linear_combination()
|
|
122
124
|
return super().__sub__(other)
|
|
123
125
|
|
|
124
126
|
def __isub__(
|
|
125
|
-
self, other: Union[raw_types.Gate,
|
|
126
|
-
) ->
|
|
127
|
+
self, other: Union[raw_types.Gate, LinearCombinationOfGates]
|
|
128
|
+
) -> LinearCombinationOfGates:
|
|
127
129
|
if not isinstance(other, LinearCombinationOfGates):
|
|
128
130
|
other = other.wrap_in_linear_combination()
|
|
129
131
|
return super().__isub__(other)
|
|
130
132
|
|
|
131
|
-
def __pow__(self, exponent: int) ->
|
|
133
|
+
def __pow__(self, exponent: int) -> LinearCombinationOfGates:
|
|
132
134
|
if not isinstance(exponent, int):
|
|
133
135
|
return NotImplemented
|
|
134
136
|
if exponent < 0:
|
|
@@ -155,8 +157,8 @@ class LinearCombinationOfGates(value.LinearDict[raw_types.Gate]):
|
|
|
155
157
|
return {name for item in self.items() for name in protocols.parameter_names(item)}
|
|
156
158
|
|
|
157
159
|
def _resolve_parameters_(
|
|
158
|
-
self, resolver:
|
|
159
|
-
) ->
|
|
160
|
+
self, resolver: cirq.ParamResolver, recursive: bool
|
|
161
|
+
) -> LinearCombinationOfGates:
|
|
160
162
|
return self.__class__(
|
|
161
163
|
{
|
|
162
164
|
protocols.resolve_parameters(
|
|
@@ -224,7 +226,7 @@ class LinearCombinationOfOperations(value.LinearDict[raw_types.Operation]):
|
|
|
224
226
|
by the identity operator. Note that A may not be unitary or even normal.
|
|
225
227
|
"""
|
|
226
228
|
|
|
227
|
-
def __init__(self, terms: Mapping[raw_types.Operation,
|
|
229
|
+
def __init__(self, terms: Mapping[raw_types.Operation, cirq.TParamValComplex]) -> None:
|
|
228
230
|
"""Initializes linear combination from a collection of terms.
|
|
229
231
|
|
|
230
232
|
Args:
|
|
@@ -233,7 +235,7 @@ class LinearCombinationOfOperations(value.LinearDict[raw_types.Operation]):
|
|
|
233
235
|
"""
|
|
234
236
|
super().__init__(terms, validator=self._is_compatible)
|
|
235
237
|
|
|
236
|
-
def _is_compatible(self, operation:
|
|
238
|
+
def _is_compatible(self, operation: cirq.Operation) -> bool:
|
|
237
239
|
return isinstance(operation, raw_types.Operation)
|
|
238
240
|
|
|
239
241
|
@property
|
|
@@ -245,7 +247,7 @@ class LinearCombinationOfOperations(value.LinearDict[raw_types.Operation]):
|
|
|
245
247
|
all_qubits = set.union(*qubit_sets)
|
|
246
248
|
return tuple(sorted(all_qubits))
|
|
247
249
|
|
|
248
|
-
def __pow__(self, exponent: int) ->
|
|
250
|
+
def __pow__(self, exponent: int) -> LinearCombinationOfOperations:
|
|
249
251
|
if not isinstance(exponent, int):
|
|
250
252
|
return NotImplemented
|
|
251
253
|
if exponent < 0:
|
|
@@ -272,8 +274,8 @@ class LinearCombinationOfOperations(value.LinearDict[raw_types.Operation]):
|
|
|
272
274
|
return {name for item in self.items() for name in protocols.parameter_names(item)}
|
|
273
275
|
|
|
274
276
|
def _resolve_parameters_(
|
|
275
|
-
self, resolver:
|
|
276
|
-
) ->
|
|
277
|
+
self, resolver: cirq.ParamResolver, recursive: bool
|
|
278
|
+
) -> LinearCombinationOfOperations:
|
|
277
279
|
return self.__class__(
|
|
278
280
|
{
|
|
279
281
|
protocols.resolve_parameters(op, resolver, recursive): protocols.resolve_parameters(
|
|
@@ -317,7 +319,7 @@ class LinearCombinationOfOperations(value.LinearDict[raw_types.Operation]):
|
|
|
317
319
|
"""Computes Pauli expansion of self from Pauli expansions of terms."""
|
|
318
320
|
|
|
319
321
|
def extend_term(
|
|
320
|
-
pauli_names: str, qubits: Tuple[
|
|
322
|
+
pauli_names: str, qubits: Tuple[cirq.Qid, ...], all_qubits: Tuple[cirq.Qid, ...]
|
|
321
323
|
) -> str:
|
|
322
324
|
"""Extends Pauli product on qubits to product on all_qubits."""
|
|
323
325
|
assert len(pauli_names) == len(qubits)
|
|
@@ -326,8 +328,8 @@ class LinearCombinationOfOperations(value.LinearDict[raw_types.Operation]):
|
|
|
326
328
|
|
|
327
329
|
def extend(
|
|
328
330
|
expansion: value.LinearDict[str],
|
|
329
|
-
qubits: Tuple[
|
|
330
|
-
all_qubits: Tuple[
|
|
331
|
+
qubits: Tuple[cirq.Qid, ...],
|
|
332
|
+
all_qubits: Tuple[cirq.Qid, ...],
|
|
331
333
|
) -> value.LinearDict[str]:
|
|
332
334
|
"""Extends Pauli expansion on qubits to expansion on all_qubits."""
|
|
333
335
|
return value.LinearDict(
|
|
@@ -358,7 +360,7 @@ def _is_linear_dict_of_unit_pauli_string(linear_dict: value.LinearDict[UnitPauli
|
|
|
358
360
|
|
|
359
361
|
|
|
360
362
|
def _pauli_string_from_unit(
|
|
361
|
-
unit: UnitPauliStringT, coefficient: Union[int, float,
|
|
363
|
+
unit: UnitPauliStringT, coefficient: Union[int, float, cirq.TParamValComplex] = 1
|
|
362
364
|
):
|
|
363
365
|
return PauliString(qubit_pauli_map=dict(unit), coefficient=coefficient)
|
|
364
366
|
|
|
@@ -444,7 +446,7 @@ class PauliSum:
|
|
|
444
446
|
return self._linear_dict
|
|
445
447
|
|
|
446
448
|
@staticmethod
|
|
447
|
-
def wrap(val: PauliSumLike) ->
|
|
449
|
+
def wrap(val: PauliSumLike) -> PauliSum:
|
|
448
450
|
"""Convert a `cirq.PauliSumLike` object to a PauliSum
|
|
449
451
|
|
|
450
452
|
Attempts to convert an existing int, float, complex, `cirq.PauliString`,
|
|
@@ -468,7 +470,7 @@ class PauliSum:
|
|
|
468
470
|
return PauliSum() + val
|
|
469
471
|
|
|
470
472
|
@classmethod
|
|
471
|
-
def from_pauli_strings(cls, terms: Union[PauliString, List[PauliString]]) ->
|
|
473
|
+
def from_pauli_strings(cls, terms: Union[PauliString, List[PauliString]]) -> PauliSum:
|
|
472
474
|
"""Returns a PauliSum by combining `cirq.PauliString` terms.
|
|
473
475
|
|
|
474
476
|
Args:
|
|
@@ -488,8 +490,8 @@ class PauliSum:
|
|
|
488
490
|
|
|
489
491
|
@classmethod
|
|
490
492
|
def from_boolean_expression(
|
|
491
|
-
cls, boolean_expr: Expr, qubit_map: Dict[str,
|
|
492
|
-
) ->
|
|
493
|
+
cls, boolean_expr: Expr, qubit_map: Dict[str, cirq.Qid]
|
|
494
|
+
) -> PauliSum:
|
|
493
495
|
"""Builds the Hamiltonian representation of a Boolean expression.
|
|
494
496
|
|
|
495
497
|
This is based on "On the representation of Boolean and real functions as Hamiltonians for
|
|
@@ -545,7 +547,7 @@ class PauliSum:
|
|
|
545
547
|
qs = {q for k in self._linear_dict.keys() for q, _ in k}
|
|
546
548
|
return tuple(sorted(qs))
|
|
547
549
|
|
|
548
|
-
def with_qubits(self, *new_qubits:
|
|
550
|
+
def with_qubits(self, *new_qubits: cirq.Qid) -> PauliSum:
|
|
549
551
|
"""Return a new PauliSum on `new_qubits`.
|
|
550
552
|
|
|
551
553
|
Args:
|
|
@@ -569,7 +571,7 @@ class PauliSum:
|
|
|
569
571
|
new_pauli_strings.append(pauli_string.map_qubits(qubit_map))
|
|
570
572
|
return PauliSum.from_pauli_strings(new_pauli_strings)
|
|
571
573
|
|
|
572
|
-
def copy(self) ->
|
|
574
|
+
def copy(self) -> PauliSum:
|
|
573
575
|
"""Return a copy of this PauliSum.
|
|
574
576
|
|
|
575
577
|
Returns: A copy of this PauliSum.
|
|
@@ -922,7 +924,7 @@ class ProjectorSum:
|
|
|
922
924
|
@classmethod
|
|
923
925
|
def from_projector_strings(
|
|
924
926
|
cls, terms: Union[ProjectorString, List[ProjectorString]]
|
|
925
|
-
) ->
|
|
927
|
+
) -> ProjectorSum:
|
|
926
928
|
"""Builds a ProjectorSum from one or more ProjectorString(s).
|
|
927
929
|
|
|
928
930
|
Args:
|
|
@@ -941,7 +943,7 @@ class ProjectorSum:
|
|
|
941
943
|
termdict[key] += pstring.coefficient
|
|
942
944
|
return cls(linear_dict=value.LinearDict(termdict))
|
|
943
945
|
|
|
944
|
-
def copy(self) ->
|
|
946
|
+
def copy(self) -> ProjectorSum:
|
|
945
947
|
return ProjectorSum(self._linear_dict.copy())
|
|
946
948
|
|
|
947
949
|
def matrix(self, projector_qids: Optional[Iterable[raw_types.Qid]] = None) -> csr_matrix:
|
|
@@ -1022,7 +1024,7 @@ class ProjectorSum:
|
|
|
1022
1024
|
def __bool__(self) -> bool:
|
|
1023
1025
|
return bool(self._linear_dict)
|
|
1024
1026
|
|
|
1025
|
-
def __iadd__(self, other: Union[
|
|
1027
|
+
def __iadd__(self, other: Union[ProjectorString, ProjectorSum]):
|
|
1026
1028
|
if isinstance(other, ProjectorString):
|
|
1027
1029
|
other = ProjectorSum.from_projector_strings(other)
|
|
1028
1030
|
elif not isinstance(other, ProjectorSum):
|
|
@@ -1030,7 +1032,7 @@ class ProjectorSum:
|
|
|
1030
1032
|
self._linear_dict += other._linear_dict
|
|
1031
1033
|
return self
|
|
1032
1034
|
|
|
1033
|
-
def __add__(self, other: Union[
|
|
1035
|
+
def __add__(self, other: Union[ProjectorString, ProjectorSum]):
|
|
1034
1036
|
if isinstance(other, ProjectorString):
|
|
1035
1037
|
other = ProjectorSum.from_projector_strings(other)
|
|
1036
1038
|
elif not isinstance(other, ProjectorSum):
|
|
@@ -1039,7 +1041,7 @@ class ProjectorSum:
|
|
|
1039
1041
|
result += other
|
|
1040
1042
|
return result
|
|
1041
1043
|
|
|
1042
|
-
def __isub__(self, other: Union[
|
|
1044
|
+
def __isub__(self, other: Union[ProjectorString, ProjectorSum]):
|
|
1043
1045
|
if isinstance(other, ProjectorString):
|
|
1044
1046
|
other = ProjectorSum.from_projector_strings(other)
|
|
1045
1047
|
elif not isinstance(other, ProjectorSum):
|
|
@@ -1047,7 +1049,7 @@ class ProjectorSum:
|
|
|
1047
1049
|
self._linear_dict -= other._linear_dict
|
|
1048
1050
|
return self
|
|
1049
1051
|
|
|
1050
|
-
def __sub__(self, other: Union[
|
|
1052
|
+
def __sub__(self, other: Union[ProjectorString, ProjectorSum]):
|
|
1051
1053
|
if isinstance(other, ProjectorString):
|
|
1052
1054
|
other = ProjectorSum.from_projector_strings(other)
|
|
1053
1055
|
elif not isinstance(other, ProjectorSum):
|
cirq/ops/matrix_gates.py
CHANGED
|
@@ -14,6 +14,8 @@
|
|
|
14
14
|
|
|
15
15
|
"""Quantum gates defined by a matrix."""
|
|
16
16
|
|
|
17
|
+
from __future__ import annotations
|
|
18
|
+
|
|
17
19
|
from typing import Any, Dict, Iterable, List, Optional, Tuple, TYPE_CHECKING
|
|
18
20
|
|
|
19
21
|
import numpy as np
|
|
@@ -109,7 +111,7 @@ class MatrixGate(raw_types.Gate):
|
|
|
109
111
|
):
|
|
110
112
|
raise ValueError(f'Not a unitary matrix: {matrix}')
|
|
111
113
|
|
|
112
|
-
def with_name(self, name: str) ->
|
|
114
|
+
def with_name(self, name: str) -> MatrixGate:
|
|
113
115
|
"""Creates a new MatrixGate with the same matrix and a new name."""
|
|
114
116
|
return MatrixGate(self._matrix, name=name, qid_shape=self._qid_shape, unitary_check=False)
|
|
115
117
|
|
|
@@ -127,13 +129,13 @@ class MatrixGate(raw_types.Gate):
|
|
|
127
129
|
def _qid_shape_(self) -> Tuple[int, ...]:
|
|
128
130
|
return self._qid_shape
|
|
129
131
|
|
|
130
|
-
def __pow__(self, exponent: Any) ->
|
|
132
|
+
def __pow__(self, exponent: Any) -> MatrixGate:
|
|
131
133
|
if not isinstance(exponent, (int, float)):
|
|
132
134
|
return NotImplemented
|
|
133
135
|
new_mat = linalg.map_eigenvalues(self._matrix, lambda b: b**exponent)
|
|
134
136
|
return MatrixGate(new_mat, qid_shape=self._qid_shape)
|
|
135
137
|
|
|
136
|
-
def _phase_by_(self, phase_turns: float, qubit_index: int) ->
|
|
138
|
+
def _phase_by_(self, phase_turns: float, qubit_index: int) -> MatrixGate:
|
|
137
139
|
if not isinstance(phase_turns, (int, float)):
|
|
138
140
|
return NotImplemented
|
|
139
141
|
if self._qid_shape[qubit_index] != 2:
|
|
@@ -147,10 +149,10 @@ class MatrixGate(raw_types.Gate):
|
|
|
147
149
|
result[linalg.slice_for_qubits_equal_to([j], 1)] *= np.conj(p)
|
|
148
150
|
return MatrixGate(matrix=result.reshape(self._matrix.shape), qid_shape=self._qid_shape)
|
|
149
151
|
|
|
150
|
-
def _decompose_(self, qubits: Tuple[
|
|
152
|
+
def _decompose_(self, qubits: Tuple[cirq.Qid, ...]) -> cirq.OP_TREE:
|
|
151
153
|
from cirq.circuits import Circuit
|
|
152
154
|
|
|
153
|
-
decomposed: List[
|
|
155
|
+
decomposed: List[cirq.Operation] = NotImplemented
|
|
154
156
|
if self._qid_shape == (2,):
|
|
155
157
|
decomposed = [
|
|
156
158
|
g.on(qubits[0])
|
|
@@ -183,9 +185,7 @@ class MatrixGate(raw_types.Gate):
|
|
|
183
185
|
def _unitary_(self) -> np.ndarray:
|
|
184
186
|
return np.copy(self._matrix)
|
|
185
187
|
|
|
186
|
-
def _circuit_diagram_info_(
|
|
187
|
-
self, args: 'cirq.CircuitDiagramInfoArgs'
|
|
188
|
-
) -> 'cirq.CircuitDiagramInfo':
|
|
188
|
+
def _circuit_diagram_info_(self, args: cirq.CircuitDiagramInfoArgs) -> cirq.CircuitDiagramInfo:
|
|
189
189
|
n_qubits = len(self._qid_shape)
|
|
190
190
|
# No diagram for zero-qubit gates; let fallback handle it
|
|
191
191
|
if n_qubits == 0:
|
|
@@ -199,7 +199,7 @@ class MatrixGate(raw_types.Gate):
|
|
|
199
199
|
rest = [f'#{i+1}' for i in range(1, n_qubits)]
|
|
200
200
|
return protocols.CircuitDiagramInfo(wire_symbols=[main, *rest])
|
|
201
201
|
|
|
202
|
-
def _qasm_(self, args:
|
|
202
|
+
def _qasm_(self, args: cirq.QasmArgs, qubits: Tuple[cirq.Qid, ...]) -> Optional[str]:
|
|
203
203
|
args.validate_version('2.0', '3.0')
|
|
204
204
|
if self._qid_shape == (2,):
|
|
205
205
|
return protocols.qasm(
|
|
@@ -233,7 +233,7 @@ class MatrixGate(raw_types.Gate):
|
|
|
233
233
|
return str(self._matrix.round(3))
|
|
234
234
|
|
|
235
235
|
|
|
236
|
-
def _matrix_to_diagram_symbol(matrix: np.ndarray, args:
|
|
236
|
+
def _matrix_to_diagram_symbol(matrix: np.ndarray, args: protocols.CircuitDiagramInfoArgs) -> str:
|
|
237
237
|
if args.precision is not None:
|
|
238
238
|
matrix = matrix.round(args.precision)
|
|
239
239
|
result = str(matrix)
|
cirq/ops/measure_util.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 Callable, Dict, Iterable, List, Optional, overload, Tuple, TYPE_CHECKING, Union
|
|
16
18
|
|
|
17
19
|
import numpy as np
|
|
@@ -31,7 +33,7 @@ def _default_measurement_key(qubits: Iterable[raw_types.Qid]) -> str:
|
|
|
31
33
|
|
|
32
34
|
def measure_single_paulistring(
|
|
33
35
|
pauli_observable: pauli_string.PauliString,
|
|
34
|
-
key: Optional[Union[str,
|
|
36
|
+
key: Optional[Union[str, cirq.MeasurementKey]] = None,
|
|
35
37
|
) -> raw_types.Operation:
|
|
36
38
|
"""Returns a single PauliMeasurementGate which measures the pauli observable
|
|
37
39
|
|
|
@@ -95,7 +97,7 @@ def measure_paulistring_terms(
|
|
|
95
97
|
@overload
|
|
96
98
|
def measure(
|
|
97
99
|
*target: raw_types.Qid,
|
|
98
|
-
key: Optional[Union[str,
|
|
100
|
+
key: Optional[Union[str, cirq.MeasurementKey]] = None,
|
|
99
101
|
invert_mask: Tuple[bool, ...] = (),
|
|
100
102
|
) -> raw_types.Operation:
|
|
101
103
|
pass
|
|
@@ -105,7 +107,7 @@ def measure(
|
|
|
105
107
|
def measure(
|
|
106
108
|
__target: Iterable[raw_types.Qid],
|
|
107
109
|
*,
|
|
108
|
-
key: Optional[Union[str,
|
|
110
|
+
key: Optional[Union[str, cirq.MeasurementKey]] = None,
|
|
109
111
|
invert_mask: Tuple[bool, ...] = (),
|
|
110
112
|
) -> raw_types.Operation:
|
|
111
113
|
pass
|
|
@@ -113,7 +115,7 @@ def measure(
|
|
|
113
115
|
|
|
114
116
|
def measure(
|
|
115
117
|
*target,
|
|
116
|
-
key: Optional[Union[str,
|
|
118
|
+
key: Optional[Union[str, cirq.MeasurementKey]] = None,
|
|
117
119
|
invert_mask: Tuple[bool, ...] = (),
|
|
118
120
|
confusion_map: Optional[Dict[Tuple[int, ...], np.ndarray]] = None,
|
|
119
121
|
) -> raw_types.Operation:
|
cirq/ops/measurement_gate.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 (
|
|
16
18
|
Any,
|
|
17
19
|
Dict,
|
|
@@ -48,7 +50,7 @@ class MeasurementGate(raw_types.Gate):
|
|
|
48
50
|
def __init__(
|
|
49
51
|
self,
|
|
50
52
|
num_qubits: Optional[int] = None,
|
|
51
|
-
key: Union[str,
|
|
53
|
+
key: Union[str, cirq.MeasurementKey] = '',
|
|
52
54
|
invert_mask: Tuple[bool, ...] = (),
|
|
53
55
|
qid_shape: Optional[Tuple[int, ...]] = None,
|
|
54
56
|
confusion_map: Optional[Dict[Tuple[int, ...], np.ndarray]] = None,
|
|
@@ -100,7 +102,7 @@ class MeasurementGate(raw_types.Gate):
|
|
|
100
102
|
return str(self.mkey)
|
|
101
103
|
|
|
102
104
|
@property
|
|
103
|
-
def mkey(self) ->
|
|
105
|
+
def mkey(self) -> cirq.MeasurementKey:
|
|
104
106
|
return self._mkey
|
|
105
107
|
|
|
106
108
|
@property
|
|
@@ -117,7 +119,7 @@ class MeasurementGate(raw_types.Gate):
|
|
|
117
119
|
def _has_unitary_(self) -> bool:
|
|
118
120
|
return False
|
|
119
121
|
|
|
120
|
-
def with_key(self, key: Union[str,
|
|
122
|
+
def with_key(self, key: Union[str, cirq.MeasurementKey]) -> MeasurementGate:
|
|
121
123
|
"""Creates a measurement gate with a new key but otherwise identical."""
|
|
122
124
|
if key == self.key:
|
|
123
125
|
return self
|
|
@@ -136,14 +138,14 @@ class MeasurementGate(raw_types.Gate):
|
|
|
136
138
|
return self.with_key(self.mkey._with_key_path_prefix_(prefix))
|
|
137
139
|
|
|
138
140
|
def _with_rescoped_keys_(
|
|
139
|
-
self, path: Tuple[str, ...], bindable_keys: FrozenSet[
|
|
141
|
+
self, path: Tuple[str, ...], bindable_keys: FrozenSet[cirq.MeasurementKey]
|
|
140
142
|
):
|
|
141
143
|
return self.with_key(protocols.with_rescoped_keys(self.mkey, path, bindable_keys))
|
|
142
144
|
|
|
143
145
|
def _with_measurement_key_mapping_(self, key_map: Mapping[str, str]):
|
|
144
146
|
return self.with_key(protocols.with_measurement_key_mapping(self.mkey, key_map))
|
|
145
147
|
|
|
146
|
-
def with_bits_flipped(self, *bit_positions: int) ->
|
|
148
|
+
def with_bits_flipped(self, *bit_positions: int) -> MeasurementGate:
|
|
147
149
|
"""Toggles whether or not the measurement inverts various outputs.
|
|
148
150
|
|
|
149
151
|
This only affects the invert_mask, which is applied after confusion
|
|
@@ -182,7 +184,7 @@ class MeasurementGate(raw_types.Gate):
|
|
|
182
184
|
def _measurement_key_name_(self) -> str:
|
|
183
185
|
return self.key
|
|
184
186
|
|
|
185
|
-
def _measurement_key_obj_(self) ->
|
|
187
|
+
def _measurement_key_obj_(self) -> cirq.MeasurementKey:
|
|
186
188
|
return self.mkey
|
|
187
189
|
|
|
188
190
|
def _kraus_(self):
|
|
@@ -198,9 +200,7 @@ class MeasurementGate(raw_types.Gate):
|
|
|
198
200
|
def _has_kraus_(self):
|
|
199
201
|
return True
|
|
200
202
|
|
|
201
|
-
def _circuit_diagram_info_(
|
|
202
|
-
self, args: 'cirq.CircuitDiagramInfoArgs'
|
|
203
|
-
) -> 'cirq.CircuitDiagramInfo':
|
|
203
|
+
def _circuit_diagram_info_(self, args: cirq.CircuitDiagramInfoArgs) -> cirq.CircuitDiagramInfo:
|
|
204
204
|
symbols = ['M'] * self.num_qubits()
|
|
205
205
|
flipped_indices = {i for i, x in enumerate(self.full_invert_mask()) if x}
|
|
206
206
|
confused_indices = {x for idxs in self.confusion_map for x in idxs}
|
|
@@ -224,7 +224,7 @@ class MeasurementGate(raw_types.Gate):
|
|
|
224
224
|
|
|
225
225
|
return protocols.CircuitDiagramInfo(symbols)
|
|
226
226
|
|
|
227
|
-
def _qasm_(self, args:
|
|
227
|
+
def _qasm_(self, args: cirq.QasmArgs, qubits: Tuple[cirq.Qid, ...]) -> Optional[str]:
|
|
228
228
|
if self.confusion_map or not all(d == 2 for d in self._qid_shape):
|
|
229
229
|
return NotImplemented
|
|
230
230
|
args.validate_version('2.0', '3.0')
|
|
@@ -243,7 +243,7 @@ class MeasurementGate(raw_types.Gate):
|
|
|
243
243
|
lines.append(args.format('x {0}; // Undo the inversion\n', qubit))
|
|
244
244
|
return ''.join(lines)
|
|
245
245
|
|
|
246
|
-
def _op_repr_(self, qubits: Sequence[
|
|
246
|
+
def _op_repr_(self, qubits: Sequence[cirq.Qid]) -> str:
|
|
247
247
|
args = list(repr(q) for q in qubits)
|
|
248
248
|
if self.key != _default_measurement_key(qubits):
|
|
249
249
|
args.append(f'key={self.mkey!r}')
|
|
@@ -304,7 +304,7 @@ class MeasurementGate(raw_types.Gate):
|
|
|
304
304
|
def _has_stabilizer_effect_(self) -> Optional[bool]:
|
|
305
305
|
return True
|
|
306
306
|
|
|
307
|
-
def _act_on_(self, sim_state:
|
|
307
|
+
def _act_on_(self, sim_state: cirq.SimulationStateBase, qubits: Sequence[cirq.Qid]) -> bool:
|
|
308
308
|
from cirq.sim import SimulationState
|
|
309
309
|
|
|
310
310
|
if not isinstance(sim_state, SimulationState):
|
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
# pylint: disable=wrong-or-nonexistent-copyright-notice
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
2
5
|
from typing import Any, Dict, FrozenSet, Iterable, Mapping, Tuple, TYPE_CHECKING, Union
|
|
3
6
|
|
|
4
7
|
import numpy as np
|
|
@@ -28,7 +31,7 @@ class MixedUnitaryChannel(raw_types.Gate):
|
|
|
28
31
|
def __init__(
|
|
29
32
|
self,
|
|
30
33
|
mixture: Iterable[Tuple[float, np.ndarray]],
|
|
31
|
-
key: Union[str,
|
|
34
|
+
key: Union[str, cirq.MeasurementKey, None] = None,
|
|
32
35
|
validate: bool = False,
|
|
33
36
|
):
|
|
34
37
|
mixture = list(mixture)
|
|
@@ -58,7 +61,7 @@ class MixedUnitaryChannel(raw_types.Gate):
|
|
|
58
61
|
|
|
59
62
|
@staticmethod
|
|
60
63
|
def from_mixture(
|
|
61
|
-
mixture:
|
|
64
|
+
mixture: protocols.SupportsMixture, key: Union[str, cirq.MeasurementKey, None] = None
|
|
62
65
|
):
|
|
63
66
|
"""Creates a copy of a mixture with the given measurement key."""
|
|
64
67
|
return MixedUnitaryChannel(mixture=list(protocols.mixture(mixture)), key=key)
|
|
@@ -85,7 +88,7 @@ class MixedUnitaryChannel(raw_types.Gate):
|
|
|
85
88
|
return NotImplemented
|
|
86
89
|
return str(self._key)
|
|
87
90
|
|
|
88
|
-
def _measurement_key_obj_(self) ->
|
|
91
|
+
def _measurement_key_obj_(self) -> cirq.MeasurementKey:
|
|
89
92
|
if self._key is None:
|
|
90
93
|
return NotImplemented
|
|
91
94
|
return self._key
|
|
@@ -108,7 +111,7 @@ class MixedUnitaryChannel(raw_types.Gate):
|
|
|
108
111
|
)
|
|
109
112
|
|
|
110
113
|
def _with_rescoped_keys_(
|
|
111
|
-
self, path: Tuple[str, ...], bindable_keys: FrozenSet[
|
|
114
|
+
self, path: Tuple[str, ...], bindable_keys: FrozenSet[cirq.MeasurementKey]
|
|
112
115
|
):
|
|
113
116
|
return MixedUnitaryChannel(
|
|
114
117
|
mixture=self._mixture, key=protocols.with_rescoped_keys(self._key, path, bindable_keys)
|
cirq/ops/named_qubit.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 functools
|
|
15
18
|
import weakref
|
|
16
19
|
from typing import Any, Dict, List, Optional, Tuple, TYPE_CHECKING
|
|
@@ -93,7 +96,7 @@ class _BaseNamedQid(raw_types.Qid):
|
|
|
93
96
|
def dimension(self) -> int:
|
|
94
97
|
return self._dimension
|
|
95
98
|
|
|
96
|
-
def with_dimension(self, dimension: int) ->
|
|
99
|
+
def with_dimension(self, dimension: int) -> NamedQid:
|
|
97
100
|
return NamedQid(self._name, dimension=dimension)
|
|
98
101
|
|
|
99
102
|
|
|
@@ -111,7 +114,7 @@ class NamedQid(_BaseNamedQid):
|
|
|
111
114
|
# Holds weak references so instances can still be garbage collected.
|
|
112
115
|
_cache = weakref.WeakValueDictionary[Tuple[str, int], 'cirq.NamedQid']()
|
|
113
116
|
|
|
114
|
-
def __new__(cls, name: str, dimension: int) ->
|
|
117
|
+
def __new__(cls, name: str, dimension: int) -> cirq.NamedQid:
|
|
115
118
|
"""Initializes a `NamedQid` with a given name and dimension.
|
|
116
119
|
|
|
117
120
|
Args:
|
|
@@ -144,7 +147,7 @@ class NamedQid(_BaseNamedQid):
|
|
|
144
147
|
return f'{self._name} (d={self._dimension})'
|
|
145
148
|
|
|
146
149
|
@staticmethod
|
|
147
|
-
def range(*args, prefix: str, dimension: int) -> List[
|
|
150
|
+
def range(*args, prefix: str, dimension: int) -> List[NamedQid]:
|
|
148
151
|
"""Returns a range of ``NamedQid``\\s.
|
|
149
152
|
|
|
150
153
|
The range returned starts with the prefix, and followed by a qid for
|
|
@@ -186,7 +189,7 @@ class NamedQubit(_BaseNamedQid):
|
|
|
186
189
|
# Holds weak references so instances can still be garbage collected.
|
|
187
190
|
_cache = weakref.WeakValueDictionary[str, 'cirq.NamedQubit']()
|
|
188
191
|
|
|
189
|
-
def __new__(cls, name: str) ->
|
|
192
|
+
def __new__(cls, name: str) -> cirq.NamedQubit:
|
|
190
193
|
"""Initializes a `NamedQid` with a given name and dimension.
|
|
191
194
|
|
|
192
195
|
Args:
|
|
@@ -216,7 +219,7 @@ class NamedQubit(_BaseNamedQid):
|
|
|
216
219
|
return f'cirq.NamedQubit({self._name!r})'
|
|
217
220
|
|
|
218
221
|
@staticmethod
|
|
219
|
-
def range(*args, prefix: str) -> List[
|
|
222
|
+
def range(*args, prefix: str) -> List[NamedQubit]:
|
|
220
223
|
r"""Returns a range of `cirq.NamedQubit`s.
|
|
221
224
|
|
|
222
225
|
The range returned starts with the prefix, and followed by a qubit for
|
cirq/ops/op_tree.py
CHANGED
|
@@ -14,6 +14,8 @@
|
|
|
14
14
|
|
|
15
15
|
"""A recursive type describing trees of operations, and utility methods for it."""
|
|
16
16
|
|
|
17
|
+
from __future__ import annotations
|
|
18
|
+
|
|
17
19
|
from typing import Callable, Iterable, Iterator, NoReturn, TYPE_CHECKING, Union
|
|
18
20
|
|
|
19
21
|
from cirq._doc import document
|
|
@@ -47,7 +49,7 @@ document(
|
|
|
47
49
|
|
|
48
50
|
def flatten_op_tree(
|
|
49
51
|
root: OP_TREE, preserve_moments: bool = False
|
|
50
|
-
) -> Iterator[Union[Operation,
|
|
52
|
+
) -> Iterator[Union[Operation, cirq.Moment]]:
|
|
51
53
|
"""Performs an in-order iteration of the operations (leaves) in an OP_TREE.
|
|
52
54
|
|
|
53
55
|
Args:
|
|
@@ -88,7 +90,7 @@ def flatten_to_ops(root: OP_TREE) -> Iterator[Operation]:
|
|
|
88
90
|
_bad_op_tree(root)
|
|
89
91
|
|
|
90
92
|
|
|
91
|
-
def flatten_to_ops_or_moments(root: OP_TREE) -> Iterator[Union[Operation,
|
|
93
|
+
def flatten_to_ops_or_moments(root: OP_TREE) -> Iterator[Union[Operation, cirq.Moment]]:
|
|
92
94
|
"""Performs an in-order iteration OP_TREE, yielding ops and moments.
|
|
93
95
|
|
|
94
96
|
Args:
|
cirq/ops/parallel_gate.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 types import NotImplementedType
|
|
16
18
|
from typing import AbstractSet, Any, Dict, Optional, Tuple, TYPE_CHECKING, Union
|
|
17
19
|
|
|
@@ -29,7 +31,7 @@ if TYPE_CHECKING:
|
|
|
29
31
|
class ParallelGate(raw_types.Gate):
|
|
30
32
|
"""Augments existing gates to be applied on one or more groups of qubits."""
|
|
31
33
|
|
|
32
|
-
def __init__(self, sub_gate:
|
|
34
|
+
def __init__(self, sub_gate: cirq.Gate, num_copies: int) -> None:
|
|
33
35
|
"""Inits ParallelGate.
|
|
34
36
|
|
|
35
37
|
Args:
|
|
@@ -52,24 +54,24 @@ class ParallelGate(raw_types.Gate):
|
|
|
52
54
|
return self.sub_gate.num_qubits() * self._num_copies
|
|
53
55
|
|
|
54
56
|
@property
|
|
55
|
-
def sub_gate(self) ->
|
|
57
|
+
def sub_gate(self) -> cirq.Gate:
|
|
56
58
|
return self._sub_gate
|
|
57
59
|
|
|
58
60
|
@property
|
|
59
61
|
def num_copies(self) -> int:
|
|
60
62
|
return self._num_copies
|
|
61
63
|
|
|
62
|
-
def _decompose_(self, qubits: Tuple[
|
|
64
|
+
def _decompose_(self, qubits: Tuple[cirq.Qid, ...]) -> DecomposeResult:
|
|
63
65
|
if len(qubits) != self.num_qubits():
|
|
64
66
|
raise ValueError(f"len(qubits)={len(qubits)} should be {self.num_qubits()}")
|
|
65
67
|
step = self.sub_gate.num_qubits()
|
|
66
68
|
return [self.sub_gate(*qubits[i : i + step]) for i in range(0, len(qubits), step)]
|
|
67
69
|
|
|
68
|
-
def with_gate(self, sub_gate:
|
|
70
|
+
def with_gate(self, sub_gate: cirq.Gate) -> ParallelGate:
|
|
69
71
|
"""ParallelGate with same number of copies but a new gate"""
|
|
70
72
|
return ParallelGate(sub_gate, self._num_copies)
|
|
71
73
|
|
|
72
|
-
def with_num_copies(self, num_copies: int) ->
|
|
74
|
+
def with_num_copies(self, num_copies: int) -> ParallelGate:
|
|
73
75
|
"""ParallelGate with same sub_gate but different num_copies"""
|
|
74
76
|
return ParallelGate(self.sub_gate, num_copies)
|
|
75
77
|
|
|
@@ -91,9 +93,7 @@ class ParallelGate(raw_types.Gate):
|
|
|
91
93
|
def _parameter_names_(self) -> AbstractSet[str]:
|
|
92
94
|
return protocols.parameter_names(self.sub_gate)
|
|
93
95
|
|
|
94
|
-
def _resolve_parameters_(
|
|
95
|
-
self, resolver: 'cirq.ParamResolver', recursive: bool
|
|
96
|
-
) -> 'ParallelGate':
|
|
96
|
+
def _resolve_parameters_(self, resolver: cirq.ParamResolver, recursive: bool) -> ParallelGate:
|
|
97
97
|
return self.with_gate(
|
|
98
98
|
sub_gate=protocols.resolve_parameters(self.sub_gate, resolver, recursive)
|
|
99
99
|
)
|
|
@@ -122,9 +122,7 @@ class ParallelGate(raw_types.Gate):
|
|
|
122
122
|
return 1.0
|
|
123
123
|
return np.sin(angle)
|
|
124
124
|
|
|
125
|
-
def _circuit_diagram_info_(
|
|
126
|
-
self, args: 'cirq.CircuitDiagramInfoArgs'
|
|
127
|
-
) -> 'cirq.CircuitDiagramInfo':
|
|
125
|
+
def _circuit_diagram_info_(self, args: cirq.CircuitDiagramInfoArgs) -> cirq.CircuitDiagramInfo:
|
|
128
126
|
diagram_info = protocols.circuit_diagram_info(self.sub_gate, args, NotImplemented)
|
|
129
127
|
if diagram_info == NotImplemented:
|
|
130
128
|
return diagram_info
|
|
@@ -136,7 +134,7 @@ class ParallelGate(raw_types.Gate):
|
|
|
136
134
|
wire_symbols=wire_symbols, exponent=diagram_info.exponent, connected=False
|
|
137
135
|
)
|
|
138
136
|
|
|
139
|
-
def __pow__(self, exponent: Any) ->
|
|
137
|
+
def __pow__(self, exponent: Any) -> ParallelGate:
|
|
140
138
|
"""Raises underlying gate to a power, applying same number of copies.
|
|
141
139
|
|
|
142
140
|
For extrapolatable gate G this means the following two are equivalent:
|
|
@@ -158,7 +156,7 @@ class ParallelGate(raw_types.Gate):
|
|
|
158
156
|
return protocols.obj_to_dict_helper(self, attribute_names=["sub_gate", "num_copies"])
|
|
159
157
|
|
|
160
158
|
|
|
161
|
-
def parallel_gate_op(gate:
|
|
159
|
+
def parallel_gate_op(gate: cirq.Gate, *targets: cirq.Qid) -> cirq.Operation:
|
|
162
160
|
"""Constructs a ParallelGate using gate and applies to all given qubits
|
|
163
161
|
|
|
164
162
|
Args:
|