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.

Files changed (57) hide show
  1. cirq/_version.py +1 -1
  2. cirq/_version_test.py +1 -1
  3. cirq/ops/dense_pauli_string.py +28 -28
  4. cirq/ops/diagonal_gate.py +12 -14
  5. cirq/ops/eigen_gate.py +8 -5
  6. cirq/ops/fourier_transform.py +8 -12
  7. cirq/ops/fsim_gate.py +38 -37
  8. cirq/ops/gate_operation.py +25 -27
  9. cirq/ops/gateset.py +7 -5
  10. cirq/ops/global_phase_op.py +11 -11
  11. cirq/ops/greedy_qubit_manager.py +9 -7
  12. cirq/ops/identity.py +8 -6
  13. cirq/ops/kraus_channel.py +7 -4
  14. cirq/ops/linear_combinations.py +36 -34
  15. cirq/ops/matrix_gates.py +10 -10
  16. cirq/ops/measure_util.py +6 -4
  17. cirq/ops/measurement_gate.py +12 -12
  18. cirq/ops/mixed_unitary_channel.py +7 -4
  19. cirq/ops/named_qubit.py +8 -5
  20. cirq/ops/op_tree.py +4 -2
  21. cirq/ops/parallel_gate.py +11 -13
  22. cirq/ops/parity_gates.py +15 -17
  23. cirq/ops/pauli_gates.py +20 -17
  24. cirq/ops/pauli_interaction_gate.py +10 -14
  25. cirq/ops/pauli_measurement_gate.py +20 -20
  26. cirq/ops/pauli_string.py +76 -79
  27. cirq/ops/pauli_string_phasor.py +30 -30
  28. cirq/ops/pauli_string_raw_types.py +6 -4
  29. cirq/ops/pauli_sum_exponential.py +11 -11
  30. cirq/ops/permutation_gate.py +5 -3
  31. cirq/ops/phased_iswap_gate.py +8 -8
  32. cirq/ops/phased_x_gate.py +8 -9
  33. cirq/ops/phased_x_z_gate.py +15 -13
  34. cirq/ops/qid_util.py +6 -4
  35. cirq/ops/qubit_manager.py +9 -7
  36. cirq/ops/random_gate_channel.py +9 -7
  37. cirq/ops/raw_types.py +70 -72
  38. cirq/ops/raw_types_test.py +10 -6
  39. cirq/ops/state_preparation_channel.py +4 -4
  40. cirq/ops/swap_gates.py +7 -9
  41. cirq/ops/three_qubit_gates.py +22 -28
  42. cirq/ops/two_qubit_diagonal_gate.py +8 -8
  43. cirq/ops/uniform_superposition_gate.py +3 -1
  44. cirq/ops/wait_gate.py +12 -9
  45. cirq/protocols/act_on_protocol.py +6 -4
  46. cirq/protocols/act_on_protocol_test.py +8 -5
  47. cirq/protocols/apply_unitary_protocol.py +10 -8
  48. cirq/protocols/circuit_diagram_info_protocol.py +10 -8
  49. cirq/protocols/control_key_protocol.py +5 -3
  50. cirq/protocols/decompose_protocol.py +25 -22
  51. cirq/protocols/decompose_protocol_test.py +5 -2
  52. cirq/protocols/inverse_protocol.py +10 -8
  53. {cirq_core-1.6.0.dev20250423233500.dist-info → cirq_core-1.6.0.dev20250425004112.dist-info}/METADATA +1 -1
  54. {cirq_core-1.6.0.dev20250423233500.dist-info → cirq_core-1.6.0.dev20250425004112.dist-info}/RECORD +57 -57
  55. {cirq_core-1.6.0.dev20250423233500.dist-info → cirq_core-1.6.0.dev20250425004112.dist-info}/WHEEL +0 -0
  56. {cirq_core-1.6.0.dev20250423233500.dist-info → cirq_core-1.6.0.dev20250425004112.dist-info}/licenses/LICENSE +0 -0
  57. {cirq_core-1.6.0.dev20250423233500.dist-info → cirq_core-1.6.0.dev20250425004112.dist-info}/top_level.txt +0 -0
@@ -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, 'cirq.TParamValComplex']) -> None:
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: 'cirq.Gate') -> bool:
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, 'LinearCombinationOfGates']
105
- ) -> 'LinearCombinationOfGates':
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, 'LinearCombinationOfGates']
112
- ) -> 'LinearCombinationOfGates':
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, 'LinearCombinationOfGates']
119
- ) -> 'LinearCombinationOfGates':
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, 'LinearCombinationOfGates']
126
- ) -> 'LinearCombinationOfGates':
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) -> 'LinearCombinationOfGates':
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: 'cirq.ParamResolver', recursive: bool
159
- ) -> 'LinearCombinationOfGates':
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, 'cirq.TParamValComplex']) -> None:
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: 'cirq.Operation') -> bool:
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) -> 'LinearCombinationOfOperations':
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: 'cirq.ParamResolver', recursive: bool
276
- ) -> 'LinearCombinationOfOperations':
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['cirq.Qid', ...], all_qubits: Tuple['cirq.Qid', ...]
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['cirq.Qid', ...],
330
- all_qubits: Tuple['cirq.Qid', ...],
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, 'cirq.TParamValComplex'] = 1
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) -> 'PauliSum':
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]]) -> 'PauliSum':
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, 'cirq.Qid']
492
- ) -> 'PauliSum':
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: 'cirq.Qid') -> 'PauliSum':
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) -> 'PauliSum':
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
- ) -> 'ProjectorSum':
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) -> 'ProjectorSum':
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['ProjectorString', 'ProjectorSum']):
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['ProjectorString', 'ProjectorSum']):
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['ProjectorString', 'ProjectorSum']):
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['ProjectorString', 'ProjectorSum']):
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) -> 'MatrixGate':
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) -> 'MatrixGate':
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) -> 'MatrixGate':
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['cirq.Qid', ...]) -> 'cirq.OP_TREE':
152
+ def _decompose_(self, qubits: Tuple[cirq.Qid, ...]) -> cirq.OP_TREE:
151
153
  from cirq.circuits import Circuit
152
154
 
153
- decomposed: List['cirq.Operation'] = NotImplemented
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: 'cirq.QasmArgs', qubits: Tuple['cirq.Qid', ...]) -> Optional[str]:
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: 'protocols.CircuitDiagramInfoArgs') -> str:
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, 'cirq.MeasurementKey']] = None,
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, 'cirq.MeasurementKey']] = None,
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, 'cirq.MeasurementKey']] = None,
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, 'cirq.MeasurementKey']] = None,
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:
@@ -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, 'cirq.MeasurementKey'] = '',
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) -> 'cirq.MeasurementKey':
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, 'cirq.MeasurementKey']) -> 'MeasurementGate':
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['cirq.MeasurementKey']
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) -> 'MeasurementGate':
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) -> 'cirq.MeasurementKey':
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: 'cirq.QasmArgs', qubits: Tuple['cirq.Qid', ...]) -> Optional[str]:
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['cirq.Qid']) -> str:
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: 'cirq.SimulationStateBase', qubits: Sequence['cirq.Qid']) -> bool:
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, 'cirq.MeasurementKey', None] = None,
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: 'protocols.SupportsMixture', key: Union[str, 'cirq.MeasurementKey', None] = None
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) -> 'cirq.MeasurementKey':
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['cirq.MeasurementKey']
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) -> 'NamedQid':
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) -> 'cirq.NamedQid':
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['NamedQid']:
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) -> 'cirq.NamedQubit':
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['NamedQubit']:
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, 'cirq.Moment']]:
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, 'cirq.Moment']]:
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: 'cirq.Gate', num_copies: int) -> None:
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) -> 'cirq.Gate':
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['cirq.Qid', ...]) -> 'DecomposeResult':
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: 'cirq.Gate') -> 'ParallelGate':
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) -> 'ParallelGate':
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) -> 'ParallelGate':
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: 'cirq.Gate', *targets: 'cirq.Qid') -> 'cirq.Operation':
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: