cirq-core 1.6.0.dev20250501173104__py3-none-any.whl → 1.6.0.dev20250501231232__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 (59) hide show
  1. cirq/_version.py +1 -1
  2. cirq/_version_test.py +1 -1
  3. cirq/contrib/paulistring/pauli_string_measurement_with_readout_mitigation.py +211 -107
  4. cirq/contrib/paulistring/pauli_string_measurement_with_readout_mitigation_test.py +347 -3
  5. cirq/transformers/analytical_decompositions/two_qubit_to_cz.py +18 -18
  6. cirq/transformers/analytical_decompositions/two_qubit_to_fsim.py +18 -19
  7. cirq/transformers/analytical_decompositions/two_qubit_to_ms.py +8 -10
  8. cirq/transformers/analytical_decompositions/two_qubit_to_sqrt_iswap.py +26 -28
  9. cirq/transformers/drop_empty_moments.py +4 -2
  10. cirq/transformers/drop_negligible_operations.py +6 -4
  11. cirq/transformers/dynamical_decoupling.py +6 -4
  12. cirq/transformers/dynamical_decoupling_test.py +8 -6
  13. cirq/transformers/eject_phased_paulis.py +14 -12
  14. cirq/transformers/eject_z.py +8 -6
  15. cirq/transformers/expand_composite.py +5 -3
  16. cirq/transformers/gauge_compiling/sqrt_cz_gauge.py +3 -1
  17. cirq/transformers/heuristic_decompositions/two_qubit_gate_tabulation.py +4 -1
  18. cirq/transformers/insertion_sort.py +6 -4
  19. cirq/transformers/measurement_transformers.py +21 -21
  20. cirq/transformers/merge_k_qubit_gates.py +11 -9
  21. cirq/transformers/merge_k_qubit_gates_test.py +5 -3
  22. cirq/transformers/merge_single_qubit_gates.py +15 -13
  23. cirq/transformers/optimize_for_target_gateset.py +14 -12
  24. cirq/transformers/optimize_for_target_gateset_test.py +7 -3
  25. cirq/transformers/qubit_management_transformers.py +10 -8
  26. cirq/transformers/randomized_measurements.py +9 -7
  27. cirq/transformers/routing/initial_mapper.py +5 -3
  28. cirq/transformers/routing/line_initial_mapper.py +15 -13
  29. cirq/transformers/routing/mapping_manager.py +9 -9
  30. cirq/transformers/routing/route_circuit_cqc.py +17 -15
  31. cirq/transformers/routing/visualize_routed_circuit.py +7 -6
  32. cirq/transformers/stratify.py +13 -11
  33. cirq/transformers/synchronize_terminal_measurements.py +9 -9
  34. cirq/transformers/target_gatesets/compilation_target_gateset.py +19 -17
  35. cirq/transformers/target_gatesets/compilation_target_gateset_test.py +11 -7
  36. cirq/transformers/target_gatesets/cz_gateset.py +4 -2
  37. cirq/transformers/target_gatesets/sqrt_iswap_gateset.py +5 -3
  38. cirq/transformers/transformer_api.py +17 -15
  39. cirq/transformers/transformer_primitives.py +22 -20
  40. cirq/transformers/transformer_primitives_test.py +3 -1
  41. cirq/value/classical_data.py +26 -26
  42. cirq/value/condition.py +23 -21
  43. cirq/value/duration.py +11 -8
  44. cirq/value/linear_dict.py +22 -20
  45. cirq/value/periodic_value.py +4 -4
  46. cirq/value/probability.py +3 -1
  47. cirq/value/product_state.py +14 -12
  48. cirq/work/collector.py +7 -5
  49. cirq/work/observable_measurement.py +24 -22
  50. cirq/work/observable_measurement_data.py +9 -7
  51. cirq/work/observable_readout_calibration.py +4 -1
  52. cirq/work/observable_readout_calibration_test.py +4 -1
  53. cirq/work/observable_settings.py +4 -2
  54. cirq/work/pauli_sum_collector.py +8 -6
  55. {cirq_core-1.6.0.dev20250501173104.dist-info → cirq_core-1.6.0.dev20250501231232.dist-info}/METADATA +1 -1
  56. {cirq_core-1.6.0.dev20250501173104.dist-info → cirq_core-1.6.0.dev20250501231232.dist-info}/RECORD +59 -59
  57. {cirq_core-1.6.0.dev20250501173104.dist-info → cirq_core-1.6.0.dev20250501231232.dist-info}/WHEEL +0 -0
  58. {cirq_core-1.6.0.dev20250501173104.dist-info → cirq_core-1.6.0.dev20250501231232.dist-info}/licenses/LICENSE +0 -0
  59. {cirq_core-1.6.0.dev20250501173104.dist-info → cirq_core-1.6.0.dev20250501231232.dist-info}/top_level.txt +0 -0
@@ -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
@@ -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],