cirq-core 1.6.0.dev20250520054601__py3-none-any.whl → 1.6.0.dev20250520181654__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/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.dev20250520181654.dist-info}/METADATA +1 -1
- {cirq_core-1.6.0.dev20250520054601.dist-info → cirq_core-1.6.0.dev20250520181654.dist-info}/RECORD +289 -289
- {cirq_core-1.6.0.dev20250520054601.dist-info → cirq_core-1.6.0.dev20250520181654.dist-info}/WHEEL +1 -1
- {cirq_core-1.6.0.dev20250520054601.dist-info → cirq_core-1.6.0.dev20250520181654.dist-info}/licenses/LICENSE +0 -0
- {cirq_core-1.6.0.dev20250520054601.dist-info → cirq_core-1.6.0.dev20250520181654.dist-info}/top_level.txt +0 -0
cirq/circuits/qasm_output.py
CHANGED
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
from __future__ import annotations
|
|
18
18
|
|
|
19
19
|
import re
|
|
20
|
-
from typing import Callable,
|
|
20
|
+
from typing import Callable, Iterator, Sequence, TYPE_CHECKING
|
|
21
21
|
|
|
22
22
|
import numpy as np
|
|
23
23
|
|
|
@@ -55,7 +55,7 @@ class QasmUGate(ops.Gate):
|
|
|
55
55
|
def _has_unitary_(self):
|
|
56
56
|
return True
|
|
57
57
|
|
|
58
|
-
def _qasm_(self, qubits:
|
|
58
|
+
def _qasm_(self, qubits: tuple[cirq.Qid, ...], args: cirq.QasmArgs) -> str:
|
|
59
59
|
args.validate_version('2.0', '3.0')
|
|
60
60
|
return args.format(
|
|
61
61
|
'u3({0:half_turns},{1:half_turns},{2:half_turns}) {3};\n',
|
|
@@ -84,7 +84,7 @@ class QasmUGate(ops.Gate):
|
|
|
84
84
|
def _value_equality_values_(self):
|
|
85
85
|
return self.lmda, self.theta, self.phi
|
|
86
86
|
|
|
87
|
-
def _json_dict_(self) ->
|
|
87
|
+
def _json_dict_(self) -> dict[str, float]:
|
|
88
88
|
return {'theta': self.theta, 'phi': self.phi, 'lmda': self.lmda}
|
|
89
89
|
|
|
90
90
|
@classmethod
|
|
@@ -173,7 +173,7 @@ class QasmOutput:
|
|
|
173
173
|
def __init__(
|
|
174
174
|
self,
|
|
175
175
|
operations: cirq.OP_TREE,
|
|
176
|
-
qubits:
|
|
176
|
+
qubits: tuple[cirq.Qid, ...],
|
|
177
177
|
header: str = '',
|
|
178
178
|
precision: int = 10,
|
|
179
179
|
version: str = '2.0',
|
|
@@ -208,10 +208,10 @@ class QasmOutput:
|
|
|
208
208
|
meas_key_bitcount={k: v[0] for k, v in self.cregs.items()},
|
|
209
209
|
)
|
|
210
210
|
|
|
211
|
-
def _generate_measurement_ids(self) ->
|
|
211
|
+
def _generate_measurement_ids(self) -> tuple[dict[str, str], dict[str, str | None]]:
|
|
212
212
|
# Pick an id for the creg that will store each measurement
|
|
213
|
-
meas_key_id_map:
|
|
214
|
-
meas_comments:
|
|
213
|
+
meas_key_id_map: dict[str, str] = {}
|
|
214
|
+
meas_comments: dict[str, str | None] = {}
|
|
215
215
|
meas_i = 0
|
|
216
216
|
for meas in self.measurements:
|
|
217
217
|
key = protocols.measurement_key_name(meas)
|
|
@@ -227,10 +227,10 @@ class QasmOutput:
|
|
|
227
227
|
meas_key_id_map[key] = meas_id
|
|
228
228
|
return meas_key_id_map, meas_comments
|
|
229
229
|
|
|
230
|
-
def _generate_qubit_ids(self) ->
|
|
230
|
+
def _generate_qubit_ids(self) -> dict[cirq.Qid, str]:
|
|
231
231
|
return {qubit: f'q[{i}]' for i, qubit in enumerate(self.qubits)}
|
|
232
232
|
|
|
233
|
-
def _generate_cregs(self, meas_key_id_map:
|
|
233
|
+
def _generate_cregs(self, meas_key_id_map: dict[str, str]) -> dict[str, tuple[int, str]]:
|
|
234
234
|
"""Pick an id for the creg that will store each measurement
|
|
235
235
|
|
|
236
236
|
This function finds the largest measurement using each key.
|
|
@@ -239,7 +239,7 @@ class QasmOutput:
|
|
|
239
239
|
|
|
240
240
|
Returns: dictionary with key of measurement id and value of (#qubits, comment).
|
|
241
241
|
"""
|
|
242
|
-
cregs:
|
|
242
|
+
cregs: dict[str, tuple[int, str]] = {}
|
|
243
243
|
for meas in self.measurements:
|
|
244
244
|
key = protocols.measurement_key_name(meas)
|
|
245
245
|
meas_id = meas_key_id_map[key]
|
|
@@ -258,7 +258,7 @@ class QasmOutput:
|
|
|
258
258
|
"""Test if id_str is a valid id in QASM grammar."""
|
|
259
259
|
return self.valid_id_re.match(id_str) is not None
|
|
260
260
|
|
|
261
|
-
def save(self, path:
|
|
261
|
+
def save(self, path: str | bytes | int) -> None:
|
|
262
262
|
"""Write QASM output to a file specified by path."""
|
|
263
263
|
with open(path, 'w') as f:
|
|
264
264
|
|
|
@@ -14,20 +14,7 @@
|
|
|
14
14
|
|
|
15
15
|
from __future__ import annotations
|
|
16
16
|
|
|
17
|
-
from typing import
|
|
18
|
-
Any,
|
|
19
|
-
Callable,
|
|
20
|
-
cast,
|
|
21
|
-
Dict,
|
|
22
|
-
Iterable,
|
|
23
|
-
List,
|
|
24
|
-
Mapping,
|
|
25
|
-
NamedTuple,
|
|
26
|
-
Optional,
|
|
27
|
-
Sequence,
|
|
28
|
-
Tuple,
|
|
29
|
-
TYPE_CHECKING,
|
|
30
|
-
)
|
|
17
|
+
from typing import Any, Callable, cast, Iterable, Mapping, NamedTuple, Sequence, TYPE_CHECKING
|
|
31
18
|
|
|
32
19
|
import numpy as np
|
|
33
20
|
|
|
@@ -73,25 +60,25 @@ class TextDiagramDrawer:
|
|
|
73
60
|
|
|
74
61
|
def __init__(
|
|
75
62
|
self,
|
|
76
|
-
entries:
|
|
77
|
-
horizontal_lines:
|
|
78
|
-
vertical_lines:
|
|
79
|
-
horizontal_padding:
|
|
80
|
-
vertical_padding:
|
|
63
|
+
entries: Mapping[tuple[int, int], _DiagramText] | None = None,
|
|
64
|
+
horizontal_lines: Iterable[_HorizontalLine] | None = None,
|
|
65
|
+
vertical_lines: Iterable[_VerticalLine] | None = None,
|
|
66
|
+
horizontal_padding: Mapping[int, int] | None = None,
|
|
67
|
+
vertical_padding: Mapping[int, int] | None = None,
|
|
81
68
|
) -> None:
|
|
82
|
-
self.entries:
|
|
69
|
+
self.entries: dict[tuple[int, int], _DiagramText] = (
|
|
83
70
|
dict() if entries is None else dict(entries)
|
|
84
71
|
)
|
|
85
|
-
self.horizontal_lines:
|
|
72
|
+
self.horizontal_lines: list[_HorizontalLine] = (
|
|
86
73
|
[] if horizontal_lines is None else list(horizontal_lines)
|
|
87
74
|
)
|
|
88
|
-
self.vertical_lines:
|
|
75
|
+
self.vertical_lines: list[_VerticalLine] = (
|
|
89
76
|
[] if vertical_lines is None else list(vertical_lines)
|
|
90
77
|
)
|
|
91
|
-
self.horizontal_padding:
|
|
78
|
+
self.horizontal_padding: dict[int, float] = (
|
|
92
79
|
dict() if horizontal_padding is None else dict(horizontal_padding)
|
|
93
80
|
)
|
|
94
|
-
self.vertical_padding:
|
|
81
|
+
self.vertical_padding: dict[int, float] = (
|
|
95
82
|
dict() if vertical_padding is None else dict(vertical_padding)
|
|
96
83
|
)
|
|
97
84
|
|
|
@@ -108,7 +95,7 @@ class TextDiagramDrawer:
|
|
|
108
95
|
def __bool__(self):
|
|
109
96
|
return any(self._value_equality_values_())
|
|
110
97
|
|
|
111
|
-
def write(self, x: int, y: int, text: str, transposed_text:
|
|
98
|
+
def write(self, x: int, y: int, text: str, transposed_text: str | None = None):
|
|
112
99
|
"""Adds text to the given location.
|
|
113
100
|
|
|
114
101
|
Args:
|
|
@@ -215,7 +202,7 @@ class TextDiagramDrawer:
|
|
|
215
202
|
"""Change the padding after the given row."""
|
|
216
203
|
self.vertical_padding[index] = padding
|
|
217
204
|
|
|
218
|
-
def _transform_coordinates(self, func: Callable[[float, float],
|
|
205
|
+
def _transform_coordinates(self, func: Callable[[float, float], tuple[float, float]]) -> None:
|
|
219
206
|
"""Helper method to transformer either row or column coordinates."""
|
|
220
207
|
|
|
221
208
|
def func_x(x: float) -> float:
|
|
@@ -225,7 +212,7 @@ class TextDiagramDrawer:
|
|
|
225
212
|
return func(0, y)[1]
|
|
226
213
|
|
|
227
214
|
self.entries = {
|
|
228
|
-
cast(
|
|
215
|
+
cast(tuple[int, int], func(int(x), int(y))): v for (x, y), v in self.entries.items()
|
|
229
216
|
}
|
|
230
217
|
self.vertical_lines = [
|
|
231
218
|
_VerticalLine(func_x(x), func_y(y1), func_y(y2), emph, doubled)
|
|
@@ -245,7 +232,7 @@ class TextDiagramDrawer:
|
|
|
245
232
|
def insert_empty_columns(self, x: int, amount: int = 1) -> None:
|
|
246
233
|
"""Insert a number of columns after the given column."""
|
|
247
234
|
|
|
248
|
-
def transform_columns(column: float, row: float) ->
|
|
235
|
+
def transform_columns(column: float, row: float) -> tuple[float, float]:
|
|
249
236
|
return column + (amount if column >= x else 0), row
|
|
250
237
|
|
|
251
238
|
self._transform_coordinates(transform_columns)
|
|
@@ -253,7 +240,7 @@ class TextDiagramDrawer:
|
|
|
253
240
|
def insert_empty_rows(self, y: int, amount: int = 1) -> None:
|
|
254
241
|
"""Insert a number of rows after the given row."""
|
|
255
242
|
|
|
256
|
-
def transform_rows(column: float, row: float) ->
|
|
243
|
+
def transform_rows(column: float, row: float) -> tuple[float, float]:
|
|
257
244
|
return column, row + (amount if row >= y else 0)
|
|
258
245
|
|
|
259
246
|
self._transform_coordinates(transform_rows)
|
|
@@ -262,7 +249,7 @@ class TextDiagramDrawer:
|
|
|
262
249
|
self,
|
|
263
250
|
horizontal_spacing: int = 1,
|
|
264
251
|
vertical_spacing: int = 1,
|
|
265
|
-
crossing_char:
|
|
252
|
+
crossing_char: str | None = None,
|
|
266
253
|
use_unicode_characters: bool = True,
|
|
267
254
|
) -> str:
|
|
268
255
|
"""Outputs text containing the diagram."""
|
|
@@ -357,7 +344,7 @@ class TextDiagramDrawer:
|
|
|
357
344
|
def vstack(
|
|
358
345
|
cls,
|
|
359
346
|
diagrams: Sequence[cirq.TextDiagramDrawer],
|
|
360
|
-
padding_resolver:
|
|
347
|
+
padding_resolver: Callable[[Sequence[int | None]], int] | None = None,
|
|
361
348
|
):
|
|
362
349
|
"""Vertically stack text diagrams.
|
|
363
350
|
|
|
@@ -386,9 +373,7 @@ class TextDiagramDrawer:
|
|
|
386
373
|
dy += diagram.height()
|
|
387
374
|
for x in stacked.horizontal_padding:
|
|
388
375
|
resolved_padding = padding_resolver(
|
|
389
|
-
tuple(
|
|
390
|
-
cast(Optional[int], diagram.horizontal_padding.get(x)) for diagram in diagrams
|
|
391
|
-
)
|
|
376
|
+
tuple(cast(int | None, diagram.horizontal_padding.get(x)) for diagram in diagrams)
|
|
392
377
|
)
|
|
393
378
|
if resolved_padding is not None:
|
|
394
379
|
stacked.horizontal_padding[x] = resolved_padding
|
|
@@ -398,7 +383,7 @@ class TextDiagramDrawer:
|
|
|
398
383
|
def hstack(
|
|
399
384
|
cls,
|
|
400
385
|
diagrams: Sequence[cirq.TextDiagramDrawer],
|
|
401
|
-
padding_resolver:
|
|
386
|
+
padding_resolver: Callable[[Sequence[int | None]], int] | None = None,
|
|
402
387
|
):
|
|
403
388
|
"""Horizontally stack text diagrams.
|
|
404
389
|
|
|
@@ -427,7 +412,7 @@ class TextDiagramDrawer:
|
|
|
427
412
|
dx += diagram.width()
|
|
428
413
|
for y in stacked.vertical_padding:
|
|
429
414
|
resolved_padding = padding_resolver(
|
|
430
|
-
tuple(cast(
|
|
415
|
+
tuple(cast(int | None, diagram.vertical_padding.get(y)) for diagram in diagrams)
|
|
431
416
|
)
|
|
432
417
|
if resolved_padding is not None:
|
|
433
418
|
stacked.vertical_padding[y] = resolved_padding
|
|
@@ -16,7 +16,7 @@ from __future__ import annotations
|
|
|
16
16
|
|
|
17
17
|
import enum
|
|
18
18
|
import itertools
|
|
19
|
-
from typing import
|
|
19
|
+
from typing import Iterator, Sequence, TYPE_CHECKING
|
|
20
20
|
|
|
21
21
|
from cirq import ops
|
|
22
22
|
from cirq.contrib.acquaintance.gates import acquaint
|
|
@@ -61,10 +61,7 @@ class BipartiteSwapNetworkGate(PermutationGate):
|
|
|
61
61
|
"""
|
|
62
62
|
|
|
63
63
|
def __init__(
|
|
64
|
-
self,
|
|
65
|
-
subgraph: Union[str, BipartiteGraphType],
|
|
66
|
-
part_size: int,
|
|
67
|
-
swap_gate: cirq.Gate = ops.SWAP,
|
|
64
|
+
self, subgraph: str | BipartiteGraphType, part_size: int, swap_gate: cirq.Gate = ops.SWAP
|
|
68
65
|
) -> None:
|
|
69
66
|
super().__init__(2 * part_size, swap_gate)
|
|
70
67
|
self.part_size = part_size
|
|
@@ -106,7 +103,7 @@ class BipartiteSwapNetworkGate(PermutationGate):
|
|
|
106
103
|
return self.decompose_matching(qubits)
|
|
107
104
|
raise NotImplementedError('No decomposition implemented for ' + str(self.subgraph))
|
|
108
105
|
|
|
109
|
-
def permutation(self) ->
|
|
106
|
+
def permutation(self) -> dict[int, int]:
|
|
110
107
|
if self.num_qubits() != 2 * self.part_size:
|
|
111
108
|
raise ValueError('qubit_count != 2 * self.part_size')
|
|
112
109
|
if self.subgraph == BipartiteGraphType.MATCHING:
|
|
@@ -124,7 +121,7 @@ class BipartiteSwapNetworkGate(PermutationGate):
|
|
|
124
121
|
return dict(enumerate(range(2 * self.part_size)))
|
|
125
122
|
raise NotImplementedError(str(self.subgraph) + 'not implemented')
|
|
126
123
|
|
|
127
|
-
def _circuit_diagram_info_(self, args: cirq.CircuitDiagramInfoArgs) ->
|
|
124
|
+
def _circuit_diagram_info_(self, args: cirq.CircuitDiagramInfoArgs) -> tuple[str, ...]:
|
|
128
125
|
qubit_count = 2 * self.part_size
|
|
129
126
|
if args.known_qubit_count not in (None, qubit_count):
|
|
130
127
|
raise ValueError('args.known_qubit_count not in (None, 2 * self.part_size)')
|
|
@@ -149,7 +146,7 @@ class BipartiteSwapNetworkGate(PermutationGate):
|
|
|
149
146
|
return wire_symbols
|
|
150
147
|
|
|
151
148
|
def __repr__(self) -> str:
|
|
152
|
-
args:
|
|
149
|
+
args: tuple[str, ...] = (repr(self.subgraph), repr(self.part_size))
|
|
153
150
|
if self.swap_gate != ops.SWAP:
|
|
154
151
|
args += (repr(self.swap_gate),)
|
|
155
152
|
args_str = ', '.join(args)
|
|
@@ -16,7 +16,7 @@ from __future__ import annotations
|
|
|
16
16
|
|
|
17
17
|
import abc
|
|
18
18
|
from collections import defaultdict
|
|
19
|
-
from typing import
|
|
19
|
+
from typing import Iterator, Sequence, TYPE_CHECKING
|
|
20
20
|
|
|
21
21
|
from cirq import circuits, devices, ops, protocols, transformers
|
|
22
22
|
from cirq.contrib.acquaintance.gates import AcquaintanceOpportunityGate
|
|
@@ -99,7 +99,7 @@ class StrategyExecutorTransformer:
|
|
|
99
99
|
self._mapping = execution_strategy.initial_mapping.copy()
|
|
100
100
|
|
|
101
101
|
def __call__(
|
|
102
|
-
self, circuit: circuits.AbstractCircuit, context:
|
|
102
|
+
self, circuit: circuits.AbstractCircuit, context: cirq.TransformerContext | None = None
|
|
103
103
|
) -> circuits.Circuit:
|
|
104
104
|
"""Executes an acquaintance strategy using cirq.map_operations_and_unroll and
|
|
105
105
|
mutates initial mapping.
|
|
@@ -174,7 +174,7 @@ class GreedyExecutionStrategy(ExecutionStrategy):
|
|
|
174
174
|
self,
|
|
175
175
|
gates: LogicalGates,
|
|
176
176
|
initial_mapping: LogicalMapping,
|
|
177
|
-
device:
|
|
177
|
+
device: cirq.Device | None = None,
|
|
178
178
|
) -> None:
|
|
179
179
|
"""Inits GreedyExecutionStrategy.
|
|
180
180
|
|
|
@@ -214,13 +214,13 @@ class GreedyExecutionStrategy(ExecutionStrategy):
|
|
|
214
214
|
yield gate(*[index_to_qubit[i] for i in gate_indices])
|
|
215
215
|
|
|
216
216
|
@staticmethod
|
|
217
|
-
def canonicalize_gates(gates: LogicalGates) ->
|
|
217
|
+
def canonicalize_gates(gates: LogicalGates) -> dict[frozenset, LogicalGates]:
|
|
218
218
|
"""Canonicalizes a set of gates by the qubits they act on.
|
|
219
219
|
|
|
220
220
|
Takes a set of gates specified by ordered sequences of logical
|
|
221
221
|
indices, and groups those that act on the same qubits regardless of
|
|
222
222
|
order."""
|
|
223
|
-
canonicalized_gates:
|
|
223
|
+
canonicalized_gates: defaultdict[frozenset, LogicalGates] = defaultdict(dict)
|
|
224
224
|
for indices, gate in gates.items():
|
|
225
225
|
indices = tuple(indices)
|
|
226
226
|
canonicalized_gates[frozenset(indices)][indices] = gate
|
|
@@ -16,7 +16,7 @@ from __future__ import annotations
|
|
|
16
16
|
|
|
17
17
|
from itertools import combinations
|
|
18
18
|
from string import ascii_lowercase
|
|
19
|
-
from typing import
|
|
19
|
+
from typing import Sequence
|
|
20
20
|
|
|
21
21
|
import numpy as np
|
|
22
22
|
import pytest
|
|
@@ -87,7 +87,7 @@ def test_executor_explicit():
|
|
|
87
87
|
|
|
88
88
|
def random_diagonal_gates(
|
|
89
89
|
num_qubits: int, acquaintance_size: int
|
|
90
|
-
) ->
|
|
90
|
+
) -> dict[tuple[cirq.Qid, ...], cirq.Gate]:
|
|
91
91
|
|
|
92
92
|
return {
|
|
93
93
|
Q: cirq.DiagonalGate(np.random.random(2**acquaintance_size))
|
|
@@ -106,7 +106,7 @@ def random_diagonal_gates(
|
|
|
106
106
|
],
|
|
107
107
|
)
|
|
108
108
|
def test_executor_random(
|
|
109
|
-
num_qubits: int, acquaintance_size: int, gates:
|
|
109
|
+
num_qubits: int, acquaintance_size: int, gates: dict[tuple[cirq.Qid, ...], cirq.Gate]
|
|
110
110
|
):
|
|
111
111
|
qubits = cirq.LineQubit.range(num_qubits)
|
|
112
112
|
circuit = cca.complete_acquaintance_strategy(qubits, acquaintance_size)
|
|
@@ -18,17 +18,7 @@ import functools
|
|
|
18
18
|
import itertools
|
|
19
19
|
import math
|
|
20
20
|
import operator
|
|
21
|
-
from typing import
|
|
22
|
-
Dict,
|
|
23
|
-
Iterable,
|
|
24
|
-
Iterator,
|
|
25
|
-
List,
|
|
26
|
-
NamedTuple,
|
|
27
|
-
Optional,
|
|
28
|
-
Sequence,
|
|
29
|
-
Tuple,
|
|
30
|
-
TYPE_CHECKING,
|
|
31
|
-
)
|
|
21
|
+
from typing import Iterable, Iterator, NamedTuple, Sequence, TYPE_CHECKING
|
|
32
22
|
|
|
33
23
|
from cirq import ops, protocols, value
|
|
34
24
|
from cirq.contrib.acquaintance.permutation import (
|
|
@@ -44,10 +34,10 @@ if TYPE_CHECKING:
|
|
|
44
34
|
|
|
45
35
|
def operations_to_part_lens(
|
|
46
36
|
qubit_order: Sequence[cirq.Qid], op_tree: cirq.OP_TREE
|
|
47
|
-
) ->
|
|
37
|
+
) -> tuple[int, ...]:
|
|
48
38
|
qubit_sort_key = functools.partial(operator.indexOf, qubit_order)
|
|
49
39
|
op_parts = [tuple(sorted(op.qubits, key=qubit_sort_key)) for op in ops.flatten_op_tree(op_tree)]
|
|
50
|
-
singletons:
|
|
40
|
+
singletons: list[tuple[cirq.Qid, ...]] = [(q,) for q in set(qubit_order).difference(*op_parts)]
|
|
51
41
|
part_sort_key = lambda p: min(qubit_sort_key(q) for q in p)
|
|
52
42
|
parts = tuple(tuple(part) for part in sorted(singletons + op_parts, key=part_sort_key))
|
|
53
43
|
|
|
@@ -87,16 +77,16 @@ def acquaint(*qubits) -> cirq.Operation:
|
|
|
87
77
|
Layers = NamedTuple(
|
|
88
78
|
'Layers',
|
|
89
79
|
[
|
|
90
|
-
('prior_interstitial',
|
|
91
|
-
('pre',
|
|
92
|
-
('intra',
|
|
93
|
-
('post',
|
|
94
|
-
('posterior_interstitial',
|
|
80
|
+
('prior_interstitial', list['cirq.Operation']),
|
|
81
|
+
('pre', list['cirq.Operation']),
|
|
82
|
+
('intra', list['cirq.Operation']),
|
|
83
|
+
('post', list['cirq.Operation']),
|
|
84
|
+
('posterior_interstitial', list['cirq.Operation']),
|
|
95
85
|
],
|
|
96
86
|
)
|
|
97
87
|
|
|
98
88
|
|
|
99
|
-
def new_layers(**kwargs:
|
|
89
|
+
def new_layers(**kwargs: list[cirq.Operation]) -> Layers:
|
|
100
90
|
return Layers._make(kwargs.get(field, []) for field in Layers._fields)
|
|
101
91
|
|
|
102
92
|
|
|
@@ -106,7 +96,7 @@ def acquaint_insides(
|
|
|
106
96
|
qubits: Sequence[cirq.Qid],
|
|
107
97
|
before: bool,
|
|
108
98
|
layers: Layers,
|
|
109
|
-
mapping:
|
|
99
|
+
mapping: dict[ops.Qid, int],
|
|
110
100
|
) -> None:
|
|
111
101
|
"""Acquaints each of the qubits with another set specified by an
|
|
112
102
|
acquaintance gate.
|
|
@@ -153,11 +143,11 @@ def _get_max_reach(size: int, round_up: bool = True) -> int:
|
|
|
153
143
|
|
|
154
144
|
|
|
155
145
|
def acquaint_and_shift(
|
|
156
|
-
parts:
|
|
146
|
+
parts: tuple[list[cirq.Qid], list[cirq.Qid]],
|
|
157
147
|
layers: Layers,
|
|
158
|
-
acquaintance_size:
|
|
148
|
+
acquaintance_size: int | None,
|
|
159
149
|
swap_gate: cirq.Gate,
|
|
160
|
-
mapping:
|
|
150
|
+
mapping: dict[ops.Qid, int],
|
|
161
151
|
):
|
|
162
152
|
"""Acquaints and shifts a pair of lists of qubits. The first part is
|
|
163
153
|
acquainted with every qubit individually in the second part, and vice
|
|
@@ -276,7 +266,7 @@ class SwapNetworkGate(PermutationGate):
|
|
|
276
266
|
def __init__(
|
|
277
267
|
self,
|
|
278
268
|
part_lens: Sequence[int],
|
|
279
|
-
acquaintance_size:
|
|
269
|
+
acquaintance_size: int | None = 0,
|
|
280
270
|
swap_gate: cirq.Gate = ops.SWAP,
|
|
281
271
|
) -> None:
|
|
282
272
|
super().__init__(sum(part_lens), swap_gate)
|
|
@@ -346,13 +336,13 @@ class SwapNetworkGate(PermutationGate):
|
|
|
346
336
|
def from_operations(
|
|
347
337
|
qubit_order: Sequence[cirq.Qid],
|
|
348
338
|
operations: Sequence[cirq.Operation],
|
|
349
|
-
acquaintance_size:
|
|
339
|
+
acquaintance_size: int | None = 0,
|
|
350
340
|
swap_gate: cirq.Gate = ops.SWAP,
|
|
351
341
|
) -> SwapNetworkGate:
|
|
352
342
|
part_sizes = operations_to_part_lens(qubit_order, operations)
|
|
353
343
|
return SwapNetworkGate(part_sizes, acquaintance_size, swap_gate)
|
|
354
344
|
|
|
355
|
-
def permutation(self) ->
|
|
345
|
+
def permutation(self) -> dict[int, int]:
|
|
356
346
|
return {i: j for i, j in enumerate(reversed(range(sum(self.part_lens))))}
|
|
357
347
|
|
|
358
348
|
def __repr__(self) -> str:
|
|
@@ -17,7 +17,7 @@ from __future__ import annotations
|
|
|
17
17
|
from itertools import combinations, product
|
|
18
18
|
from random import randint
|
|
19
19
|
from string import ascii_lowercase as alphabet
|
|
20
|
-
from typing import
|
|
20
|
+
from typing import Sequence
|
|
21
21
|
|
|
22
22
|
import numpy
|
|
23
23
|
import pytest
|
|
@@ -141,7 +141,7 @@ def test_acquaint_part_pairs(part_lens):
|
|
|
141
141
|
assert expected_opps == actual_opps
|
|
142
142
|
|
|
143
143
|
|
|
144
|
-
acquaintance_sizes:
|
|
144
|
+
acquaintance_sizes: tuple[int | None, ...] = (None,)
|
|
145
145
|
acquaintance_sizes += tuple(range(5))
|
|
146
146
|
|
|
147
147
|
|
|
@@ -256,7 +256,7 @@ class OtherOperation(cirq.Operation):
|
|
|
256
256
|
self._qubits = tuple(qubits)
|
|
257
257
|
|
|
258
258
|
@property
|
|
259
|
-
def qubits(self) ->
|
|
259
|
+
def qubits(self) -> tuple[cirq.Qid, ...]:
|
|
260
260
|
return self._qubits
|
|
261
261
|
|
|
262
262
|
def with_qubits(self, *new_qubits: cirq.Qid) -> OtherOperation:
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
from __future__ import annotations
|
|
16
16
|
|
|
17
17
|
import collections
|
|
18
|
-
from typing import cast,
|
|
18
|
+
from typing import cast, Sequence, TYPE_CHECKING
|
|
19
19
|
|
|
20
20
|
from cirq import circuits, ops, transformers
|
|
21
21
|
from cirq.contrib.acquaintance.devices import get_acquaintance_size
|
|
@@ -25,7 +25,7 @@ from cirq.contrib.acquaintance.permutation import PermutationGate
|
|
|
25
25
|
if TYPE_CHECKING:
|
|
26
26
|
import cirq
|
|
27
27
|
|
|
28
|
-
STRATEGY_GATE =
|
|
28
|
+
STRATEGY_GATE = AcquaintanceOpportunityGate | PermutationGate
|
|
29
29
|
|
|
30
30
|
|
|
31
31
|
def rectify_acquaintance_strategy(circuit: cirq.Circuit, acquaint_first: bool = True) -> None:
|
|
@@ -43,7 +43,7 @@ def rectify_acquaintance_strategy(circuit: cirq.Circuit, acquaint_first: bool =
|
|
|
43
43
|
"""
|
|
44
44
|
rectified_moments = []
|
|
45
45
|
for moment in circuit:
|
|
46
|
-
gate_type_to_ops:
|
|
46
|
+
gate_type_to_ops: dict[bool, list[ops.GateOperation]] = collections.defaultdict(list)
|
|
47
47
|
for op in moment.operations:
|
|
48
48
|
gate_op = cast(ops.GateOperation, op)
|
|
49
49
|
is_acquaintance = isinstance(gate_op.gate, AcquaintanceOpportunityGate)
|
|
@@ -59,7 +59,7 @@ def rectify_acquaintance_strategy(circuit: cirq.Circuit, acquaint_first: bool =
|
|
|
59
59
|
def replace_acquaintance_with_swap_network(
|
|
60
60
|
circuit: cirq.Circuit,
|
|
61
61
|
qubit_order: Sequence[cirq.Qid],
|
|
62
|
-
acquaintance_size:
|
|
62
|
+
acquaintance_size: int | None = 0,
|
|
63
63
|
swap_gate: cirq.Gate = ops.SWAP,
|
|
64
64
|
) -> bool:
|
|
65
65
|
"""Replace every rectified moment with acquaintance gates with a generalized swap network.
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
|
|
15
15
|
from __future__ import annotations
|
|
16
16
|
|
|
17
|
-
from typing import cast,
|
|
17
|
+
from typing import cast, Sequence, TYPE_CHECKING
|
|
18
18
|
|
|
19
19
|
from cirq import circuits
|
|
20
20
|
from cirq.contrib.acquaintance.executor import AcquaintanceOperation
|
|
@@ -36,11 +36,11 @@ def remove_redundant_acquaintance_opportunities(strategy: cirq.Circuit) -> int:
|
|
|
36
36
|
annotated_strategy = strategy.copy()
|
|
37
37
|
LogicalAnnotator(mapping)(annotated_strategy)
|
|
38
38
|
|
|
39
|
-
new_moments:
|
|
40
|
-
acquaintance_opps:
|
|
39
|
+
new_moments: list[cirq.Moment] = []
|
|
40
|
+
acquaintance_opps: set[frozenset[int]] = set()
|
|
41
41
|
n_removed = 0
|
|
42
42
|
for moment in annotated_strategy:
|
|
43
|
-
new_moment:
|
|
43
|
+
new_moment: list[cirq.Operation] = []
|
|
44
44
|
for op in moment:
|
|
45
45
|
if isinstance(op, AcquaintanceOperation):
|
|
46
46
|
opp = frozenset(cast(Sequence[int], op.logical_indices))
|
|
@@ -16,19 +16,7 @@ from __future__ import annotations
|
|
|
16
16
|
|
|
17
17
|
import abc
|
|
18
18
|
from types import NotImplementedType
|
|
19
|
-
from typing import
|
|
20
|
-
Any,
|
|
21
|
-
cast,
|
|
22
|
-
Dict,
|
|
23
|
-
Iterable,
|
|
24
|
-
Iterator,
|
|
25
|
-
Optional,
|
|
26
|
-
Sequence,
|
|
27
|
-
Tuple,
|
|
28
|
-
TYPE_CHECKING,
|
|
29
|
-
TypeVar,
|
|
30
|
-
Union,
|
|
31
|
-
)
|
|
19
|
+
from typing import Any, cast, Iterable, Iterator, Sequence, TYPE_CHECKING, TypeVar
|
|
32
20
|
|
|
33
21
|
from cirq import circuits, ops, protocols, transformers, value
|
|
34
22
|
|
|
@@ -37,10 +25,10 @@ if TYPE_CHECKING:
|
|
|
37
25
|
|
|
38
26
|
|
|
39
27
|
LogicalIndex = TypeVar('LogicalIndex', int, ops.Qid)
|
|
40
|
-
LogicalIndexSequence =
|
|
41
|
-
LogicalGates =
|
|
28
|
+
LogicalIndexSequence = Sequence[int] | Sequence['cirq.Qid']
|
|
29
|
+
LogicalGates = dict[tuple[LogicalIndex, ...], ops.Gate]
|
|
42
30
|
LogicalMappingKey = TypeVar('LogicalMappingKey', bound=ops.Qid)
|
|
43
|
-
LogicalMapping =
|
|
31
|
+
LogicalMapping = dict[LogicalMappingKey, LogicalIndex]
|
|
44
32
|
|
|
45
33
|
|
|
46
34
|
class PermutationGate(ops.Gate, metaclass=abc.ABCMeta):
|
|
@@ -61,12 +49,12 @@ class PermutationGate(ops.Gate, metaclass=abc.ABCMeta):
|
|
|
61
49
|
return self._num_qubits
|
|
62
50
|
|
|
63
51
|
@abc.abstractmethod
|
|
64
|
-
def permutation(self) ->
|
|
52
|
+
def permutation(self) -> dict[int, int]:
|
|
65
53
|
"""permutation = {i: s[i]} indicates that the i-th element is mapped to
|
|
66
54
|
the s[i]-th element."""
|
|
67
55
|
|
|
68
56
|
def update_mapping(
|
|
69
|
-
self, mapping:
|
|
57
|
+
self, mapping: dict[ops.Qid, LogicalIndex], keys: Sequence[cirq.Qid]
|
|
70
58
|
) -> None:
|
|
71
59
|
"""Updates a mapping (in place) from qubits to logical indices.
|
|
72
60
|
|
|
@@ -86,7 +74,7 @@ class PermutationGate(ops.Gate, metaclass=abc.ABCMeta):
|
|
|
86
74
|
mapping[new_key] = old_element
|
|
87
75
|
|
|
88
76
|
@staticmethod
|
|
89
|
-
def validate_permutation(permutation:
|
|
77
|
+
def validate_permutation(permutation: dict[int, int], n_elements: int | None = None) -> None:
|
|
90
78
|
if not permutation:
|
|
91
79
|
return
|
|
92
80
|
if set(permutation.values()) != set(permutation):
|
|
@@ -99,7 +87,7 @@ class PermutationGate(ops.Gate, metaclass=abc.ABCMeta):
|
|
|
99
87
|
|
|
100
88
|
def _circuit_diagram_info_(
|
|
101
89
|
self, args: cirq.CircuitDiagramInfoArgs
|
|
102
|
-
) ->
|
|
90
|
+
) -> str | Iterable[str] | cirq.CircuitDiagramInfo:
|
|
103
91
|
if args.known_qubit_count is None:
|
|
104
92
|
return NotImplemented
|
|
105
93
|
permutation = self.permutation()
|
|
@@ -150,7 +138,7 @@ class SwapPermutationGate(PermutationGate):
|
|
|
150
138
|
def __init__(self, swap_gate: cirq.Gate = ops.SWAP):
|
|
151
139
|
super().__init__(2, swap_gate)
|
|
152
140
|
|
|
153
|
-
def permutation(self) ->
|
|
141
|
+
def permutation(self) -> dict[int, int]:
|
|
154
142
|
return {0: 1, 1: 0}
|
|
155
143
|
|
|
156
144
|
def _decompose_(self, qubits: Sequence[cirq.Qid]) -> Iterator[cirq.OP_TREE]:
|
|
@@ -166,7 +154,7 @@ class SwapPermutationGate(PermutationGate):
|
|
|
166
154
|
def _value_equality_values_(self) -> Any:
|
|
167
155
|
return (self.swap_gate,)
|
|
168
156
|
|
|
169
|
-
def _commutes_(self, other: Any, *, atol: float = 1e-8) ->
|
|
157
|
+
def _commutes_(self, other: Any, *, atol: float = 1e-8) -> bool | NotImplementedType:
|
|
170
158
|
if (
|
|
171
159
|
isinstance(other, ops.Gate)
|
|
172
160
|
and isinstance(other, ops.InterchangeableQubitsGate)
|
|
@@ -176,7 +164,7 @@ class SwapPermutationGate(PermutationGate):
|
|
|
176
164
|
return NotImplemented
|
|
177
165
|
|
|
178
166
|
|
|
179
|
-
def _canonicalize_permutation(permutation:
|
|
167
|
+
def _canonicalize_permutation(permutation: dict[int, int]) -> dict[int, int]:
|
|
180
168
|
return {i: j for i, j in permutation.items() if i != j}
|
|
181
169
|
|
|
182
170
|
|
|
@@ -186,7 +174,7 @@ class LinearPermutationGate(PermutationGate):
|
|
|
186
174
|
sorting network."""
|
|
187
175
|
|
|
188
176
|
def __init__(
|
|
189
|
-
self, num_qubits: int, permutation:
|
|
177
|
+
self, num_qubits: int, permutation: dict[int, int], swap_gate: cirq.Gate = ops.SWAP
|
|
190
178
|
) -> None:
|
|
191
179
|
"""Initializes a linear permutation gate.
|
|
192
180
|
|
|
@@ -199,7 +187,7 @@ class LinearPermutationGate(PermutationGate):
|
|
|
199
187
|
PermutationGate.validate_permutation(permutation, num_qubits)
|
|
200
188
|
self._permutation = permutation
|
|
201
189
|
|
|
202
|
-
def permutation(self) ->
|
|
190
|
+
def permutation(self) -> dict[int, int]:
|
|
203
191
|
return self._permutation
|
|
204
192
|
|
|
205
193
|
def _decompose_(self, qubits: Sequence[cirq.Qid]) -> Iterator[cirq.OP_TREE]:
|
|
@@ -238,7 +226,7 @@ class LinearPermutationGate(PermutationGate):
|
|
|
238
226
|
return NotImplemented
|
|
239
227
|
|
|
240
228
|
|
|
241
|
-
def update_mapping(mapping:
|
|
229
|
+
def update_mapping(mapping: dict[ops.Qid, LogicalIndex], operations: cirq.OP_TREE) -> None:
|
|
242
230
|
"""Updates a mapping (in place) from qubits to logical indices according to
|
|
243
231
|
a set of permutation gates. Any gates other than permutation gates are
|
|
244
232
|
ignored.
|
|
@@ -253,7 +241,7 @@ def update_mapping(mapping: Dict[ops.Qid, LogicalIndex], operations: cirq.OP_TRE
|
|
|
253
241
|
|
|
254
242
|
|
|
255
243
|
def get_logical_operations(
|
|
256
|
-
operations: cirq.OP_TREE, initial_mapping:
|
|
244
|
+
operations: cirq.OP_TREE, initial_mapping: dict[ops.Qid, ops.Qid]
|
|
257
245
|
) -> Iterable[cirq.Operation]:
|
|
258
246
|
"""Gets the logical operations specified by the physical operations and
|
|
259
247
|
initial mapping.
|