cirq-core 1.5.0.dev20250403161251__py3-none-any.whl → 1.5.0.dev20250404021339__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.
- cirq/_version.py +1 -1
- cirq/_version_test.py +1 -1
- cirq/circuits/circuit.py +144 -147
- cirq/circuits/circuit_operation.py +37 -34
- cirq/circuits/circuit_operation_test.py +1 -1
- cirq/circuits/circuit_test.py +4 -6
- cirq/circuits/frozen_circuit.py +30 -26
- cirq/circuits/moment.py +37 -37
- cirq/circuits/optimization_pass.py +11 -11
- cirq/circuits/optimization_pass_test.py +6 -8
- cirq/circuits/qasm_output.py +13 -11
- cirq/circuits/text_diagram_drawer.py +9 -7
- cirq/contrib/acquaintance/bipartite.py +7 -5
- cirq/contrib/acquaintance/devices.py +3 -1
- cirq/contrib/acquaintance/executor.py +14 -16
- cirq/contrib/acquaintance/gates.py +19 -21
- cirq/contrib/acquaintance/inspection_utils.py +8 -6
- cirq/contrib/acquaintance/mutation_utils.py +8 -6
- cirq/contrib/acquaintance/optimizers.py +5 -3
- cirq/contrib/acquaintance/permutation.py +19 -19
- cirq/contrib/acquaintance/shift.py +5 -3
- cirq/contrib/acquaintance/shift_swap_network.py +5 -3
- cirq/contrib/acquaintance/strategies/complete.py +4 -2
- cirq/contrib/acquaintance/strategies/cubic.py +4 -2
- cirq/contrib/acquaintance/strategies/quartic_paired.py +8 -6
- cirq/contrib/acquaintance/topological_sort.py +4 -2
- cirq/contrib/bayesian_network/bayesian_network_gate.py +4 -2
- cirq/contrib/circuitdag/circuit_dag.py +18 -16
- cirq/contrib/custom_simulators/custom_state_simulator.py +10 -8
- cirq/contrib/custom_simulators/custom_state_simulator_test.py +9 -7
- cirq/contrib/graph_device/graph_device.py +4 -2
- cirq/contrib/noise_models/noise_models.py +7 -5
- cirq/contrib/paulistring/clifford_target_gateset.py +11 -9
- cirq/contrib/qcircuit/qcircuit_diagram.py +5 -2
- cirq/contrib/quantum_volume/quantum_volume.py +4 -4
- cirq/contrib/quimb/mps_simulator.py +25 -26
- cirq/contrib/routing/greedy.py +5 -3
- cirq/contrib/routing/initialization.py +3 -1
- cirq/contrib/routing/swap_network.py +5 -5
- cirq/contrib/routing/utils.py +4 -2
- cirq/contrib/svg/svg.py +9 -6
- cirq/devices/device.py +11 -9
- cirq/devices/grid_device_metadata.py +14 -11
- cirq/devices/grid_qubit.py +17 -21
- cirq/devices/grid_qubit_test.py +1 -1
- cirq/devices/insertion_noise_model.py +5 -5
- cirq/devices/line_qubit.py +15 -17
- cirq/devices/named_topologies.py +6 -4
- cirq/devices/noise_model.py +27 -31
- {cirq_core-1.5.0.dev20250403161251.dist-info → cirq_core-1.5.0.dev20250404021339.dist-info}/METADATA +1 -1
- {cirq_core-1.5.0.dev20250403161251.dist-info → cirq_core-1.5.0.dev20250404021339.dist-info}/RECORD +54 -54
- {cirq_core-1.5.0.dev20250403161251.dist-info → cirq_core-1.5.0.dev20250404021339.dist-info}/LICENSE +0 -0
- {cirq_core-1.5.0.dev20250403161251.dist-info → cirq_core-1.5.0.dev20250404021339.dist-info}/WHEEL +0 -0
- {cirq_core-1.5.0.dev20250403161251.dist-info → cirq_core-1.5.0.dev20250404021339.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:
|
|
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:
|
|
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[
|
|
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[
|
|
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[
|
|
117
|
-
self._control_keys: Optional[FrozenSet[
|
|
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:
|
|
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[
|
|
136
|
+
def operations(self) -> Tuple[cirq.Operation, ...]:
|
|
135
137
|
return self._operations
|
|
136
138
|
|
|
137
139
|
@cached_property
|
|
138
|
-
def qubits(self) -> FrozenSet[
|
|
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:
|
|
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[
|
|
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[
|
|
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:
|
|
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:
|
|
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[
|
|
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[
|
|
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[
|
|
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[
|
|
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[
|
|
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[
|
|
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[
|
|
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) ->
|
|
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[
|
|
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[
|
|
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[
|
|
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[
|
|
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:
|
|
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:
|
|
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:
|
|
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) ->
|
|
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]) ->
|
|
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:
|
|
570
|
+
self: cirq.Moment,
|
|
571
571
|
*,
|
|
572
|
-
xy_breakdown_func: Callable[[
|
|
573
|
-
extra_qubits: Iterable[
|
|
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[
|
|
34
|
-
new_operations:
|
|
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:
|
|
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:
|
|
109
|
-
) -> Optional[
|
|
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:
|
|
130
|
-
frontier: Dict[
|
|
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
|
-
|
|
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:
|
|
67
|
-
) -> Optional[
|
|
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:
|
|
161
|
-
) -> Optional[
|
|
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))
|
cirq/circuits/qasm_output.py
CHANGED
|
@@ -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) ->
|
|
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[
|
|
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) ->
|
|
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:
|
|
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) ->
|
|
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[
|
|
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:
|
|
174
|
-
qubits: Tuple[
|
|
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[
|
|
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:
|
|
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:
|
|
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) ->
|
|
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) ->
|
|
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) ->
|
|
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:
|
|
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:
|
|
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[
|
|
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[
|
|
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:
|
|
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[
|
|
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[
|
|
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[
|
|
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:
|
|
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:
|
|
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
|
):
|