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
@@ -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 Dict, Optional, Set, Tuple, TYPE_CHECKING
16
18
 
17
19
  from cirq import circuits, ops
@@ -21,8 +23,8 @@ if TYPE_CHECKING:
21
23
 
22
24
 
23
25
  def _get_qubit_mapping_first_and_last_moment(
24
- circuit: 'cirq.AbstractCircuit',
25
- ) -> Dict['cirq.Qid', Tuple[int, int]]:
26
+ circuit: cirq.AbstractCircuit,
27
+ ) -> Dict[cirq.Qid, Tuple[int, int]]:
26
28
  """Computes `(first_moment_idx, last_moment_idx)` tuple for each qubit in the input circuit.
27
29
 
28
30
  Args:
@@ -41,13 +43,13 @@ def _get_qubit_mapping_first_and_last_moment(
41
43
  return ret
42
44
 
43
45
 
44
- def _is_temp(q: 'cirq.Qid') -> bool:
46
+ def _is_temp(q: cirq.Qid) -> bool:
45
47
  return isinstance(q, (ops.CleanQubit, ops.BorrowableQubit))
46
48
 
47
49
 
48
50
  def map_clean_and_borrowable_qubits(
49
- circuit: 'cirq.AbstractCircuit', *, qm: Optional['cirq.QubitManager'] = None
50
- ) -> 'cirq.Circuit':
51
+ circuit: cirq.AbstractCircuit, *, qm: Optional[cirq.QubitManager] = None
52
+ ) -> cirq.Circuit:
51
53
  """Uses `qm: QubitManager` to map all `CleanQubit`/`BorrowableQubit`s to system qubits.
52
54
 
53
55
  `CleanQubit` and `BorrowableQubit` are internal qubit types that are used as placeholder qubits
@@ -97,11 +99,11 @@ def map_clean_and_borrowable_qubits(
97
99
  trivial_map = {q: q for q in all_qubits}
98
100
  # `allocated_map` maintains the mapping of all temporary qubits seen so far, mapping each of
99
101
  # them to either a newly allocated managed ancilla or an existing borrowed system qubit.
100
- allocated_map: Dict['cirq.Qid', 'cirq.Qid'] = {}
101
- to_free: Set['cirq.Qid'] = set()
102
+ allocated_map: Dict[cirq.Qid, cirq.Qid] = {}
103
+ to_free: Set[cirq.Qid] = set()
102
104
  last_op_idx = -1
103
105
 
104
- def map_func(op: 'cirq.Operation', idx: int) -> 'cirq.OP_TREE':
106
+ def map_func(op: cirq.Operation, idx: int) -> cirq.OP_TREE:
105
107
  nonlocal last_op_idx, to_free
106
108
  assert isinstance(qm, ops.QubitManager)
107
109
 
@@ -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 collections.abc import Sequence
16
18
  from typing import Any
17
19
 
@@ -39,12 +41,12 @@ class RandomizedMeasurements:
39
41
 
40
42
  def __call__(
41
43
  self,
42
- circuit: "cirq.AbstractCircuit",
44
+ circuit: cirq.AbstractCircuit,
43
45
  unitary_ensemble: str = "pauli",
44
46
  rng: np.random.Generator | None = None,
45
47
  *,
46
48
  context: transformer_api.TransformerContext | None = None,
47
- ) -> "cirq.Circuit":
49
+ ) -> cirq.Circuit:
48
50
  """Apply the transformer to the given circuit. Given an input circuit returns
49
51
  a new circuit with the pre-measurement unitaries and measurements gates added.
50
52
  to the qubits in the subsystem provided.If no subsystem is specified in the
@@ -80,7 +82,7 @@ class RandomizedMeasurements:
80
82
 
81
83
  def random_single_qubit_unitary_moment(
82
84
  self, unitary_ensemble: str, qubits: Sequence[Any], rng: np.random.Generator
83
- ) -> "cirq.Moment":
85
+ ) -> cirq.Moment:
84
86
  """Outputs the cirq moment associated with the pre-measurement rotations.
85
87
 
86
88
  Args:
@@ -115,7 +117,7 @@ class RandomizedMeasurements:
115
117
  return cirq.Moment.from_ops(*op_list)
116
118
 
117
119
 
118
- def _pauli_basis_rotation(rng: np.random.Generator) -> "cirq.Gate":
120
+ def _pauli_basis_rotation(rng: np.random.Generator) -> cirq.Gate:
119
121
  """Randomly generate a Pauli basis rotation.
120
122
 
121
123
  Args:
@@ -127,7 +129,7 @@ def _pauli_basis_rotation(rng: np.random.Generator) -> "cirq.Gate":
127
129
  basis_idx = rng.choice(np.arange(3))
128
130
 
129
131
  if basis_idx == 0:
130
- gate: "cirq.Gate" = cirq.Ry(rads=-np.pi / 2)
132
+ gate: cirq.Gate = cirq.Ry(rads=-np.pi / 2)
131
133
  elif basis_idx == 1:
132
134
  gate = cirq.Rx(rads=np.pi / 2)
133
135
  else:
@@ -135,7 +137,7 @@ def _pauli_basis_rotation(rng: np.random.Generator) -> "cirq.Gate":
135
137
  return gate
136
138
 
137
139
 
138
- def _single_qubit_clifford(rng: np.random.Generator) -> "cirq.Gate":
140
+ def _single_qubit_clifford(rng: np.random.Generator) -> cirq.Gate:
139
141
  """Randomly generate a single-qubit Clifford rotation.
140
142
 
141
143
  Args:
@@ -153,7 +155,7 @@ def _single_qubit_clifford(rng: np.random.Generator) -> "cirq.Gate":
153
155
  )
154
156
 
155
157
 
156
- def _single_qubit_cue(rng: np.random.Generator) -> "cirq.Gate":
158
+ def _single_qubit_cue(rng: np.random.Generator) -> cirq.Gate:
157
159
  """Randomly generate a CUE gate.
158
160
 
159
161
  Args:
@@ -12,6 +12,8 @@
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
14
 
15
+ from __future__ import annotations
16
+
15
17
  import abc
16
18
  from typing import Dict, TYPE_CHECKING
17
19
 
@@ -37,7 +39,7 @@ class AbstractInitialMapper(metaclass=abc.ABCMeta):
37
39
  """
38
40
 
39
41
  @abc.abstractmethod
40
- def initial_mapping(self, circuit: 'cirq.AbstractCircuit') -> Dict['cirq.Qid', 'cirq.Qid']:
42
+ def initial_mapping(self, circuit: cirq.AbstractCircuit) -> Dict[cirq.Qid, cirq.Qid]:
41
43
  """Maps the logical qubits of a circuit onto physical qubits on a device.
42
44
 
43
45
  Args:
@@ -52,10 +54,10 @@ class AbstractInitialMapper(metaclass=abc.ABCMeta):
52
54
  class HardCodedInitialMapper(AbstractInitialMapper):
53
55
  """Initial Mapper class takes a hard-coded mapping and returns it."""
54
56
 
55
- def __init__(self, _map: Dict['cirq.Qid', 'cirq.Qid']) -> None:
57
+ def __init__(self, _map: Dict[cirq.Qid, cirq.Qid]) -> None:
56
58
  self._map = _map
57
59
 
58
- def initial_mapping(self, circuit: 'cirq.AbstractCircuit') -> Dict['cirq.Qid', 'cirq.Qid']:
60
+ def initial_mapping(self, circuit: cirq.AbstractCircuit) -> Dict[cirq.Qid, cirq.Qid]:
59
61
  """Returns the hard-coded initial mapping.
60
62
 
61
63
  Args:
@@ -30,6 +30,8 @@ If some logical qubits are unampped after this first procedure then there are tw
30
30
  the nearest available neighbor to the center of the device.
31
31
  """
32
32
 
33
+ from __future__ import annotations
34
+
33
35
  from collections import deque
34
36
  from typing import Deque, Dict, List, Set, Tuple, TYPE_CHECKING
35
37
 
@@ -82,8 +84,8 @@ class LineInitialMapper(initial_mapper.AbstractInitialMapper):
82
84
  self.center = nx.center(self.device_graph)[0]
83
85
 
84
86
  def _make_circuit_graph(
85
- self, circuit: 'cirq.AbstractCircuit'
86
- ) -> Tuple[List[Deque['cirq.Qid']], Dict['cirq.Qid', 'cirq.Qid']]:
87
+ self, circuit: cirq.AbstractCircuit
88
+ ) -> Tuple[List[Deque[cirq.Qid]], Dict[cirq.Qid, cirq.Qid]]:
87
89
  """Creates a (potentially incomplete) qubit connectivity graph of the circuit.
88
90
 
89
91
  Iterates over moments in the circuit from left to right and adds edges between logical
@@ -99,11 +101,11 @@ class LineInitialMapper(initial_mapper.AbstractInitialMapper):
99
101
  The (potentially incomplete) qubit connectivity graph of the circuit, which is
100
102
  guaranteed to be a forest of line graphs.
101
103
  """
102
- circuit_graph: List[Deque['cirq.Qid']] = [deque([q]) for q in sorted(circuit.all_qubits())]
103
- component_id: Dict['cirq.Qid', int] = {q[0]: i for i, q in enumerate(circuit_graph)}
104
- partners: Dict['cirq.Qid', 'cirq.Qid'] = {}
104
+ circuit_graph: List[Deque[cirq.Qid]] = [deque([q]) for q in sorted(circuit.all_qubits())]
105
+ component_id: Dict[cirq.Qid, int] = {q[0]: i for i, q in enumerate(circuit_graph)}
106
+ partners: Dict[cirq.Qid, cirq.Qid] = {}
105
107
 
106
- def degree_lt_two(q: 'cirq.Qid'):
108
+ def degree_lt_two(q: cirq.Qid):
107
109
  return any(circuit_graph[component_id[q]][i] == q for i in [-1, 0])
108
110
 
109
111
  for op in circuit.all_operations():
@@ -141,7 +143,7 @@ class LineInitialMapper(initial_mapper.AbstractInitialMapper):
141
143
  )
142
144
  return graph, partners
143
145
 
144
- def initial_mapping(self, circuit: 'cirq.AbstractCircuit') -> Dict['cirq.Qid', 'cirq.Qid']:
146
+ def initial_mapping(self, circuit: cirq.AbstractCircuit) -> Dict[cirq.Qid, cirq.Qid]:
145
147
  """Maps disjoint lines of logical qubits onto lines of physical qubits.
146
148
 
147
149
  Args:
@@ -151,13 +153,13 @@ class LineInitialMapper(initial_mapper.AbstractInitialMapper):
151
153
  a dictionary that maps logical qubits in the circuit (keys) to physical qubits on the
152
154
  device (values).
153
155
  """
154
- mapped_physicals: Set['cirq.Qid'] = set()
155
- qubit_map: Dict['cirq.Qid', 'cirq.Qid'] = {}
156
+ mapped_physicals: Set[cirq.Qid] = set()
157
+ qubit_map: Dict[cirq.Qid, cirq.Qid] = {}
156
158
  circuit_graph, partners = self._make_circuit_graph(circuit)
157
159
 
158
160
  def next_physical(
159
- current_physical: 'cirq.Qid', partner: 'cirq.Qid', isolated: bool = False
160
- ) -> 'cirq.Qid':
161
+ current_physical: cirq.Qid, partner: cirq.Qid, isolated: bool = False
162
+ ) -> cirq.Qid:
161
163
  # Handle the first physical qubit getting mapped.
162
164
  if current_physical not in mapped_physicals:
163
165
  return current_physical
@@ -189,8 +191,8 @@ class LineInitialMapper(initial_mapper.AbstractInitialMapper):
189
191
  return qubit_map
190
192
 
191
193
  def _closest_unmapped_qubit(
192
- self, source: 'cirq.Qid', mapped_physicals: Set['cirq.Qid']
193
- ) -> 'cirq.Qid':
194
+ self, source: cirq.Qid, mapped_physicals: Set[cirq.Qid]
195
+ ) -> cirq.Qid:
194
196
  """Finds the closest available neighbor to a physical qubit 'source' on the device.
195
197
 
196
198
  Args:
@@ -14,6 +14,8 @@
14
14
 
15
15
  """Manages the mapping from logical to physical qubits during a routing procedure."""
16
16
 
17
+ from __future__ import annotations
18
+
17
19
  from typing import Dict, List, Sequence, TYPE_CHECKING
18
20
 
19
21
  import networkx as nx
@@ -35,9 +37,7 @@ class MappingManager:
35
37
  logical qubits are mapped to, via `self.logical_qid_to_int` map).
36
38
  """
37
39
 
38
- def __init__(
39
- self, device_graph: nx.Graph, initial_mapping: Dict['cirq.Qid', 'cirq.Qid']
40
- ) -> None:
40
+ def __init__(self, device_graph: nx.Graph, initial_mapping: Dict[cirq.Qid, cirq.Qid]) -> None:
41
41
  """Initializes MappingManager.
42
42
 
43
43
  Args:
@@ -84,12 +84,12 @@ class MappingManager:
84
84
  )
85
85
 
86
86
  @property
87
- def physical_qid_to_int(self) -> Dict['cirq.Qid', int]:
87
+ def physical_qid_to_int(self) -> Dict[cirq.Qid, int]:
88
88
  """Mapping of physical qubits, that were part of the initial mapping, to unique integers."""
89
89
  return self._physical_qid_to_int
90
90
 
91
91
  @property
92
- def int_to_physical_qid(self) -> List['cirq.Qid']:
92
+ def int_to_physical_qid(self) -> List[cirq.Qid]:
93
93
  """Inverse mapping of unique integers to corresponding physical qubits.
94
94
 
95
95
  `self.physical_qid_to_int[self.int_to_physical_qid[i]] == i` for each i.
@@ -97,12 +97,12 @@ class MappingManager:
97
97
  return self._int_to_physical_qid
98
98
 
99
99
  @property
100
- def logical_qid_to_int(self) -> Dict['cirq.Qid', int]:
100
+ def logical_qid_to_int(self) -> Dict[cirq.Qid, int]:
101
101
  """Mapping of logical qubits, that were part of the initial mapping, to unique integers."""
102
102
  return self._logical_qid_to_int
103
103
 
104
104
  @property
105
- def int_to_logical_qid(self) -> List['cirq.Qid']:
105
+ def int_to_logical_qid(self) -> List[cirq.Qid]:
106
106
  """Inverse mapping of unique integers to corresponding physical qubits.
107
107
 
108
108
  `self.logical_qid_to_int[self.int_to_logical_qid[i]] == i` for each i.
@@ -178,7 +178,7 @@ class MappingManager:
178
178
  self._logical_to_physical[[lq1, lq2]] = self._logical_to_physical[[lq2, lq1]]
179
179
  self._physical_to_logical[[pq1, pq2]] = self._physical_to_logical[[pq2, pq1]]
180
180
 
181
- def mapped_op(self, op: 'cirq.Operation') -> 'cirq.Operation':
181
+ def mapped_op(self, op: cirq.Operation) -> cirq.Operation:
182
182
  """Transforms the given logical operation to act on corresponding physical qubits.
183
183
 
184
184
  Args:
@@ -189,7 +189,7 @@ class MappingManager:
189
189
  """
190
190
  logical_ints = [self._logical_qid_to_int[q] for q in op.qubits]
191
191
  physical_ints = self.logical_to_physical[logical_ints]
192
- qubit_map: Dict['cirq.Qid', 'cirq.Qid'] = {
192
+ qubit_map: Dict[cirq.Qid, cirq.Qid] = {
193
193
  q: self._int_to_physical_qid[physical_ints[i]] for i, q in enumerate(op.qubits)
194
194
  }
195
195
  return op.transform_qubits(qubit_map)
@@ -14,6 +14,8 @@
14
14
 
15
15
  """Heuristic qubit routing algorithm based on arxiv:1902.08091."""
16
16
 
17
+ from __future__ import annotations
18
+
17
19
  import itertools
18
20
  from typing import Any, Dict, List, Optional, Sequence, Set, Tuple, TYPE_CHECKING
19
21
 
@@ -108,13 +110,13 @@ class RouteCQC:
108
110
 
109
111
  def __call__(
110
112
  self,
111
- circuit: 'cirq.AbstractCircuit',
113
+ circuit: cirq.AbstractCircuit,
112
114
  *,
113
115
  lookahead_radius: int = 8,
114
116
  tag_inserted_swaps: bool = False,
115
- initial_mapper: Optional['cirq.AbstractInitialMapper'] = None,
116
- context: Optional['cirq.TransformerContext'] = None,
117
- ) -> 'cirq.AbstractCircuit':
117
+ initial_mapper: Optional[cirq.AbstractInitialMapper] = None,
118
+ context: Optional[cirq.TransformerContext] = None,
119
+ ) -> cirq.AbstractCircuit:
118
120
  """Transforms the given circuit to make it executable on the device.
119
121
 
120
122
  This method calls self.route_circuit and returns the routed circuit. See docstring of
@@ -150,13 +152,13 @@ class RouteCQC:
150
152
 
151
153
  def route_circuit(
152
154
  self,
153
- circuit: 'cirq.AbstractCircuit',
155
+ circuit: cirq.AbstractCircuit,
154
156
  *,
155
157
  lookahead_radius: int = 8,
156
158
  tag_inserted_swaps: bool = False,
157
- initial_mapper: Optional['cirq.AbstractInitialMapper'] = None,
158
- context: Optional['cirq.TransformerContext'] = None,
159
- ) -> Tuple['cirq.AbstractCircuit', Dict['cirq.Qid', 'cirq.Qid'], Dict['cirq.Qid', 'cirq.Qid']]:
159
+ initial_mapper: Optional[cirq.AbstractInitialMapper] = None,
160
+ context: Optional[cirq.TransformerContext] = None,
161
+ ) -> Tuple[cirq.AbstractCircuit, Dict[cirq.Qid, cirq.Qid], Dict[cirq.Qid, cirq.Qid]]:
160
162
  """Transforms the given circuit to make it executable on the device.
161
163
 
162
164
  This transformer assumes that all multi-qubit operations have been decomposed into 2-qubit
@@ -241,8 +243,8 @@ class RouteCQC:
241
243
 
242
244
  @classmethod
243
245
  def _get_one_and_two_qubit_ops_as_timesteps(
244
- cls, circuit: 'cirq.AbstractCircuit'
245
- ) -> Tuple[List[List['cirq.Operation']], List[List['cirq.Operation']]]:
246
+ cls, circuit: cirq.AbstractCircuit
247
+ ) -> Tuple[List[List[cirq.Operation]], List[List[cirq.Operation]]]:
246
248
  """Gets the single and two qubit operations of the circuit factored into timesteps.
247
249
 
248
250
  The i'th entry in the nested two-qubit and single-qubit ops correspond to the two-qubit
@@ -286,11 +288,11 @@ class RouteCQC:
286
288
  def _route(
287
289
  cls,
288
290
  mm: mapping_manager.MappingManager,
289
- two_qubit_ops: List[List['cirq.Operation']],
290
- single_qubit_ops: List[List['cirq.Operation']],
291
+ two_qubit_ops: List[List[cirq.Operation]],
292
+ single_qubit_ops: List[List[cirq.Operation]],
291
293
  lookahead_radius: int,
292
294
  tag_inserted_swaps: bool = False,
293
- ) -> List[List['cirq.Operation']]:
295
+ ) -> List[List[cirq.Operation]]:
294
296
  """Main routing procedure that inserts necessary swaps on the given timesteps.
295
297
 
296
298
  The i'th element of the returned list corresponds to the routed operatiosn in the i'th
@@ -316,10 +318,10 @@ class RouteCQC:
316
318
  ]
317
319
  for timestep_ops in two_qubit_ops
318
320
  ]
319
- routed_ops: List[List['cirq.Operation']] = []
321
+ routed_ops: List[List[cirq.Operation]] = []
320
322
 
321
323
  def process_executable_two_qubit_ops(timestep: int) -> int:
322
- unexecutable_ops: List['cirq.Operation'] = []
324
+ unexecutable_ops: List[cirq.Operation] = []
323
325
  unexecutable_ops_ints: List[QidIntPair] = []
324
326
  for op, op_ints in zip(two_qubit_ops[timestep], two_qubit_ops_ints[timestep]):
325
327
  if mm.is_adjacent(*op_ints):
@@ -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 Dict, Optional, Tuple, TYPE_CHECKING
16
18
 
17
19
  from cirq import circuits, ops
@@ -23,20 +25,19 @@ if TYPE_CHECKING:
23
25
  class _SwapPrintGate(ops.Gate):
24
26
  """A gate that displays the string representation of each qubits on the circuit."""
25
27
 
26
- def __init__(self, qubits: Tuple[Tuple['cirq.Qid', 'cirq.Qid'], ...]) -> None:
28
+ def __init__(self, qubits: Tuple[Tuple[cirq.Qid, cirq.Qid], ...]) -> None:
27
29
  self.qubits = qubits
28
30
 
29
31
  def num_qubits(self):
30
32
  return len(self.qubits)
31
33
 
32
- def _circuit_diagram_info_(self, args: 'cirq.CircuitDiagramInfoArgs') -> Tuple[str, ...]:
34
+ def _circuit_diagram_info_(self, args: cirq.CircuitDiagramInfoArgs) -> Tuple[str, ...]:
33
35
  return tuple(f'{str(q[1])}' for q in self.qubits)
34
36
 
35
37
 
36
38
  def routed_circuit_with_mapping(
37
- routed_circuit: 'cirq.AbstractCircuit',
38
- initial_map: Optional[Dict['cirq.Qid', 'cirq.Qid']] = None,
39
- ) -> 'cirq.AbstractCircuit':
39
+ routed_circuit: cirq.AbstractCircuit, initial_map: Optional[Dict[cirq.Qid, cirq.Qid]] = None
40
+ ) -> cirq.AbstractCircuit:
40
41
  """Returns the same circuits with information about the permutation of qubits after each swap.
41
42
 
42
43
  Args:
@@ -54,7 +55,7 @@ def routed_circuit_with_mapping(
54
55
  initial_map = qdict.copy()
55
56
  inverse_map = {v: k for k, v in initial_map.items()}
56
57
 
57
- def swap_print_moment() -> 'cirq.Operation':
58
+ def swap_print_moment() -> cirq.Operation:
58
59
  return _SwapPrintGate(
59
60
  tuple(zip(qdict.values(), [inverse_map[x] for x in qdict.values()]))
60
61
  ).on(*all_qubits)
@@ -14,6 +14,8 @@
14
14
 
15
15
  """Transformer pass to repack circuits avoiding simultaneous operations with different classes."""
16
16
 
17
+ from __future__ import annotations
18
+
17
19
  import itertools
18
20
  from typing import Callable, Dict, Iterable, List, Optional, Sequence, Type, TYPE_CHECKING, Union
19
21
 
@@ -37,11 +39,11 @@ Category = Union[
37
39
 
38
40
  @transformer_api.transformer(add_deep_support=True)
39
41
  def stratified_circuit(
40
- circuit: 'cirq.AbstractCircuit',
42
+ circuit: cirq.AbstractCircuit,
41
43
  *,
42
- context: Optional['cirq.TransformerContext'] = None,
44
+ context: Optional[cirq.TransformerContext] = None,
43
45
  categories: Iterable[Category] = (),
44
- ) -> 'cirq.Circuit':
46
+ ) -> cirq.Circuit:
45
47
  """Repacks avoiding simultaneous operations with different classes.
46
48
 
47
49
  This transforms the given circuit to ensure that no operations of different categories are
@@ -96,9 +98,9 @@ def stratified_circuit(
96
98
  def _stratify_circuit(
97
99
  circuit: circuits.AbstractCircuit,
98
100
  *,
99
- context: 'cirq.TransformerContext',
101
+ context: cirq.TransformerContext,
100
102
  classifiers: Sequence[Classifier],
101
- ) -> 'cirq.Circuit':
103
+ ) -> cirq.Circuit:
102
104
  """Performs the stratification by iterating through the operations in the
103
105
  circuit and using the given classifiers to align them.
104
106
 
@@ -115,12 +117,12 @@ def _stratify_circuit(
115
117
  The stratified circuit.
116
118
  """
117
119
  num_classes = len(classifiers) + 1 # include one "extra" category for ignored operations
118
- new_moments: List[List['cirq.Operation']] = []
120
+ new_moments: List[List[cirq.Operation]] = []
119
121
 
120
122
  # Keep track of the latest time index for each qubit, measurement key, and control key.
121
- qubit_time_index: Dict['cirq.Qid', int] = {}
122
- measurement_time_index: Dict['cirq.MeasurementKey', int] = {}
123
- control_time_index: Dict['cirq.MeasurementKey', int] = {}
123
+ qubit_time_index: Dict[cirq.Qid, int] = {}
124
+ measurement_time_index: Dict[cirq.MeasurementKey, int] = {}
125
+ control_time_index: Dict[cirq.MeasurementKey, int] = {}
124
126
 
125
127
  # The minimum time index for operations with a tag in context.tags_to_ignore.
126
128
  last_ignored_ops_time_index = 0
@@ -221,12 +223,12 @@ def _category_to_classifier(category) -> Classifier:
221
223
  )
222
224
 
223
225
 
224
- def _mock_classifier(op: 'cirq.Operation') -> bool:
226
+ def _mock_classifier(op: cirq.Operation) -> bool:
225
227
  """Mock classifier, used to "complete" a collection of classifiers and make it exhaustive."""
226
228
  return False # pragma: no cover
227
229
 
228
230
 
229
- def _get_op_class(op: 'cirq.Operation', classifiers: Sequence[Classifier]) -> int:
231
+ def _get_op_class(op: cirq.Operation, classifiers: Sequence[Classifier]) -> int:
230
232
  """Get the "class" of an operator, by index."""
231
233
  for class_index, classifier in enumerate(classifiers):
232
234
  if classifier is _mock_classifier:
@@ -14,6 +14,8 @@
14
14
 
15
15
  """Transformer pass to move terminal measurements to the end of circuit."""
16
16
 
17
+ from __future__ import annotations
18
+
17
19
  from typing import List, Optional, Set, Tuple, TYPE_CHECKING
18
20
 
19
21
  from cirq import circuits, protocols
@@ -23,9 +25,7 @@ if TYPE_CHECKING:
23
25
  import cirq
24
26
 
25
27
 
26
- def find_terminal_measurements(
27
- circuit: 'cirq.AbstractCircuit',
28
- ) -> List[Tuple[int, 'cirq.Operation']]:
28
+ def find_terminal_measurements(circuit: cirq.AbstractCircuit) -> List[Tuple[int, cirq.Operation]]:
29
29
  """Finds all terminal measurements in the given circuit.
30
30
 
31
31
  A measurement is terminal if there are no other operations acting on the measured qubits
@@ -39,9 +39,9 @@ def find_terminal_measurements(
39
39
  (moment_index, measurement_operation).
40
40
  """
41
41
 
42
- open_qubits: Set['cirq.Qid'] = set(circuit.all_qubits())
43
- seen_control_keys: Set['cirq.MeasurementKey'] = set()
44
- terminal_measurements: Set[Tuple[int, 'cirq.Operation']] = set()
42
+ open_qubits: Set[cirq.Qid] = set(circuit.all_qubits())
43
+ seen_control_keys: Set[cirq.MeasurementKey] = set()
44
+ terminal_measurements: Set[Tuple[int, cirq.Operation]] = set()
45
45
  for i in range(len(circuit) - 1, -1, -1):
46
46
  moment = circuit[i]
47
47
  for q in open_qubits:
@@ -62,11 +62,11 @@ def find_terminal_measurements(
62
62
 
63
63
  @transformer_api.transformer(add_deep_support=True)
64
64
  def synchronize_terminal_measurements(
65
- circuit: 'cirq.AbstractCircuit',
65
+ circuit: cirq.AbstractCircuit,
66
66
  *,
67
- context: Optional['cirq.TransformerContext'] = None,
67
+ context: Optional[cirq.TransformerContext] = None,
68
68
  after_other_operations: bool = True,
69
- ) -> 'cirq.Circuit':
69
+ ) -> cirq.Circuit:
70
70
  """Move measurements to the end of the circuit.
71
71
 
72
72
  Move all measurements in a circuit to the final moment, if it can accommodate them (without