cirq-core 1.5.0.dev20250403170622__py3-none-any.whl → 1.5.0.dev20250404165440__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 (56) hide show
  1. cirq/_version.py +1 -1
  2. cirq/_version_test.py +1 -1
  3. cirq/circuits/circuit.py +144 -147
  4. cirq/circuits/circuit_operation.py +37 -34
  5. cirq/circuits/circuit_operation_test.py +1 -1
  6. cirq/circuits/circuit_test.py +4 -6
  7. cirq/circuits/frozen_circuit.py +30 -26
  8. cirq/circuits/moment.py +37 -37
  9. cirq/circuits/optimization_pass.py +11 -11
  10. cirq/circuits/optimization_pass_test.py +6 -8
  11. cirq/circuits/qasm_output.py +13 -11
  12. cirq/circuits/text_diagram_drawer.py +9 -7
  13. cirq/contrib/acquaintance/bipartite.py +7 -5
  14. cirq/contrib/acquaintance/devices.py +3 -1
  15. cirq/contrib/acquaintance/executor.py +14 -16
  16. cirq/contrib/acquaintance/gates.py +19 -21
  17. cirq/contrib/acquaintance/inspection_utils.py +8 -6
  18. cirq/contrib/acquaintance/mutation_utils.py +8 -6
  19. cirq/contrib/acquaintance/optimizers.py +5 -3
  20. cirq/contrib/acquaintance/permutation.py +19 -19
  21. cirq/contrib/acquaintance/shift.py +5 -3
  22. cirq/contrib/acquaintance/shift_swap_network.py +5 -3
  23. cirq/contrib/acquaintance/strategies/complete.py +4 -2
  24. cirq/contrib/acquaintance/strategies/cubic.py +4 -2
  25. cirq/contrib/acquaintance/strategies/quartic_paired.py +8 -6
  26. cirq/contrib/acquaintance/topological_sort.py +4 -2
  27. cirq/contrib/bayesian_network/bayesian_network_gate.py +4 -2
  28. cirq/contrib/circuitdag/circuit_dag.py +18 -16
  29. cirq/contrib/custom_simulators/custom_state_simulator.py +10 -8
  30. cirq/contrib/custom_simulators/custom_state_simulator_test.py +9 -7
  31. cirq/contrib/graph_device/graph_device.py +4 -2
  32. cirq/contrib/noise_models/noise_models.py +7 -5
  33. cirq/contrib/paulistring/clifford_target_gateset.py +11 -9
  34. cirq/contrib/qcircuit/qcircuit_diagram.py +5 -2
  35. cirq/contrib/qcircuit/qcircuit_pdf.py +7 -11
  36. cirq/contrib/qcircuit/qcircuit_pdf_test.py +10 -2
  37. cirq/contrib/quantum_volume/quantum_volume.py +4 -4
  38. cirq/contrib/quimb/mps_simulator.py +25 -26
  39. cirq/contrib/routing/greedy.py +5 -3
  40. cirq/contrib/routing/initialization.py +3 -1
  41. cirq/contrib/routing/swap_network.py +5 -5
  42. cirq/contrib/routing/utils.py +4 -2
  43. cirq/contrib/svg/svg.py +9 -6
  44. cirq/devices/device.py +11 -9
  45. cirq/devices/grid_device_metadata.py +14 -11
  46. cirq/devices/grid_qubit.py +17 -21
  47. cirq/devices/grid_qubit_test.py +1 -1
  48. cirq/devices/insertion_noise_model.py +5 -5
  49. cirq/devices/line_qubit.py +15 -17
  50. cirq/devices/named_topologies.py +6 -4
  51. cirq/devices/noise_model.py +27 -31
  52. {cirq_core-1.5.0.dev20250403170622.dist-info → cirq_core-1.5.0.dev20250404165440.dist-info}/METADATA +1 -1
  53. {cirq_core-1.5.0.dev20250403170622.dist-info → cirq_core-1.5.0.dev20250404165440.dist-info}/RECORD +56 -56
  54. {cirq_core-1.5.0.dev20250403170622.dist-info → cirq_core-1.5.0.dev20250404165440.dist-info}/LICENSE +0 -0
  55. {cirq_core-1.5.0.dev20250403170622.dist-info → cirq_core-1.5.0.dev20250404165440.dist-info}/WHEEL +0 -0
  56. {cirq_core-1.5.0.dev20250403170622.dist-info → cirq_core-1.5.0.dev20250404165440.dist-info}/top_level.txt +0 -0
cirq/circuits/moment.py CHANGED
@@ -14,6 +14,8 @@
14
14
 
15
15
  """A simplified time-slice of operations within a sequenced circuit."""
16
16
 
17
+ from __future__ import annotations
18
+
17
19
  import itertools
18
20
  from functools import cached_property
19
21
  from types import NotImplementedType
@@ -55,7 +57,7 @@ text_diagram_drawer = LazyLoader(
55
57
  )
56
58
 
57
59
 
58
- def _default_breakdown(qid: 'cirq.Qid') -> Tuple[Any, Any]:
60
+ def _default_breakdown(qid: cirq.Qid) -> Tuple[Any, Any]:
59
61
  # Attempt to convert into a position on the complex plane.
60
62
  try:
61
63
  plane_pos = complex(qid) # type: ignore
@@ -82,7 +84,7 @@ class Moment:
82
84
  are no such operations, returns an empty Moment.
83
85
  """
84
86
 
85
- def __init__(self, *contents: 'cirq.OP_TREE', _flatten_contents: bool = True) -> None:
87
+ def __init__(self, *contents: cirq.OP_TREE, _flatten_contents: bool = True) -> None:
86
88
  """Constructs a moment with the given operations.
87
89
 
88
90
  Args:
@@ -102,10 +104,10 @@ class Moment:
102
104
  if _flatten_contents
103
105
  else cast(Tuple['cirq.Operation'], contents)
104
106
  )
105
- self._sorted_operations: Optional[Tuple['cirq.Operation', ...]] = None
107
+ self._sorted_operations: Optional[Tuple[cirq.Operation, ...]] = None
106
108
 
107
109
  # An internal dictionary to support efficient operation access by qubit.
108
- self._qubit_to_op: Dict['cirq.Qid', 'cirq.Operation'] = {}
110
+ self._qubit_to_op: Dict[cirq.Qid, cirq.Operation] = {}
109
111
  for op in self.operations:
110
112
  for q in op.qubits:
111
113
  # Check that operations don't overlap.
@@ -113,11 +115,11 @@ class Moment:
113
115
  raise ValueError(f'Overlapping operations: {self.operations}')
114
116
  self._qubit_to_op[q] = op
115
117
 
116
- self._measurement_key_objs: Optional[FrozenSet['cirq.MeasurementKey']] = None
117
- self._control_keys: Optional[FrozenSet['cirq.MeasurementKey']] = None
118
+ self._measurement_key_objs: Optional[FrozenSet[cirq.MeasurementKey]] = None
119
+ self._control_keys: Optional[FrozenSet[cirq.MeasurementKey]] = None
118
120
 
119
121
  @classmethod
120
- def from_ops(cls, *ops: 'cirq.Operation') -> 'cirq.Moment':
122
+ def from_ops(cls, *ops: cirq.Operation) -> cirq.Moment:
121
123
  """Construct a Moment from the given operations.
122
124
 
123
125
  This avoids calling `flatten_to_ops` in the moment constructor, which
@@ -131,14 +133,14 @@ class Moment:
131
133
  return cls(*ops, _flatten_contents=False)
132
134
 
133
135
  @property
134
- def operations(self) -> Tuple['cirq.Operation', ...]:
136
+ def operations(self) -> Tuple[cirq.Operation, ...]:
135
137
  return self._operations
136
138
 
137
139
  @cached_property
138
- def qubits(self) -> FrozenSet['cirq.Qid']:
140
+ def qubits(self) -> FrozenSet[cirq.Qid]:
139
141
  return frozenset(self._qubit_to_op)
140
142
 
141
- def operates_on_single_qubit(self, qubit: 'cirq.Qid') -> bool:
143
+ def operates_on_single_qubit(self, qubit: cirq.Qid) -> bool:
142
144
  """Determines if the moment has operations touching the given qubit.
143
145
  Args:
144
146
  qubit: The qubit that may or may not be touched by operations.
@@ -147,7 +149,7 @@ class Moment:
147
149
  """
148
150
  return qubit in self._qubit_to_op
149
151
 
150
- def operates_on(self, qubits: Iterable['cirq.Qid']) -> bool:
152
+ def operates_on(self, qubits: Iterable[cirq.Qid]) -> bool:
151
153
  """Determines if the moment has operations touching the given qubits.
152
154
 
153
155
  Args:
@@ -158,7 +160,7 @@ class Moment:
158
160
  """
159
161
  return not self._qubit_to_op.keys().isdisjoint(qubits)
160
162
 
161
- def operation_at(self, qubit: raw_types.Qid) -> Optional['cirq.Operation']:
163
+ def operation_at(self, qubit: raw_types.Qid) -> Optional[cirq.Operation]:
162
164
  """Returns the operation on a certain qubit for the moment.
163
165
 
164
166
  Args:
@@ -172,7 +174,7 @@ class Moment:
172
174
  return self.__getitem__(qubit)
173
175
  return None
174
176
 
175
- def with_operation(self, operation: 'cirq.Operation') -> 'cirq.Moment':
177
+ def with_operation(self, operation: cirq.Operation) -> cirq.Moment:
176
178
  """Returns an equal moment, but with the given op added.
177
179
 
178
180
  Args:
@@ -200,7 +202,7 @@ class Moment:
200
202
 
201
203
  return m
202
204
 
203
- def with_operations(self, *contents: 'cirq.OP_TREE') -> 'cirq.Moment':
205
+ def with_operations(self, *contents: cirq.OP_TREE) -> cirq.Moment:
204
206
  """Returns a new moment with the given contents added.
205
207
 
206
208
  Args:
@@ -237,7 +239,7 @@ class Moment:
237
239
 
238
240
  return m
239
241
 
240
- def without_operations_touching(self, qubits: Iterable['cirq.Qid']) -> 'cirq.Moment':
242
+ def without_operations_touching(self, qubits: Iterable[cirq.Qid]) -> cirq.Moment:
241
243
  """Returns an equal moment, but without ops on the given qubits.
242
244
 
243
245
  Args:
@@ -263,11 +265,9 @@ class Moment:
263
265
  def _parameter_names_(self) -> AbstractSet[str]:
264
266
  return {name for op in self for name in protocols.parameter_names(op)}
265
267
 
266
- def _resolve_parameters_(
267
- self, resolver: 'cirq.ParamResolver', recursive: bool
268
- ) -> 'cirq.Moment':
268
+ def _resolve_parameters_(self, resolver: cirq.ParamResolver, recursive: bool) -> cirq.Moment:
269
269
  changed = False
270
- resolved_ops: List['cirq.Operation'] = []
270
+ resolved_ops: List[cirq.Operation] = []
271
271
  for op in self:
272
272
  resolved_op = protocols.resolve_parameters(op, resolver, recursive)
273
273
  changed = (
@@ -294,21 +294,21 @@ class Moment:
294
294
  def _measurement_key_names_(self) -> FrozenSet[str]:
295
295
  return frozenset(str(key) for key in self._measurement_key_objs_())
296
296
 
297
- def _measurement_key_objs_(self) -> FrozenSet['cirq.MeasurementKey']:
297
+ def _measurement_key_objs_(self) -> FrozenSet[cirq.MeasurementKey]:
298
298
  if self._measurement_key_objs is None:
299
299
  self._measurement_key_objs = frozenset(
300
300
  key for op in self.operations for key in protocols.measurement_key_objs(op)
301
301
  )
302
302
  return self._measurement_key_objs
303
303
 
304
- def _control_keys_(self) -> FrozenSet['cirq.MeasurementKey']:
304
+ def _control_keys_(self) -> FrozenSet[cirq.MeasurementKey]:
305
305
  if self._control_keys is None:
306
306
  self._control_keys = frozenset(
307
307
  k for op in self.operations for k in protocols.control_keys(op)
308
308
  )
309
309
  return self._control_keys
310
310
 
311
- def _sorted_operations_(self) -> Tuple['cirq.Operation', ...]:
311
+ def _sorted_operations_(self) -> Tuple[cirq.Operation, ...]:
312
312
  if self._sorted_operations is None:
313
313
  self._sorted_operations = tuple(sorted(self._operations, key=lambda op: op.qubits))
314
314
  return self._sorted_operations
@@ -330,7 +330,7 @@ class Moment:
330
330
  )
331
331
 
332
332
  def _with_rescoped_keys_(
333
- self, path: Tuple[str, ...], bindable_keys: FrozenSet['cirq.MeasurementKey']
333
+ self, path: Tuple[str, ...], bindable_keys: FrozenSet[cirq.MeasurementKey]
334
334
  ):
335
335
  return Moment(
336
336
  protocols.with_rescoped_keys(op, path, bindable_keys) for op in self.operations
@@ -373,7 +373,7 @@ class Moment:
373
373
  del state[hash_attr]
374
374
  return state
375
375
 
376
- def __iter__(self) -> Iterator['cirq.Operation']:
376
+ def __iter__(self) -> Iterator[cirq.Operation]:
377
377
  return iter(self.operations)
378
378
 
379
379
  def __pow__(self, power):
@@ -402,12 +402,12 @@ class Moment:
402
402
  def __str__(self) -> str:
403
403
  return self.to_text_diagram()
404
404
 
405
- def _decompose_(self) -> 'cirq.OP_TREE':
405
+ def _decompose_(self) -> cirq.OP_TREE:
406
406
  """See `cirq.SupportsDecompose`."""
407
407
  return self._operations
408
408
 
409
409
  def transform_qubits(
410
- self, qubit_map: Union[Dict['cirq.Qid', 'cirq.Qid'], Callable[['cirq.Qid'], 'cirq.Qid']]
410
+ self, qubit_map: Union[Dict[cirq.Qid, cirq.Qid], Callable[[cirq.Qid], cirq.Qid]]
411
411
  ) -> Self:
412
412
  """Returns the same moment, but with different qubits.
413
413
 
@@ -421,7 +421,7 @@ class Moment:
421
421
  """
422
422
  return self.__class__(op.transform_qubits(qubit_map) for op in self.operations)
423
423
 
424
- def expand_to(self, qubits: Iterable['cirq.Qid']) -> 'cirq.Moment':
424
+ def expand_to(self, qubits: Iterable[cirq.Qid]) -> cirq.Moment:
425
425
  """Returns self expanded to given superset of qubits by making identities explicit.
426
426
 
427
427
  Args:
@@ -480,13 +480,13 @@ class Moment:
480
480
  qubit_to_row_subscript = dict(zip(qubits, 'abcdefghij'))
481
481
  qubit_to_col_subscript = dict(zip(qubits, 'ABCDEFGHIJ'))
482
482
 
483
- def row_subscripts(qs: Sequence['cirq.Qid']) -> str:
483
+ def row_subscripts(qs: Sequence[cirq.Qid]) -> str:
484
484
  return ''.join(qubit_to_row_subscript[q] for q in qs)
485
485
 
486
- def col_subscripts(qs: Sequence['cirq.Qid']) -> str:
486
+ def col_subscripts(qs: Sequence[cirq.Qid]) -> str:
487
487
  return ''.join(qubit_to_col_subscript[q] for q in qs)
488
488
 
489
- def kraus_tensors(op: 'cirq.Operation') -> Sequence[np.ndarray]:
489
+ def kraus_tensors(op: cirq.Operation) -> Sequence[np.ndarray]:
490
490
  return tuple(np.reshape(k, (2, 2) * len(op.qubits)) for k in protocols.kraus(op))
491
491
 
492
492
  input_subscripts = ','.join(
@@ -523,12 +523,12 @@ class Moment:
523
523
  def _from_json_dict_(cls, operations, **kwargs):
524
524
  return cls.from_ops(*operations)
525
525
 
526
- def __add__(self, other: 'cirq.OP_TREE') -> 'cirq.Moment':
526
+ def __add__(self, other: cirq.OP_TREE) -> cirq.Moment:
527
527
  if isinstance(other, circuit.AbstractCircuit):
528
528
  return NotImplemented # Delegate to Circuit.__radd__.
529
529
  return self.with_operations(other)
530
530
 
531
- def __sub__(self, other: 'cirq.OP_TREE') -> 'cirq.Moment':
531
+ def __sub__(self, other: cirq.OP_TREE) -> cirq.Moment:
532
532
  must_remove = set(op_tree.flatten_to_ops(other))
533
533
  new_ops = []
534
534
  for op in self.operations:
@@ -546,11 +546,11 @@ class Moment:
546
546
 
547
547
  # pylint: disable=function-redefined
548
548
  @overload
549
- def __getitem__(self, key: raw_types.Qid) -> 'cirq.Operation':
549
+ def __getitem__(self, key: raw_types.Qid) -> cirq.Operation:
550
550
  pass
551
551
 
552
552
  @overload
553
- def __getitem__(self, key: Iterable[raw_types.Qid]) -> 'cirq.Moment':
553
+ def __getitem__(self, key: Iterable[raw_types.Qid]) -> cirq.Moment:
554
554
  pass
555
555
 
556
556
  def __getitem__(self, key):
@@ -567,10 +567,10 @@ class Moment:
567
567
  return Moment(frozenset(ops_to_keep))
568
568
 
569
569
  def to_text_diagram(
570
- self: 'cirq.Moment',
570
+ self: cirq.Moment,
571
571
  *,
572
- xy_breakdown_func: Callable[['cirq.Qid'], Tuple[Any, Any]] = _default_breakdown,
573
- extra_qubits: Iterable['cirq.Qid'] = (),
572
+ xy_breakdown_func: Callable[[cirq.Qid], Tuple[Any, Any]] = _default_breakdown,
573
+ extra_qubits: Iterable[cirq.Qid] = (),
574
574
  use_unicode_characters: bool = True,
575
575
  precision: Optional[int] = None,
576
576
  include_tags: bool = True,
@@ -13,6 +13,9 @@
13
13
  # limitations under the License.
14
14
 
15
15
  """Defines the OptimizationPass type."""
16
+
17
+ from __future__ import annotations
18
+
16
19
  import abc
17
20
  from collections import defaultdict
18
21
  from typing import Callable, cast, Dict, Iterable, Optional, Sequence, Tuple, TYPE_CHECKING
@@ -21,7 +24,6 @@ from cirq import ops
21
24
 
22
25
  if TYPE_CHECKING:
23
26
  import cirq
24
- from cirq.ops import Qid
25
27
 
26
28
 
27
29
  class PointOptimizationSummary:
@@ -30,8 +32,8 @@ class PointOptimizationSummary:
30
32
  def __init__(
31
33
  self,
32
34
  clear_span: int,
33
- clear_qubits: Iterable['cirq.Qid'],
34
- new_operations: 'cirq.OP_TREE',
35
+ clear_qubits: Iterable[cirq.Qid],
36
+ new_operations: cirq.OP_TREE,
35
37
  preserve_moments: bool = False,
36
38
  ) -> None:
37
39
  """Inits PointOptimizationSummary.
@@ -87,9 +89,7 @@ class PointOptimizer:
87
89
 
88
90
  def __init__(
89
91
  self,
90
- post_clean_up: Callable[
91
- [Sequence['cirq.Operation']], 'cirq.OP_TREE'
92
- ] = lambda op_list: op_list,
92
+ post_clean_up: Callable[[Sequence[cirq.Operation]], cirq.OP_TREE] = lambda op_list: op_list,
93
93
  ) -> None:
94
94
  """Inits PointOptimizer.
95
95
 
@@ -100,13 +100,13 @@ class PointOptimizer:
100
100
  """
101
101
  self.post_clean_up = post_clean_up
102
102
 
103
- def __call__(self, circuit: 'cirq.Circuit'):
103
+ def __call__(self, circuit: cirq.Circuit):
104
104
  return self.optimize_circuit(circuit)
105
105
 
106
106
  @abc.abstractmethod
107
107
  def optimization_at(
108
- self, circuit: 'cirq.Circuit', index: int, op: 'cirq.Operation'
109
- ) -> Optional['cirq.PointOptimizationSummary']:
108
+ self, circuit: cirq.Circuit, index: int, op: cirq.Operation
109
+ ) -> Optional[cirq.PointOptimizationSummary]:
110
110
  """Describes how to change operations near the given location.
111
111
 
112
112
  For example, this method could realize that the given operation is an
@@ -126,8 +126,8 @@ class PointOptimizer:
126
126
  change should be made.
127
127
  """
128
128
 
129
- def optimize_circuit(self, circuit: 'cirq.Circuit'):
130
- frontier: Dict['Qid', int] = defaultdict(lambda: 0)
129
+ def optimize_circuit(self, circuit: cirq.Circuit):
130
+ frontier: Dict[cirq.Qid, int] = defaultdict(lambda: 0)
131
131
  i = 0
132
132
  while i < len(circuit): # Note: circuit may mutate as we go.
133
133
  for op in circuit[i].operations:
@@ -11,7 +11,8 @@
11
11
  # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
- from typing import List, Optional, Set, TYPE_CHECKING
14
+
15
+ from typing import List, Optional, Set
15
16
 
16
17
  import pytest
17
18
 
@@ -19,9 +20,6 @@ import cirq
19
20
  from cirq import Operation, PointOptimizationSummary, PointOptimizer
20
21
  from cirq.testing import EqualsTester
21
22
 
22
- if TYPE_CHECKING:
23
- import cirq
24
-
25
23
 
26
24
  def test_equality():
27
25
  a = cirq.NamedQubit('a')
@@ -63,8 +61,8 @@ class ReplaceWithXGates(PointOptimizer):
63
61
  """
64
62
 
65
63
  def optimization_at(
66
- self, circuit: 'cirq.Circuit', index: int, op: 'cirq.Operation'
67
- ) -> Optional['cirq.PointOptimizationSummary']:
64
+ self, circuit: cirq.Circuit, index: int, op: cirq.Operation
65
+ ) -> Optional[cirq.PointOptimizationSummary]:
68
66
  end = index + 1
69
67
  new_ops = [cirq.X(q) for q in op.qubits]
70
68
  done = False
@@ -157,8 +155,8 @@ def test_point_optimizer_raises_on_gates_changing_qubits():
157
155
  """Changes all single qubit operations to act on LineQubit(42)"""
158
156
 
159
157
  def optimization_at(
160
- self, circuit: 'cirq.Circuit', index: int, op: 'cirq.Operation'
161
- ) -> Optional['cirq.PointOptimizationSummary']:
158
+ self, circuit: cirq.Circuit, index: int, op: cirq.Operation
159
+ ) -> Optional[cirq.PointOptimizationSummary]:
162
160
  new_op = op
163
161
  if len(op.qubits) == 1 and isinstance(op, cirq.GateOperation):
164
162
  new_op = op.gate(cirq.LineQubit(42))
@@ -14,6 +14,8 @@
14
14
 
15
15
  """Utility classes for representing QASM."""
16
16
 
17
+ from __future__ import annotations
18
+
17
19
  import re
18
20
  from typing import Callable, Dict, Iterator, Optional, Sequence, Tuple, TYPE_CHECKING, Union
19
21
 
@@ -46,14 +48,14 @@ class QasmUGate(ops.Gate):
46
48
  return 1
47
49
 
48
50
  @staticmethod
49
- def from_matrix(mat: np.ndarray) -> 'QasmUGate':
51
+ def from_matrix(mat: np.ndarray) -> QasmUGate:
50
52
  pre_phase, rotation, post_phase = linalg.deconstruct_single_qubit_matrix_into_angles(mat)
51
53
  return QasmUGate(rotation / np.pi, post_phase / np.pi, pre_phase / np.pi)
52
54
 
53
55
  def _has_unitary_(self):
54
56
  return True
55
57
 
56
- def _qasm_(self, qubits: Tuple['cirq.Qid', ...], args: 'cirq.QasmArgs') -> str:
58
+ def _qasm_(self, qubits: Tuple[cirq.Qid, ...], args: cirq.QasmArgs) -> str:
57
59
  args.validate_version('2.0', '3.0')
58
60
  return args.format(
59
61
  'u3({0:half_turns},{1:half_turns},{2:half_turns}) {3};\n',
@@ -86,13 +88,13 @@ class QasmUGate(ops.Gate):
86
88
  return {'theta': self.theta, 'phi': self.phi, 'lmda': self.lmda}
87
89
 
88
90
  @classmethod
89
- def _from_json_dict_(cls, theta: float, phi: float, lmda: float, **kwargs) -> 'QasmUGate':
91
+ def _from_json_dict_(cls, theta: float, phi: float, lmda: float, **kwargs) -> QasmUGate:
90
92
  return cls(theta, phi, lmda)
91
93
 
92
94
 
93
95
  @value.value_equality
94
96
  class QasmTwoQubitGate(ops.Gate):
95
- def __init__(self, kak: 'cirq.KakDecomposition') -> None:
97
+ def __init__(self, kak: cirq.KakDecomposition) -> None:
96
98
  """A two qubit gate represented in QASM by the KAK decomposition.
97
99
 
98
100
  All angles are in half turns. Assumes a canonicalized KAK
@@ -110,7 +112,7 @@ class QasmTwoQubitGate(ops.Gate):
110
112
  return self.kak
111
113
 
112
114
  @staticmethod
113
- def from_matrix(mat: np.ndarray, atol=1e-8) -> 'QasmTwoQubitGate':
115
+ def from_matrix(mat: np.ndarray, atol=1e-8) -> QasmTwoQubitGate:
114
116
  """Creates a QasmTwoQubitGate from the given matrix.
115
117
 
116
118
  Args:
@@ -126,7 +128,7 @@ class QasmTwoQubitGate(ops.Gate):
126
128
  def _unitary_(self):
127
129
  return protocols.unitary(self.kak)
128
130
 
129
- def _decompose_(self, qubits: Sequence['cirq.Qid']) -> Iterator['cirq.OP_TREE']:
131
+ def _decompose_(self, qubits: Sequence[cirq.Qid]) -> Iterator[cirq.OP_TREE]:
130
132
  q0, q1 = qubits
131
133
  x, y, z = self.kak.interaction_coefficients
132
134
  a = x * -2 / np.pi + 0.5
@@ -170,8 +172,8 @@ class QasmOutput:
170
172
 
171
173
  def __init__(
172
174
  self,
173
- operations: 'cirq.OP_TREE',
174
- qubits: Tuple['cirq.Qid', ...],
175
+ operations: cirq.OP_TREE,
176
+ qubits: Tuple[cirq.Qid, ...],
175
177
  header: str = '',
176
178
  precision: int = 10,
177
179
  version: str = '2.0',
@@ -225,7 +227,7 @@ class QasmOutput:
225
227
  meas_key_id_map[key] = meas_id
226
228
  return meas_key_id_map, meas_comments
227
229
 
228
- def _generate_qubit_ids(self) -> Dict['cirq.Qid', str]:
230
+ def _generate_qubit_ids(self) -> Dict[cirq.Qid, str]:
229
231
  return {qubit: f'q[{i}]' for i, qubit in enumerate(self.qubits)}
230
232
 
231
233
  def _generate_cregs(self, meas_key_id_map: Dict[str, str]) -> Dict[str, tuple[int, str]]:
@@ -333,11 +335,11 @@ class QasmOutput:
333
335
 
334
336
  def _write_operations(
335
337
  self,
336
- op_tree: 'cirq.OP_TREE',
338
+ op_tree: cirq.OP_TREE,
337
339
  output: Callable[[str], None],
338
340
  output_line_gap: Callable[[int], None],
339
341
  ) -> None:
340
- def keep(op: 'cirq.Operation') -> bool:
342
+ def keep(op: cirq.Operation) -> bool:
341
343
  return protocols.qasm(op, args=self.args, default=None) is not None
342
344
 
343
345
  def fallback(op):
@@ -12,6 +12,8 @@
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
14
 
15
+ from __future__ import annotations
16
+
15
17
  from typing import (
16
18
  Any,
17
19
  Callable,
@@ -171,7 +173,7 @@ class TextDiagramDrawer:
171
173
  x1, x2 = sorted([x1, x2])
172
174
  self.horizontal_lines.append(_HorizontalLine(y, x1, x2, emphasize, doubled))
173
175
 
174
- def transpose(self) -> 'cirq.TextDiagramDrawer':
176
+ def transpose(self) -> cirq.TextDiagramDrawer:
175
177
  """Returns the same diagram, but mirrored across its diagonal."""
176
178
  out = TextDiagramDrawer()
177
179
  out.entries = {
@@ -333,14 +335,14 @@ class TextDiagramDrawer:
333
335
  horizontal_padding=self.horizontal_padding,
334
336
  )
335
337
 
336
- def shift(self, dx: int = 0, dy: int = 0) -> 'cirq.TextDiagramDrawer':
338
+ def shift(self, dx: int = 0, dy: int = 0) -> cirq.TextDiagramDrawer:
337
339
  self._transform_coordinates(lambda x, y: (x + dx, y + dy))
338
340
  return self
339
341
 
340
- def shifted(self, dx: int = 0, dy: int = 0) -> 'cirq.TextDiagramDrawer':
342
+ def shifted(self, dx: int = 0, dy: int = 0) -> cirq.TextDiagramDrawer:
341
343
  return self.copy().shift(dx, dy)
342
344
 
343
- def superimpose(self, other: 'cirq.TextDiagramDrawer') -> 'cirq.TextDiagramDrawer':
345
+ def superimpose(self, other: cirq.TextDiagramDrawer) -> cirq.TextDiagramDrawer:
344
346
  self.entries.update(other.entries)
345
347
  self.horizontal_lines += other.horizontal_lines
346
348
  self.vertical_lines += other.vertical_lines
@@ -348,13 +350,13 @@ class TextDiagramDrawer:
348
350
  self.vertical_padding.update(other.vertical_padding)
349
351
  return self
350
352
 
351
- def superimposed(self, other: 'cirq.TextDiagramDrawer') -> 'cirq.TextDiagramDrawer':
353
+ def superimposed(self, other: cirq.TextDiagramDrawer) -> cirq.TextDiagramDrawer:
352
354
  return self.copy().superimpose(other)
353
355
 
354
356
  @classmethod
355
357
  def vstack(
356
358
  cls,
357
- diagrams: Sequence['cirq.TextDiagramDrawer'],
359
+ diagrams: Sequence[cirq.TextDiagramDrawer],
358
360
  padding_resolver: Optional[Callable[[Sequence[Optional[int]]], int]] = None,
359
361
  ):
360
362
  """Vertically stack text diagrams.
@@ -395,7 +397,7 @@ class TextDiagramDrawer:
395
397
  @classmethod
396
398
  def hstack(
397
399
  cls,
398
- diagrams: Sequence['cirq.TextDiagramDrawer'],
400
+ diagrams: Sequence[cirq.TextDiagramDrawer],
399
401
  padding_resolver: Optional[Callable[[Sequence[Optional[int]]], int]] = None,
400
402
  ):
401
403
  """Horizontally stack text diagrams.
@@ -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 enum
16
18
  import itertools
17
19
  from typing import Dict, Iterator, Sequence, Tuple, TYPE_CHECKING, Union
@@ -62,7 +64,7 @@ class BipartiteSwapNetworkGate(PermutationGate):
62
64
  self,
63
65
  subgraph: Union[str, BipartiteGraphType],
64
66
  part_size: int,
65
- swap_gate: 'cirq.Gate' = ops.SWAP,
67
+ swap_gate: cirq.Gate = ops.SWAP,
66
68
  ) -> None:
67
69
  super().__init__(2 * part_size, swap_gate)
68
70
  self.part_size = part_size
@@ -71,7 +73,7 @@ class BipartiteSwapNetworkGate(PermutationGate):
71
73
  )
72
74
  self.swap_gate = swap_gate
73
75
 
74
- def decompose_complete(self, qubits: Sequence['cirq.Qid']) -> Iterator['cirq.OP_TREE']:
76
+ def decompose_complete(self, qubits: Sequence[cirq.Qid]) -> Iterator[cirq.OP_TREE]:
75
77
  swap_gate = SwapPermutationGate(self.swap_gate)
76
78
  if self.part_size == 1:
77
79
  yield acquaint(*qubits)
@@ -86,7 +88,7 @@ class BipartiteSwapNetworkGate(PermutationGate):
86
88
  yield acquaint(*qubits[x : x + 2])
87
89
  yield swap_gate(*qubits[x : x + 2])
88
90
 
89
- def decompose_matching(self, qubits: Sequence['cirq.Qid']) -> Iterator['cirq.OP_TREE']:
91
+ def decompose_matching(self, qubits: Sequence[cirq.Qid]) -> Iterator[cirq.OP_TREE]:
90
92
  swap_gate = SwapPermutationGate(self.swap_gate)
91
93
  for k in range(-self.part_size + 1, self.part_size):
92
94
  for x in range(abs(k), 2 * self.part_size - abs(k), 2):
@@ -95,7 +97,7 @@ class BipartiteSwapNetworkGate(PermutationGate):
95
97
  else:
96
98
  yield acquaint(*qubits[x : x + 2])
97
99
 
98
- def _decompose_(self, qubits: Sequence['cirq.Qid']) -> 'cirq.OP_TREE':
100
+ def _decompose_(self, qubits: Sequence[cirq.Qid]) -> cirq.OP_TREE:
99
101
  if len(qubits) != 2 * self.part_size:
100
102
  raise ValueError('len(qubits) != 2 * self.part_size')
101
103
  if self.subgraph == BipartiteGraphType.COMPLETE:
@@ -122,7 +124,7 @@ class BipartiteSwapNetworkGate(PermutationGate):
122
124
  return dict(enumerate(range(2 * self.part_size)))
123
125
  raise NotImplementedError(str(self.subgraph) + 'not implemented')
124
126
 
125
- def _circuit_diagram_info_(self, args: 'cirq.CircuitDiagramInfoArgs') -> Tuple[str, ...]:
127
+ def _circuit_diagram_info_(self, args: cirq.CircuitDiagramInfoArgs) -> Tuple[str, ...]:
126
128
  qubit_count = 2 * self.part_size
127
129
  if args.known_qubit_count not in (None, qubit_count):
128
130
  raise ValueError('args.known_qubit_count not in (None, 2 * self.part_size)')
@@ -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 TYPE_CHECKING, Union
17
19
 
@@ -30,7 +32,7 @@ class AcquaintanceDevice(devices.Device, metaclass=abc.ABCMeta):
30
32
 
31
33
  gate_types = (AcquaintanceOpportunityGate, PermutationGate)
32
34
 
33
- def validate_operation(self, operation: 'cirq.Operation') -> None:
35
+ def validate_operation(self, operation: cirq.Operation) -> None:
34
36
  if not (
35
37
  isinstance(operation, ops.GateOperation) and isinstance(operation.gate, self.gate_types)
36
38
  ):