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
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
|
|
15
15
|
from __future__ import annotations
|
|
16
16
|
|
|
17
|
-
from typing import Sequence
|
|
17
|
+
from typing import Sequence
|
|
18
18
|
|
|
19
19
|
import numpy as np
|
|
20
20
|
import pytest
|
|
@@ -34,8 +34,8 @@ def assert_sim_eq(circuit1: cirq.AbstractCircuit, circuit2: cirq.AbstractCircuit
|
|
|
34
34
|
|
|
35
35
|
def assert_dd(
|
|
36
36
|
input_circuit: cirq.AbstractCircuit,
|
|
37
|
-
expected_circuit:
|
|
38
|
-
schema:
|
|
37
|
+
expected_circuit: str | cirq.AbstractCircuit,
|
|
38
|
+
schema: str | tuple[cirq.Gate, ...] = 'DEFAULT',
|
|
39
39
|
single_qubit_gate_moments_only: bool = True,
|
|
40
40
|
):
|
|
41
41
|
transformed_circuit = add_dynamical_decoupling(
|
|
@@ -254,7 +254,7 @@ def test_pull_through_h_gate_case2(single_qubit_gate_moments_only: bool):
|
|
|
254
254
|
),
|
|
255
255
|
],
|
|
256
256
|
)
|
|
257
|
-
def test_invalid_dd_schema(schema:
|
|
257
|
+
def test_invalid_dd_schema(schema: str | tuple[cirq.Gate, ...], error_msg_regex):
|
|
258
258
|
a = cirq.NamedQubit('a')
|
|
259
259
|
input_circuit = cirq.Circuit(cirq.H(a))
|
|
260
260
|
with pytest.raises(ValueError, match=error_msg_regex):
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
|
|
17
17
|
from __future__ import annotations
|
|
18
18
|
|
|
19
|
-
from typing import cast,
|
|
19
|
+
from typing import cast, Iterable, Iterator, TYPE_CHECKING
|
|
20
20
|
|
|
21
21
|
import numpy as np
|
|
22
22
|
import sympy
|
|
@@ -33,7 +33,7 @@ if TYPE_CHECKING:
|
|
|
33
33
|
def eject_phased_paulis(
|
|
34
34
|
circuit: cirq.AbstractCircuit,
|
|
35
35
|
*,
|
|
36
|
-
context:
|
|
36
|
+
context: cirq.TransformerContext | None = None,
|
|
37
37
|
atol: float = 1e-8,
|
|
38
38
|
eject_parameterized: bool = False,
|
|
39
39
|
) -> cirq.Circuit:
|
|
@@ -59,7 +59,7 @@ def eject_phased_paulis(
|
|
|
59
59
|
Returns:
|
|
60
60
|
Copy of the transformed input circuit.
|
|
61
61
|
"""
|
|
62
|
-
held_w_phases:
|
|
62
|
+
held_w_phases: dict[ops.Qid, value.TParamVal] = {}
|
|
63
63
|
tags_to_ignore = set(context.tags_to_ignore) if context else set()
|
|
64
64
|
|
|
65
65
|
def map_func(op: cirq.Operation, _: int) -> cirq.OP_TREE:
|
|
@@ -108,7 +108,7 @@ def eject_phased_paulis(
|
|
|
108
108
|
|
|
109
109
|
|
|
110
110
|
def _absorb_z_into_w(
|
|
111
|
-
op: ops.Operation, held_w_phases:
|
|
111
|
+
op: ops.Operation, held_w_phases: dict[ops.Qid, value.TParamVal]
|
|
112
112
|
) -> cirq.OP_TREE:
|
|
113
113
|
"""Absorbs a Z^t gate into a W(a) flip.
|
|
114
114
|
|
|
@@ -129,7 +129,7 @@ def _absorb_z_into_w(
|
|
|
129
129
|
|
|
130
130
|
|
|
131
131
|
def _dump_held(
|
|
132
|
-
qubits: Iterable[ops.Qid], held_w_phases:
|
|
132
|
+
qubits: Iterable[ops.Qid], held_w_phases: dict[ops.Qid, value.TParamVal], atol: float
|
|
133
133
|
) -> Iterator[cirq.OP_TREE]:
|
|
134
134
|
# Note: sorting is to avoid non-determinism in the insertion order.
|
|
135
135
|
for q in sorted(qubits):
|
|
@@ -141,7 +141,7 @@ def _dump_held(
|
|
|
141
141
|
|
|
142
142
|
|
|
143
143
|
def _dump_into_measurement(
|
|
144
|
-
op: ops.Operation, held_w_phases:
|
|
144
|
+
op: ops.Operation, held_w_phases: dict[ops.Qid, value.TParamVal]
|
|
145
145
|
) -> cirq.OP_TREE:
|
|
146
146
|
measurement = cast(ops.MeasurementGate, cast(ops.GateOperation, op).gate)
|
|
147
147
|
new_measurement = measurement.with_bits_flipped(
|
|
@@ -153,7 +153,7 @@ def _dump_into_measurement(
|
|
|
153
153
|
|
|
154
154
|
|
|
155
155
|
def _potential_cross_whole_w(
|
|
156
|
-
op: ops.Operation, atol: float, held_w_phases:
|
|
156
|
+
op: ops.Operation, atol: float, held_w_phases: dict[ops.Qid, value.TParamVal]
|
|
157
157
|
) -> cirq.OP_TREE:
|
|
158
158
|
"""Grabs or cancels a held W gate against an existing W gate.
|
|
159
159
|
|
|
@@ -167,7 +167,7 @@ def _potential_cross_whole_w(
|
|
|
167
167
|
≡ ───Z^2(b-a)───
|
|
168
168
|
"""
|
|
169
169
|
_, phase_exponent = cast(
|
|
170
|
-
|
|
170
|
+
tuple[value.TParamVal, value.TParamVal], _try_get_known_phased_pauli(op)
|
|
171
171
|
)
|
|
172
172
|
q = op.qubits[0]
|
|
173
173
|
a = held_w_phases.get(q, None)
|
|
@@ -186,7 +186,7 @@ def _potential_cross_whole_w(
|
|
|
186
186
|
|
|
187
187
|
|
|
188
188
|
def _potential_cross_partial_w(
|
|
189
|
-
op: ops.Operation, held_w_phases:
|
|
189
|
+
op: ops.Operation, held_w_phases: dict[ops.Qid, value.TParamVal], atol: float
|
|
190
190
|
) -> cirq.OP_TREE:
|
|
191
191
|
"""Cross the held W over a partial W gate.
|
|
192
192
|
|
|
@@ -204,7 +204,7 @@ def _potential_cross_partial_w(
|
|
|
204
204
|
if a is None:
|
|
205
205
|
return op
|
|
206
206
|
exponent, phase_exponent = cast(
|
|
207
|
-
|
|
207
|
+
tuple[value.TParamVal, value.TParamVal], _try_get_known_phased_pauli(op)
|
|
208
208
|
)
|
|
209
209
|
gate = _phased_x_or_pauli_gate(
|
|
210
210
|
exponent=exponent, phase_exponent=2 * a - phase_exponent, atol=atol
|
|
@@ -252,7 +252,7 @@ def _single_cross_over_cz(op: ops.Operation, qubit_with_w: cirq.Qid) -> cirq.OP_
|
|
|
252
252
|
|
|
253
253
|
|
|
254
254
|
def _double_cross_over_cz(
|
|
255
|
-
op: ops.Operation, held_w_phases:
|
|
255
|
+
op: ops.Operation, held_w_phases: dict[ops.Qid, value.TParamVal]
|
|
256
256
|
) -> cirq.OP_TREE:
|
|
257
257
|
"""Crosses two W flips over a partial CZ.
|
|
258
258
|
|
|
@@ -296,7 +296,7 @@ def _double_cross_over_cz(
|
|
|
296
296
|
|
|
297
297
|
def _try_get_known_cz_half_turns(
|
|
298
298
|
op: ops.Operation, no_symbolic: bool = False
|
|
299
|
-
) ->
|
|
299
|
+
) -> value.TParamVal | None:
|
|
300
300
|
if not isinstance(op.gate, ops.CZPowGate):
|
|
301
301
|
return None
|
|
302
302
|
h = op.gate.exponent
|
|
@@ -307,7 +307,7 @@ def _try_get_known_cz_half_turns(
|
|
|
307
307
|
|
|
308
308
|
def _try_get_known_phased_pauli(
|
|
309
309
|
op: ops.Operation, no_symbolic: bool = False
|
|
310
|
-
) ->
|
|
310
|
+
) -> tuple[value.TParamVal, value.TParamVal] | None:
|
|
311
311
|
if no_symbolic and protocols.is_parameterized(op):
|
|
312
312
|
return None
|
|
313
313
|
gate = op.gate
|
|
@@ -335,7 +335,7 @@ def _try_get_known_phased_pauli(
|
|
|
335
335
|
|
|
336
336
|
def _try_get_known_z_half_turns(
|
|
337
337
|
op: ops.Operation, no_symbolic: bool = False
|
|
338
|
-
) ->
|
|
338
|
+
) -> value.TParamVal | None:
|
|
339
339
|
g = op.gate
|
|
340
340
|
if (
|
|
341
341
|
isinstance(g, ops.PhasedXZGate)
|
|
@@ -356,8 +356,8 @@ def _try_get_known_z_half_turns(
|
|
|
356
356
|
|
|
357
357
|
|
|
358
358
|
def _phased_x_or_pauli_gate(
|
|
359
|
-
exponent:
|
|
360
|
-
) ->
|
|
359
|
+
exponent: float | sympy.Expr, phase_exponent: float | sympy.Expr, atol: float
|
|
360
|
+
) -> cirq.PhasedXPowGate | cirq.XPowGate | cirq.YPowGate:
|
|
361
361
|
"""Return PhasedXPowGate or X or Y gate if equivalent within atol in z-axis turns."""
|
|
362
362
|
if not isinstance(phase_exponent, sympy.Expr) or phase_exponent.is_constant():
|
|
363
363
|
half_turns = value.canonicalize_half_turns(float(phase_exponent))
|
cirq/transformers/eject_z.py
CHANGED
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
from __future__ import annotations
|
|
18
18
|
|
|
19
19
|
from collections import defaultdict
|
|
20
|
-
from typing import
|
|
20
|
+
from typing import Iterable, Iterator, TYPE_CHECKING
|
|
21
21
|
|
|
22
22
|
import numpy as np
|
|
23
23
|
|
|
@@ -50,7 +50,7 @@ def _is_swaplike(gate: cirq.Gate):
|
|
|
50
50
|
def eject_z(
|
|
51
51
|
circuit: cirq.AbstractCircuit,
|
|
52
52
|
*,
|
|
53
|
-
context:
|
|
53
|
+
context: cirq.TransformerContext | None = None,
|
|
54
54
|
atol: float = 0.0,
|
|
55
55
|
eject_parameterized: bool = False,
|
|
56
56
|
) -> cirq.Circuit:
|
|
@@ -72,12 +72,10 @@ def eject_z(
|
|
|
72
72
|
Copy of the transformed input circuit.
|
|
73
73
|
"""
|
|
74
74
|
# Tracks qubit phases (in half turns; multiply by pi to get radians).
|
|
75
|
-
qubit_phase:
|
|
75
|
+
qubit_phase: dict[ops.Qid, float] = defaultdict(lambda: 0)
|
|
76
76
|
tags_to_ignore = set(context.tags_to_ignore) if context else set()
|
|
77
|
-
phased_xz_replacements:
|
|
78
|
-
last_phased_xz_op:
|
|
79
|
-
lambda: None
|
|
80
|
-
)
|
|
77
|
+
phased_xz_replacements: dict[tuple[int, ops.Operation], ops.PhasedXZGate] = {}
|
|
78
|
+
last_phased_xz_op: dict[ops.Qid, tuple[int, ops.Operation] | None] = defaultdict(lambda: None)
|
|
81
79
|
|
|
82
80
|
def dump_tracked_phase(qubits: Iterable[ops.Qid]) -> Iterator[cirq.OP_TREE]:
|
|
83
81
|
"""Zeroes qubit_phase entries by emitting Z gates."""
|
|
@@ -21,7 +21,7 @@ import functools
|
|
|
21
21
|
import itertools
|
|
22
22
|
from dataclasses import dataclass
|
|
23
23
|
from numbers import Real
|
|
24
|
-
from typing import Callable,
|
|
24
|
+
from typing import Callable, Sequence, TYPE_CHECKING
|
|
25
25
|
|
|
26
26
|
import numpy as np
|
|
27
27
|
import sympy
|
|
@@ -70,16 +70,16 @@ class ConstantGauge(Gauge):
|
|
|
70
70
|
"""A gauge that replaces a two qubit gate with a constant gauge."""
|
|
71
71
|
|
|
72
72
|
two_qubit_gate: ops.Gate
|
|
73
|
-
pre_q0:
|
|
73
|
+
pre_q0: tuple[ops.Gate, ...] = field(
|
|
74
74
|
default=(), converter=lambda g: (g,) if isinstance(g, ops.Gate) else tuple(g)
|
|
75
75
|
)
|
|
76
|
-
pre_q1:
|
|
76
|
+
pre_q1: tuple[ops.Gate, ...] = field(
|
|
77
77
|
default=(), converter=lambda g: (g,) if isinstance(g, ops.Gate) else tuple(g)
|
|
78
78
|
)
|
|
79
|
-
post_q0:
|
|
79
|
+
post_q0: tuple[ops.Gate, ...] = field(
|
|
80
80
|
default=(), converter=lambda g: (g,) if isinstance(g, ops.Gate) else tuple(g)
|
|
81
81
|
)
|
|
82
|
-
post_q1:
|
|
82
|
+
post_q1: tuple[ops.Gate, ...] = field(
|
|
83
83
|
default=(), converter=lambda g: (g,) if isinstance(g, ops.Gate) else tuple(g)
|
|
84
84
|
)
|
|
85
85
|
swap_qubits: bool = False
|
|
@@ -88,12 +88,12 @@ class ConstantGauge(Gauge):
|
|
|
88
88
|
return self
|
|
89
89
|
|
|
90
90
|
@property
|
|
91
|
-
def pre(self) ->
|
|
91
|
+
def pre(self) -> tuple[tuple[ops.Gate, ...], tuple[ops.Gate, ...]]:
|
|
92
92
|
"""A tuple (ops to apply to q0, ops to apply to q1)."""
|
|
93
93
|
return self.pre_q0, self.pre_q1
|
|
94
94
|
|
|
95
95
|
@property
|
|
96
|
-
def post(self) ->
|
|
96
|
+
def post(self) -> tuple[tuple[ops.Gate, ...], tuple[ops.Gate, ...]]:
|
|
97
97
|
"""A tuple (ops to apply to q0, ops to apply to q1)."""
|
|
98
98
|
return self.post_q0, self.post_q1
|
|
99
99
|
|
|
@@ -108,16 +108,16 @@ class ConstantGauge(Gauge):
|
|
|
108
108
|
class SameGateGauge(Gauge):
|
|
109
109
|
"""Same as ConstantGauge but the new two-qubit gate equals the old gate."""
|
|
110
110
|
|
|
111
|
-
pre_q0:
|
|
111
|
+
pre_q0: tuple[ops.Gate, ...] = field(
|
|
112
112
|
default=(), converter=lambda g: (g,) if isinstance(g, ops.Gate) else tuple(g)
|
|
113
113
|
)
|
|
114
|
-
pre_q1:
|
|
114
|
+
pre_q1: tuple[ops.Gate, ...] = field(
|
|
115
115
|
default=(), converter=lambda g: (g,) if isinstance(g, ops.Gate) else tuple(g)
|
|
116
116
|
)
|
|
117
|
-
post_q0:
|
|
117
|
+
post_q0: tuple[ops.Gate, ...] = field(
|
|
118
118
|
default=(), converter=lambda g: (g,) if isinstance(g, ops.Gate) else tuple(g)
|
|
119
119
|
)
|
|
120
|
-
post_q1:
|
|
120
|
+
post_q1: tuple[ops.Gate, ...] = field(
|
|
121
121
|
default=(), converter=lambda g: (g,) if isinstance(g, ops.Gate) else tuple(g)
|
|
122
122
|
)
|
|
123
123
|
swap_qubits: bool = False
|
|
@@ -144,12 +144,12 @@ class TwoQubitGateSymbolizer:
|
|
|
144
144
|
n_symbols: The number of symbols to use for parameterization.
|
|
145
145
|
"""
|
|
146
146
|
|
|
147
|
-
symbolizer_fn: Callable[[ops.Gate, Sequence[sympy.Symbol]],
|
|
147
|
+
symbolizer_fn: Callable[[ops.Gate, Sequence[sympy.Symbol]], tuple[ops.Gate, dict[str, Real]]]
|
|
148
148
|
n_symbols: int
|
|
149
149
|
|
|
150
150
|
def __call__(
|
|
151
151
|
self, two_qubit_gate: ops.Gate, symbols: Sequence[sympy.Symbol]
|
|
152
|
-
) ->
|
|
152
|
+
) -> tuple[ops.Gate, dict[str, Real]]:
|
|
153
153
|
"""Symbolizes a two qubit gate to a parameterized gate.
|
|
154
154
|
|
|
155
155
|
Args:
|
|
@@ -197,9 +197,9 @@ class GaugeTransformer:
|
|
|
197
197
|
self,
|
|
198
198
|
# target can be either a specific gate, gatefamily or gateset
|
|
199
199
|
# which allows matching parametric gates.
|
|
200
|
-
target:
|
|
200
|
+
target: ops.Gate | ops.Gateset | ops.GateFamily,
|
|
201
201
|
gauge_selector: Callable[[np.random.Generator], Gauge],
|
|
202
|
-
two_qubit_gate_symbolizer:
|
|
202
|
+
two_qubit_gate_symbolizer: TwoQubitGateSymbolizer | None = None,
|
|
203
203
|
) -> None:
|
|
204
204
|
"""Constructs a GaugeTransformer.
|
|
205
205
|
|
|
@@ -217,8 +217,8 @@ class GaugeTransformer:
|
|
|
217
217
|
self,
|
|
218
218
|
circuit: circuits.AbstractCircuit,
|
|
219
219
|
*,
|
|
220
|
-
context:
|
|
221
|
-
prng:
|
|
220
|
+
context: transformer_api.TransformerContext | None = None,
|
|
221
|
+
prng: np.random.Generator | None = None,
|
|
222
222
|
) -> circuits.AbstractCircuit:
|
|
223
223
|
rng = np.random.default_rng() if prng is None else prng
|
|
224
224
|
if context is None:
|
|
@@ -226,12 +226,12 @@ class GaugeTransformer:
|
|
|
226
226
|
if context.deep:
|
|
227
227
|
raise ValueError('GaugeTransformer cannot be used with deep=True')
|
|
228
228
|
new_moments = []
|
|
229
|
-
left:
|
|
230
|
-
right:
|
|
229
|
+
left: list[list[ops.Operation]] = []
|
|
230
|
+
right: list[list[ops.Operation]] = []
|
|
231
231
|
for moment in circuit:
|
|
232
232
|
left.clear()
|
|
233
233
|
right.clear()
|
|
234
|
-
center:
|
|
234
|
+
center: list[ops.Operation] = []
|
|
235
235
|
for op in moment:
|
|
236
236
|
if isinstance(op, ops.TaggedOperation) and set(op.tags).intersection(
|
|
237
237
|
context.tags_to_ignore
|
|
@@ -258,9 +258,9 @@ class GaugeTransformer:
|
|
|
258
258
|
circuit: circuits.AbstractCircuit,
|
|
259
259
|
*,
|
|
260
260
|
N: int,
|
|
261
|
-
context:
|
|
262
|
-
prng:
|
|
263
|
-
) ->
|
|
261
|
+
context: transformer_api.TransformerContext | None = None,
|
|
262
|
+
prng: np.random.Generator | None = None,
|
|
263
|
+
) -> tuple[circuits.AbstractCircuit, cirq.Sweepable]:
|
|
264
264
|
"""Generates a parameterized circuit with *N* sets of sweepable parameters.
|
|
265
265
|
|
|
266
266
|
Args:
|
|
@@ -276,31 +276,31 @@ class GaugeTransformer:
|
|
|
276
276
|
context = transformer_api.TransformerContext(deep=False)
|
|
277
277
|
if context.deep:
|
|
278
278
|
raise ValueError('GaugeTransformer cannot be used with deep=True')
|
|
279
|
-
new_moments:
|
|
279
|
+
new_moments: list[list[ops.Operation]] = [] # Store parameterized circuits.
|
|
280
280
|
phxz_sid = itertools.count()
|
|
281
281
|
two_qubit_gate_sid = itertools.count()
|
|
282
282
|
# Map from "((pre|post),$qid,$moment_id)" to gate parameters.
|
|
283
283
|
# E.g., {(post,q1,2): {"x_exponent": "x1", "z_exponent": "z1", "axis_phase": "a1"}}
|
|
284
|
-
phxz_symbols_by_locs:
|
|
284
|
+
phxz_symbols_by_locs: dict[tuple[str, ops.Qid, int], dict[str, sympy.Symbol]] = {}
|
|
285
285
|
# Map from "($q0,$q1,$moment_id)" to gate parameters.
|
|
286
286
|
# E.g., {(q0,q1,0): ["s0"]}.
|
|
287
|
-
two_qubit_gate_symbols_by_locs:
|
|
287
|
+
two_qubit_gate_symbols_by_locs: dict[tuple[ops.Qid, ops.Qid, int], list[sympy.Symbol]] = {}
|
|
288
288
|
|
|
289
|
-
def single_qubit_next_symbol() ->
|
|
289
|
+
def single_qubit_next_symbol() -> dict[str, sympy.Symbol]:
|
|
290
290
|
sid = next(phxz_sid)
|
|
291
291
|
return _parameterize_to_phxz(sid)
|
|
292
292
|
|
|
293
|
-
def two_qubit_gate_next_symbol_list(n: int) ->
|
|
293
|
+
def two_qubit_gate_next_symbol_list(n: int) -> list[sympy.Symbol]:
|
|
294
294
|
"""Returns symbols for 2 qubit gate parameterization."""
|
|
295
295
|
sid = next(two_qubit_gate_sid)
|
|
296
|
-
symbols:
|
|
296
|
+
symbols: list[sympy.Symbol] = [sympy.Symbol(f"s{sid}_{sub}") for sub in range(n)]
|
|
297
297
|
return symbols
|
|
298
298
|
|
|
299
299
|
# Build parameterized circuit.
|
|
300
300
|
for moment_id, moment in enumerate(circuit):
|
|
301
|
-
center_moment:
|
|
302
|
-
left_moment:
|
|
303
|
-
right_moment:
|
|
301
|
+
center_moment: list[ops.Operation] = []
|
|
302
|
+
left_moment: list[ops.Operation] = []
|
|
303
|
+
right_moment: list[ops.Operation] = []
|
|
304
304
|
for op in moment:
|
|
305
305
|
if isinstance(op, ops.TaggedOperation) and set(op.tags).intersection(
|
|
306
306
|
context.tags_to_ignore
|
|
@@ -342,7 +342,7 @@ class GaugeTransformer:
|
|
|
342
342
|
)
|
|
343
343
|
|
|
344
344
|
# Initialize the map from symbol names to their N values.
|
|
345
|
-
values_by_params:
|
|
345
|
+
values_by_params: dict[str, list[float]] = {
|
|
346
346
|
**{
|
|
347
347
|
str(symbol): []
|
|
348
348
|
for symbols_by_names in phxz_symbols_by_locs.values()
|
|
@@ -389,14 +389,14 @@ class GaugeTransformer:
|
|
|
389
389
|
for key, value in phxz_params.items():
|
|
390
390
|
values_by_params[key].append(float(value))
|
|
391
391
|
|
|
392
|
-
sweeps:
|
|
392
|
+
sweeps: list[Points] = [
|
|
393
393
|
Points(key=key, points=values) for key, values in values_by_params.items()
|
|
394
394
|
]
|
|
395
395
|
|
|
396
396
|
return circuits.Circuit.from_moments(*new_moments), Zip(*sweeps)
|
|
397
397
|
|
|
398
398
|
|
|
399
|
-
def _build_moments(operation_by_qubits:
|
|
399
|
+
def _build_moments(operation_by_qubits: list[list[ops.Operation]]) -> list[list[ops.Operation]]:
|
|
400
400
|
"""Builds moments from a list of operations grouped by qubits.
|
|
401
401
|
|
|
402
402
|
Returns a list of moments from a list whose ith element is a list of operations applied
|
|
@@ -408,7 +408,7 @@ def _build_moments(operation_by_qubits: List[List[ops.Operation]]) -> List[List[
|
|
|
408
408
|
return moments
|
|
409
409
|
|
|
410
410
|
|
|
411
|
-
def _parameterize_to_phxz(symbol_id: int) ->
|
|
411
|
+
def _parameterize_to_phxz(symbol_id: int) -> dict[str, sympy.Symbol]:
|
|
412
412
|
"""Returns symbolized parameters for the gate."""
|
|
413
413
|
|
|
414
414
|
# Parameterize single qubit gate to parameterized PhasedXZGate.
|
|
@@ -421,8 +421,8 @@ def _parameterize_to_phxz(symbol_id: int) -> Dict[str, sympy.Symbol]:
|
|
|
421
421
|
|
|
422
422
|
|
|
423
423
|
def _gate_sequence_to_phxz_params(
|
|
424
|
-
gates:
|
|
425
|
-
) ->
|
|
424
|
+
gates: tuple[ops.Gate, ...], xza_by_symbols: dict[str, sympy.Symbol]
|
|
425
|
+
) -> dict[str, float]:
|
|
426
426
|
identity_gate_in_phxz = {
|
|
427
427
|
str(xza_by_symbols["x_exponent"]): 0.0,
|
|
428
428
|
str(xza_by_symbols["z_exponent"]): 0.0,
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
from __future__ import annotations
|
|
19
19
|
|
|
20
20
|
from numbers import Real
|
|
21
|
-
from typing import
|
|
21
|
+
from typing import Sequence, TYPE_CHECKING
|
|
22
22
|
|
|
23
23
|
from cirq.ops import CZ, CZPowGate, Gate, Gateset, S, X
|
|
24
24
|
from cirq.transformers.gauge_compiling.gauge_compiling import (
|
|
@@ -67,7 +67,7 @@ class SqrtCZGauge(Gauge):
|
|
|
67
67
|
|
|
68
68
|
def _symbolize_as_cz_pow(
|
|
69
69
|
two_qubit_gate: Gate, symbols: Sequence[sympy.Symbol]
|
|
70
|
-
) ->
|
|
70
|
+
) -> tuple[Gate, dict[str, Real]]:
|
|
71
71
|
"""Symbolizes a CZPowGate to a parameterized CZPowGate."""
|
|
72
72
|
|
|
73
73
|
if not isinstance(two_qubit_gate, CZPowGate) or not isinstance(two_qubit_gate.exponent, Real):
|
|
@@ -19,7 +19,7 @@ from __future__ import annotations
|
|
|
19
19
|
|
|
20
20
|
from dataclasses import dataclass
|
|
21
21
|
from functools import reduce
|
|
22
|
-
from typing import
|
|
22
|
+
from typing import NamedTuple, Sequence
|
|
23
23
|
|
|
24
24
|
import numpy as np
|
|
25
25
|
|
|
@@ -34,7 +34,7 @@ from cirq.transformers.heuristic_decompositions.gate_tabulation_math_utils impor
|
|
|
34
34
|
weyl_chamber_mesh,
|
|
35
35
|
)
|
|
36
36
|
|
|
37
|
-
_SingleQubitGatePair =
|
|
37
|
+
_SingleQubitGatePair = tuple[np.ndarray, np.ndarray]
|
|
38
38
|
|
|
39
39
|
|
|
40
40
|
class TwoQubitGateTabulationResult(NamedTuple):
|
|
@@ -61,7 +61,7 @@ class TwoQubitGateTabulationResult(NamedTuple):
|
|
|
61
61
|
|
|
62
62
|
base_gate_unitary: np.ndarray
|
|
63
63
|
target_gate: np.ndarray
|
|
64
|
-
local_unitaries:
|
|
64
|
+
local_unitaries: tuple[_SingleQubitGatePair, ...]
|
|
65
65
|
actual_gate: np.ndarray
|
|
66
66
|
success: bool
|
|
67
67
|
|
|
@@ -82,7 +82,7 @@ class TwoQubitGateTabulation:
|
|
|
82
82
|
summary: str # Text summarizing the results of the tabulation procedure.
|
|
83
83
|
# Any KAK vectors which are expected to be compilable (within infidelity
|
|
84
84
|
# max_expected_infidelity) using 2 or 3 base gates.
|
|
85
|
-
missed_points:
|
|
85
|
+
missed_points: tuple[np.ndarray, ...]
|
|
86
86
|
|
|
87
87
|
def compile_two_qubit_gate(self, unitary: np.ndarray) -> TwoQubitGateTabulationResult:
|
|
88
88
|
r"""Compute single qubit gates required to compile a desired unitary.
|
|
@@ -201,7 +201,7 @@ class TwoQubitGateTabulation:
|
|
|
201
201
|
|
|
202
202
|
def _outer_locals_for_unitary(
|
|
203
203
|
target: np.ndarray, base: np.ndarray
|
|
204
|
-
) ->
|
|
204
|
+
) -> tuple[_SingleQubitGatePair, _SingleQubitGatePair, np.ndarray]:
|
|
205
205
|
"""Local unitaries mapping between locally equivalent 2-local unitaries.
|
|
206
206
|
|
|
207
207
|
Finds the left and right 1-local unitaries kL, kR such that
|
|
@@ -246,10 +246,10 @@ def _outer_locals_for_unitary(
|
|
|
246
246
|
|
|
247
247
|
class _TabulationStepResult(NamedTuple):
|
|
248
248
|
# Generated KAK vectors that are uniquely close to at least one mesh point.
|
|
249
|
-
kept_kaks:
|
|
249
|
+
kept_kaks: list[np.ndarray]
|
|
250
250
|
# The corresponding single qubit unitaries required to obtain the desired
|
|
251
251
|
# KAK vectors.
|
|
252
|
-
kept_cycles:
|
|
252
|
+
kept_cycles: list[tuple[_SingleQubitGatePair, ...]]
|
|
253
253
|
|
|
254
254
|
|
|
255
255
|
def _tabulate_kak_vectors(
|
|
@@ -361,7 +361,7 @@ def two_qubit_gate_product_tabulation(
|
|
|
361
361
|
|
|
362
362
|
# include the base gate itself
|
|
363
363
|
kak_vecs = [cirq.kak_vector(base_gate, check_preconditions=False)]
|
|
364
|
-
sq_cycles:
|
|
364
|
+
sq_cycles: list[tuple[_SingleQubitGatePair, ...]] = [()]
|
|
365
365
|
|
|
366
366
|
# Tabulate gates that are close to gates in the mesh
|
|
367
367
|
u_locals_0 = random_qubit_unitary((num_samples,), rng=rng)
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
|
|
17
17
|
from __future__ import annotations
|
|
18
18
|
|
|
19
|
-
from typing import
|
|
19
|
+
from typing import TYPE_CHECKING
|
|
20
20
|
|
|
21
21
|
from cirq import circuits, protocols
|
|
22
22
|
from cirq.transformers import transformer_api
|
|
@@ -27,7 +27,7 @@ if TYPE_CHECKING:
|
|
|
27
27
|
|
|
28
28
|
@transformer_api.transformer(add_deep_support=True)
|
|
29
29
|
def insertion_sort_transformer(
|
|
30
|
-
circuit: cirq.AbstractCircuit, *, context:
|
|
30
|
+
circuit: cirq.AbstractCircuit, *, context: cirq.TransformerContext | None = None
|
|
31
31
|
) -> cirq.Circuit:
|
|
32
32
|
"""Sorts the operations using their sorted `.qubits` property as comparison key.
|
|
33
33
|
|
|
@@ -37,11 +37,11 @@ def insertion_sort_transformer(
|
|
|
37
37
|
circuit: input circuit.
|
|
38
38
|
context: optional TransformerContext (not used),
|
|
39
39
|
"""
|
|
40
|
-
final_operations:
|
|
41
|
-
qubit_index:
|
|
40
|
+
final_operations: list[cirq.Operation] = []
|
|
41
|
+
qubit_index: dict[cirq.Qid, int] = {
|
|
42
42
|
q: idx for idx, q in enumerate(sorted(circuit.all_qubits()))
|
|
43
43
|
}
|
|
44
|
-
cached_qubit_indices:
|
|
44
|
+
cached_qubit_indices: dict[int, list[int]] = {}
|
|
45
45
|
for pos, op in enumerate(circuit.all_operations()):
|
|
46
46
|
# here `pos` is at the append position of final_operations
|
|
47
47
|
if (op_qubit_indices := cached_qubit_indices.get(id(op))) is None:
|
|
@@ -16,7 +16,7 @@ from __future__ import annotations
|
|
|
16
16
|
|
|
17
17
|
import itertools
|
|
18
18
|
from collections import defaultdict
|
|
19
|
-
from typing import Any, cast,
|
|
19
|
+
from typing import Any, cast, Iterable, Sequence, TYPE_CHECKING
|
|
20
20
|
|
|
21
21
|
import numpy as np
|
|
22
22
|
|
|
@@ -35,7 +35,7 @@ class _MeasurementQid(ops.Qid):
|
|
|
35
35
|
Exactly one qubit will be created per qubit in the measurement gate.
|
|
36
36
|
"""
|
|
37
37
|
|
|
38
|
-
def __init__(self, key:
|
|
38
|
+
def __init__(self, key: str | cirq.MeasurementKey, qid: cirq.Qid, index: int = 0):
|
|
39
39
|
"""Initializes the qubit.
|
|
40
40
|
|
|
41
41
|
Args:
|
|
@@ -65,7 +65,7 @@ class _MeasurementQid(ops.Qid):
|
|
|
65
65
|
|
|
66
66
|
@transformer_api.transformer
|
|
67
67
|
def defer_measurements(
|
|
68
|
-
circuit: cirq.AbstractCircuit, *, context:
|
|
68
|
+
circuit: cirq.AbstractCircuit, *, context: cirq.TransformerContext | None = None
|
|
69
69
|
) -> cirq.Circuit:
|
|
70
70
|
"""Implements the Deferred Measurement Principle.
|
|
71
71
|
|
|
@@ -96,7 +96,7 @@ def defer_measurements(
|
|
|
96
96
|
|
|
97
97
|
circuit = transformer_primitives.unroll_circuit_op(circuit, deep=True, tags_to_check=None)
|
|
98
98
|
terminal_measurements = {op for _, op in find_terminal_measurements(circuit)}
|
|
99
|
-
measurement_qubits:
|
|
99
|
+
measurement_qubits: dict[cirq.MeasurementKey, list[tuple[cirq.Qid, ...]]] = defaultdict(list)
|
|
100
100
|
|
|
101
101
|
def defer(op: cirq.Operation, _) -> cirq.OP_TREE:
|
|
102
102
|
if op in terminal_measurements:
|
|
@@ -169,8 +169,8 @@ def defer_measurements(
|
|
|
169
169
|
|
|
170
170
|
|
|
171
171
|
def _all_possible_datastore_states(
|
|
172
|
-
keys: Iterable[
|
|
173
|
-
measurement_qubits:
|
|
172
|
+
keys: Iterable[tuple[cirq.MeasurementKey, int]],
|
|
173
|
+
measurement_qubits: dict[cirq.MeasurementKey, list[tuple[cirq.Qid, ...]]],
|
|
174
174
|
) -> Iterable[cirq.ClassicalDataStoreReader]:
|
|
175
175
|
"""The cartesian product of all possible DataStore states for the given keys."""
|
|
176
176
|
# First we get the list of all possible values. So if we have a key mapped to qubits of shape
|
|
@@ -216,7 +216,7 @@ def _all_possible_datastore_states(
|
|
|
216
216
|
def dephase_measurements(
|
|
217
217
|
circuit: cirq.AbstractCircuit,
|
|
218
218
|
*,
|
|
219
|
-
context:
|
|
219
|
+
context: cirq.TransformerContext | None = transformer_api.TransformerContext(deep=True),
|
|
220
220
|
) -> cirq.Circuit:
|
|
221
221
|
"""Changes all measurements to a dephase operation.
|
|
222
222
|
|
|
@@ -259,7 +259,7 @@ def dephase_measurements(
|
|
|
259
259
|
def drop_terminal_measurements(
|
|
260
260
|
circuit: cirq.AbstractCircuit,
|
|
261
261
|
*,
|
|
262
|
-
context:
|
|
262
|
+
context: cirq.TransformerContext | None = transformer_api.TransformerContext(deep=True),
|
|
263
263
|
) -> cirq.Circuit:
|
|
264
264
|
"""Removes terminal measurements from a circuit.
|
|
265
265
|
|
|
@@ -426,20 +426,20 @@ class _ConfusionChannel(ops.Gate):
|
|
|
426
426
|
self._confusion_map = confusion_map.copy()
|
|
427
427
|
self._kraus = tuple(kraus)
|
|
428
428
|
|
|
429
|
-
def _qid_shape_(self) ->
|
|
429
|
+
def _qid_shape_(self) -> tuple[int, ...]:
|
|
430
430
|
return self._shape
|
|
431
431
|
|
|
432
|
-
def _kraus_(self) ->
|
|
432
|
+
def _kraus_(self) -> tuple[np.ndarray, ...]:
|
|
433
433
|
return self._kraus
|
|
434
434
|
|
|
435
435
|
def _apply_channel_(self, args: cirq.ApplyChannelArgs):
|
|
436
|
-
configs:
|
|
436
|
+
configs: list[transformations._BuildFromSlicesArgs] = []
|
|
437
437
|
for i in range(np.prod(self._shape) ** 2):
|
|
438
438
|
scale = cast(complex, self._confusion_map.flat[i])
|
|
439
439
|
if scale == 0:
|
|
440
440
|
continue
|
|
441
441
|
index: Any = np.unravel_index(i, self._shape * 2)
|
|
442
|
-
slices:
|
|
442
|
+
slices: list[transformations._SliceConfig] = []
|
|
443
443
|
axis_count = len(args.left_axes)
|
|
444
444
|
for j in range(axis_count):
|
|
445
445
|
s1 = transformations._SliceConfig(
|
|
@@ -469,13 +469,13 @@ class _ModAdd(ops.ArithmeticGate):
|
|
|
469
469
|
def __init__(self, dimension: int):
|
|
470
470
|
self._dimension = dimension
|
|
471
471
|
|
|
472
|
-
def registers(self) ->
|
|
472
|
+
def registers(self) -> tuple[tuple[int], tuple[int]]:
|
|
473
473
|
return (self._dimension,), (self._dimension,)
|
|
474
474
|
|
|
475
475
|
def with_registers(self, *new_registers) -> _ModAdd:
|
|
476
476
|
raise NotImplementedError()
|
|
477
477
|
|
|
478
|
-
def apply(self, *register_values: int) ->
|
|
478
|
+
def apply(self, *register_values: int) -> tuple[int, int]:
|
|
479
479
|
return register_values[0], sum(register_values)
|
|
480
480
|
|
|
481
481
|
def _value_equality_values_(self) -> int:
|
|
@@ -16,8 +16,6 @@
|
|
|
16
16
|
|
|
17
17
|
from __future__ import annotations
|
|
18
18
|
|
|
19
|
-
from typing import List
|
|
20
|
-
|
|
21
19
|
import numpy as np
|
|
22
20
|
import pytest
|
|
23
21
|
|
|
@@ -26,7 +24,7 @@ import cirq
|
|
|
26
24
|
|
|
27
25
|
def assert_optimizes(optimized: cirq.AbstractCircuit, expected: cirq.AbstractCircuit):
|
|
28
26
|
# Ignore differences that would be caught by follow-up optimizations.
|
|
29
|
-
followup_transformers:
|
|
27
|
+
followup_transformers: list[cirq.TRANSFORMER] = [
|
|
30
28
|
cirq.drop_negligible_operations,
|
|
31
29
|
cirq.drop_empty_moments,
|
|
32
30
|
]
|
|
@@ -14,14 +14,12 @@
|
|
|
14
14
|
|
|
15
15
|
from __future__ import annotations
|
|
16
16
|
|
|
17
|
-
from typing import List
|
|
18
|
-
|
|
19
17
|
import cirq
|
|
20
18
|
|
|
21
19
|
|
|
22
20
|
def assert_optimizes(optimized: cirq.AbstractCircuit, expected: cirq.AbstractCircuit):
|
|
23
21
|
# Ignore differences that would be caught by follow-up optimizations.
|
|
24
|
-
followup_transformers:
|
|
22
|
+
followup_transformers: list[cirq.TRANSFORMER] = [
|
|
25
23
|
cirq.drop_negligible_operations,
|
|
26
24
|
cirq.drop_empty_moments,
|
|
27
25
|
]
|