cirq-core 1.6.0.dev20250520054601__py3-none-any.whl → 1.6.0.dev20250520183459__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/_compat.py +15 -17
- cirq/_compat_test.py +6 -9
- cirq/_doc.py +2 -2
- cirq/_import.py +6 -6
- cirq/_version.py +1 -1
- cirq/_version_test.py +1 -1
- cirq/circuits/_block_diagram_drawer.py +9 -10
- cirq/circuits/_box_drawing_character_data.py +6 -8
- cirq/circuits/_bucket_priority_queue.py +7 -7
- cirq/circuits/circuit.py +118 -125
- cirq/circuits/circuit_operation.py +38 -52
- cirq/circuits/circuit_test.py +4 -4
- cirq/circuits/frozen_circuit.py +13 -23
- cirq/circuits/moment.py +23 -29
- cirq/circuits/optimization_pass.py +4 -4
- cirq/circuits/optimization_pass_test.py +4 -6
- cirq/circuits/qasm_output.py +11 -11
- cirq/circuits/text_diagram_drawer.py +21 -36
- cirq/contrib/acquaintance/bipartite.py +5 -8
- cirq/contrib/acquaintance/executor.py +5 -5
- cirq/contrib/acquaintance/executor_test.py +3 -3
- cirq/contrib/acquaintance/gates.py +16 -26
- cirq/contrib/acquaintance/gates_test.py +3 -3
- cirq/contrib/acquaintance/mutation_utils.py +4 -4
- cirq/contrib/acquaintance/optimizers.py +4 -4
- cirq/contrib/acquaintance/permutation.py +15 -27
- cirq/contrib/acquaintance/shift.py +3 -3
- cirq/contrib/acquaintance/shift_swap_network.py +4 -4
- cirq/contrib/acquaintance/strategies/cubic.py +2 -2
- cirq/contrib/acquaintance/strategies/quartic_paired.py +6 -6
- cirq/contrib/bayesian_network/bayesian_network_gate.py +9 -10
- cirq/contrib/circuitdag/circuit_dag.py +2 -2
- cirq/contrib/custom_simulators/custom_state_simulator.py +3 -3
- cirq/contrib/custom_simulators/custom_state_simulator_test.py +4 -4
- cirq/contrib/graph_device/graph_device.py +5 -5
- cirq/contrib/graph_device/hypergraph.py +12 -12
- cirq/contrib/graph_device/uniform_graph_device.py +4 -4
- cirq/contrib/paulistring/clifford_optimize.py +2 -2
- cirq/contrib/paulistring/clifford_target_gateset.py +7 -7
- cirq/contrib/paulistring/pauli_string_measurement_with_readout_mitigation.py +31 -31
- cirq/contrib/paulistring/pauli_string_measurement_with_readout_mitigation_test.py +23 -23
- cirq/contrib/paulistring/recombine.py +3 -3
- cirq/contrib/paulistring/separate.py +2 -2
- cirq/contrib/qasm_import/_parser.py +20 -32
- cirq/contrib/qcircuit/qcircuit_diagram_info.py +3 -5
- cirq/contrib/quantum_volume/quantum_volume.py +24 -24
- cirq/contrib/quimb/density_matrix.py +12 -14
- cirq/contrib/quimb/mps_simulator.py +20 -20
- cirq/contrib/quimb/state_vector.py +6 -10
- cirq/contrib/quirk/export_to_quirk.py +3 -3
- cirq/contrib/quirk/quirk_gate.py +15 -15
- cirq/contrib/routing/device.py +3 -3
- cirq/contrib/routing/greedy.py +10 -21
- cirq/contrib/routing/initialization.py +2 -2
- cirq/contrib/routing/swap_network.py +3 -3
- cirq/contrib/routing/utils.py +2 -2
- cirq/contrib/shuffle_circuits/shuffle_circuits_with_readout_benchmarking.py +8 -8
- cirq/contrib/svg/svg.py +3 -3
- cirq/devices/grid_device_metadata.py +10 -10
- cirq/devices/grid_qubit.py +20 -20
- cirq/devices/insertion_noise_model.py +5 -5
- cirq/devices/line_qubit.py +13 -13
- cirq/devices/named_topologies.py +18 -29
- cirq/devices/noise_model.py +3 -3
- cirq/devices/noise_properties.py +2 -2
- cirq/devices/noise_properties_test.py +1 -3
- cirq/devices/noise_utils.py +7 -7
- cirq/devices/superconducting_qubits_noise_properties.py +21 -21
- cirq/devices/superconducting_qubits_noise_properties_test.py +5 -7
- cirq/devices/thermal_noise_model.py +14 -14
- cirq/devices/unconstrained_device.py +2 -2
- cirq/experiments/benchmarking/parallel_xeb.py +29 -31
- cirq/experiments/n_qubit_tomography.py +5 -7
- cirq/experiments/qubit_characterizations.py +29 -40
- cirq/experiments/qubit_characterizations_test.py +1 -1
- cirq/experiments/random_quantum_circuit_generation.py +19 -33
- cirq/experiments/random_quantum_circuit_generation_test.py +6 -6
- cirq/experiments/readout_confusion_matrix.py +14 -14
- cirq/experiments/single_qubit_readout_calibration.py +12 -12
- cirq/experiments/t2_decay_experiment.py +7 -7
- cirq/experiments/two_qubit_xeb.py +32 -32
- cirq/experiments/two_qubit_xeb_test.py +5 -5
- cirq/experiments/xeb_fitting.py +25 -25
- cirq/experiments/xeb_sampling.py +22 -33
- cirq/experiments/xeb_simulation.py +5 -5
- cirq/experiments/xeb_simulation_test.py +3 -3
- cirq/experiments/z_phase_calibration.py +19 -19
- cirq/interop/quirk/cells/arithmetic_cells.py +23 -36
- cirq/interop/quirk/cells/cell.py +9 -21
- cirq/interop/quirk/cells/composite_cell.py +7 -22
- cirq/interop/quirk/cells/control_cells.py +8 -8
- cirq/interop/quirk/cells/input_cells.py +4 -4
- cirq/interop/quirk/cells/input_rotation_cells.py +5 -5
- cirq/interop/quirk/cells/parse.py +20 -23
- cirq/interop/quirk/cells/qubit_permutation_cells.py +3 -3
- cirq/interop/quirk/cells/swap_cell.py +3 -3
- cirq/interop/quirk/cells/testing.py +5 -7
- cirq/interop/quirk/url_to_circuit.py +17 -33
- cirq/json_resolver_cache.py +6 -6
- cirq/linalg/decompositions.py +20 -31
- cirq/linalg/diagonalize.py +4 -4
- cirq/linalg/diagonalize_test.py +3 -4
- cirq/linalg/operator_spaces.py +5 -5
- cirq/linalg/predicates.py +7 -7
- cirq/linalg/transformations.py +20 -20
- cirq/ops/arithmetic_operation.py +13 -15
- cirq/ops/boolean_hamiltonian.py +17 -17
- cirq/ops/classically_controlled_operation.py +13 -25
- cirq/ops/clifford_gate.py +31 -35
- cirq/ops/clifford_gate_test.py +2 -3
- cirq/ops/common_channels.py +30 -32
- cirq/ops/common_gates.py +64 -74
- cirq/ops/control_values.py +12 -12
- cirq/ops/controlled_gate.py +15 -30
- cirq/ops/controlled_gate_test.py +5 -5
- cirq/ops/controlled_operation.py +12 -25
- cirq/ops/controlled_operation_test.py +5 -5
- cirq/ops/dense_pauli_string.py +23 -34
- cirq/ops/dense_pauli_string_test.py +1 -2
- cirq/ops/diagonal_gate.py +9 -20
- cirq/ops/diagonal_gate_test.py +1 -3
- cirq/ops/eigen_gate.py +11 -23
- cirq/ops/eigen_gate_test.py +6 -8
- cirq/ops/fourier_transform.py +5 -5
- cirq/ops/fsim_gate.py +14 -14
- cirq/ops/gate_operation.py +23 -44
- cirq/ops/gateset.py +23 -37
- cirq/ops/gateset_test.py +2 -2
- cirq/ops/global_phase_op.py +8 -10
- cirq/ops/greedy_qubit_manager.py +6 -6
- cirq/ops/identity.py +9 -9
- cirq/ops/kraus_channel.py +7 -7
- cirq/ops/linear_combinations.py +29 -48
- cirq/ops/matrix_gates.py +8 -8
- cirq/ops/measure_util.py +13 -14
- cirq/ops/measurement_gate.py +18 -29
- cirq/ops/mixed_unitary_channel.py +8 -8
- cirq/ops/named_qubit.py +10 -10
- cirq/ops/op_tree.py +7 -7
- cirq/ops/parallel_gate.py +5 -5
- cirq/ops/parity_gates.py +14 -14
- cirq/ops/pauli_gates.py +8 -10
- cirq/ops/pauli_interaction_gate.py +6 -6
- cirq/ops/pauli_measurement_gate.py +11 -23
- cirq/ops/pauli_string.py +35 -52
- cirq/ops/pauli_string_phasor.py +4 -14
- cirq/ops/pauli_string_raw_types.py +3 -3
- cirq/ops/pauli_sum_exponential.py +2 -2
- cirq/ops/permutation_gate.py +4 -4
- cirq/ops/phased_iswap_gate.py +9 -9
- cirq/ops/phased_x_gate.py +10 -10
- cirq/ops/phased_x_z_gate.py +11 -11
- cirq/ops/projector.py +6 -6
- cirq/ops/qubit_manager.py +6 -6
- cirq/ops/qubit_order.py +3 -3
- cirq/ops/random_gate_channel.py +4 -4
- cirq/ops/raw_types.py +48 -70
- cirq/ops/state_preparation_channel.py +3 -3
- cirq/ops/swap_gates.py +9 -9
- cirq/ops/tags.py +2 -4
- cirq/ops/three_qubit_gates.py +20 -38
- cirq/ops/two_qubit_diagonal_gate.py +5 -5
- cirq/ops/uniform_superposition_gate.py +2 -2
- cirq/ops/wait_gate.py +5 -5
- cirq/protocols/act_on_protocol_test.py +3 -3
- cirq/protocols/apply_channel_protocol.py +8 -14
- cirq/protocols/apply_mixture_protocol.py +14 -16
- cirq/protocols/apply_mixture_protocol_test.py +5 -6
- cirq/protocols/apply_unitary_protocol.py +17 -19
- cirq/protocols/circuit_diagram_info_protocol.py +19 -30
- cirq/protocols/decompose_protocol.py +30 -34
- cirq/protocols/inverse_protocol.py +7 -7
- cirq/protocols/json_serialization.py +32 -51
- cirq/protocols/json_serialization_test.py +9 -10
- cirq/protocols/kraus_protocol.py +4 -4
- cirq/protocols/kraus_protocol_test.py +3 -3
- cirq/protocols/measurement_key_protocol.py +11 -13
- cirq/protocols/mixture_protocol.py +4 -4
- cirq/protocols/qasm.py +11 -13
- cirq/protocols/qid_shape_protocol.py +6 -8
- cirq/qis/clifford_tableau.py +12 -12
- cirq/qis/measures.py +7 -7
- cirq/qis/quantum_state_representation.py +3 -3
- cirq/qis/states.py +51 -51
- cirq/sim/classical_simulator.py +10 -10
- cirq/sim/clifford/clifford_simulator.py +6 -6
- cirq/sim/clifford/clifford_tableau_simulation_state_test.py +1 -3
- cirq/sim/clifford/stabilizer_sampler.py +4 -4
- cirq/sim/clifford/stabilizer_state_ch_form.py +3 -3
- cirq/sim/density_matrix_simulation_state.py +15 -15
- cirq/sim/density_matrix_simulator.py +11 -11
- cirq/sim/density_matrix_utils.py +9 -9
- cirq/sim/mux.py +9 -9
- cirq/sim/simulation_product_state.py +9 -9
- cirq/sim/simulation_product_state_test.py +2 -2
- cirq/sim/simulation_state.py +14 -27
- cirq/sim/simulation_state_base.py +8 -24
- cirq/sim/simulation_utils.py +3 -4
- cirq/sim/simulator.py +28 -43
- cirq/sim/simulator_base.py +12 -25
- cirq/sim/simulator_base_test.py +6 -6
- cirq/sim/simulator_test.py +7 -7
- cirq/sim/sparse_simulator.py +8 -8
- cirq/sim/state_vector.py +8 -8
- cirq/sim/state_vector_simulation_state.py +17 -17
- cirq/sim/state_vector_simulator.py +4 -4
- cirq/study/flatten_expressions.py +12 -14
- cirq/study/resolver.py +9 -11
- cirq/study/result.py +11 -24
- cirq/study/sweepable.py +5 -5
- cirq/study/sweeps.py +27 -40
- cirq/testing/circuit_compare.py +5 -5
- cirq/testing/consistent_controlled_gate_op_test.py +7 -11
- cirq/testing/consistent_protocols.py +10 -10
- cirq/testing/consistent_protocols_test.py +7 -7
- cirq/testing/consistent_qasm.py +4 -4
- cirq/testing/consistent_qasm_test.py +2 -3
- cirq/testing/devices.py +4 -5
- cirq/testing/equals_tester.py +2 -2
- cirq/testing/equivalent_basis_map.py +4 -4
- cirq/testing/equivalent_repr_eval.py +3 -3
- cirq/testing/json.py +14 -14
- cirq/testing/logs.py +3 -3
- cirq/testing/no_identifier_qubit.py +2 -3
- cirq/testing/random_circuit.py +7 -7
- cirq/testing/random_circuit_test.py +3 -3
- cirq/transformers/analytical_decompositions/clifford_decomposition.py +16 -16
- cirq/transformers/analytical_decompositions/controlled_gate_decomposition.py +13 -13
- cirq/transformers/analytical_decompositions/cphase_to_fsim.py +5 -5
- cirq/transformers/analytical_decompositions/cphase_to_fsim_test.py +3 -3
- cirq/transformers/analytical_decompositions/pauli_string_decomposition.py +3 -3
- cirq/transformers/analytical_decompositions/quantum_shannon_decomposition.py +4 -4
- cirq/transformers/analytical_decompositions/single_qubit_decompositions.py +6 -7
- cirq/transformers/analytical_decompositions/single_to_two_qubit_isometry.py +2 -2
- cirq/transformers/analytical_decompositions/three_qubit_decomposition.py +7 -7
- cirq/transformers/analytical_decompositions/two_qubit_state_preparation.py +4 -4
- cirq/transformers/analytical_decompositions/two_qubit_to_cz.py +7 -7
- cirq/transformers/analytical_decompositions/two_qubit_to_fsim.py +11 -11
- cirq/transformers/analytical_decompositions/two_qubit_to_ms.py +5 -5
- cirq/transformers/analytical_decompositions/two_qubit_to_sqrt_iswap.py +14 -14
- cirq/transformers/dynamical_decoupling.py +13 -13
- cirq/transformers/dynamical_decoupling_test.py +4 -4
- cirq/transformers/eject_phased_paulis.py +16 -16
- cirq/transformers/eject_z.py +5 -7
- cirq/transformers/gauge_compiling/gauge_compiling.py +38 -38
- cirq/transformers/gauge_compiling/sqrt_cz_gauge.py +2 -2
- cirq/transformers/heuristic_decompositions/two_qubit_gate_tabulation.py +8 -8
- cirq/transformers/insertion_sort.py +5 -5
- cirq/transformers/measurement_transformers.py +14 -14
- cirq/transformers/merge_k_qubit_gates_test.py +1 -3
- cirq/transformers/merge_single_qubit_gates_test.py +1 -3
- cirq/transformers/qubit_management_transformers.py +5 -5
- cirq/transformers/routing/initial_mapper.py +4 -4
- cirq/transformers/routing/line_initial_mapper.py +9 -9
- cirq/transformers/routing/mapping_manager.py +7 -7
- cirq/transformers/routing/route_circuit_cqc.py +27 -27
- cirq/transformers/routing/visualize_routed_circuit.py +4 -4
- cirq/transformers/stratify.py +8 -8
- cirq/transformers/synchronize_terminal_measurements.py +6 -6
- cirq/transformers/target_gatesets/compilation_target_gateset.py +8 -8
- cirq/transformers/target_gatesets/compilation_target_gateset_test.py +2 -2
- cirq/transformers/target_gatesets/cz_gateset.py +4 -4
- cirq/transformers/target_gatesets/sqrt_iswap_gateset.py +5 -5
- cirq/transformers/transformer_api.py +11 -26
- cirq/transformers/transformer_primitives.py +24 -36
- cirq/transformers/transformer_primitives_test.py +3 -3
- cirq/value/classical_data.py +18 -18
- cirq/value/condition.py +8 -8
- cirq/value/digits.py +7 -7
- cirq/value/duration.py +12 -12
- cirq/value/linear_dict.py +8 -12
- cirq/value/linear_dict_test.py +2 -2
- cirq/value/measurement_key.py +8 -8
- cirq/value/product_state.py +9 -9
- cirq/value/value_equality_attr.py +4 -4
- cirq/vis/heatmap.py +23 -35
- cirq/work/collector.py +9 -17
- cirq/work/observable_grouping.py +4 -7
- cirq/work/observable_measurement.py +29 -41
- cirq/work/observable_measurement_data.py +14 -14
- cirq/work/observable_measurement_test.py +2 -2
- cirq/work/observable_settings.py +9 -10
- cirq/work/pauli_sum_collector.py +5 -5
- cirq/work/sampler.py +17 -17
- cirq/work/zeros_sampler.py +3 -3
- {cirq_core-1.6.0.dev20250520054601.dist-info → cirq_core-1.6.0.dev20250520183459.dist-info}/METADATA +1 -1
- {cirq_core-1.6.0.dev20250520054601.dist-info → cirq_core-1.6.0.dev20250520183459.dist-info}/RECORD +290 -290
- {cirq_core-1.6.0.dev20250520054601.dist-info → cirq_core-1.6.0.dev20250520183459.dist-info}/WHEEL +1 -1
- {cirq_core-1.6.0.dev20250520054601.dist-info → cirq_core-1.6.0.dev20250520183459.dist-info}/licenses/LICENSE +0 -0
- {cirq_core-1.6.0.dev20250520054601.dist-info → cirq_core-1.6.0.dev20250520183459.dist-info}/top_level.txt +0 -0
cirq/circuits/circuit.py
CHANGED
|
@@ -33,19 +33,12 @@ from typing import (
|
|
|
33
33
|
Any,
|
|
34
34
|
Callable,
|
|
35
35
|
cast,
|
|
36
|
-
Dict,
|
|
37
|
-
FrozenSet,
|
|
38
36
|
Iterable,
|
|
39
37
|
Iterator,
|
|
40
|
-
List,
|
|
41
38
|
Mapping,
|
|
42
39
|
MutableSequence,
|
|
43
|
-
Optional,
|
|
44
40
|
overload,
|
|
45
41
|
Sequence,
|
|
46
|
-
Set,
|
|
47
|
-
Tuple,
|
|
48
|
-
Type,
|
|
49
42
|
TYPE_CHECKING,
|
|
50
43
|
TypeVar,
|
|
51
44
|
Union,
|
|
@@ -93,7 +86,7 @@ document(
|
|
|
93
86
|
""",
|
|
94
87
|
)
|
|
95
88
|
|
|
96
|
-
_INT_TYPE =
|
|
89
|
+
_INT_TYPE = int | np.integer
|
|
97
90
|
|
|
98
91
|
|
|
99
92
|
class Alignment(enum.Enum):
|
|
@@ -148,7 +141,7 @@ class AbstractCircuit(abc.ABC):
|
|
|
148
141
|
"""
|
|
149
142
|
|
|
150
143
|
@classmethod
|
|
151
|
-
def from_moments(cls:
|
|
144
|
+
def from_moments(cls: type[CIRCUIT_TYPE], *moments: cirq.OP_TREE | None) -> CIRCUIT_TYPE:
|
|
152
145
|
"""Create a circuit from moment op trees.
|
|
153
146
|
|
|
154
147
|
Args:
|
|
@@ -166,7 +159,7 @@ class AbstractCircuit(abc.ABC):
|
|
|
166
159
|
return cls._from_moments(cls._make_moments(moments))
|
|
167
160
|
|
|
168
161
|
@staticmethod
|
|
169
|
-
def _make_moments(moments: Iterable[
|
|
162
|
+
def _make_moments(moments: Iterable[cirq.OP_TREE | None]) -> Iterator[cirq.Moment]:
|
|
170
163
|
for m in moments:
|
|
171
164
|
if isinstance(m, Moment):
|
|
172
165
|
yield m
|
|
@@ -177,7 +170,7 @@ class AbstractCircuit(abc.ABC):
|
|
|
177
170
|
|
|
178
171
|
@classmethod
|
|
179
172
|
@abc.abstractmethod
|
|
180
|
-
def _from_moments(cls:
|
|
173
|
+
def _from_moments(cls: type[CIRCUIT_TYPE], moments: Iterable[cirq.Moment]) -> CIRCUIT_TYPE:
|
|
181
174
|
"""Create a circuit from moments.
|
|
182
175
|
|
|
183
176
|
This must be implemented by subclasses. It provides a more efficient way
|
|
@@ -246,11 +239,11 @@ class AbstractCircuit(abc.ABC):
|
|
|
246
239
|
pass
|
|
247
240
|
|
|
248
241
|
@overload
|
|
249
|
-
def __getitem__(self, key:
|
|
242
|
+
def __getitem__(self, key: tuple[int, cirq.Qid]) -> cirq.Operation:
|
|
250
243
|
pass
|
|
251
244
|
|
|
252
245
|
@overload
|
|
253
|
-
def __getitem__(self, key:
|
|
246
|
+
def __getitem__(self, key: tuple[int, Iterable[cirq.Qid]]) -> cirq.Moment:
|
|
254
247
|
pass
|
|
255
248
|
|
|
256
249
|
@overload
|
|
@@ -258,11 +251,11 @@ class AbstractCircuit(abc.ABC):
|
|
|
258
251
|
pass
|
|
259
252
|
|
|
260
253
|
@overload
|
|
261
|
-
def __getitem__(self, key:
|
|
254
|
+
def __getitem__(self, key: tuple[slice, cirq.Qid]) -> Self:
|
|
262
255
|
pass
|
|
263
256
|
|
|
264
257
|
@overload
|
|
265
|
-
def __getitem__(self, key:
|
|
258
|
+
def __getitem__(self, key: tuple[slice, Iterable[cirq.Qid]]) -> Self:
|
|
266
259
|
pass
|
|
267
260
|
|
|
268
261
|
def __getitem__(self, key):
|
|
@@ -318,7 +311,7 @@ class AbstractCircuit(abc.ABC):
|
|
|
318
311
|
|
|
319
312
|
def _first_moment_operating_on(
|
|
320
313
|
self, qubits: Iterable[cirq.Qid], indices: Iterable[int]
|
|
321
|
-
) ->
|
|
314
|
+
) -> int | None:
|
|
322
315
|
qubits = frozenset(qubits)
|
|
323
316
|
for m in indices:
|
|
324
317
|
if self._has_op_at(m, qubits):
|
|
@@ -329,8 +322,8 @@ class AbstractCircuit(abc.ABC):
|
|
|
329
322
|
self,
|
|
330
323
|
qubits: Iterable[cirq.Qid],
|
|
331
324
|
start_moment_index: int = 0,
|
|
332
|
-
max_distance:
|
|
333
|
-
) ->
|
|
325
|
+
max_distance: int | None = None,
|
|
326
|
+
) -> int | None:
|
|
334
327
|
"""Finds the index of the next moment that touches the given qubits.
|
|
335
328
|
|
|
336
329
|
Args:
|
|
@@ -360,7 +353,7 @@ class AbstractCircuit(abc.ABC):
|
|
|
360
353
|
|
|
361
354
|
def next_moments_operating_on(
|
|
362
355
|
self, qubits: Iterable[cirq.Qid], start_moment_index: int = 0
|
|
363
|
-
) ->
|
|
356
|
+
) -> dict[cirq.Qid, int]:
|
|
364
357
|
"""Finds the index of the next moment that touches each qubit.
|
|
365
358
|
|
|
366
359
|
Args:
|
|
@@ -383,9 +376,9 @@ class AbstractCircuit(abc.ABC):
|
|
|
383
376
|
def prev_moment_operating_on(
|
|
384
377
|
self,
|
|
385
378
|
qubits: Sequence[cirq.Qid],
|
|
386
|
-
end_moment_index:
|
|
387
|
-
max_distance:
|
|
388
|
-
) ->
|
|
379
|
+
end_moment_index: int | None = None,
|
|
380
|
+
max_distance: int | None = None,
|
|
381
|
+
) -> int | None:
|
|
389
382
|
"""Finds the index of the previous moment that touches the given qubits.
|
|
390
383
|
|
|
391
384
|
Args:
|
|
@@ -427,10 +420,10 @@ class AbstractCircuit(abc.ABC):
|
|
|
427
420
|
|
|
428
421
|
def reachable_frontier_from(
|
|
429
422
|
self,
|
|
430
|
-
start_frontier:
|
|
423
|
+
start_frontier: dict[cirq.Qid, int],
|
|
431
424
|
*,
|
|
432
425
|
is_blocker: Callable[[cirq.Operation], bool] = lambda op: False,
|
|
433
|
-
) ->
|
|
426
|
+
) -> dict[cirq.Qid, int]:
|
|
434
427
|
"""Determines how far can be reached into a circuit under certain rules.
|
|
435
428
|
|
|
436
429
|
The location L = (qubit, moment_index) is *reachable* if and only if the
|
|
@@ -566,7 +559,7 @@ class AbstractCircuit(abc.ABC):
|
|
|
566
559
|
where i is the moment index, q is the qubit, and end_frontier is the
|
|
567
560
|
result of this method.
|
|
568
561
|
"""
|
|
569
|
-
active:
|
|
562
|
+
active: set[cirq.Qid] = set()
|
|
570
563
|
end_frontier = {}
|
|
571
564
|
queue = BucketPriorityQueue[ops.Operation](drop_duplicate_entries=True)
|
|
572
565
|
|
|
@@ -610,10 +603,10 @@ class AbstractCircuit(abc.ABC):
|
|
|
610
603
|
|
|
611
604
|
def findall_operations_between(
|
|
612
605
|
self,
|
|
613
|
-
start_frontier:
|
|
614
|
-
end_frontier:
|
|
606
|
+
start_frontier: dict[cirq.Qid, int],
|
|
607
|
+
end_frontier: dict[cirq.Qid, int],
|
|
615
608
|
omit_crossing_operations: bool = False,
|
|
616
|
-
) ->
|
|
609
|
+
) -> list[tuple[int, cirq.Operation]]:
|
|
617
610
|
"""Finds operations between the two given frontiers.
|
|
618
611
|
|
|
619
612
|
If a qubit is in `start_frontier` but not `end_frontier`, its end index
|
|
@@ -658,9 +651,9 @@ class AbstractCircuit(abc.ABC):
|
|
|
658
651
|
|
|
659
652
|
def findall_operations_until_blocked(
|
|
660
653
|
self,
|
|
661
|
-
start_frontier:
|
|
654
|
+
start_frontier: dict[cirq.Qid, int],
|
|
662
655
|
is_blocker: Callable[[cirq.Operation], bool] = lambda op: False,
|
|
663
|
-
) ->
|
|
656
|
+
) -> list[tuple[int, cirq.Operation]]:
|
|
664
657
|
"""Finds all operations until a blocking operation is hit.
|
|
665
658
|
|
|
666
659
|
An operation is considered blocking if both of the following hold:
|
|
@@ -746,11 +739,11 @@ class AbstractCircuit(abc.ABC):
|
|
|
746
739
|
and the second item is the operation itself.
|
|
747
740
|
|
|
748
741
|
"""
|
|
749
|
-
op_list:
|
|
742
|
+
op_list: list[tuple[int, ops.Operation]] = []
|
|
750
743
|
if not start_frontier:
|
|
751
744
|
return op_list
|
|
752
745
|
start_index = min(start_frontier.values())
|
|
753
|
-
blocked_qubits:
|
|
746
|
+
blocked_qubits: set[cirq.Qid] = set()
|
|
754
747
|
for index, moment in enumerate(self[start_index:], start_index):
|
|
755
748
|
active_qubits = set(q for q, s in start_frontier.items() if s <= index)
|
|
756
749
|
for op in moment.operations:
|
|
@@ -762,7 +755,7 @@ class AbstractCircuit(abc.ABC):
|
|
|
762
755
|
break
|
|
763
756
|
return op_list
|
|
764
757
|
|
|
765
|
-
def operation_at(self, qubit: cirq.Qid, moment_index: int) ->
|
|
758
|
+
def operation_at(self, qubit: cirq.Qid, moment_index: int) -> cirq.Operation | None:
|
|
766
759
|
"""Finds the operation on a qubit within a moment, if any.
|
|
767
760
|
|
|
768
761
|
Args:
|
|
@@ -780,7 +773,7 @@ class AbstractCircuit(abc.ABC):
|
|
|
780
773
|
|
|
781
774
|
def findall_operations(
|
|
782
775
|
self, predicate: Callable[[cirq.Operation], bool]
|
|
783
|
-
) -> Iterable[
|
|
776
|
+
) -> Iterable[tuple[int, cirq.Operation]]:
|
|
784
777
|
"""Find the locations of all operations that satisfy a given condition.
|
|
785
778
|
|
|
786
779
|
This returns an iterator of (index, operation) tuples where each
|
|
@@ -800,8 +793,8 @@ class AbstractCircuit(abc.ABC):
|
|
|
800
793
|
yield index, op
|
|
801
794
|
|
|
802
795
|
def findall_operations_with_gate_type(
|
|
803
|
-
self, gate_type:
|
|
804
|
-
) -> Iterable[
|
|
796
|
+
self, gate_type: type[_TGate]
|
|
797
|
+
) -> Iterable[tuple[int, cirq.GateOperation, _TGate]]:
|
|
805
798
|
"""Find the locations of all gate operations of a given type.
|
|
806
799
|
|
|
807
800
|
Args:
|
|
@@ -922,7 +915,7 @@ class AbstractCircuit(abc.ABC):
|
|
|
922
915
|
qubits
|
|
923
916
|
)
|
|
924
917
|
|
|
925
|
-
def all_qubits(self) ->
|
|
918
|
+
def all_qubits(self) -> frozenset[cirq.Qid]:
|
|
926
919
|
"""Returns the qubits acted upon by Operations in this circuit.
|
|
927
920
|
|
|
928
921
|
Returns: FrozenSet of `cirq.Qid` objects acted on by all operations
|
|
@@ -956,7 +949,7 @@ class AbstractCircuit(abc.ABC):
|
|
|
956
949
|
|
|
957
950
|
def qid_shape(
|
|
958
951
|
self, qubit_order: cirq.QubitOrderOrList = ops.QubitOrder.DEFAULT
|
|
959
|
-
) ->
|
|
952
|
+
) -> tuple[int, ...]:
|
|
960
953
|
"""Get the qubit shapes of all qubits in this circuit.
|
|
961
954
|
|
|
962
955
|
Returns: A tuple containing the dimensions (shape) of all qudits
|
|
@@ -965,12 +958,12 @@ class AbstractCircuit(abc.ABC):
|
|
|
965
958
|
qids = ops.QubitOrder.as_qubit_order(qubit_order).order_for(self.all_qubits())
|
|
966
959
|
return protocols.qid_shape(qids)
|
|
967
960
|
|
|
968
|
-
def all_measurement_key_objs(self) ->
|
|
961
|
+
def all_measurement_key_objs(self) -> frozenset[cirq.MeasurementKey]:
|
|
969
962
|
return frozenset(
|
|
970
963
|
key for op in self.all_operations() for key in protocols.measurement_key_objs(op)
|
|
971
964
|
)
|
|
972
965
|
|
|
973
|
-
def _measurement_key_objs_(self) ->
|
|
966
|
+
def _measurement_key_objs_(self) -> frozenset[cirq.MeasurementKey]:
|
|
974
967
|
"""Returns the set of all measurement keys in this circuit.
|
|
975
968
|
|
|
976
969
|
Returns: FrozenSet of `cirq.MeasurementKey` objects that are
|
|
@@ -978,7 +971,7 @@ class AbstractCircuit(abc.ABC):
|
|
|
978
971
|
"""
|
|
979
972
|
return self.all_measurement_key_objs()
|
|
980
973
|
|
|
981
|
-
def all_measurement_key_names(self) ->
|
|
974
|
+
def all_measurement_key_names(self) -> frozenset[str]:
|
|
982
975
|
"""Returns the set of all measurement key names in this circuit.
|
|
983
976
|
|
|
984
977
|
Returns: FrozenSet of strings that are the measurement key
|
|
@@ -988,7 +981,7 @@ class AbstractCircuit(abc.ABC):
|
|
|
988
981
|
key for op in self.all_operations() for key in protocols.measurement_key_names(op)
|
|
989
982
|
)
|
|
990
983
|
|
|
991
|
-
def _measurement_key_names_(self) ->
|
|
984
|
+
def _measurement_key_names_(self) -> frozenset[str]:
|
|
992
985
|
return self.all_measurement_key_names()
|
|
993
986
|
|
|
994
987
|
def _with_measurement_key_mapping_(self, key_map: Mapping[str, str]):
|
|
@@ -996,16 +989,16 @@ class AbstractCircuit(abc.ABC):
|
|
|
996
989
|
protocols.with_measurement_key_mapping(moment, key_map) for moment in self.moments
|
|
997
990
|
)
|
|
998
991
|
|
|
999
|
-
def _with_key_path_(self, path:
|
|
992
|
+
def _with_key_path_(self, path: tuple[str, ...]):
|
|
1000
993
|
return self._from_moments(protocols.with_key_path(moment, path) for moment in self.moments)
|
|
1001
994
|
|
|
1002
|
-
def _with_key_path_prefix_(self, prefix:
|
|
995
|
+
def _with_key_path_prefix_(self, prefix: tuple[str, ...]):
|
|
1003
996
|
return self._from_moments(
|
|
1004
997
|
protocols.with_key_path_prefix(moment, prefix) for moment in self.moments
|
|
1005
998
|
)
|
|
1006
999
|
|
|
1007
1000
|
def _with_rescoped_keys_(
|
|
1008
|
-
self, path:
|
|
1001
|
+
self, path: tuple[str, ...], bindable_keys: frozenset[cirq.MeasurementKey]
|
|
1009
1002
|
):
|
|
1010
1003
|
moments = []
|
|
1011
1004
|
for moment in self.moments:
|
|
@@ -1014,7 +1007,7 @@ class AbstractCircuit(abc.ABC):
|
|
|
1014
1007
|
bindable_keys |= protocols.measurement_key_objs(new_moment)
|
|
1015
1008
|
return self._from_moments(moments)
|
|
1016
1009
|
|
|
1017
|
-
def _qid_shape_(self) ->
|
|
1010
|
+
def _qid_shape_(self) -> tuple[int, ...]:
|
|
1018
1011
|
return self.qid_shape()
|
|
1019
1012
|
|
|
1020
1013
|
def _has_unitary_(self) -> bool:
|
|
@@ -1029,7 +1022,7 @@ class AbstractCircuit(abc.ABC):
|
|
|
1029
1022
|
)
|
|
1030
1023
|
return all(protocols.has_unitary(e) for e in unitary_ops)
|
|
1031
1024
|
|
|
1032
|
-
def _unitary_(self) ->
|
|
1025
|
+
def _unitary_(self) -> np.ndarray | NotImplementedType:
|
|
1033
1026
|
"""Converts the circuit into a unitary matrix, if possible.
|
|
1034
1027
|
|
|
1035
1028
|
If the circuit contains any non-terminal measurements, the conversion
|
|
@@ -1047,7 +1040,7 @@ class AbstractCircuit(abc.ABC):
|
|
|
1047
1040
|
qubit_order: cirq.QubitOrderOrList = ops.QubitOrder.DEFAULT,
|
|
1048
1041
|
qubits_that_should_be_present: Iterable[cirq.Qid] = (),
|
|
1049
1042
|
ignore_terminal_measurements: bool = True,
|
|
1050
|
-
dtype:
|
|
1043
|
+
dtype: type[np.complexfloating] = np.complex128,
|
|
1051
1044
|
) -> np.ndarray:
|
|
1052
1045
|
"""Converts the circuit into a unitary matrix, if possible.
|
|
1053
1046
|
|
|
@@ -1124,7 +1117,7 @@ class AbstractCircuit(abc.ABC):
|
|
|
1124
1117
|
initial_state: cirq.STATE_VECTOR_LIKE = 0,
|
|
1125
1118
|
qubit_order: cirq.QubitOrderOrList = ops.QubitOrder.DEFAULT,
|
|
1126
1119
|
ignore_terminal_measurements: bool = False,
|
|
1127
|
-
dtype:
|
|
1120
|
+
dtype: type[np.complexfloating] = np.complex128,
|
|
1128
1121
|
param_resolver: cirq.ParamResolverOrSimilarType = None,
|
|
1129
1122
|
seed: cirq.RANDOM_STATE_OR_SEED_LIKE = None,
|
|
1130
1123
|
) -> np.ndarray:
|
|
@@ -1183,7 +1176,7 @@ class AbstractCircuit(abc.ABC):
|
|
|
1183
1176
|
use_unicode_characters: bool = True,
|
|
1184
1177
|
transpose: bool = False,
|
|
1185
1178
|
include_tags: bool = True,
|
|
1186
|
-
precision:
|
|
1179
|
+
precision: int | None = 3,
|
|
1187
1180
|
qubit_order: cirq.QubitOrderOrList = ops.QubitOrder.DEFAULT,
|
|
1188
1181
|
) -> str:
|
|
1189
1182
|
"""Returns text containing a diagram describing the circuit.
|
|
@@ -1217,15 +1210,15 @@ class AbstractCircuit(abc.ABC):
|
|
|
1217
1210
|
self,
|
|
1218
1211
|
*,
|
|
1219
1212
|
use_unicode_characters: bool = True,
|
|
1220
|
-
qubit_namer:
|
|
1213
|
+
qubit_namer: Callable[[cirq.Qid], str] | None = None,
|
|
1221
1214
|
transpose: bool = False,
|
|
1222
1215
|
include_tags: bool = True,
|
|
1223
1216
|
draw_moment_groups: bool = True,
|
|
1224
|
-
precision:
|
|
1217
|
+
precision: int | None = 3,
|
|
1225
1218
|
qubit_order: cirq.QubitOrderOrList = ops.QubitOrder.DEFAULT,
|
|
1226
|
-
get_circuit_diagram_info:
|
|
1227
|
-
Callable[[cirq.Operation, cirq.CircuitDiagramInfoArgs], cirq.CircuitDiagramInfo]
|
|
1228
|
-
|
|
1219
|
+
get_circuit_diagram_info: (
|
|
1220
|
+
Callable[[cirq.Operation, cirq.CircuitDiagramInfoArgs], cirq.CircuitDiagramInfo] | None
|
|
1221
|
+
) = None,
|
|
1229
1222
|
) -> cirq.TextDiagramDrawer:
|
|
1230
1223
|
"""Returns a TextDiagramDrawer with the circuit drawn into it.
|
|
1231
1224
|
|
|
@@ -1276,7 +1269,7 @@ class AbstractCircuit(abc.ABC):
|
|
|
1276
1269
|
diagram.write(0, max(label_map.values(), default=0) + 1, 'global phase:')
|
|
1277
1270
|
first_annotation_row += 1
|
|
1278
1271
|
|
|
1279
|
-
moment_groups:
|
|
1272
|
+
moment_groups: list[tuple[int, int]] = []
|
|
1280
1273
|
for moment in self.moments:
|
|
1281
1274
|
_draw_moment_in_diagram(
|
|
1282
1275
|
moment=moment,
|
|
@@ -1311,7 +1304,7 @@ class AbstractCircuit(abc.ABC):
|
|
|
1311
1304
|
|
|
1312
1305
|
def _resolve_parameters_(self, resolver: cirq.ParamResolver, recursive: bool) -> Self:
|
|
1313
1306
|
changed = False
|
|
1314
|
-
resolved_moments:
|
|
1307
|
+
resolved_moments: list[cirq.Moment] = []
|
|
1315
1308
|
for moment in self:
|
|
1316
1309
|
resolved_moment = protocols.resolve_parameters(moment, resolver, recursive)
|
|
1317
1310
|
if resolved_moment is not moment:
|
|
@@ -1321,7 +1314,7 @@ class AbstractCircuit(abc.ABC):
|
|
|
1321
1314
|
return self # pragma: no cover
|
|
1322
1315
|
return self._from_moments(resolved_moments)
|
|
1323
1316
|
|
|
1324
|
-
def _qasm_(self, args:
|
|
1317
|
+
def _qasm_(self, args: cirq.QasmArgs | None = None) -> str:
|
|
1325
1318
|
if args is None:
|
|
1326
1319
|
output = self._to_qasm_output()
|
|
1327
1320
|
else:
|
|
@@ -1330,7 +1323,7 @@ class AbstractCircuit(abc.ABC):
|
|
|
1330
1323
|
|
|
1331
1324
|
def _to_qasm_output(
|
|
1332
1325
|
self,
|
|
1333
|
-
header:
|
|
1326
|
+
header: str | None = None,
|
|
1334
1327
|
precision: int = 10,
|
|
1335
1328
|
qubit_order: cirq.QubitOrderOrList = ops.QubitOrder.DEFAULT,
|
|
1336
1329
|
version: str = '2.0',
|
|
@@ -1359,7 +1352,7 @@ class AbstractCircuit(abc.ABC):
|
|
|
1359
1352
|
|
|
1360
1353
|
def to_qasm(
|
|
1361
1354
|
self,
|
|
1362
|
-
header:
|
|
1355
|
+
header: str | None = None,
|
|
1363
1356
|
precision: int = 10,
|
|
1364
1357
|
qubit_order: cirq.QubitOrderOrList = ops.QubitOrder.DEFAULT,
|
|
1365
1358
|
version: str = '2.0',
|
|
@@ -1380,8 +1373,8 @@ class AbstractCircuit(abc.ABC):
|
|
|
1380
1373
|
|
|
1381
1374
|
def save_qasm(
|
|
1382
1375
|
self,
|
|
1383
|
-
file_path:
|
|
1384
|
-
header:
|
|
1376
|
+
file_path: str | bytes | int,
|
|
1377
|
+
header: str | None = None,
|
|
1385
1378
|
precision: int = 10,
|
|
1386
1379
|
qubit_order: cirq.QubitOrderOrList = ops.QubitOrder.DEFAULT,
|
|
1387
1380
|
) -> None:
|
|
@@ -1405,7 +1398,7 @@ class AbstractCircuit(abc.ABC):
|
|
|
1405
1398
|
return cls(moments, strategy=InsertStrategy.EARLIEST)
|
|
1406
1399
|
|
|
1407
1400
|
def zip(
|
|
1408
|
-
*circuits: cirq.AbstractCircuit, align:
|
|
1401
|
+
*circuits: cirq.AbstractCircuit, align: cirq.Alignment | str = Alignment.LEFT
|
|
1409
1402
|
) -> cirq.AbstractCircuit:
|
|
1410
1403
|
"""Combines operations from circuits in a moment-by-moment fashion.
|
|
1411
1404
|
|
|
@@ -1481,7 +1474,7 @@ class AbstractCircuit(abc.ABC):
|
|
|
1481
1474
|
return result
|
|
1482
1475
|
|
|
1483
1476
|
def concat_ragged(
|
|
1484
|
-
*circuits: cirq.AbstractCircuit, align:
|
|
1477
|
+
*circuits: cirq.AbstractCircuit, align: cirq.Alignment | str = Alignment.LEFT
|
|
1485
1478
|
) -> cirq.AbstractCircuit:
|
|
1486
1479
|
"""Concatenates circuits, overlapping them if possible due to ragged edges.
|
|
1487
1480
|
|
|
@@ -1537,7 +1530,7 @@ class AbstractCircuit(abc.ABC):
|
|
|
1537
1530
|
|
|
1538
1531
|
return cirq.Circuit(buffer[offset : offset + n_acc])
|
|
1539
1532
|
|
|
1540
|
-
def get_independent_qubit_sets(self) ->
|
|
1533
|
+
def get_independent_qubit_sets(self) -> list[set[cirq.Qid]]:
|
|
1541
1534
|
"""Divide circuit's qubits into independent qubit sets.
|
|
1542
1535
|
|
|
1543
1536
|
Independent qubit sets are the qubit sets such that there are
|
|
@@ -1616,7 +1609,7 @@ class AbstractCircuit(abc.ABC):
|
|
|
1616
1609
|
# moments.
|
|
1617
1610
|
return (self._from_moments(m[qubits] for m in self.moments) for qubits in qubit_factors)
|
|
1618
1611
|
|
|
1619
|
-
def _control_keys_(self) ->
|
|
1612
|
+
def _control_keys_(self) -> frozenset[cirq.MeasurementKey]:
|
|
1620
1613
|
controls = frozenset(k for op in self.all_operations() for k in protocols.control_keys(op))
|
|
1621
1614
|
return controls - protocols.measurement_key_objs(self)
|
|
1622
1615
|
|
|
@@ -1626,7 +1619,7 @@ def _overlap_collision_time(
|
|
|
1626
1619
|
) -> int:
|
|
1627
1620
|
# Tracks the first used moment index for each qubit in c2.
|
|
1628
1621
|
# Tracks the complementary last used moment index for each qubit in c1.
|
|
1629
|
-
seen_times:
|
|
1622
|
+
seen_times: dict[cirq.Qid, int] = {}
|
|
1630
1623
|
|
|
1631
1624
|
# Start scanning from end of first and start of second.
|
|
1632
1625
|
if align == Alignment.LEFT:
|
|
@@ -1667,7 +1660,7 @@ def _concat_ragged_helper(
|
|
|
1667
1660
|
buf: MutableSequence[cirq.Moment],
|
|
1668
1661
|
c2: Sequence[cirq.Moment],
|
|
1669
1662
|
align: cirq.Alignment,
|
|
1670
|
-
) ->
|
|
1663
|
+
) -> tuple[int, int]:
|
|
1671
1664
|
n2 = len(c2)
|
|
1672
1665
|
shift = _overlap_collision_time(buf[c1_offset : c1_offset + n1], c2, align)
|
|
1673
1666
|
c2_offset = c1_offset + n1 - shift
|
|
@@ -1772,17 +1765,17 @@ class Circuit(AbstractCircuit):
|
|
|
1772
1765
|
together. This option does not affect later insertions into the
|
|
1773
1766
|
circuit.
|
|
1774
1767
|
"""
|
|
1775
|
-
self._placement_cache:
|
|
1776
|
-
self._moments:
|
|
1768
|
+
self._placement_cache: _PlacementCache | None = _PlacementCache()
|
|
1769
|
+
self._moments: list[cirq.Moment] = []
|
|
1777
1770
|
|
|
1778
1771
|
# Implementation note: the following cached properties are set lazily and then
|
|
1779
1772
|
# invalidated and reset to None in `self._mutated()`, which is called any time
|
|
1780
1773
|
# `self._moments` is changed.
|
|
1781
|
-
self._all_qubits:
|
|
1782
|
-
self._frozen:
|
|
1783
|
-
self._is_measurement:
|
|
1784
|
-
self._is_parameterized:
|
|
1785
|
-
self._parameter_names:
|
|
1774
|
+
self._all_qubits: frozenset[cirq.Qid] | None = None
|
|
1775
|
+
self._frozen: cirq.FrozenCircuit | None = None
|
|
1776
|
+
self._is_measurement: bool | None = None
|
|
1777
|
+
self._is_parameterized: bool | None = None
|
|
1778
|
+
self._parameter_names: AbstractSet[str] | None = None
|
|
1786
1779
|
if not contents:
|
|
1787
1780
|
return
|
|
1788
1781
|
flattened_contents = tuple(ops.flatten_to_ops_or_moments(contents))
|
|
@@ -1837,8 +1830,8 @@ class Circuit(AbstractCircuit):
|
|
|
1837
1830
|
|
|
1838
1831
|
# We also maintain the dict from moment index to moments/ops that go into it, for use when
|
|
1839
1832
|
# building the actual moments at the end.
|
|
1840
|
-
op_lists_by_index:
|
|
1841
|
-
moments_by_index:
|
|
1833
|
+
op_lists_by_index: dict[int, list[cirq.Operation]] = defaultdict(list)
|
|
1834
|
+
moments_by_index: dict[int, cirq.Moment] = {}
|
|
1842
1835
|
|
|
1843
1836
|
# "mop" means current moment-or-operation
|
|
1844
1837
|
for mop in ops.flatten_to_ops_or_moments(contents):
|
|
@@ -1875,7 +1868,7 @@ class Circuit(AbstractCircuit):
|
|
|
1875
1868
|
def unfreeze(self, copy: bool = True) -> cirq.Circuit:
|
|
1876
1869
|
return self.copy() if copy else self
|
|
1877
1870
|
|
|
1878
|
-
def all_qubits(self) ->
|
|
1871
|
+
def all_qubits(self) -> frozenset[cirq.Qid]:
|
|
1879
1872
|
if self._all_qubits is None:
|
|
1880
1873
|
self._all_qubits = super().all_qubits()
|
|
1881
1874
|
return self._all_qubits
|
|
@@ -1925,7 +1918,7 @@ class Circuit(AbstractCircuit):
|
|
|
1925
1918
|
|
|
1926
1919
|
# pylint: enable=function-redefined
|
|
1927
1920
|
|
|
1928
|
-
def __delitem__(self, key:
|
|
1921
|
+
def __delitem__(self, key: int | slice):
|
|
1929
1922
|
del self._moments[key]
|
|
1930
1923
|
self._mutated()
|
|
1931
1924
|
|
|
@@ -1993,21 +1986,21 @@ class Circuit(AbstractCircuit):
|
|
|
1993
1986
|
__hash__ = None # type: ignore
|
|
1994
1987
|
|
|
1995
1988
|
def concat_ragged(
|
|
1996
|
-
*circuits: cirq.AbstractCircuit, align:
|
|
1989
|
+
*circuits: cirq.AbstractCircuit, align: cirq.Alignment | str = Alignment.LEFT
|
|
1997
1990
|
) -> cirq.Circuit:
|
|
1998
1991
|
return AbstractCircuit.concat_ragged(*circuits, align=align).unfreeze(copy=False)
|
|
1999
1992
|
|
|
2000
1993
|
concat_ragged.__doc__ = AbstractCircuit.concat_ragged.__doc__
|
|
2001
1994
|
|
|
2002
1995
|
def zip(
|
|
2003
|
-
*circuits: cirq.AbstractCircuit, align:
|
|
1996
|
+
*circuits: cirq.AbstractCircuit, align: cirq.Alignment | str = Alignment.LEFT
|
|
2004
1997
|
) -> cirq.Circuit:
|
|
2005
1998
|
return AbstractCircuit.zip(*circuits, align=align).unfreeze(copy=False)
|
|
2006
1999
|
|
|
2007
2000
|
zip.__doc__ = AbstractCircuit.zip.__doc__
|
|
2008
2001
|
|
|
2009
2002
|
def transform_qubits(
|
|
2010
|
-
self, qubit_map:
|
|
2003
|
+
self, qubit_map: dict[cirq.Qid, cirq.Qid] | Callable[[cirq.Qid], cirq.Qid]
|
|
2011
2004
|
) -> cirq.Circuit:
|
|
2012
2005
|
"""Returns the same circuit, but with different qubits.
|
|
2013
2006
|
|
|
@@ -2055,7 +2048,7 @@ class Circuit(AbstractCircuit):
|
|
|
2055
2048
|
return Circuit(op_list)
|
|
2056
2049
|
|
|
2057
2050
|
def earliest_available_moment(
|
|
2058
|
-
self, op: cirq.Operation, *, end_moment_index:
|
|
2051
|
+
self, op: cirq.Operation, *, end_moment_index: int | None = None
|
|
2059
2052
|
) -> int:
|
|
2060
2053
|
"""Finds the index of the earliest (i.e. left most) moment which can accommodate `op`.
|
|
2061
2054
|
|
|
@@ -2148,7 +2141,7 @@ class Circuit(AbstractCircuit):
|
|
|
2148
2141
|
and not all(
|
|
2149
2142
|
(strategy is InsertStrategy.EARLIEST and self._can_add_op_at(k, op))
|
|
2150
2143
|
or (k > 0 and self._can_add_op_at(k - 1, op))
|
|
2151
|
-
for op in cast(
|
|
2144
|
+
for op in cast(list[cirq.Operation], batch)
|
|
2152
2145
|
)
|
|
2153
2146
|
):
|
|
2154
2147
|
self._moments.insert(k, Moment())
|
|
@@ -2227,10 +2220,10 @@ class Circuit(AbstractCircuit):
|
|
|
2227
2220
|
|
|
2228
2221
|
def _push_frontier(
|
|
2229
2222
|
self,
|
|
2230
|
-
early_frontier:
|
|
2231
|
-
late_frontier:
|
|
2232
|
-
update_qubits:
|
|
2233
|
-
) ->
|
|
2223
|
+
early_frontier: dict[cirq.Qid, int],
|
|
2224
|
+
late_frontier: dict[cirq.Qid, int],
|
|
2225
|
+
update_qubits: Iterable[cirq.Qid] | None = None,
|
|
2226
|
+
) -> tuple[int, int]:
|
|
2234
2227
|
"""Inserts moments to separate two frontiers.
|
|
2235
2228
|
|
|
2236
2229
|
After insertion n_new moments, the following holds:
|
|
@@ -2292,15 +2285,15 @@ class Circuit(AbstractCircuit):
|
|
|
2292
2285
|
raise ValueError('operations and insertion_indices must have the same length.')
|
|
2293
2286
|
self._moments += [Moment() for _ in range(1 + max(insertion_indices) - len(self))]
|
|
2294
2287
|
self._mutated()
|
|
2295
|
-
moment_to_ops:
|
|
2288
|
+
moment_to_ops: dict[int, list[cirq.Operation]] = defaultdict(list)
|
|
2296
2289
|
for op_index, moment_index in enumerate(insertion_indices):
|
|
2297
2290
|
moment_to_ops[moment_index].append(operations[op_index])
|
|
2298
2291
|
for moment_index, new_ops in moment_to_ops.items():
|
|
2299
2292
|
self._moments[moment_index] = self._moments[moment_index].with_operations(*new_ops)
|
|
2300
2293
|
|
|
2301
2294
|
def insert_at_frontier(
|
|
2302
|
-
self, operations: cirq.OP_TREE, start: int, frontier:
|
|
2303
|
-
) ->
|
|
2295
|
+
self, operations: cirq.OP_TREE, start: int, frontier: dict[cirq.Qid, int] | None = None
|
|
2296
|
+
) -> dict[cirq.Qid, int]:
|
|
2304
2297
|
"""Inserts operations inline at frontier.
|
|
2305
2298
|
|
|
2306
2299
|
Args:
|
|
@@ -2334,7 +2327,7 @@ class Circuit(AbstractCircuit):
|
|
|
2334
2327
|
|
|
2335
2328
|
return frontier
|
|
2336
2329
|
|
|
2337
|
-
def batch_remove(self, removals: Iterable[
|
|
2330
|
+
def batch_remove(self, removals: Iterable[tuple[int, cirq.Operation]]) -> None:
|
|
2338
2331
|
"""Removes several operations from a circuit.
|
|
2339
2332
|
|
|
2340
2333
|
Args:
|
|
@@ -2358,7 +2351,7 @@ class Circuit(AbstractCircuit):
|
|
|
2358
2351
|
self._mutated()
|
|
2359
2352
|
|
|
2360
2353
|
def batch_replace(
|
|
2361
|
-
self, replacements: Iterable[
|
|
2354
|
+
self, replacements: Iterable[tuple[int, cirq.Operation, cirq.Operation]]
|
|
2362
2355
|
) -> None:
|
|
2363
2356
|
"""Replaces several operations in a circuit with new operations.
|
|
2364
2357
|
|
|
@@ -2382,7 +2375,7 @@ class Circuit(AbstractCircuit):
|
|
|
2382
2375
|
self._moments = copy._moments
|
|
2383
2376
|
self._mutated()
|
|
2384
2377
|
|
|
2385
|
-
def batch_insert_into(self, insert_intos: Iterable[
|
|
2378
|
+
def batch_insert_into(self, insert_intos: Iterable[tuple[int, cirq.OP_TREE]]) -> None:
|
|
2386
2379
|
"""Inserts operations into empty spaces in existing moments.
|
|
2387
2380
|
|
|
2388
2381
|
If any of the insertions fails (due to colliding with an existing
|
|
@@ -2403,7 +2396,7 @@ class Circuit(AbstractCircuit):
|
|
|
2403
2396
|
self._moments = copy._moments
|
|
2404
2397
|
self._mutated()
|
|
2405
2398
|
|
|
2406
|
-
def batch_insert(self, insertions: Iterable[
|
|
2399
|
+
def batch_insert(self, insertions: Iterable[tuple[int, cirq.OP_TREE]]) -> None:
|
|
2407
2400
|
"""Applies a batched insert operation to the circuit.
|
|
2408
2401
|
|
|
2409
2402
|
Transparently handles the fact that earlier insertions may shift
|
|
@@ -2495,8 +2488,8 @@ class Circuit(AbstractCircuit):
|
|
|
2495
2488
|
def _pick_inserted_ops_moment_indices(
|
|
2496
2489
|
operations: Sequence[cirq.Operation],
|
|
2497
2490
|
start: int = 0,
|
|
2498
|
-
frontier:
|
|
2499
|
-
) ->
|
|
2491
|
+
frontier: dict[cirq.Qid, int] | None = None,
|
|
2492
|
+
) -> tuple[Sequence[int], dict[cirq.Qid, int]]:
|
|
2500
2493
|
"""Greedily assigns operations to moments.
|
|
2501
2494
|
|
|
2502
2495
|
Args:
|
|
@@ -2541,9 +2534,9 @@ def _draw_moment_annotations(
|
|
|
2541
2534
|
moment: cirq.Moment,
|
|
2542
2535
|
col: int,
|
|
2543
2536
|
use_unicode_characters: bool,
|
|
2544
|
-
label_map:
|
|
2537
|
+
label_map: dict[cirq.LabelEntity, int],
|
|
2545
2538
|
out_diagram: cirq.TextDiagramDrawer,
|
|
2546
|
-
precision:
|
|
2539
|
+
precision: int | None,
|
|
2547
2540
|
get_circuit_diagram_info: Callable[
|
|
2548
2541
|
[cirq.Operation, cirq.CircuitDiagramInfoArgs], cirq.CircuitDiagramInfo
|
|
2549
2542
|
],
|
|
@@ -2572,13 +2565,13 @@ def _draw_moment_in_diagram(
|
|
|
2572
2565
|
*,
|
|
2573
2566
|
moment: cirq.Moment,
|
|
2574
2567
|
use_unicode_characters: bool,
|
|
2575
|
-
label_map:
|
|
2568
|
+
label_map: dict[cirq.LabelEntity, int],
|
|
2576
2569
|
out_diagram: cirq.TextDiagramDrawer,
|
|
2577
|
-
precision:
|
|
2578
|
-
moment_groups:
|
|
2579
|
-
get_circuit_diagram_info:
|
|
2580
|
-
Callable[[cirq.Operation, cirq.CircuitDiagramInfoArgs], cirq.CircuitDiagramInfo]
|
|
2581
|
-
|
|
2570
|
+
precision: int | None,
|
|
2571
|
+
moment_groups: list[tuple[int, int]],
|
|
2572
|
+
get_circuit_diagram_info: (
|
|
2573
|
+
Callable[[cirq.Operation, cirq.CircuitDiagramInfoArgs], cirq.CircuitDiagramInfo] | None
|
|
2574
|
+
),
|
|
2582
2575
|
include_tags: bool,
|
|
2583
2576
|
first_annotation_row: int,
|
|
2584
2577
|
transpose: bool,
|
|
@@ -2662,7 +2655,7 @@ def _draw_moment_in_diagram(
|
|
|
2662
2655
|
moment_groups.append((x0, max_x))
|
|
2663
2656
|
|
|
2664
2657
|
|
|
2665
|
-
def _get_global_phase_and_tags_for_op(op: cirq.Operation) ->
|
|
2658
|
+
def _get_global_phase_and_tags_for_op(op: cirq.Operation) -> tuple[complex | None, list[Any]]:
|
|
2666
2659
|
if isinstance(op.gate, ops.GlobalPhaseGate):
|
|
2667
2660
|
return complex(op.gate.coefficient), list(op.tags)
|
|
2668
2661
|
elif isinstance(op.untagged, CircuitOperation):
|
|
@@ -2671,9 +2664,9 @@ def _get_global_phase_and_tags_for_op(op: cirq.Operation) -> Tuple[Optional[comp
|
|
|
2671
2664
|
return None, []
|
|
2672
2665
|
|
|
2673
2666
|
|
|
2674
|
-
def _get_global_phase_and_tags_for_ops(op_list: Any) ->
|
|
2675
|
-
global_phase:
|
|
2676
|
-
tags:
|
|
2667
|
+
def _get_global_phase_and_tags_for_ops(op_list: Any) -> tuple[complex | None, list[Any]]:
|
|
2668
|
+
global_phase: complex | None = None
|
|
2669
|
+
tags: list[Any] = []
|
|
2677
2670
|
for op in op_list:
|
|
2678
2671
|
op_phase, op_tags = _get_global_phase_and_tags_for_op(op)
|
|
2679
2672
|
if op_phase:
|
|
@@ -2685,7 +2678,7 @@ def _get_global_phase_and_tags_for_ops(op_list: Any) -> Tuple[Optional[complex],
|
|
|
2685
2678
|
return global_phase, tags
|
|
2686
2679
|
|
|
2687
2680
|
|
|
2688
|
-
def _formatted_phase(coefficient: complex, unicode: bool, precision:
|
|
2681
|
+
def _formatted_phase(coefficient: complex, unicode: bool, precision: int | None) -> str:
|
|
2689
2682
|
h = math.atan2(coefficient.imag, coefficient.real) / math.pi
|
|
2690
2683
|
unit = 'π' if unicode else 'pi'
|
|
2691
2684
|
if h == 1:
|
|
@@ -2694,7 +2687,7 @@ def _formatted_phase(coefficient: complex, unicode: bool, precision: Optional[in
|
|
|
2694
2687
|
|
|
2695
2688
|
|
|
2696
2689
|
def _draw_moment_groups_in_diagram(
|
|
2697
|
-
moment_groups:
|
|
2690
|
+
moment_groups: list[tuple[int, int]],
|
|
2698
2691
|
use_unicode_characters: bool,
|
|
2699
2692
|
out_diagram: cirq.TextDiagramDrawer,
|
|
2700
2693
|
):
|
|
@@ -2728,8 +2721,8 @@ def _draw_moment_groups_in_diagram(
|
|
|
2728
2721
|
def _apply_unitary_circuit(
|
|
2729
2722
|
circuit: cirq.AbstractCircuit,
|
|
2730
2723
|
state: np.ndarray,
|
|
2731
|
-
qubits:
|
|
2732
|
-
dtype:
|
|
2724
|
+
qubits: tuple[cirq.Qid, ...],
|
|
2725
|
+
dtype: type[np.complexfloating],
|
|
2733
2726
|
) -> np.ndarray:
|
|
2734
2727
|
"""Applies a circuit's unitary effect to the given vector or matrix.
|
|
2735
2728
|
|
|
@@ -2792,14 +2785,14 @@ _TKey = TypeVar('_TKey')
|
|
|
2792
2785
|
@overload
|
|
2793
2786
|
def _group_until_different(
|
|
2794
2787
|
items: Iterable[_TIn], key: Callable[[_TIn], _TKey]
|
|
2795
|
-
) -> Iterable[
|
|
2788
|
+
) -> Iterable[tuple[_TKey, list[_TIn]]]:
|
|
2796
2789
|
pass
|
|
2797
2790
|
|
|
2798
2791
|
|
|
2799
2792
|
@overload
|
|
2800
2793
|
def _group_until_different(
|
|
2801
2794
|
items: Iterable[_TIn], key: Callable[[_TIn], _TKey], val: Callable[[_TIn], _TOut]
|
|
2802
|
-
) -> Iterable[
|
|
2795
|
+
) -> Iterable[tuple[_TKey, list[_TOut]]]:
|
|
2803
2796
|
pass
|
|
2804
2797
|
|
|
2805
2798
|
|
|
@@ -2829,7 +2822,7 @@ def _group_until_different(items: Iterable[_TIn], key: Callable[[_TIn], _TKey],
|
|
|
2829
2822
|
return ((k, [val(i) for i in v]) for (k, v) in itertools.groupby(items, key))
|
|
2830
2823
|
|
|
2831
2824
|
|
|
2832
|
-
def _group_into_moment_compatible(inputs: Sequence[_MOMENT_OR_OP]) -> Iterator[
|
|
2825
|
+
def _group_into_moment_compatible(inputs: Sequence[_MOMENT_OR_OP]) -> Iterator[list[_MOMENT_OR_OP]]:
|
|
2833
2826
|
"""Groups sequential ops into those that can coexist in a single moment.
|
|
2834
2827
|
|
|
2835
2828
|
This function will go through the input sequence in order, emitting lists of sequential
|
|
@@ -2844,8 +2837,8 @@ def _group_into_moment_compatible(inputs: Sequence[_MOMENT_OR_OP]) -> Iterator[L
|
|
|
2844
2837
|
[X(a), X(a), X(b)] -> [[X(a)], [X(a), X(b)]]
|
|
2845
2838
|
[X(a), Moment(X(b)), X(c)] -> [[X(a)], [Moment(X(b))], [X(c)]]
|
|
2846
2839
|
"""
|
|
2847
|
-
batch:
|
|
2848
|
-
batch_qubits:
|
|
2840
|
+
batch: list[_MOMENT_OR_OP] = []
|
|
2841
|
+
batch_qubits: set[cirq.Qid] = set()
|
|
2849
2842
|
for mop in inputs:
|
|
2850
2843
|
is_moment = isinstance(mop, cirq.Moment)
|
|
2851
2844
|
if (is_moment and batch) or not batch_qubits.isdisjoint(mop.qubits):
|
|
@@ -2863,10 +2856,10 @@ def _group_into_moment_compatible(inputs: Sequence[_MOMENT_OR_OP]) -> Iterator[L
|
|
|
2863
2856
|
|
|
2864
2857
|
def get_earliest_accommodating_moment_index(
|
|
2865
2858
|
moment_or_operation: _MOMENT_OR_OP,
|
|
2866
|
-
qubit_indices:
|
|
2867
|
-
mkey_indices:
|
|
2868
|
-
ckey_indices:
|
|
2869
|
-
length:
|
|
2859
|
+
qubit_indices: dict[cirq.Qid, int],
|
|
2860
|
+
mkey_indices: dict[cirq.MeasurementKey, int],
|
|
2861
|
+
ckey_indices: dict[cirq.MeasurementKey, int],
|
|
2862
|
+
length: int | None = None,
|
|
2870
2863
|
) -> int:
|
|
2871
2864
|
"""Get the index of the earliest moment that can accommodate the given moment or operation.
|
|
2872
2865
|
|
|
@@ -2951,9 +2944,9 @@ class _PlacementCache:
|
|
|
2951
2944
|
|
|
2952
2945
|
def __init__(self) -> None:
|
|
2953
2946
|
# These are dicts from the qubit/key to the greatest moment index that has it.
|
|
2954
|
-
self._qubit_indices:
|
|
2955
|
-
self._mkey_indices:
|
|
2956
|
-
self._ckey_indices:
|
|
2947
|
+
self._qubit_indices: dict[cirq.Qid, int] = {}
|
|
2948
|
+
self._mkey_indices: dict[cirq.MeasurementKey, int] = {}
|
|
2949
|
+
self._ckey_indices: dict[cirq.MeasurementKey, int] = {}
|
|
2957
2950
|
|
|
2958
2951
|
# For keeping track of length of the circuit thus far.
|
|
2959
2952
|
self._length = 0
|