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,6 +14,8 @@
14
14
 
15
15
  """Transformer pass that pushes 180° rotations around axes in the XY plane later in the circuit."""
16
16
 
17
+ from __future__ import annotations
18
+
17
19
  from typing import cast, Dict, Iterable, Iterator, Optional, Tuple, TYPE_CHECKING, Union
18
20
 
19
21
  import numpy as np
@@ -29,12 +31,12 @@ if TYPE_CHECKING:
29
31
 
30
32
  @transformer_api.transformer(add_deep_support=True)
31
33
  def eject_phased_paulis(
32
- circuit: 'cirq.AbstractCircuit',
34
+ circuit: cirq.AbstractCircuit,
33
35
  *,
34
- context: Optional['cirq.TransformerContext'] = None,
36
+ context: Optional[cirq.TransformerContext] = None,
35
37
  atol: float = 1e-8,
36
38
  eject_parameterized: bool = False,
37
- ) -> 'cirq.Circuit':
39
+ ) -> cirq.Circuit:
38
40
  """Transformer pass to push X, Y, PhasedX & (certain) PhasedXZ gates to the end of the circuit.
39
41
 
40
42
  As the gates get pushed, they may absorb Z gates, cancel against other
@@ -60,7 +62,7 @@ def eject_phased_paulis(
60
62
  held_w_phases: Dict[ops.Qid, value.TParamVal] = {}
61
63
  tags_to_ignore = set(context.tags_to_ignore) if context else set()
62
64
 
63
- def map_func(op: 'cirq.Operation', _: int) -> 'cirq.OP_TREE':
65
+ def map_func(op: cirq.Operation, _: int) -> cirq.OP_TREE:
64
66
  # Dump if `op` marked with a no compile tag.
65
67
  if set(op.tags) & tags_to_ignore:
66
68
  return [_dump_held(op.qubits, held_w_phases, atol), op]
@@ -107,7 +109,7 @@ def eject_phased_paulis(
107
109
 
108
110
  def _absorb_z_into_w(
109
111
  op: ops.Operation, held_w_phases: Dict[ops.Qid, value.TParamVal]
110
- ) -> 'cirq.OP_TREE':
112
+ ) -> cirq.OP_TREE:
111
113
  """Absorbs a Z^t gate into a W(a) flip.
112
114
 
113
115
  [Where W(a) is shorthand for PhasedX(phase_exponent=a).]
@@ -128,7 +130,7 @@ def _absorb_z_into_w(
128
130
 
129
131
  def _dump_held(
130
132
  qubits: Iterable[ops.Qid], held_w_phases: Dict[ops.Qid, value.TParamVal], atol: float
131
- ) -> Iterator['cirq.OP_TREE']:
133
+ ) -> Iterator[cirq.OP_TREE]:
132
134
  # Note: sorting is to avoid non-determinism in the insertion order.
133
135
  for q in sorted(qubits):
134
136
  p = held_w_phases.get(q)
@@ -140,7 +142,7 @@ def _dump_held(
140
142
 
141
143
  def _dump_into_measurement(
142
144
  op: ops.Operation, held_w_phases: Dict[ops.Qid, value.TParamVal]
143
- ) -> 'cirq.OP_TREE':
145
+ ) -> cirq.OP_TREE:
144
146
  measurement = cast(ops.MeasurementGate, cast(ops.GateOperation, op).gate)
145
147
  new_measurement = measurement.with_bits_flipped(
146
148
  *[i for i, q in enumerate(op.qubits) if q in held_w_phases]
@@ -152,7 +154,7 @@ def _dump_into_measurement(
152
154
 
153
155
  def _potential_cross_whole_w(
154
156
  op: ops.Operation, atol: float, held_w_phases: Dict[ops.Qid, value.TParamVal]
155
- ) -> 'cirq.OP_TREE':
157
+ ) -> cirq.OP_TREE:
156
158
  """Grabs or cancels a held W gate against an existing W gate.
157
159
 
158
160
  [Where W(a) is shorthand for PhasedX(phase_exponent=a).]
@@ -185,7 +187,7 @@ def _potential_cross_whole_w(
185
187
 
186
188
  def _potential_cross_partial_w(
187
189
  op: ops.Operation, held_w_phases: Dict[ops.Qid, value.TParamVal], atol: float
188
- ) -> 'cirq.OP_TREE':
190
+ ) -> cirq.OP_TREE:
189
191
  """Cross the held W over a partial W gate.
190
192
 
191
193
  [Where W(a) is shorthand for PhasedX(phase_exponent=a).]
@@ -210,7 +212,7 @@ def _potential_cross_partial_w(
210
212
  return gate.on(op.qubits[0])
211
213
 
212
214
 
213
- def _single_cross_over_cz(op: ops.Operation, qubit_with_w: 'cirq.Qid') -> 'cirq.OP_TREE':
215
+ def _single_cross_over_cz(op: ops.Operation, qubit_with_w: cirq.Qid) -> cirq.OP_TREE:
214
216
  """Crosses exactly one W flip over a partial CZ.
215
217
 
216
218
  [Where W(a) is shorthand for PhasedX(phase_exponent=a).]
@@ -251,7 +253,7 @@ def _single_cross_over_cz(op: ops.Operation, qubit_with_w: 'cirq.Qid') -> 'cirq.
251
253
 
252
254
  def _double_cross_over_cz(
253
255
  op: ops.Operation, held_w_phases: Dict[ops.Qid, value.TParamVal]
254
- ) -> 'cirq.OP_TREE':
256
+ ) -> cirq.OP_TREE:
255
257
  """Crosses two W flips over a partial CZ.
256
258
 
257
259
  [Where W(a) is shorthand for PhasedX(phase_exponent=a).]
@@ -355,7 +357,7 @@ def _try_get_known_z_half_turns(
355
357
 
356
358
  def _phased_x_or_pauli_gate(
357
359
  exponent: Union[float, sympy.Expr], phase_exponent: Union[float, sympy.Expr], atol: float
358
- ) -> Union['cirq.PhasedXPowGate', 'cirq.XPowGate', 'cirq.YPowGate']:
360
+ ) -> Union[cirq.PhasedXPowGate, cirq.XPowGate, cirq.YPowGate]:
359
361
  """Return PhasedXPowGate or X or Y gate if equivalent within atol in z-axis turns."""
360
362
  if not isinstance(phase_exponent, sympy.Expr) or phase_exponent.is_constant():
361
363
  half_turns = value.canonicalize_half_turns(float(phase_exponent))
@@ -14,6 +14,8 @@
14
14
 
15
15
  """Transformer pass that pushes Z gates later and later in the circuit."""
16
16
 
17
+ from __future__ import annotations
18
+
17
19
  from collections import defaultdict
18
20
  from typing import Dict, Iterable, Iterator, Optional, Tuple, TYPE_CHECKING
19
21
 
@@ -31,7 +33,7 @@ def _is_integer(n):
31
33
  return np.isclose(n, np.round(n))
32
34
 
33
35
 
34
- def _is_swaplike(gate: 'cirq.Gate'):
36
+ def _is_swaplike(gate: cirq.Gate):
35
37
  if isinstance(gate, ops.SwapPowGate):
36
38
  return gate.exponent == 1
37
39
 
@@ -46,12 +48,12 @@ def _is_swaplike(gate: 'cirq.Gate'):
46
48
 
47
49
  @transformer_api.transformer(add_deep_support=True)
48
50
  def eject_z(
49
- circuit: 'cirq.AbstractCircuit',
51
+ circuit: cirq.AbstractCircuit,
50
52
  *,
51
- context: Optional['cirq.TransformerContext'] = None,
53
+ context: Optional[cirq.TransformerContext] = None,
52
54
  atol: float = 0.0,
53
55
  eject_parameterized: bool = False,
54
- ) -> 'cirq.Circuit':
56
+ ) -> cirq.Circuit:
55
57
  """Pushes Z gates towards the end of the circuit.
56
58
 
57
59
  As the Z gates get pushed they may absorb other Z gates, get absorbed into
@@ -77,7 +79,7 @@ def eject_z(
77
79
  lambda: None
78
80
  )
79
81
 
80
- def dump_tracked_phase(qubits: Iterable[ops.Qid]) -> Iterator['cirq.OP_TREE']:
82
+ def dump_tracked_phase(qubits: Iterable[ops.Qid]) -> Iterator[cirq.OP_TREE]:
81
83
  """Zeroes qubit_phase entries by emitting Z gates."""
82
84
  for q in qubits:
83
85
  p, key = qubit_phase[q], last_phased_xz_op[q]
@@ -87,7 +89,7 @@ def eject_z(
87
89
  elif key:
88
90
  phased_xz_replacements[key] = phased_xz_replacements[key].with_z_exponent(p * 2)
89
91
 
90
- def map_func(op: 'cirq.Operation', moment_index: int) -> 'cirq.OP_TREE':
92
+ def map_func(op: cirq.Operation, moment_index: int) -> cirq.OP_TREE:
91
93
  last_phased_xz_op.update({q: None for q in op.qubits})
92
94
 
93
95
  if tags_to_ignore & set(op.tags):
@@ -14,6 +14,8 @@
14
14
 
15
15
  """Transformer pass that expands composite operations via `cirq.decompose`."""
16
16
 
17
+ from __future__ import annotations
18
+
17
19
  from typing import Callable, Optional, TYPE_CHECKING
18
20
 
19
21
  from cirq import circuits, ops, protocols
@@ -25,9 +27,9 @@ if TYPE_CHECKING:
25
27
 
26
28
  @transformer_api.transformer
27
29
  def expand_composite(
28
- circuit: 'cirq.AbstractCircuit',
30
+ circuit: cirq.AbstractCircuit,
29
31
  *,
30
- context: Optional['cirq.TransformerContext'] = None,
32
+ context: Optional[cirq.TransformerContext] = None,
31
33
  no_decomp: Callable[[ops.Operation], bool] = (lambda _: False),
32
34
  ):
33
35
  """A transformer that expands composite operations via `cirq.decompose`.
@@ -48,7 +50,7 @@ def expand_composite(
48
50
  Copy of the transformed input circuit.
49
51
  """
50
52
 
51
- def map_func(op: 'cirq.Operation', _) -> 'cirq.OP_TREE':
53
+ def map_func(op: cirq.Operation, _) -> cirq.OP_TREE:
52
54
  if context and context.deep and isinstance(op.untagged, circuits.CircuitOperation):
53
55
  return op
54
56
  return protocols.decompose(op, keep=no_decomp, on_stuck_raise=None)
@@ -15,6 +15,8 @@
15
15
  """A Gauge transformer for CZ**0.5 and CZ**-0.5 gates."""
16
16
 
17
17
 
18
+ from __future__ import annotations
19
+
18
20
  from numbers import Real
19
21
  from typing import Dict, Sequence, Tuple, TYPE_CHECKING
20
22
 
@@ -42,7 +44,7 @@ class SqrtCZGauge(Gauge):
42
44
  def weight(self) -> float:
43
45
  return 3.0
44
46
 
45
- def sample(self, gate: 'cirq.Gate', prng: np.random.Generator) -> ConstantGauge:
47
+ def sample(self, gate: cirq.Gate, prng: np.random.Generator) -> ConstantGauge:
46
48
  if prng.choice([True, False]):
47
49
  return ConstantGauge(two_qubit_gate=gate)
48
50
  swap_qubits = prng.choice([True, False])
@@ -14,6 +14,9 @@
14
14
 
15
15
  """Attempt to tabulate single qubit gates required to generate a target 2Q gate
16
16
  with a product A k A."""
17
+
18
+ from __future__ import annotations
19
+
17
20
  from dataclasses import dataclass
18
21
  from functools import reduce
19
22
  from typing import List, NamedTuple, Sequence, Tuple
@@ -316,7 +319,7 @@ def two_qubit_gate_product_tabulation(
316
319
  *,
317
320
  sample_scaling: int = 50,
318
321
  allow_missed_points: bool = True,
319
- random_state: 'cirq.RANDOM_STATE_OR_SEED_LIKE' = None,
322
+ random_state: cirq.RANDOM_STATE_OR_SEED_LIKE = None,
320
323
  ) -> TwoQubitGateTabulation:
321
324
  r"""Generate a TwoQubitGateTabulation for a base two qubit unitary.
322
325
 
@@ -14,6 +14,8 @@
14
14
 
15
15
  """Transformer that sorts commuting operations in increasing order of their `.qubits` tuple."""
16
16
 
17
+ from __future__ import annotations
18
+
17
19
  from typing import Dict, List, Optional, TYPE_CHECKING
18
20
 
19
21
  from cirq import circuits, protocols
@@ -25,8 +27,8 @@ if TYPE_CHECKING:
25
27
 
26
28
  @transformer_api.transformer(add_deep_support=True)
27
29
  def insertion_sort_transformer(
28
- circuit: 'cirq.AbstractCircuit', *, context: Optional['cirq.TransformerContext'] = None
29
- ) -> 'cirq.Circuit':
30
+ circuit: cirq.AbstractCircuit, *, context: Optional[cirq.TransformerContext] = None
31
+ ) -> cirq.Circuit:
30
32
  """Sorts the operations using their sorted `.qubits` property as comparison key.
31
33
 
32
34
  Operations are swapped only if they commute.
@@ -35,8 +37,8 @@ def insertion_sort_transformer(
35
37
  circuit: input circuit.
36
38
  context: optional TransformerContext (not used),
37
39
  """
38
- final_operations: List['cirq.Operation'] = []
39
- qubit_index: Dict['cirq.Qid', int] = {
40
+ final_operations: List[cirq.Operation] = []
41
+ qubit_index: Dict[cirq.Qid, int] = {
40
42
  q: idx for idx, q in enumerate(sorted(circuit.all_qubits()))
41
43
  }
42
44
  cached_qubit_indices: Dict[int, List[int]] = {}
@@ -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 itertools
16
18
  from collections import defaultdict
17
19
  from typing import Any, cast, Dict, Iterable, List, Optional, Sequence, Tuple, TYPE_CHECKING, Union
@@ -33,7 +35,7 @@ class _MeasurementQid(ops.Qid):
33
35
  Exactly one qubit will be created per qubit in the measurement gate.
34
36
  """
35
37
 
36
- def __init__(self, key: Union[str, 'cirq.MeasurementKey'], qid: 'cirq.Qid', index: int = 0):
38
+ def __init__(self, key: Union[str, cirq.MeasurementKey], qid: cirq.Qid, index: int = 0):
37
39
  """Initializes the qubit.
38
40
 
39
41
  Args:
@@ -63,8 +65,8 @@ class _MeasurementQid(ops.Qid):
63
65
 
64
66
  @transformer_api.transformer
65
67
  def defer_measurements(
66
- circuit: 'cirq.AbstractCircuit', *, context: Optional['cirq.TransformerContext'] = None
67
- ) -> 'cirq.Circuit':
68
+ circuit: cirq.AbstractCircuit, *, context: Optional[cirq.TransformerContext] = None
69
+ ) -> cirq.Circuit:
68
70
  """Implements the Deferred Measurement Principle.
69
71
 
70
72
  Uses the Deferred Measurement Principle to move all measurements to the
@@ -94,11 +96,9 @@ def defer_measurements(
94
96
 
95
97
  circuit = transformer_primitives.unroll_circuit_op(circuit, deep=True, tags_to_check=None)
96
98
  terminal_measurements = {op for _, op in find_terminal_measurements(circuit)}
97
- measurement_qubits: Dict['cirq.MeasurementKey', List[Tuple['cirq.Qid', ...]]] = defaultdict(
98
- list
99
- )
99
+ measurement_qubits: Dict[cirq.MeasurementKey, List[Tuple[cirq.Qid, ...]]] = defaultdict(list)
100
100
 
101
- def defer(op: 'cirq.Operation', _) -> 'cirq.OP_TREE':
101
+ def defer(op: cirq.Operation, _) -> cirq.OP_TREE:
102
102
  if op in terminal_measurements:
103
103
  return op
104
104
  gate = op.gate
@@ -169,9 +169,9 @@ def defer_measurements(
169
169
 
170
170
 
171
171
  def _all_possible_datastore_states(
172
- keys: Iterable[Tuple['cirq.MeasurementKey', int]],
173
- measurement_qubits: Dict['cirq.MeasurementKey', List[Tuple['cirq.Qid', ...]]],
174
- ) -> Iterable['cirq.ClassicalDataStoreReader']:
172
+ keys: Iterable[Tuple[cirq.MeasurementKey, int]],
173
+ measurement_qubits: Dict[cirq.MeasurementKey, List[Tuple[cirq.Qid, ...]]],
174
+ ) -> Iterable[cirq.ClassicalDataStoreReader]:
175
175
  """The cartesian product of all possible DataStore states for the given keys."""
176
176
  # First we get the list of all possible values. So if we have a key mapped to qubits of shape
177
177
  # (2, 2) and a key mapped to a qutrit, the possible measurement values are:
@@ -214,10 +214,10 @@ def _all_possible_datastore_states(
214
214
 
215
215
  @transformer_api.transformer
216
216
  def dephase_measurements(
217
- circuit: 'cirq.AbstractCircuit',
217
+ circuit: cirq.AbstractCircuit,
218
218
  *,
219
- context: Optional['cirq.TransformerContext'] = transformer_api.TransformerContext(deep=True),
220
- ) -> 'cirq.Circuit':
219
+ context: Optional[cirq.TransformerContext] = transformer_api.TransformerContext(deep=True),
220
+ ) -> cirq.Circuit:
221
221
  """Changes all measurements to a dephase operation.
222
222
 
223
223
  This transformer is useful when using a density matrix simulator, when
@@ -240,7 +240,7 @@ def dephase_measurements(
240
240
  surprises.
241
241
  """
242
242
 
243
- def dephase(op: 'cirq.Operation', _) -> 'cirq.OP_TREE':
243
+ def dephase(op: cirq.Operation, _) -> cirq.OP_TREE:
244
244
  gate = op.gate
245
245
  if isinstance(gate, ops.MeasurementGate):
246
246
  key = value.MeasurementKey.parse_serialized(gate.key)
@@ -257,10 +257,10 @@ def dephase_measurements(
257
257
 
258
258
  @transformer_api.transformer
259
259
  def drop_terminal_measurements(
260
- circuit: 'cirq.AbstractCircuit',
260
+ circuit: cirq.AbstractCircuit,
261
261
  *,
262
- context: Optional['cirq.TransformerContext'] = transformer_api.TransformerContext(deep=True),
263
- ) -> 'cirq.Circuit':
262
+ context: Optional[cirq.TransformerContext] = transformer_api.TransformerContext(deep=True),
263
+ ) -> cirq.Circuit:
264
264
  """Removes terminal measurements from a circuit.
265
265
 
266
266
  This transformer is helpful when trying to capture the final state vector
@@ -289,7 +289,7 @@ def drop_terminal_measurements(
289
289
  if not circuit.are_all_measurements_terminal():
290
290
  raise ValueError('Circuit contains a non-terminal measurement.')
291
291
 
292
- def flip_inversion(op: 'cirq.Operation', _) -> 'cirq.OP_TREE':
292
+ def flip_inversion(op: cirq.Operation, _) -> cirq.OP_TREE:
293
293
  if isinstance(op.gate, ops.MeasurementGate):
294
294
  return [
295
295
  (
@@ -432,7 +432,7 @@ class _ConfusionChannel(ops.Gate):
432
432
  def _kraus_(self) -> Tuple[np.ndarray, ...]:
433
433
  return self._kraus
434
434
 
435
- def _apply_channel_(self, args: 'cirq.ApplyChannelArgs'):
435
+ def _apply_channel_(self, args: cirq.ApplyChannelArgs):
436
436
  configs: List[transformations._BuildFromSlicesArgs] = []
437
437
  for i in range(np.prod(self._shape) ** 2):
438
438
  scale = cast(complex, self._confusion_map.flat[i])
@@ -472,7 +472,7 @@ class _ModAdd(ops.ArithmeticGate):
472
472
  def registers(self) -> Tuple[Tuple[int], Tuple[int]]:
473
473
  return (self._dimension,), (self._dimension,)
474
474
 
475
- def with_registers(self, *new_registers) -> '_ModAdd':
475
+ def with_registers(self, *new_registers) -> _ModAdd:
476
476
  raise NotImplementedError()
477
477
 
478
478
  def apply(self, *register_values: int) -> Tuple[int, int]:
@@ -482,7 +482,7 @@ class _ModAdd(ops.ArithmeticGate):
482
482
  return self._dimension
483
483
 
484
484
 
485
- def _mod_add(source: 'cirq.Qid', target: 'cirq.Qid') -> 'cirq.Operation':
485
+ def _mod_add(source: cirq.Qid, target: cirq.Qid) -> cirq.Operation:
486
486
  assert source.dimension == target.dimension
487
487
  if source.dimension == 2:
488
488
  # Use a CX gate in 2D case for simplicity.
@@ -14,6 +14,8 @@
14
14
 
15
15
  """Transformer pass to merge connected components of k-qubit unitary operations."""
16
16
 
17
+ from __future__ import annotations
18
+
17
19
  from typing import Callable, cast, Optional, TYPE_CHECKING
18
20
 
19
21
  from cirq import circuits, ops, protocols
@@ -24,16 +26,16 @@ if TYPE_CHECKING:
24
26
 
25
27
 
26
28
  def _rewrite_merged_k_qubit_unitaries(
27
- circuit: 'cirq.AbstractCircuit',
29
+ circuit: cirq.AbstractCircuit,
28
30
  *,
29
- context: Optional['cirq.TransformerContext'] = None,
31
+ context: Optional[cirq.TransformerContext] = None,
30
32
  k: int = 0,
31
- rewriter: Optional[Callable[['cirq.CircuitOperation'], 'cirq.OP_TREE']] = None,
33
+ rewriter: Optional[Callable[[cirq.CircuitOperation], cirq.OP_TREE]] = None,
32
34
  merged_circuit_op_tag: str = "_merged_k_qubit_unitaries_component",
33
- ) -> 'cirq.Circuit':
35
+ ) -> cirq.Circuit:
34
36
  deep = context.deep if context else False
35
37
 
36
- def map_func(op: 'cirq.Operation', _) -> 'cirq.OP_TREE':
38
+ def map_func(op: cirq.Operation, _) -> cirq.OP_TREE:
37
39
  op_untagged = op.untagged
38
40
  if (
39
41
  deep
@@ -66,12 +68,12 @@ def _rewrite_merged_k_qubit_unitaries(
66
68
 
67
69
  @transformer_api.transformer
68
70
  def merge_k_qubit_unitaries(
69
- circuit: 'cirq.AbstractCircuit',
71
+ circuit: cirq.AbstractCircuit,
70
72
  *,
71
- context: Optional['cirq.TransformerContext'] = None,
73
+ context: Optional[cirq.TransformerContext] = None,
72
74
  k: int = 0,
73
- rewriter: Optional[Callable[['cirq.CircuitOperation'], 'cirq.OP_TREE']] = None,
74
- ) -> 'cirq.Circuit':
75
+ rewriter: Optional[Callable[[cirq.CircuitOperation], cirq.OP_TREE]] = None,
76
+ ) -> cirq.Circuit:
75
77
  """Merges connected components of unitary operations, acting on <= k qubits.
76
78
 
77
79
  Uses rewriter to convert a connected component of unitary operations acting on <= k-qubits
@@ -14,6 +14,8 @@
14
14
 
15
15
  # pylint: skip-file
16
16
 
17
+ from __future__ import annotations
18
+
17
19
  from typing import List
18
20
 
19
21
  import numpy as np
@@ -133,7 +135,7 @@ a: ═════════════════════════
133
135
  )
134
136
  component_id = 0
135
137
 
136
- def rewriter_merge_to_circuit_op(op: 'cirq.CircuitOperation') -> 'cirq.OP_TREE':
138
+ def rewriter_merge_to_circuit_op(op: cirq.CircuitOperation) -> cirq.OP_TREE:
137
139
  nonlocal component_id
138
140
  component_id = component_id + 1
139
141
  return op.with_tags(f'{component_id}')
@@ -160,7 +162,7 @@ a: ═════════════════════════
160
162
 
161
163
  component_id = 0
162
164
 
163
- def rewriter_replace_with_decomp(op: 'cirq.CircuitOperation') -> 'cirq.OP_TREE':
165
+ def rewriter_replace_with_decomp(op: cirq.CircuitOperation) -> cirq.OP_TREE:
164
166
  nonlocal component_id
165
167
  component_id = component_id + 1
166
168
  tag = f'{component_id}'
@@ -220,7 +222,7 @@ def test_merge_k_qubit_unitaries_deep():
220
222
 
221
223
  component_id = 0
222
224
 
223
- def rewriter_merge_to_circuit_op(op: 'cirq.CircuitOperation') -> 'cirq.OP_TREE':
225
+ def rewriter_merge_to_circuit_op(op: cirq.CircuitOperation) -> cirq.OP_TREE:
224
226
  nonlocal component_id
225
227
  component_id = component_id + 1
226
228
  return op.with_tags(f'{component_id}')
@@ -14,6 +14,8 @@
14
14
 
15
15
  """Transformer passes to combine adjacent single-qubit rotations."""
16
16
 
17
+ from __future__ import annotations
18
+
17
19
  from typing import Optional, TYPE_CHECKING
18
20
 
19
21
  from cirq import circuits, ops, protocols
@@ -26,11 +28,11 @@ if TYPE_CHECKING:
26
28
 
27
29
  @transformer_api.transformer
28
30
  def merge_single_qubit_gates_to_phased_x_and_z(
29
- circuit: 'cirq.AbstractCircuit',
31
+ circuit: cirq.AbstractCircuit,
30
32
  *,
31
- context: Optional['cirq.TransformerContext'] = None,
33
+ context: Optional[cirq.TransformerContext] = None,
32
34
  atol: float = 1e-8,
33
- ) -> 'cirq.Circuit':
35
+ ) -> cirq.Circuit:
34
36
  """Replaces runs of single qubit rotations with `cirq.PhasedXPowGate` and `cirq.ZPowGate`.
35
37
 
36
38
  Specifically, any run of non-parameterized single-qubit unitaries will be replaced by an
@@ -46,7 +48,7 @@ def merge_single_qubit_gates_to_phased_x_and_z(
46
48
  Copy of the transformed input circuit.
47
49
  """
48
50
 
49
- def rewriter(op: 'cirq.CircuitOperation') -> 'cirq.OP_TREE':
51
+ def rewriter(op: cirq.CircuitOperation) -> cirq.OP_TREE:
50
52
  u = protocols.unitary(op)
51
53
  if protocols.num_qubits(op) == 0:
52
54
  return ops.GlobalPhaseGate(u[0, 0]).on()
@@ -62,11 +64,11 @@ def merge_single_qubit_gates_to_phased_x_and_z(
62
64
 
63
65
  @transformer_api.transformer
64
66
  def merge_single_qubit_gates_to_phxz(
65
- circuit: 'cirq.AbstractCircuit',
67
+ circuit: cirq.AbstractCircuit,
66
68
  *,
67
- context: Optional['cirq.TransformerContext'] = None,
69
+ context: Optional[cirq.TransformerContext] = None,
68
70
  atol: float = 1e-8,
69
- ) -> 'cirq.Circuit':
71
+ ) -> cirq.Circuit:
70
72
  """Replaces runs of single qubit rotations with a single optional `cirq.PhasedXZGate`.
71
73
 
72
74
  Specifically, any run of non-parameterized single-qubit unitaries will be replaced by an
@@ -82,7 +84,7 @@ def merge_single_qubit_gates_to_phxz(
82
84
  Copy of the transformed input circuit.
83
85
  """
84
86
 
85
- def rewriter(op: 'cirq.CircuitOperation') -> 'cirq.OP_TREE':
87
+ def rewriter(op: cirq.CircuitOperation) -> cirq.OP_TREE:
86
88
  u = protocols.unitary(op)
87
89
  if protocols.num_qubits(op) == 0:
88
90
  return ops.GlobalPhaseGate(u[0, 0]).on()
@@ -96,11 +98,11 @@ def merge_single_qubit_gates_to_phxz(
96
98
 
97
99
  @transformer_api.transformer
98
100
  def merge_single_qubit_moments_to_phxz(
99
- circuit: 'cirq.AbstractCircuit',
101
+ circuit: cirq.AbstractCircuit,
100
102
  *,
101
- context: Optional['cirq.TransformerContext'] = None,
103
+ context: Optional[cirq.TransformerContext] = None,
102
104
  atol: float = 1e-8,
103
- ) -> 'cirq.Circuit':
105
+ ) -> cirq.Circuit:
104
106
  """Merges adjacent moments with only 1-qubit rotations to a single moment with PhasedXZ gates.
105
107
 
106
108
  Args:
@@ -114,7 +116,7 @@ def merge_single_qubit_moments_to_phxz(
114
116
  """
115
117
  tags_to_ignore = set(context.tags_to_ignore) if context else set()
116
118
 
117
- def can_merge_moment(m: 'cirq.Moment'):
119
+ def can_merge_moment(m: cirq.Moment):
118
120
  return all(
119
121
  protocols.num_qubits(op) == 1
120
122
  and protocols.has_unitary(op)
@@ -122,7 +124,7 @@ def merge_single_qubit_moments_to_phxz(
122
124
  for op in m
123
125
  )
124
126
 
125
- def merge_func(m1: 'cirq.Moment', m2: 'cirq.Moment') -> Optional['cirq.Moment']:
127
+ def merge_func(m1: cirq.Moment, m2: cirq.Moment) -> Optional[cirq.Moment]:
126
128
  if not (can_merge_moment(m1) and can_merge_moment(m2)):
127
129
  return None
128
130
  ret_ops = []
@@ -14,6 +14,8 @@
14
14
 
15
15
  """Transformers to rewrite a circuit using gates from a given target gateset."""
16
16
 
17
+ from __future__ import annotations
18
+
17
19
  from typing import Callable, Hashable, Optional, Sequence, TYPE_CHECKING, Union
18
20
 
19
21
  from cirq import circuits
@@ -24,8 +26,8 @@ if TYPE_CHECKING:
24
26
  import cirq
25
27
 
26
28
 
27
- def _create_on_stuck_raise_error(gateset: 'cirq.Gateset'):
28
- def _value_error_describing_bad_operation(op: 'cirq.Operation') -> ValueError:
29
+ def _create_on_stuck_raise_error(gateset: cirq.Gateset):
30
+ def _value_error_describing_bad_operation(op: cirq.Operation) -> ValueError:
29
31
  return ValueError(f"Unable to convert {op} to target gateset {gateset!r}")
30
32
 
31
33
  return _value_error_describing_bad_operation
@@ -33,14 +35,14 @@ def _create_on_stuck_raise_error(gateset: 'cirq.Gateset'):
33
35
 
34
36
  @transformer_api.transformer
35
37
  def _decompose_operations_to_target_gateset(
36
- circuit: 'cirq.AbstractCircuit',
38
+ circuit: cirq.AbstractCircuit,
37
39
  *,
38
- context: Optional['cirq.TransformerContext'] = None,
39
- gateset: Optional['cirq.Gateset'] = None,
40
- decomposer: Callable[['cirq.Operation', int], dp.DecomposeResult] = lambda *_: NotImplemented,
40
+ context: Optional[cirq.TransformerContext] = None,
41
+ gateset: Optional[cirq.Gateset] = None,
42
+ decomposer: Callable[[cirq.Operation, int], dp.DecomposeResult] = lambda *_: NotImplemented,
41
43
  ignore_failures: bool = True,
42
44
  tags_to_decompose: Sequence[Hashable] = (),
43
- ) -> 'cirq.Circuit':
45
+ ) -> cirq.Circuit:
44
46
  """Decomposes every operation to `gateset` using `cirq.decompose` and `decomposer`.
45
47
 
46
48
  This transformer attempts to decompose every operation `op` in the given circuit to `gateset`
@@ -68,7 +70,7 @@ def _decompose_operations_to_target_gateset(
68
70
  ValueError: If any input operation fails to convert and `ignore_failures` is False.
69
71
  """
70
72
 
71
- def map_func(op: 'cirq.Operation', moment_index: int):
73
+ def map_func(op: cirq.Operation, moment_index: int):
72
74
  if (
73
75
  context
74
76
  and context.deep
@@ -97,13 +99,13 @@ def _decompose_operations_to_target_gateset(
97
99
 
98
100
  @transformer_api.transformer
99
101
  def optimize_for_target_gateset(
100
- circuit: 'cirq.AbstractCircuit',
102
+ circuit: cirq.AbstractCircuit,
101
103
  *,
102
- context: Optional['cirq.TransformerContext'] = None,
103
- gateset: Optional['cirq.CompilationTargetGateset'] = None,
104
+ context: Optional[cirq.TransformerContext] = None,
105
+ gateset: Optional[cirq.CompilationTargetGateset] = None,
104
106
  ignore_failures: bool = True,
105
107
  max_num_passes: Union[int, None] = 1,
106
- ) -> 'cirq.Circuit':
108
+ ) -> cirq.Circuit:
107
109
  """Transforms the given circuit into an equivalent circuit using gates accepted by `gateset`.
108
110
 
109
111
  Repeat max_num_passes times or when `max_num_passes=None` until no further changes can be done
@@ -12,14 +12,18 @@
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
14
 
15
- from typing import Union
15
+ from __future__ import annotations
16
+
17
+ from typing import TYPE_CHECKING, Union
16
18
 
17
19
  import pytest
18
20
 
19
21
  import cirq
20
- from cirq.protocols.decompose_protocol import DecomposeResult
21
22
  from cirq.transformers.optimize_for_target_gateset import _decompose_operations_to_target_gateset
22
23
 
24
+ if TYPE_CHECKING:
25
+ from cirq.protocols.decompose_protocol import DecomposeResult
26
+
23
27
 
24
28
  def test_decompose_operations_raises_on_stuck():
25
29
  c_orig = cirq.Circuit(cirq.X(cirq.NamedQubit("q")).with_tags("ignore"))
@@ -121,7 +125,7 @@ class MatrixGateTargetGateset(cirq.CompilationTargetGateset):
121
125
  def num_qubits(self) -> int:
122
126
  return 2
123
127
 
124
- def decompose_to_target_gateset(self, op: 'cirq.Operation', _) -> DecomposeResult:
128
+ def decompose_to_target_gateset(self, op: cirq.Operation, _) -> DecomposeResult:
125
129
  if cirq.num_qubits(op) != 2 or not cirq.has_unitary(op):
126
130
  return NotImplemented
127
131
  return cirq.MatrixGate(cirq.unitary(op), name="M").on(*op.qubits)