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
@@ -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 collections import defaultdict
17
19
  from typing import DefaultDict, Dict, Iterator, Optional, Sequence, TYPE_CHECKING
@@ -42,7 +44,7 @@ class ExecutionStrategy(metaclass=abc.ABCMeta):
42
44
 
43
45
  @property
44
46
  @abc.abstractmethod
45
- def device(self) -> 'cirq.Device':
47
+ def device(self) -> cirq.Device:
46
48
  """The device for which the executed acquaintance strategy should be
47
49
  valid.
48
50
  """
@@ -54,8 +56,8 @@ class ExecutionStrategy(metaclass=abc.ABCMeta):
54
56
 
55
57
  @abc.abstractmethod
56
58
  def get_operations(
57
- self, indices: Sequence[LogicalIndex], qubits: Sequence['cirq.Qid']
58
- ) -> 'cirq.OP_TREE':
59
+ self, indices: Sequence[LogicalIndex], qubits: Sequence[cirq.Qid]
60
+ ) -> cirq.OP_TREE:
59
61
  """Gets the logical operations to apply to qubits."""
60
62
 
61
63
  def __call__(self, *args, **kwargs):
@@ -97,13 +99,13 @@ class StrategyExecutorTransformer:
97
99
  self._mapping = execution_strategy.initial_mapping.copy()
98
100
 
99
101
  def __call__(
100
- self, circuit: circuits.AbstractCircuit, context: Optional['cirq.TransformerContext'] = None
102
+ self, circuit: circuits.AbstractCircuit, context: Optional[cirq.TransformerContext] = None
101
103
  ) -> circuits.Circuit:
102
104
  """Executes an acquaintance strategy using cirq.map_operations_and_unroll and
103
105
  mutates initial mapping.
104
106
 
105
107
  Args:
106
- circuit: 'cirq.Circuit' input circuit to transform.
108
+ circuit: `cirq.Circuit` input circuit to transform.
107
109
  context: `cirq.TransformerContext` storing common configurable
108
110
  options for transformers.
109
111
 
@@ -126,7 +128,7 @@ class StrategyExecutorTransformer:
126
128
  def mapping(self) -> LogicalMapping:
127
129
  return self._mapping
128
130
 
129
- def _map_func(self, op: 'cirq.Operation', index) -> 'cirq.OP_TREE':
131
+ def _map_func(self, op: cirq.Operation, index) -> cirq.OP_TREE:
130
132
  if isinstance(op.gate, AcquaintanceOpportunityGate):
131
133
  logical_indices = tuple(self._mapping[q] for q in op.qubits)
132
134
  logical_operations = self.execution_strategy.get_operations(logical_indices, op.qubits)
@@ -150,17 +152,13 @@ class AcquaintanceOperation(ops.GateOperation):
150
152
  logical indices on a particular set of physical qubits.
151
153
  """
152
154
 
153
- def __init__(
154
- self, qubits: Sequence['cirq.Qid'], logical_indices: Sequence[LogicalIndex]
155
- ) -> None:
155
+ def __init__(self, qubits: Sequence[cirq.Qid], logical_indices: Sequence[LogicalIndex]) -> None:
156
156
  if len(logical_indices) != len(qubits):
157
157
  raise ValueError('len(logical_indices) != len(qubits)')
158
158
  super().__init__(AcquaintanceOpportunityGate(num_qubits=len(qubits)), qubits)
159
159
  self.logical_indices: LogicalIndexSequence = logical_indices
160
160
 
161
- def _circuit_diagram_info_(
162
- self, args: 'cirq.CircuitDiagramInfoArgs'
163
- ) -> 'cirq.CircuitDiagramInfo':
161
+ def _circuit_diagram_info_(self, args: cirq.CircuitDiagramInfoArgs) -> cirq.CircuitDiagramInfo:
164
162
  wire_symbols = tuple(f'({i})' for i in self.logical_indices)
165
163
  return protocols.CircuitDiagramInfo(wire_symbols=wire_symbols)
166
164
 
@@ -176,7 +174,7 @@ class GreedyExecutionStrategy(ExecutionStrategy):
176
174
  self,
177
175
  gates: LogicalGates,
178
176
  initial_mapping: LogicalMapping,
179
- device: Optional['cirq.Device'] = None,
177
+ device: Optional[cirq.Device] = None,
180
178
  ) -> None:
181
179
  """Inits GreedyExecutionStrategy.
182
180
 
@@ -202,12 +200,12 @@ class GreedyExecutionStrategy(ExecutionStrategy):
202
200
  return self._initial_mapping
203
201
 
204
202
  @property
205
- def device(self) -> 'cirq.Device':
203
+ def device(self) -> cirq.Device:
206
204
  return self._device
207
205
 
208
206
  def get_operations(
209
- self, indices: Sequence[LogicalIndex], qubits: Sequence['cirq.Qid']
210
- ) -> Iterator['cirq.OP_TREE']:
207
+ self, indices: Sequence[LogicalIndex], qubits: Sequence[cirq.Qid]
208
+ ) -> Iterator[cirq.OP_TREE]:
211
209
  index_set = frozenset(indices)
212
210
  if index_set in self.index_set_to_gates:
213
211
  gates = self.index_set_to_gates.pop(index_set)
@@ -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 functools
16
18
  import itertools
17
19
  import math
@@ -41,13 +43,11 @@ if TYPE_CHECKING:
41
43
 
42
44
 
43
45
  def operations_to_part_lens(
44
- qubit_order: Sequence['cirq.Qid'], op_tree: 'cirq.OP_TREE'
46
+ qubit_order: Sequence[cirq.Qid], op_tree: cirq.OP_TREE
45
47
  ) -> Tuple[int, ...]:
46
48
  qubit_sort_key = functools.partial(operator.indexOf, qubit_order)
47
49
  op_parts = [tuple(sorted(op.qubits, key=qubit_sort_key)) for op in ops.flatten_op_tree(op_tree)]
48
- singletons: List[Tuple['cirq.Qid', ...]] = [
49
- (q,) for q in set(qubit_order).difference(*op_parts)
50
- ]
50
+ singletons: List[Tuple[cirq.Qid, ...]] = [(q,) for q in set(qubit_order).difference(*op_parts)]
51
51
  part_sort_key = lambda p: min(qubit_sort_key(q) for q in p)
52
52
  parts = tuple(tuple(part) for part in sorted(singletons + op_parts, key=part_sort_key))
53
53
 
@@ -71,7 +71,7 @@ class AcquaintanceOpportunityGate(ops.Gate, ops.InterchangeableQubitsGate):
71
71
  f'num_qubits={self.num_qubits()!r})'
72
72
  )
73
73
 
74
- def _circuit_diagram_info_(self, args: 'cirq.CircuitDiagramInfoArgs') -> Iterable[str]:
74
+ def _circuit_diagram_info_(self, args: cirq.CircuitDiagramInfoArgs) -> Iterable[str]:
75
75
  wire_symbol = '█' if args.use_unicode_characters else 'Acq'
76
76
  wire_symbols = (wire_symbol,) * self.num_qubits()
77
77
  return wire_symbols
@@ -80,7 +80,7 @@ class AcquaintanceOpportunityGate(ops.Gate, ops.InterchangeableQubitsGate):
80
80
  return self._num_qubits
81
81
 
82
82
 
83
- def acquaint(*qubits) -> 'cirq.Operation':
83
+ def acquaint(*qubits) -> cirq.Operation:
84
84
  return AcquaintanceOpportunityGate(len(qubits)).on(*qubits)
85
85
 
86
86
 
@@ -96,14 +96,14 @@ Layers = NamedTuple(
96
96
  )
97
97
 
98
98
 
99
- def new_layers(**kwargs: List['cirq.Operation']) -> Layers:
99
+ def new_layers(**kwargs: List[cirq.Operation]) -> Layers:
100
100
  return Layers._make(kwargs.get(field, []) for field in Layers._fields)
101
101
 
102
102
 
103
103
  def acquaint_insides(
104
- swap_gate: 'cirq.Gate',
105
- acquaintance_gate: 'cirq.Operation',
106
- qubits: Sequence['cirq.Qid'],
104
+ swap_gate: cirq.Gate,
105
+ acquaintance_gate: cirq.Operation,
106
+ qubits: Sequence[cirq.Qid],
107
107
  before: bool,
108
108
  layers: Layers,
109
109
  mapping: Dict[ops.Qid, int],
@@ -153,10 +153,10 @@ def _get_max_reach(size: int, round_up: bool = True) -> int:
153
153
 
154
154
 
155
155
  def acquaint_and_shift(
156
- parts: Tuple[List['cirq.Qid'], List['cirq.Qid']],
156
+ parts: Tuple[List[cirq.Qid], List[cirq.Qid]],
157
157
  layers: Layers,
158
158
  acquaintance_size: Optional[int],
159
- swap_gate: 'cirq.Gate',
159
+ swap_gate: cirq.Gate,
160
160
  mapping: Dict[ops.Qid, int],
161
161
  ):
162
162
  """Acquaints and shifts a pair of lists of qubits. The first part is
@@ -277,7 +277,7 @@ class SwapNetworkGate(PermutationGate):
277
277
  self,
278
278
  part_lens: Sequence[int],
279
279
  acquaintance_size: Optional[int] = 0,
280
- swap_gate: 'cirq.Gate' = ops.SWAP,
280
+ swap_gate: cirq.Gate = ops.SWAP,
281
281
  ) -> None:
282
282
  super().__init__(sum(part_lens), swap_gate)
283
283
  if len(part_lens) < 2:
@@ -285,7 +285,7 @@ class SwapNetworkGate(PermutationGate):
285
285
  self.part_lens = tuple(part_lens)
286
286
  self.acquaintance_size = acquaintance_size
287
287
 
288
- def _decompose_(self, qubits: Sequence['cirq.Qid']) -> Iterator['cirq.OP_TREE']:
288
+ def _decompose_(self, qubits: Sequence[cirq.Qid]) -> Iterator[cirq.OP_TREE]:
289
289
  qubit_to_position = {q: i for i, q in enumerate(qubits)}
290
290
  mapping = dict(qubit_to_position)
291
291
  parts = []
@@ -333,9 +333,7 @@ class SwapNetworkGate(PermutationGate):
333
333
  if final_gate:
334
334
  yield final_gate(*qubits)
335
335
 
336
- def _circuit_diagram_info_(
337
- self, args: 'cirq.CircuitDiagramInfoArgs'
338
- ) -> 'cirq.CircuitDiagramInfo':
336
+ def _circuit_diagram_info_(self, args: cirq.CircuitDiagramInfoArgs) -> cirq.CircuitDiagramInfo:
339
337
  wire_symbol = '×' if args.use_unicode_characters else 'swap'
340
338
  wire_symbols = tuple(
341
339
  wire_symbol + f'({part_index},{qubit_index})'
@@ -346,11 +344,11 @@ class SwapNetworkGate(PermutationGate):
346
344
 
347
345
  @staticmethod
348
346
  def from_operations(
349
- qubit_order: Sequence['cirq.Qid'],
350
- operations: Sequence['cirq.Operation'],
347
+ qubit_order: Sequence[cirq.Qid],
348
+ operations: Sequence[cirq.Operation],
351
349
  acquaintance_size: Optional[int] = 0,
352
- swap_gate: 'cirq.Gate' = ops.SWAP,
353
- ) -> 'SwapNetworkGate':
350
+ swap_gate: cirq.Gate = ops.SWAP,
351
+ ) -> SwapNetworkGate:
354
352
  part_sizes = operations_to_part_lens(qubit_order, operations)
355
353
  return SwapNetworkGate(part_sizes, acquaintance_size, swap_gate)
356
354
 
@@ -12,16 +12,18 @@
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 FrozenSet, Iterator, Sequence, Set, TYPE_CHECKING
16
18
 
17
19
  from cirq import devices
18
20
  from cirq.contrib import circuitdag
19
21
  from cirq.contrib.acquaintance.executor import AcquaintanceOperation, ExecutionStrategy
20
22
  from cirq.contrib.acquaintance.mutation_utils import expose_acquaintance_gates
21
- from cirq.contrib.acquaintance.permutation import LogicalIndex, LogicalMapping
22
23
 
23
24
  if TYPE_CHECKING:
24
25
  import cirq
26
+ from cirq.contrib.acquaintance.permutation import LogicalIndex, LogicalMapping
25
27
 
26
28
 
27
29
  class LogicalAnnotator(ExecutionStrategy):
@@ -40,16 +42,16 @@ class LogicalAnnotator(ExecutionStrategy):
40
42
  return self._initial_mapping
41
43
 
42
44
  @property
43
- def device(self) -> 'cirq.Device':
45
+ def device(self) -> cirq.Device:
44
46
  return devices.UNCONSTRAINED_DEVICE
45
47
 
46
48
  def get_operations(
47
- self, indices: Sequence[LogicalIndex], qubits: Sequence['cirq.Qid']
48
- ) -> Iterator['cirq.OP_TREE']:
49
+ self, indices: Sequence[LogicalIndex], qubits: Sequence[cirq.Qid]
50
+ ) -> Iterator[cirq.OP_TREE]:
49
51
  yield AcquaintanceOperation(qubits, indices)
50
52
 
51
53
 
52
- def get_acquaintance_dag(strategy: 'cirq.Circuit', initial_mapping: LogicalMapping):
54
+ def get_acquaintance_dag(strategy: cirq.Circuit, initial_mapping: LogicalMapping):
53
55
  strategy = strategy.copy()
54
56
  expose_acquaintance_gates(strategy)
55
57
  LogicalAnnotator(initial_mapping)(strategy)
@@ -63,7 +65,7 @@ def get_acquaintance_dag(strategy: 'cirq.Circuit', initial_mapping: LogicalMappi
63
65
 
64
66
 
65
67
  def get_logical_acquaintance_opportunities(
66
- strategy: 'cirq.Circuit', initial_mapping: LogicalMapping
68
+ strategy: cirq.Circuit, initial_mapping: LogicalMapping
67
69
  ) -> Set[FrozenSet[LogicalIndex]]:
68
70
  acquaintance_dag = get_acquaintance_dag(strategy, initial_mapping)
69
71
  logical_acquaintance_opportunities = set()
@@ -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 collections
16
18
  from typing import cast, Dict, List, Optional, Sequence, TYPE_CHECKING, Union
17
19
 
@@ -26,7 +28,7 @@ if TYPE_CHECKING:
26
28
  STRATEGY_GATE = Union[AcquaintanceOpportunityGate, PermutationGate]
27
29
 
28
30
 
29
- def rectify_acquaintance_strategy(circuit: 'cirq.Circuit', acquaint_first: bool = True) -> None:
31
+ def rectify_acquaintance_strategy(circuit: cirq.Circuit, acquaint_first: bool = True) -> None:
30
32
  """Splits moments so that they contain either only acquaintance or permutation gates.
31
33
 
32
34
  Orders resulting moments so that the first one is of the same type as the previous one.
@@ -55,10 +57,10 @@ def rectify_acquaintance_strategy(circuit: 'cirq.Circuit', acquaint_first: bool
55
57
 
56
58
 
57
59
  def replace_acquaintance_with_swap_network(
58
- circuit: 'cirq.Circuit',
59
- qubit_order: Sequence['cirq.Qid'],
60
+ circuit: cirq.Circuit,
61
+ qubit_order: Sequence[cirq.Qid],
60
62
  acquaintance_size: Optional[int] = 0,
61
- swap_gate: 'cirq.Gate' = ops.SWAP,
63
+ swap_gate: cirq.Gate = ops.SWAP,
62
64
  ) -> bool:
63
65
  """Replace every rectified moment with acquaintance gates with a generalized swap network.
64
66
 
@@ -104,10 +106,10 @@ class ExposeAcquaintanceGates:
104
106
  not get_acquaintance_size(op) or isinstance(op.gate, AcquaintanceOpportunityGate)
105
107
  )
106
108
 
107
- def optimize_circuit(self, circuit: 'cirq.Circuit') -> None:
109
+ def optimize_circuit(self, circuit: cirq.Circuit) -> None:
108
110
  circuit._moments = [*transformers.expand_composite(circuit, no_decomp=self.no_decomp)]
109
111
 
110
- def __call__(self, circuit: 'cirq.Circuit') -> None:
112
+ def __call__(self, circuit: cirq.Circuit) -> None:
111
113
  self.optimize_circuit(circuit)
112
114
 
113
115
 
@@ -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 cast, FrozenSet, List, Sequence, Set, TYPE_CHECKING
16
18
 
17
19
  from cirq import circuits
@@ -24,7 +26,7 @@ if TYPE_CHECKING:
24
26
  import cirq
25
27
 
26
28
 
27
- def remove_redundant_acquaintance_opportunities(strategy: 'cirq.Circuit') -> int:
29
+ def remove_redundant_acquaintance_opportunities(strategy: cirq.Circuit) -> int:
28
30
  """Removes redundant acquaintance opportunities."""
29
31
 
30
32
  qubits = sorted(strategy.all_qubits())
@@ -34,11 +36,11 @@ def remove_redundant_acquaintance_opportunities(strategy: 'cirq.Circuit') -> int
34
36
  annotated_strategy = strategy.copy()
35
37
  LogicalAnnotator(mapping)(annotated_strategy)
36
38
 
37
- new_moments: List['cirq.Moment'] = []
39
+ new_moments: List[cirq.Moment] = []
38
40
  acquaintance_opps: Set[FrozenSet[int]] = set()
39
41
  n_removed = 0
40
42
  for moment in annotated_strategy:
41
- new_moment: List['cirq.Operation'] = []
43
+ new_moment: List[cirq.Operation] = []
42
44
  for op in moment:
43
45
  if isinstance(op, AcquaintanceOperation):
44
46
  opp = frozenset(cast(Sequence[int], op.logical_indices))
@@ -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 types import NotImplementedType
17
19
  from typing import (
@@ -51,7 +53,7 @@ class PermutationGate(ops.Gate, metaclass=abc.ABCMeta):
51
53
  qubits (e.g. SWAP or fermionic swap).
52
54
  """
53
55
 
54
- def __init__(self, num_qubits: int, swap_gate: 'cirq.Gate' = ops.SWAP) -> None:
56
+ def __init__(self, num_qubits: int, swap_gate: cirq.Gate = ops.SWAP) -> None:
55
57
  self._num_qubits = num_qubits
56
58
  self.swap_gate = swap_gate
57
59
 
@@ -64,7 +66,7 @@ class PermutationGate(ops.Gate, metaclass=abc.ABCMeta):
64
66
  the s[i]-th element."""
65
67
 
66
68
  def update_mapping(
67
- self, mapping: Dict[ops.Qid, LogicalIndex], keys: Sequence['cirq.Qid']
69
+ self, mapping: Dict[ops.Qid, LogicalIndex], keys: Sequence[cirq.Qid]
68
70
  ) -> None:
69
71
  """Updates a mapping (in place) from qubits to logical indices.
70
72
 
@@ -96,8 +98,8 @@ class PermutationGate(ops.Gate, metaclass=abc.ABCMeta):
96
98
  raise IndexError('key is out of bounds.')
97
99
 
98
100
  def _circuit_diagram_info_(
99
- self, args: 'cirq.CircuitDiagramInfoArgs'
100
- ) -> Union[str, Iterable[str], 'cirq.CircuitDiagramInfo']:
101
+ self, args: cirq.CircuitDiagramInfoArgs
102
+ ) -> Union[str, Iterable[str], cirq.CircuitDiagramInfo]:
101
103
  if args.known_qubit_count is None:
102
104
  return NotImplemented
103
105
  permutation = self.permutation()
@@ -118,14 +120,12 @@ class MappingDisplayGate(ops.Gate):
118
120
  def num_qubits(self) -> int:
119
121
  return self._num_qubits
120
122
 
121
- def _circuit_diagram_info_(
122
- self, args: 'cirq.CircuitDiagramInfoArgs'
123
- ) -> 'cirq.CircuitDiagramInfo':
123
+ def _circuit_diagram_info_(self, args: cirq.CircuitDiagramInfoArgs) -> cirq.CircuitDiagramInfo:
124
124
  wire_symbols = tuple('' if i is None else str(i) for i in self.indices)
125
125
  return protocols.CircuitDiagramInfo(wire_symbols, connected=False)
126
126
 
127
127
 
128
- def display_mapping(circuit: 'cirq.Circuit', initial_mapping: LogicalMapping) -> None:
128
+ def display_mapping(circuit: cirq.Circuit, initial_mapping: LogicalMapping) -> None:
129
129
  """Inserts display gates between moments to indicate the mapping throughout
130
130
  the circuit."""
131
131
  qubits = sorted(circuit.all_qubits())
@@ -147,13 +147,13 @@ def display_mapping(circuit: 'cirq.Circuit', initial_mapping: LogicalMapping) ->
147
147
  class SwapPermutationGate(PermutationGate):
148
148
  """Generic swap gate."""
149
149
 
150
- def __init__(self, swap_gate: 'cirq.Gate' = ops.SWAP):
150
+ def __init__(self, swap_gate: cirq.Gate = ops.SWAP):
151
151
  super().__init__(2, swap_gate)
152
152
 
153
153
  def permutation(self) -> Dict[int, int]:
154
154
  return {0: 1, 1: 0}
155
155
 
156
- def _decompose_(self, qubits: Sequence['cirq.Qid']) -> Iterator['cirq.OP_TREE']:
156
+ def _decompose_(self, qubits: Sequence[cirq.Qid]) -> Iterator[cirq.OP_TREE]:
157
157
  yield self.swap_gate(*qubits)
158
158
 
159
159
  def __repr__(self) -> str:
@@ -186,7 +186,7 @@ class LinearPermutationGate(PermutationGate):
186
186
  sorting network."""
187
187
 
188
188
  def __init__(
189
- self, num_qubits: int, permutation: Dict[int, int], swap_gate: 'cirq.Gate' = ops.SWAP
189
+ self, num_qubits: int, permutation: Dict[int, int], swap_gate: cirq.Gate = ops.SWAP
190
190
  ) -> None:
191
191
  """Initializes a linear permutation gate.
192
192
 
@@ -202,7 +202,7 @@ class LinearPermutationGate(PermutationGate):
202
202
  def permutation(self) -> Dict[int, int]:
203
203
  return self._permutation
204
204
 
205
- def _decompose_(self, qubits: Sequence['cirq.Qid']) -> Iterator['cirq.OP_TREE']:
205
+ def _decompose_(self, qubits: Sequence[cirq.Qid]) -> Iterator[cirq.OP_TREE]:
206
206
  swap_gate = SwapPermutationGate(self.swap_gate)
207
207
  n_qubits = len(qubits)
208
208
  mapping = {i: self._permutation.get(i, i) for i in range(n_qubits)}
@@ -238,7 +238,7 @@ class LinearPermutationGate(PermutationGate):
238
238
  return NotImplemented
239
239
 
240
240
 
241
- def update_mapping(mapping: Dict[ops.Qid, LogicalIndex], operations: 'cirq.OP_TREE') -> None:
241
+ def update_mapping(mapping: Dict[ops.Qid, LogicalIndex], operations: cirq.OP_TREE) -> None:
242
242
  """Updates a mapping (in place) from qubits to logical indices according to
243
243
  a set of permutation gates. Any gates other than permutation gates are
244
244
  ignored.
@@ -253,8 +253,8 @@ def update_mapping(mapping: Dict[ops.Qid, LogicalIndex], operations: 'cirq.OP_TR
253
253
 
254
254
 
255
255
  def get_logical_operations(
256
- operations: 'cirq.OP_TREE', initial_mapping: Dict[ops.Qid, ops.Qid]
257
- ) -> Iterable['cirq.Operation']:
256
+ operations: cirq.OP_TREE, initial_mapping: Dict[ops.Qid, ops.Qid]
257
+ ) -> Iterable[cirq.Operation]:
258
258
  """Gets the logical operations specified by the physical operations and
259
259
  initial mapping.
260
260
 
@@ -300,10 +300,10 @@ class DecomposePermutationGates:
300
300
  not all([isinstance(op, ops.GateOperation), isinstance(op.gate, PermutationGate)])
301
301
  )
302
302
 
303
- def optimize_circuit(self, circuit: 'cirq.Circuit') -> None:
303
+ def optimize_circuit(self, circuit: cirq.Circuit) -> None:
304
304
  circuit._moments = [*transformers.expand_composite(circuit, no_decomp=self.no_decomp)]
305
305
 
306
- def __call__(self, circuit: 'cirq.Circuit') -> None:
306
+ def __call__(self, circuit: cirq.Circuit) -> None:
307
307
  self.optimize_circuit(circuit)
308
308
 
309
309
 
@@ -311,7 +311,7 @@ EXPAND_PERMUTATION_GATES = DecomposePermutationGates(keep_swap_permutations=True
311
311
  DECOMPOSE_PERMUTATION_GATES = DecomposePermutationGates(keep_swap_permutations=False)
312
312
 
313
313
 
314
- def return_to_initial_mapping(circuit: 'cirq.Circuit', swap_gate: 'cirq.Gate' = ops.SWAP) -> None:
314
+ def return_to_initial_mapping(circuit: cirq.Circuit, swap_gate: cirq.Gate = ops.SWAP) -> None:
315
315
  qubits = sorted(circuit.all_qubits())
316
316
  n_qubits = len(qubits)
317
317
 
@@ -323,7 +323,7 @@ def return_to_initial_mapping(circuit: 'cirq.Circuit', swap_gate: 'cirq.Gate' =
323
323
  circuit.append(returning_permutation_op)
324
324
 
325
325
 
326
- def uses_consistent_swap_gate(circuit: 'cirq.Circuit', swap_gate: 'cirq.Gate') -> bool:
326
+ def uses_consistent_swap_gate(circuit: cirq.Circuit, swap_gate: cirq.Gate) -> bool:
327
327
  for op in circuit.all_operations():
328
328
  if isinstance(op, ops.GateOperation) and isinstance(op.gate, PermutationGate):
329
329
  if op.gate.swap_gate != swap_gate:
@@ -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 typing import Any, Dict, Iterator, Sequence, Tuple, TYPE_CHECKING
17
19
 
@@ -26,7 +28,7 @@ if TYPE_CHECKING:
26
28
  class CircularShiftGate(PermutationGate):
27
29
  """Performs a cyclical permutation of the qubits to the left by a specified amount."""
28
30
 
29
- def __init__(self, num_qubits: int, shift: int, swap_gate: 'cirq.Gate' = ops.SWAP) -> None:
31
+ def __init__(self, num_qubits: int, shift: int, swap_gate: cirq.Gate = ops.SWAP) -> None:
30
32
  """Construct a circular shift gate.
31
33
 
32
34
  Args:
@@ -47,7 +49,7 @@ class CircularShiftGate(PermutationGate):
47
49
  def _value_equality_values_(self) -> Any:
48
50
  return self.shift, self.swap_gate, self.num_qubits()
49
51
 
50
- def _decompose_(self, qubits: Sequence['cirq.Qid']) -> Iterator['cirq.OP_TREE']:
52
+ def _decompose_(self, qubits: Sequence[cirq.Qid]) -> Iterator[cirq.OP_TREE]:
51
53
  n = len(qubits)
52
54
  left_shift = self.shift % n
53
55
  right_shift = n - left_shift
@@ -58,7 +60,7 @@ class CircularShiftGate(PermutationGate):
58
60
  for k in range(i, j, 2):
59
61
  yield swap_gate(*qubits[k : k + 2])
60
62
 
61
- def _circuit_diagram_info_(self, args: 'cirq.CircuitDiagramInfoArgs') -> Tuple[str, ...]:
63
+ def _circuit_diagram_info_(self, args: cirq.CircuitDiagramInfoArgs) -> Tuple[str, ...]:
62
64
  if args.known_qubit_count is None:
63
65
  return NotImplemented # pragma: no cover
64
66
  direction_symbols = ('╲', '╱') if args.use_unicode_characters else ('\\', '/')
@@ -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 functools
16
18
  import itertools
17
19
  from typing import Dict, Iterable, Iterator, Optional, Sequence, Tuple, TYPE_CHECKING
@@ -51,7 +53,7 @@ class ShiftSwapNetworkGate(PermutationGate):
51
53
  self,
52
54
  left_part_lens: Iterable[int],
53
55
  right_part_lens: Iterable[int],
54
- swap_gate: 'cirq.Gate' = ops.SWAP,
56
+ swap_gate: cirq.Gate = ops.SWAP,
55
57
  ) -> None:
56
58
 
57
59
  self.part_lens = {'left': tuple(left_part_lens), 'right': tuple(right_part_lens)}
@@ -65,7 +67,7 @@ class ShiftSwapNetworkGate(PermutationGate):
65
67
  def acquaintance_size(self) -> int:
66
68
  return sum(max(self.part_lens[side]) for side in ('left', 'right'))
67
69
 
68
- def _decompose_(self, qubits: Sequence['cirq.Qid']) -> Iterator['cirq.OP_TREE']:
70
+ def _decompose_(self, qubits: Sequence[cirq.Qid]) -> Iterator[cirq.OP_TREE]:
69
71
  part_lens = list(itertools.chain(*(self.part_lens[side] for side in ('left', 'right'))))
70
72
 
71
73
  n_qubits = 0
@@ -110,7 +112,7 @@ class ShiftSwapNetworkGate(PermutationGate):
110
112
  )
111
113
  )
112
114
 
113
- def _circuit_diagram_info_(self, args: 'cirq.CircuitDiagramInfoArgs') -> Tuple[str, ...]:
115
+ def _circuit_diagram_info_(self, args: cirq.CircuitDiagramInfoArgs) -> Tuple[str, ...]:
114
116
  qubit_count = self.qubit_count()
115
117
  assert args.known_qubit_count in (None, qubit_count)
116
118
 
@@ -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 Sequence, TYPE_CHECKING
16
18
 
17
19
  from cirq import circuits, ops
@@ -26,8 +28,8 @@ if TYPE_CHECKING:
26
28
 
27
29
 
28
30
  def complete_acquaintance_strategy(
29
- qubit_order: Sequence['cirq.Qid'], acquaintance_size: int = 0, swap_gate: 'cirq.Gate' = ops.SWAP
30
- ) -> 'cirq.Circuit':
31
+ qubit_order: Sequence[cirq.Qid], acquaintance_size: int = 0, swap_gate: cirq.Gate = ops.SWAP
32
+ ) -> cirq.Circuit:
31
33
  """Returns an acquaintance strategy with can handle the given number of qubits.
32
34
 
33
35
  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 itertools
16
18
  from typing import Iterable, Sequence, Tuple, TYPE_CHECKING, TypeVar
17
19
 
@@ -35,8 +37,8 @@ def skip_and_wrap_around(items: Sequence[TItem]) -> Tuple[TItem, ...]:
35
37
 
36
38
 
37
39
  def cubic_acquaintance_strategy(
38
- qubits: Iterable['cirq.Qid'], swap_gate: 'cirq.Gate' = ops.SWAP
39
- ) -> 'cirq.Circuit':
40
+ qubits: Iterable[cirq.Qid], swap_gate: cirq.Gate = ops.SWAP
41
+ ) -> cirq.Circuit:
40
42
  """Acquaints every triple of qubits.
41
43
 
42
44
  Exploits the fact that in a simple linear swap network every pair of
@@ -12,9 +12,11 @@
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 cast, Iterable, List, Sequence, Tuple, TYPE_CHECKING
16
18
 
17
- from cirq import circuits, ops
19
+ from cirq import circuits
18
20
  from cirq.contrib.acquaintance.gates import acquaint, SwapNetworkGate
19
21
  from cirq.contrib.acquaintance.mutation_utils import expose_acquaintance_gates
20
22
 
@@ -22,7 +24,7 @@ if TYPE_CHECKING:
22
24
  import cirq
23
25
 
24
26
 
25
- def qubit_pairs_to_qubit_order(qubit_pairs: Sequence[Sequence['cirq.Qid']]) -> List['cirq.Qid']:
27
+ def qubit_pairs_to_qubit_order(qubit_pairs: Sequence[Sequence[cirq.Qid]]) -> List[cirq.Qid]:
26
28
  """Takes a sequence of qubit pairs and returns a sequence in which every
27
29
  pair is at distance two.
28
30
 
@@ -33,7 +35,7 @@ def qubit_pairs_to_qubit_order(qubit_pairs: Sequence[Sequence['cirq.Qid']]) -> L
33
35
  if set(len(qubit_pair) for qubit_pair in qubit_pairs) != set((2,)):
34
36
  raise ValueError('set(len(qubit_pair) for qubit_pair in qubit_pairs) != set((2,))')
35
37
  n_pairs = len(qubit_pairs)
36
- qubits: List['cirq.Qid'] = []
38
+ qubits: List[cirq.Qid] = []
37
39
  for i in range(0, 2 * (n_pairs // 2), 2):
38
40
  qubits += [
39
41
  qubit_pairs[i][0],
@@ -47,15 +49,15 @@ def qubit_pairs_to_qubit_order(qubit_pairs: Sequence[Sequence['cirq.Qid']]) -> L
47
49
 
48
50
 
49
51
  def quartic_paired_acquaintance_strategy(
50
- qubit_pairs: Iterable[Tuple['cirq.Qid', ops.Qid]],
51
- ) -> Tuple['cirq.Circuit', Sequence['cirq.Qid']]:
52
+ qubit_pairs: Iterable[Tuple[cirq.Qid, cirq.Qid]],
53
+ ) -> Tuple[cirq.Circuit, Sequence[cirq.Qid]]:
52
54
  """Acquaintance strategy for pairs of pairs.
53
55
 
54
56
  Implements UpCCGSD ansatz from arXiv:1810.02327.
55
57
  """
56
58
 
57
59
  qubit_pairs = tuple(
58
- cast(Tuple['cirq.Qid', ops.Qid], tuple(qubit_pair)) for qubit_pair in qubit_pairs
60
+ cast(Tuple['cirq.Qid', 'cirq.Qid'], tuple(qubit_pair)) for qubit_pair in qubit_pairs
59
61
  )
60
62
  qubits = qubit_pairs_to_qubit_order(qubit_pairs)
61
63
  n_qubits = len(qubits)
@@ -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 operator
16
18
  import random
17
19
  from typing import Any, Callable, cast, Iterable, TYPE_CHECKING
@@ -25,8 +27,8 @@ if TYPE_CHECKING:
25
27
 
26
28
 
27
29
  def is_topologically_sorted(
28
- dag: 'cirq.contrib.CircuitDag',
29
- operations: 'cirq.OP_TREE',
30
+ dag: cirq.contrib.CircuitDag,
31
+ operations: cirq.OP_TREE,
30
32
  equals: Callable[[ops.Operation, ops.Operation], bool] = operator.eq,
31
33
  ) -> bool:
32
34
  """Whether a given order of operations is consistent with the DAG.