cirq-core 1.6.0.dev20250501173104__py3-none-any.whl → 1.6.0.dev20250501192724__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/transformers/analytical_decompositions/two_qubit_to_cz.py +18 -18
  4. cirq/transformers/analytical_decompositions/two_qubit_to_fsim.py +18 -19
  5. cirq/transformers/analytical_decompositions/two_qubit_to_ms.py +8 -10
  6. cirq/transformers/analytical_decompositions/two_qubit_to_sqrt_iswap.py +26 -28
  7. cirq/transformers/drop_empty_moments.py +4 -2
  8. cirq/transformers/drop_negligible_operations.py +6 -4
  9. cirq/transformers/dynamical_decoupling.py +6 -4
  10. cirq/transformers/dynamical_decoupling_test.py +8 -6
  11. cirq/transformers/eject_phased_paulis.py +14 -12
  12. cirq/transformers/eject_z.py +8 -6
  13. cirq/transformers/expand_composite.py +5 -3
  14. cirq/transformers/gauge_compiling/sqrt_cz_gauge.py +3 -1
  15. cirq/transformers/heuristic_decompositions/two_qubit_gate_tabulation.py +4 -1
  16. cirq/transformers/insertion_sort.py +6 -4
  17. cirq/transformers/measurement_transformers.py +21 -21
  18. cirq/transformers/merge_k_qubit_gates.py +11 -9
  19. cirq/transformers/merge_k_qubit_gates_test.py +5 -3
  20. cirq/transformers/merge_single_qubit_gates.py +15 -13
  21. cirq/transformers/optimize_for_target_gateset.py +14 -12
  22. cirq/transformers/optimize_for_target_gateset_test.py +7 -3
  23. cirq/transformers/qubit_management_transformers.py +10 -8
  24. cirq/transformers/randomized_measurements.py +9 -7
  25. cirq/transformers/routing/initial_mapper.py +5 -3
  26. cirq/transformers/routing/line_initial_mapper.py +15 -13
  27. cirq/transformers/routing/mapping_manager.py +9 -9
  28. cirq/transformers/routing/route_circuit_cqc.py +17 -15
  29. cirq/transformers/routing/visualize_routed_circuit.py +7 -6
  30. cirq/transformers/stratify.py +13 -11
  31. cirq/transformers/synchronize_terminal_measurements.py +9 -9
  32. cirq/transformers/target_gatesets/compilation_target_gateset.py +19 -17
  33. cirq/transformers/target_gatesets/compilation_target_gateset_test.py +11 -7
  34. cirq/transformers/target_gatesets/cz_gateset.py +4 -2
  35. cirq/transformers/target_gatesets/sqrt_iswap_gateset.py +5 -3
  36. cirq/transformers/transformer_api.py +17 -15
  37. cirq/transformers/transformer_primitives.py +22 -20
  38. cirq/transformers/transformer_primitives_test.py +3 -1
  39. cirq/value/classical_data.py +26 -26
  40. cirq/value/condition.py +23 -21
  41. cirq/value/duration.py +11 -8
  42. cirq/value/linear_dict.py +22 -20
  43. cirq/value/periodic_value.py +4 -4
  44. cirq/value/probability.py +3 -1
  45. cirq/value/product_state.py +14 -12
  46. cirq/work/collector.py +7 -5
  47. cirq/work/observable_measurement.py +24 -22
  48. cirq/work/observable_measurement_data.py +9 -7
  49. cirq/work/observable_readout_calibration.py +4 -1
  50. cirq/work/observable_readout_calibration_test.py +4 -1
  51. cirq/work/observable_settings.py +4 -2
  52. cirq/work/pauli_sum_collector.py +8 -6
  53. {cirq_core-1.6.0.dev20250501173104.dist-info → cirq_core-1.6.0.dev20250501192724.dist-info}/METADATA +1 -1
  54. {cirq_core-1.6.0.dev20250501173104.dist-info → cirq_core-1.6.0.dev20250501192724.dist-info}/RECORD +57 -57
  55. {cirq_core-1.6.0.dev20250501173104.dist-info → cirq_core-1.6.0.dev20250501192724.dist-info}/WHEEL +0 -0
  56. {cirq_core-1.6.0.dev20250501173104.dist-info → cirq_core-1.6.0.dev20250501192724.dist-info}/licenses/LICENSE +0 -0
  57. {cirq_core-1.6.0.dev20250501173104.dist-info → cirq_core-1.6.0.dev20250501192724.dist-info}/top_level.txt +0 -0
@@ -14,18 +14,20 @@
14
14
 
15
15
  """Base class for creating custom target gatesets which can be used for compilation."""
16
16
 
17
+ from __future__ import annotations
18
+
17
19
  import abc
18
20
  from typing import Hashable, List, Optional, Type, TYPE_CHECKING, Union
19
21
 
20
22
  from cirq import circuits, ops, protocols, transformers
21
- from cirq.protocols.decompose_protocol import DecomposeResult
22
23
  from cirq.transformers import merge_k_qubit_gates, merge_single_qubit_gates
23
24
 
24
25
  if TYPE_CHECKING:
25
26
  import cirq
27
+ from cirq.protocols.decompose_protocol import DecomposeResult
26
28
 
27
29
 
28
- def create_transformer_with_kwargs(transformer: 'cirq.TRANSFORMER', **kwargs) -> 'cirq.TRANSFORMER':
30
+ def create_transformer_with_kwargs(transformer: cirq.TRANSFORMER, **kwargs) -> cirq.TRANSFORMER:
29
31
  """Method to capture additional keyword arguments to transformers while preserving mypy type.
30
32
 
31
33
  Returns a `cirq.TRANSFORMER` which, when called with a circuit and transformer context, is
@@ -33,13 +35,13 @@ def create_transformer_with_kwargs(transformer: 'cirq.TRANSFORMER', **kwargs) ->
33
35
  capture keyword arguments of a transformer before passing them as an argument to an API that
34
36
  expects `cirq.TRANSFORMER`. For example:
35
37
 
36
- >>> def run_transformers(transformers: 'List[cirq.TRANSFORMER]'):
38
+ >>> def run_transformers(transformers: list[cirq.TRANSFORMER]):
37
39
  ... circuit = cirq.Circuit(cirq.X(cirq.q(0)))
38
40
  ... context = cirq.TransformerContext()
39
41
  ... for transformer in transformers:
40
42
  ... transformer(circuit, context=context)
41
43
  ...
42
- >>> transformers: 'List[cirq.TRANSFORMER]' = []
44
+ >>> transformers: list[cirq.TRANSFORMER] = []
43
45
  >>> transformers.append(
44
46
  ... cirq.create_transformer_with_kwargs(
45
47
  ... cirq.expand_composite, no_decomp=lambda op: cirq.num_qubits(op) <= 2
@@ -65,8 +67,8 @@ def create_transformer_with_kwargs(transformer: 'cirq.TRANSFORMER', **kwargs) ->
65
67
  raise SyntaxError('**kwargs to be captured must not contain `context`.')
66
68
 
67
69
  def transformer_with_kwargs(
68
- circuit: 'cirq.AbstractCircuit', *, context: Optional['cirq.TransformerContext'] = None
69
- ) -> 'cirq.AbstractCircuit':
70
+ circuit: cirq.AbstractCircuit, *, context: Optional[cirq.TransformerContext] = None
71
+ ) -> cirq.AbstractCircuit:
70
72
  return transformer(circuit, context=context, **kwargs)
71
73
 
72
74
  return transformer_with_kwargs
@@ -81,7 +83,7 @@ class CompilationTargetGateset(ops.Gateset, metaclass=abc.ABCMeta):
81
83
 
82
84
  def __init__(
83
85
  self,
84
- *gates: Union[Type['cirq.Gate'], 'cirq.Gate', 'cirq.GateFamily'],
86
+ *gates: Union[Type[cirq.Gate], cirq.Gate, cirq.GateFamily],
85
87
  name: Optional[str] = None,
86
88
  unroll_circuit_op: bool = True,
87
89
  preserve_moment_structure: bool = True,
@@ -116,7 +118,7 @@ class CompilationTargetGateset(ops.Gateset, metaclass=abc.ABCMeta):
116
118
  """Maximum number of qubits on which a gate from this gateset can act upon."""
117
119
 
118
120
  @abc.abstractmethod
119
- def decompose_to_target_gateset(self, op: 'cirq.Operation', moment_idx: int) -> DecomposeResult:
121
+ def decompose_to_target_gateset(self, op: cirq.Operation, moment_idx: int) -> DecomposeResult:
120
122
  """Method to rewrite the given operation using gates from this gateset.
121
123
 
122
124
  Args:
@@ -128,7 +130,7 @@ class CompilationTargetGateset(ops.Gateset, metaclass=abc.ABCMeta):
128
130
  - `None` or `NotImplemented` if does not know how to decompose `op`.
129
131
  """
130
132
 
131
- def _validate_operation(self, op: 'cirq.Operation') -> bool:
133
+ def _validate_operation(self, op: cirq.Operation) -> bool:
132
134
  """Validates whether the given `cirq.Operation` is contained in this Gateset.
133
135
 
134
136
  Overrides the method on the base gateset class to ensure that operations which created
@@ -153,7 +155,7 @@ class CompilationTargetGateset(ops.Gateset, metaclass=abc.ABCMeta):
153
155
  return "_default_merged_k_qubit_unitaries"
154
156
 
155
157
  @property
156
- def preprocess_transformers(self) -> List['cirq.TRANSFORMER']:
158
+ def preprocess_transformers(self) -> List[cirq.TRANSFORMER]:
157
159
  """List of transformers which should be run before decomposing individual operations."""
158
160
  reorder_transfomers = (
159
161
  [transformers.insertion_sort_transformer] if self._reorder_operations else []
@@ -172,9 +174,9 @@ class CompilationTargetGateset(ops.Gateset, metaclass=abc.ABCMeta):
172
174
  ]
173
175
 
174
176
  @property
175
- def postprocess_transformers(self) -> List['cirq.TRANSFORMER']:
177
+ def postprocess_transformers(self) -> List[cirq.TRANSFORMER]:
176
178
  """List of transformers which should be run after decomposing individual operations."""
177
- processors: List['cirq.TRANSFORMER'] = [
179
+ processors: List[cirq.TRANSFORMER] = [
178
180
  merge_single_qubit_gates.merge_single_qubit_moments_to_phxz,
179
181
  transformers.drop_negligible_operations,
180
182
  transformers.drop_empty_moments,
@@ -221,7 +223,7 @@ class TwoQubitCompilationTargetGateset(CompilationTargetGateset):
221
223
  def num_qubits(self) -> int:
222
224
  return 2
223
225
 
224
- def decompose_to_target_gateset(self, op: 'cirq.Operation', moment_idx: int) -> DecomposeResult:
226
+ def decompose_to_target_gateset(self, op: cirq.Operation, moment_idx: int) -> DecomposeResult:
225
227
  if not 1 <= protocols.num_qubits(op) <= 2:
226
228
  return self._decompose_multi_qubit_operation(op, moment_idx)
227
229
  if protocols.num_qubits(op) == 1:
@@ -248,7 +250,7 @@ class TwoQubitCompilationTargetGateset(CompilationTargetGateset):
248
250
  )
249
251
  if switch_to_new:
250
252
  return new_optree
251
- mapped_old_optree: List['cirq.OP_TREE'] = []
253
+ mapped_old_optree: List[cirq.OP_TREE] = []
252
254
  for old_op in ops.flatten_to_ops(old_optree):
253
255
  if old_op in self:
254
256
  mapped_old_optree.append(old_op)
@@ -260,7 +262,7 @@ class TwoQubitCompilationTargetGateset(CompilationTargetGateset):
260
262
  return mapped_old_optree
261
263
 
262
264
  def _decompose_single_qubit_operation(
263
- self, op: 'cirq.Operation', moment_idx: int
265
+ self, op: cirq.Operation, moment_idx: int
264
266
  ) -> DecomposeResult:
265
267
  """Decomposes (connected component of) 1-qubit operations using gates from this gateset.
266
268
 
@@ -282,7 +284,7 @@ class TwoQubitCompilationTargetGateset(CompilationTargetGateset):
282
284
  )
283
285
 
284
286
  def _decompose_multi_qubit_operation(
285
- self, op: 'cirq.Operation', moment_idx: int
287
+ self, op: cirq.Operation, moment_idx: int
286
288
  ) -> DecomposeResult:
287
289
  """Decomposes operations acting on more than 2 qubits using gates from this gateset.
288
290
 
@@ -298,7 +300,7 @@ class TwoQubitCompilationTargetGateset(CompilationTargetGateset):
298
300
 
299
301
  @abc.abstractmethod
300
302
  def _decompose_two_qubit_operation(
301
- self, op: 'cirq.Operation', moment_idx: int
303
+ self, op: cirq.Operation, moment_idx: int
302
304
  ) -> DecomposeResult:
303
305
  """Decomposes (connected component of) 2-qubit operations using gates from this gateset.
304
306
 
@@ -12,12 +12,16 @@
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
14
 
15
- from typing import List
15
+ from __future__ import annotations
16
+
17
+ from typing import List, TYPE_CHECKING
16
18
 
17
19
  import pytest
18
20
 
19
21
  import cirq
20
- from cirq.protocols.decompose_protocol import DecomposeResult
22
+
23
+ if TYPE_CHECKING:
24
+ from cirq.protocols.decompose_protocol import DecomposeResult
21
25
 
22
26
 
23
27
  def test_compilation_target_gateset():
@@ -29,7 +33,7 @@ def test_compilation_target_gateset():
29
33
  def num_qubits(self) -> int:
30
34
  return 2
31
35
 
32
- def decompose_to_target_gateset(self, op: 'cirq.Operation', _) -> DecomposeResult:
36
+ def decompose_to_target_gateset(self, op: cirq.Operation, _) -> DecomposeResult:
33
37
  return op if cirq.num_qubits(op) == 2 and cirq.has_unitary(op) else NotImplemented
34
38
 
35
39
  @property
@@ -63,7 +67,7 @@ class ExampleCXTargetGateset(cirq.TwoQubitCompilationTargetGateset):
63
67
  def __init__(self):
64
68
  super().__init__(cirq.AnyUnitaryGateFamily(1), cirq.CNOT)
65
69
 
66
- def _decompose_two_qubit_operation(self, op: 'cirq.Operation', _) -> DecomposeResult:
70
+ def _decompose_two_qubit_operation(self, op: cirq.Operation, _) -> DecomposeResult:
67
71
  if not cirq.has_unitary(op):
68
72
  return NotImplemented
69
73
 
@@ -77,7 +81,7 @@ class ExampleCXTargetGateset(cirq.TwoQubitCompilationTargetGateset):
77
81
  cirq.Z.on_each(q0, q1),
78
82
  ]
79
83
 
80
- def _decompose_single_qubit_operation(self, op: 'cirq.Operation', _) -> DecomposeResult:
84
+ def _decompose_single_qubit_operation(self, op: cirq.Operation, _) -> DecomposeResult:
81
85
  if not cirq.has_unitary(op):
82
86
  return NotImplemented
83
87
  assert self._intermediate_result_tag in op.tags
@@ -209,11 +213,11 @@ def test_two_qubit_compilation_replaces_only_if_2q_gate_count_is_less():
209
213
  def __init__(self):
210
214
  super().__init__(cirq.X, cirq.CNOT)
211
215
 
212
- def _decompose_two_qubit_operation(self, op: 'cirq.Operation', _) -> DecomposeResult:
216
+ def _decompose_two_qubit_operation(self, op: cirq.Operation, _) -> DecomposeResult:
213
217
  q0, q1 = op.qubits
214
218
  return [cirq.X.on_each(q0, q1), cirq.CNOT(q0, q1)] * 10
215
219
 
216
- def _decompose_single_qubit_operation(self, op: 'cirq.Operation', _) -> DecomposeResult:
220
+ def _decompose_single_qubit_operation(self, op: cirq.Operation, _) -> DecomposeResult:
217
221
  return cirq.X(*op.qubits) if op.gate == cirq.Y else NotImplemented
218
222
 
219
223
  q = cirq.LineQubit.range(2)
@@ -14,6 +14,8 @@
14
14
 
15
15
  """Target gateset used for compiling circuits to CZ + 1-q rotations + measurement gates."""
16
16
 
17
+ from __future__ import annotations
18
+
17
19
  from typing import Any, Dict, Sequence, Type, TYPE_CHECKING, Union
18
20
 
19
21
  from cirq import ops, protocols
@@ -47,7 +49,7 @@ class CZTargetGateset(compilation_target_gateset.TwoQubitCompilationTargetGatese
47
49
  *,
48
50
  atol: float = 1e-8,
49
51
  allow_partial_czs: bool = False,
50
- additional_gates: Sequence[Union[Type['cirq.Gate'], 'cirq.Gate', 'cirq.GateFamily']] = (),
52
+ additional_gates: Sequence[Union[Type[cirq.Gate], cirq.Gate, cirq.GateFamily]] = (),
51
53
  preserve_moment_structure: bool = True,
52
54
  reorder_operations: bool = False,
53
55
  ) -> None:
@@ -83,7 +85,7 @@ class CZTargetGateset(compilation_target_gateset.TwoQubitCompilationTargetGatese
83
85
  self.atol = atol
84
86
  self.allow_partial_czs = allow_partial_czs
85
87
 
86
- def _decompose_two_qubit_operation(self, op: 'cirq.Operation', _) -> 'cirq.OP_TREE':
88
+ def _decompose_two_qubit_operation(self, op: cirq.Operation, _) -> cirq.OP_TREE:
87
89
  if not protocols.has_unitary(op):
88
90
  return NotImplemented
89
91
  return two_qubit_to_cz.two_qubit_matrix_to_cz_operations(
@@ -14,15 +14,17 @@
14
14
 
15
15
  """Target gateset used for compiling circuits to √iSWAP + 1-q rotations + measurement gates."""
16
16
 
17
+ from __future__ import annotations
18
+
17
19
  from typing import Any, Dict, Optional, Sequence, Type, TYPE_CHECKING, Union
18
20
 
19
21
  from cirq import ops, protocols
20
- from cirq.protocols.decompose_protocol import DecomposeResult
21
22
  from cirq.transformers.analytical_decompositions import two_qubit_to_sqrt_iswap
22
23
  from cirq.transformers.target_gatesets import compilation_target_gateset
23
24
 
24
25
  if TYPE_CHECKING:
25
26
  import cirq
27
+ from cirq.protocols.decompose_protocol import DecomposeResult
26
28
 
27
29
 
28
30
  class SqrtIswapTargetGateset(compilation_target_gateset.TwoQubitCompilationTargetGateset):
@@ -49,7 +51,7 @@ class SqrtIswapTargetGateset(compilation_target_gateset.TwoQubitCompilationTarge
49
51
  atol: float = 1e-8,
50
52
  required_sqrt_iswap_count: Optional[int] = None,
51
53
  use_sqrt_iswap_inv: bool = False,
52
- additional_gates: Sequence[Union[Type['cirq.Gate'], 'cirq.Gate', 'cirq.GateFamily']] = (),
54
+ additional_gates: Sequence[Union[Type[cirq.Gate], cirq.Gate, cirq.GateFamily]] = (),
53
55
  ):
54
56
  """Initializes `cirq.SqrtIswapTargetGateset`
55
57
 
@@ -87,7 +89,7 @@ class SqrtIswapTargetGateset(compilation_target_gateset.TwoQubitCompilationTarge
87
89
  self.required_sqrt_iswap_count = required_sqrt_iswap_count
88
90
  self.use_sqrt_iswap_inv = use_sqrt_iswap_inv
89
91
 
90
- def _decompose_two_qubit_operation(self, op: 'cirq.Operation', _) -> DecomposeResult:
92
+ def _decompose_two_qubit_operation(self, op: cirq.Operation, _) -> DecomposeResult:
91
93
  if protocols.has_unitary(op):
92
94
  return two_qubit_to_sqrt_iswap.two_qubit_matrix_to_sqrt_iswap_operations(
93
95
  op.qubits[0],
@@ -14,6 +14,8 @@
14
14
 
15
15
  """Defines the API for circuit transformers in Cirq."""
16
16
 
17
+ from __future__ import annotations
18
+
17
19
  import dataclasses
18
20
  import enum
19
21
  import functools
@@ -83,8 +85,8 @@ class _LoggerNode:
83
85
 
84
86
  transformer_id: int
85
87
  transformer_name: str
86
- initial_circuit: 'cirq.AbstractCircuit'
87
- final_circuit: 'cirq.AbstractCircuit'
88
+ initial_circuit: cirq.AbstractCircuit
89
+ final_circuit: cirq.AbstractCircuit
88
90
  logs: List[Tuple[LogLevel, Tuple[str, ...]]] = dataclasses.field(default_factory=list)
89
91
  nested_loggers: List[int] = dataclasses.field(default_factory=list)
90
92
 
@@ -116,7 +118,7 @@ class TransformerLogger:
116
118
  self._logs: List[_LoggerNode] = []
117
119
  self._stack: List[int] = []
118
120
 
119
- def register_initial(self, circuit: 'cirq.AbstractCircuit', transformer_name: str) -> None:
121
+ def register_initial(self, circuit: cirq.AbstractCircuit, transformer_name: str) -> None:
120
122
  """Register the beginning of a new transformer stage.
121
123
 
122
124
  Args:
@@ -143,7 +145,7 @@ class TransformerLogger:
143
145
  raise ValueError('No active transformer found.')
144
146
  self._logs[self._stack[-1]].logs.append((level, args))
145
147
 
146
- def register_final(self, circuit: 'cirq.AbstractCircuit', transformer_name: str) -> None:
148
+ def register_final(self, circuit: cirq.AbstractCircuit, transformer_name: str) -> None:
147
149
  """Register the end of the currently active transformer stage.
148
150
 
149
151
  Args:
@@ -195,13 +197,13 @@ class TransformerLogger:
195
197
  class NoOpTransformerLogger(TransformerLogger):
196
198
  """All calls to this logger are a no-op"""
197
199
 
198
- def register_initial(self, circuit: 'cirq.AbstractCircuit', transformer_name: str) -> None:
200
+ def register_initial(self, circuit: cirq.AbstractCircuit, transformer_name: str) -> None:
199
201
  pass
200
202
 
201
203
  def log(self, *args: str, level: LogLevel = LogLevel.INFO) -> None:
202
204
  pass
203
205
 
204
- def register_final(self, circuit: 'cirq.AbstractCircuit', transformer_name: str) -> None:
206
+ def register_final(self, circuit: cirq.AbstractCircuit, transformer_name: str) -> None:
205
207
  pass
206
208
 
207
209
  def show(self, level: LogLevel = LogLevel.INFO) -> None:
@@ -262,8 +264,8 @@ class TRANSFORMER(Protocol):
262
264
  """
263
265
 
264
266
  def __call__(
265
- self, circuit: 'cirq.AbstractCircuit', *, context: Optional[TransformerContext] = None
266
- ) -> 'cirq.AbstractCircuit': ...
267
+ self, circuit: cirq.AbstractCircuit, *, context: Optional[TransformerContext] = None
268
+ ) -> cirq.AbstractCircuit: ...
267
269
 
268
270
 
269
271
  _TRANSFORMER_T = TypeVar('_TRANSFORMER_T', bound=TRANSFORMER)
@@ -357,8 +359,8 @@ def transformer(cls_or_func: Any = None, *, add_deep_support: bool = False) -> A
357
359
 
358
360
  @functools.wraps(method)
359
361
  def method_with_logging(
360
- self, circuit: 'cirq.AbstractCircuit', **kwargs
361
- ) -> 'cirq.AbstractCircuit':
362
+ self, circuit: cirq.AbstractCircuit, **kwargs
363
+ ) -> cirq.AbstractCircuit:
362
364
  return _transform_and_log(
363
365
  add_deep_support,
364
366
  lambda circuit, **kwargs: method(self, circuit, **kwargs),
@@ -376,7 +378,7 @@ def transformer(cls_or_func: Any = None, *, add_deep_support: bool = False) -> A
376
378
  default_context = _get_default_context(func)
377
379
 
378
380
  @functools.wraps(func)
379
- def func_with_logging(circuit: 'cirq.AbstractCircuit', **kwargs) -> 'cirq.AbstractCircuit':
381
+ def func_with_logging(circuit: cirq.AbstractCircuit, **kwargs) -> cirq.AbstractCircuit:
380
382
  return _transform_and_log(
381
383
  add_deep_support,
382
384
  func,
@@ -401,10 +403,10 @@ def _get_default_context(func: TRANSFORMER) -> TransformerContext:
401
403
  def _run_transformer_on_circuit(
402
404
  add_deep_support: bool,
403
405
  func: TRANSFORMER,
404
- circuit: 'cirq.AbstractCircuit',
406
+ circuit: cirq.AbstractCircuit,
405
407
  extracted_context: Optional[TransformerContext],
406
408
  **kwargs,
407
- ) -> 'cirq.AbstractCircuit':
409
+ ) -> cirq.AbstractCircuit:
408
410
  mutable_circuit = None
409
411
  if extracted_context and extracted_context.deep and add_deep_support:
410
412
  batch_replace = []
@@ -429,10 +431,10 @@ def _transform_and_log(
429
431
  add_deep_support: bool,
430
432
  func: TRANSFORMER,
431
433
  transformer_name: str,
432
- circuit: 'cirq.AbstractCircuit',
434
+ circuit: cirq.AbstractCircuit,
433
435
  extracted_context: Optional[TransformerContext],
434
436
  **kwargs,
435
- ) -> 'cirq.AbstractCircuit':
437
+ ) -> cirq.AbstractCircuit:
436
438
  """Helper to log initial and final circuits before and after calling the transformer."""
437
439
  if extracted_context:
438
440
  extracted_context.logger.register_initial(circuit, transformer_name)
@@ -14,6 +14,8 @@
14
14
 
15
15
  """Defines primitives for common transformer patterns."""
16
16
 
17
+ from __future__ import annotations
18
+
17
19
  import bisect
18
20
  import dataclasses
19
21
  from collections import defaultdict
@@ -157,7 +159,7 @@ def _map_operations_impl(
157
159
  """
158
160
  tags_to_ignore_set = set(tags_to_ignore)
159
161
 
160
- def apply_map_func(op: 'cirq.Operation', idx: int) -> List['cirq.Operation']:
162
+ def apply_map_func(op: cirq.Operation, idx: int) -> List[cirq.Operation]:
161
163
  if tags_to_ignore_set.intersection(op.tags):
162
164
  return [op]
163
165
  if deep and isinstance(op.untagged, circuits.CircuitOperation):
@@ -173,7 +175,7 @@ def _map_operations_impl(
173
175
  ).with_tags(*op.tags)
174
176
  mapped_ops = [*ops.flatten_to_ops(map_func(op, idx))]
175
177
  op_qubits = set(op.qubits)
176
- mapped_ops_qubits: Set['cirq.Qid'] = set()
178
+ mapped_ops_qubits: Set[cirq.Qid] = set()
177
179
  has_overlapping_ops = False
178
180
  for mapped_op in mapped_ops:
179
181
  if raise_if_add_qubits and not op_qubits.issuperset(mapped_op.qubits):
@@ -194,9 +196,9 @@ def _map_operations_impl(
194
196
  ]
195
197
  return mapped_ops
196
198
 
197
- new_moments: List[List['cirq.Operation']] = []
199
+ new_moments: List[List[cirq.Operation]] = []
198
200
  for idx, moment in enumerate(circuit):
199
- curr_moments: List[List['cirq.Operation']] = [[]] if wrap_in_circuit_op else []
201
+ curr_moments: List[List[cirq.Operation]] = [[]] if wrap_in_circuit_op else []
200
202
  placement_cache = circuits.circuit._PlacementCache()
201
203
  for op in moment:
202
204
  mapped_ops = apply_map_func(op, idx)
@@ -305,21 +307,21 @@ class _MergedCircuit:
305
307
  of a set to store operations to preserve insertion order.
306
308
  """
307
309
 
308
- qubit_indexes: Dict['cirq.Qid', List[int]] = dataclasses.field(
310
+ qubit_indexes: Dict[cirq.Qid, List[int]] = dataclasses.field(
309
311
  default_factory=lambda: defaultdict(lambda: [-1])
310
312
  )
311
- mkey_indexes: Dict['cirq.MeasurementKey', List[int]] = dataclasses.field(
313
+ mkey_indexes: Dict[cirq.MeasurementKey, List[int]] = dataclasses.field(
312
314
  default_factory=lambda: defaultdict(lambda: [-1])
313
315
  )
314
- ckey_indexes: Dict['cirq.MeasurementKey', List[int]] = dataclasses.field(
316
+ ckey_indexes: Dict[cirq.MeasurementKey, List[int]] = dataclasses.field(
315
317
  default_factory=lambda: defaultdict(lambda: [-1])
316
318
  )
317
- ops_by_index: List[Dict['cirq.Operation', int]] = dataclasses.field(default_factory=list)
319
+ ops_by_index: List[Dict[cirq.Operation, int]] = dataclasses.field(default_factory=list)
318
320
 
319
321
  def append_empty_moment(self) -> None:
320
322
  self.ops_by_index.append({})
321
323
 
322
- def add_op_to_moment(self, moment_index: int, op: 'cirq.Operation') -> None:
324
+ def add_op_to_moment(self, moment_index: int, op: cirq.Operation) -> None:
323
325
  self.ops_by_index[moment_index][op] = 0
324
326
  for q in op.qubits:
325
327
  if moment_index > self.qubit_indexes[q][-1]:
@@ -331,7 +333,7 @@ class _MergedCircuit:
331
333
  for ckey in protocols.control_keys(op):
332
334
  bisect.insort(self.ckey_indexes[ckey], moment_index)
333
335
 
334
- def remove_op_from_moment(self, moment_index: int, op: 'cirq.Operation') -> None:
336
+ def remove_op_from_moment(self, moment_index: int, op: cirq.Operation) -> None:
335
337
  self.ops_by_index[moment_index].pop(op)
336
338
  for q in op.qubits:
337
339
  if self.qubit_indexes[q][-1] == moment_index:
@@ -344,8 +346,8 @@ class _MergedCircuit:
344
346
  self.ckey_indexes[ckey].remove(moment_index)
345
347
 
346
348
  def get_mergeable_ops(
347
- self, op: 'cirq.Operation', op_qs: Set['cirq.Qid']
348
- ) -> Tuple[int, List['cirq.Operation']]:
349
+ self, op: cirq.Operation, op_qs: Set[cirq.Qid]
350
+ ) -> Tuple[int, List[cirq.Operation]]:
349
351
  # Find the index of previous moment which can be merged with `op`.
350
352
  idx = max([self.qubit_indexes[q][-1] for q in op_qs], default=-1)
351
353
  idx = max([idx] + [self.mkey_indexes[ckey][-1] for ckey in protocols.control_keys(op)])
@@ -360,7 +362,7 @@ class _MergedCircuit:
360
362
  left_op for left_op in self.ops_by_index[idx] if not op_qs.isdisjoint(left_op.qubits)
361
363
  ]
362
364
 
363
- def get_cirq_circuit(self) -> 'cirq.Circuit':
365
+ def get_cirq_circuit(self) -> cirq.Circuit:
364
366
  return circuits.Circuit(circuits.Moment(m.keys()) for m in self.ops_by_index)
365
367
 
366
368
 
@@ -493,7 +495,7 @@ def merge_operations(
493
495
 
494
496
  def merge_operations_to_circuit_op(
495
497
  circuit: CIRCUIT_TYPE,
496
- can_merge: Callable[[Sequence['cirq.Operation'], Sequence['cirq.Operation']], bool],
498
+ can_merge: Callable[[Sequence[cirq.Operation], Sequence[cirq.Operation]], bool],
497
499
  *,
498
500
  tags_to_ignore: Sequence[Hashable] = (),
499
501
  merged_circuit_op_tag: str = "Merged connected component",
@@ -524,8 +526,8 @@ def merge_operations_to_circuit_op(
524
526
  Copy of input circuit with valid connected components wrapped in tagged circuit operations.
525
527
  """
526
528
 
527
- def merge_func(op1: 'cirq.Operation', op2: 'cirq.Operation') -> Optional['cirq.Operation']:
528
- def get_ops(op: 'cirq.Operation'):
529
+ def merge_func(op1: cirq.Operation, op2: cirq.Operation) -> Optional[cirq.Operation]:
530
+ def get_ops(op: cirq.Operation):
529
531
  op_untagged = op.untagged
530
532
  return (
531
533
  [*op_untagged.circuit.all_operations()]
@@ -573,7 +575,7 @@ def merge_k_qubit_unitaries_to_circuit_op(
573
575
  Copy of input circuit with valid connected components wrapped in tagged circuit operations.
574
576
  """
575
577
 
576
- def can_merge(ops1: Sequence['cirq.Operation'], ops2: Sequence['cirq.Operation']) -> bool:
578
+ def can_merge(ops1: Sequence[cirq.Operation], ops2: Sequence[cirq.Operation]) -> bool:
577
579
  return all(
578
580
  protocols.num_qubits(op) <= k and protocols.has_unitary(op)
579
581
  for op_list in [ops1, ops2]
@@ -659,7 +661,7 @@ def unroll_circuit_op(
659
661
  """
660
662
 
661
663
  def map_func(m: circuits.Moment, _: int):
662
- to_zip: List['cirq.AbstractCircuit'] = []
664
+ to_zip: List[cirq.AbstractCircuit] = []
663
665
  for op in m:
664
666
  op_untagged = op.untagged
665
667
  if isinstance(op_untagged, circuits.CircuitOperation):
@@ -751,7 +753,7 @@ def unroll_circuit_op_greedy_frontier(
751
753
  Copy of input circuit with (Tagged) CircuitOperation's expanded inline at qubit frontier.
752
754
  """
753
755
  unrolled_circuit = circuit.unfreeze(copy=True)
754
- frontier: Dict['cirq.Qid', int] = defaultdict(lambda: 0)
756
+ frontier: Dict[cirq.Qid, int] = defaultdict(lambda: 0)
755
757
  idx = 0
756
758
  while idx < len(unrolled_circuit):
757
759
  for op in unrolled_circuit[idx].operations:
@@ -799,7 +801,7 @@ def toggle_tags(circuit: CIRCUIT_TYPE, tags: Sequence[Hashable], *, deep: bool =
799
801
  """
800
802
  tags_to_xor = set(tags)
801
803
 
802
- def map_func(op: 'cirq.Operation', _) -> 'cirq.Operation':
804
+ def map_func(op: cirq.Operation, _) -> cirq.Operation:
803
805
  return (
804
806
  op
805
807
  if deep and isinstance(op, circuits.CircuitOperation)
@@ -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 Iterator, List, Optional
16
18
 
17
19
  import pytest
@@ -721,7 +723,7 @@ def test_merge_operations_to_circuit_op_merges_connected_component():
721
723
  ''',
722
724
  )
723
725
 
724
- def can_merge(ops1: List['cirq.Operation'], ops2: List['cirq.Operation']) -> bool:
726
+ def can_merge(ops1: List[cirq.Operation], ops2: List[cirq.Operation]) -> bool:
725
727
  """Artificial example where a CZ will absorb any merge-able operation."""
726
728
  return any(o.gate == cirq.CZ for op_list in [ops1, ops2] for o in op_list)
727
729