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
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
from __future__ import annotations
|
|
16
16
|
|
|
17
17
|
import itertools
|
|
18
|
-
from typing import
|
|
18
|
+
from typing import Sequence
|
|
19
19
|
|
|
20
20
|
import numpy as np
|
|
21
21
|
import pytest
|
|
@@ -113,9 +113,9 @@ def test_valid_cphase_exponents(theta, phi):
|
|
|
113
113
|
assert_decomposition_valid(cphase_gate, fsim_gate=fsim_gate)
|
|
114
114
|
|
|
115
115
|
|
|
116
|
-
def complement_intervals(intervals: Sequence[
|
|
116
|
+
def complement_intervals(intervals: Sequence[tuple[float, float]]) -> Sequence[tuple[float, float]]:
|
|
117
117
|
"""Computes complement of union of intervals in [0, 2]."""
|
|
118
|
-
complements:
|
|
118
|
+
complements: list[tuple[float, float]] = []
|
|
119
119
|
a = 0.0
|
|
120
120
|
for b, c in intervals:
|
|
121
121
|
complements.append((a, b))
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
|
|
15
15
|
from __future__ import annotations
|
|
16
16
|
|
|
17
|
-
from typing import cast
|
|
17
|
+
from typing import cast
|
|
18
18
|
|
|
19
19
|
import numpy as np
|
|
20
20
|
import numpy.typing as npt
|
|
@@ -23,7 +23,7 @@ from cirq import protocols
|
|
|
23
23
|
from cirq.ops import DensePauliString
|
|
24
24
|
|
|
25
25
|
|
|
26
|
-
def _argmax(V: npt.NDArray) ->
|
|
26
|
+
def _argmax(V: npt.NDArray) -> tuple[int, float]:
|
|
27
27
|
"""Returns a tuple (index of max number, max number)."""
|
|
28
28
|
V = (V * V.conj()).real
|
|
29
29
|
idx_max = np.argmax(V)
|
|
@@ -62,7 +62,7 @@ def _conjugate_with_hadamard(U: npt.NDArray) -> npt.NDArray:
|
|
|
62
62
|
return U
|
|
63
63
|
|
|
64
64
|
|
|
65
|
-
def unitary_to_pauli_string(U: npt.NDArray, eps: float = 1e-15) ->
|
|
65
|
+
def unitary_to_pauli_string(U: npt.NDArray, eps: float = 1e-15) -> DensePauliString | None:
|
|
66
66
|
"""Attempts to find a pauli string (with possible phase) equivalent to U up to eps.
|
|
67
67
|
|
|
68
68
|
Based on this answer https://shorturl.at/aA079.
|
|
@@ -21,7 +21,7 @@ https://arxiv.org/abs/quant-ph/0406176
|
|
|
21
21
|
|
|
22
22
|
from __future__ import annotations
|
|
23
23
|
|
|
24
|
-
from typing import Callable, Iterable,
|
|
24
|
+
from typing import Callable, Iterable, TYPE_CHECKING
|
|
25
25
|
|
|
26
26
|
import numpy as np
|
|
27
27
|
from scipy.linalg import cossin
|
|
@@ -42,7 +42,7 @@ if TYPE_CHECKING:
|
|
|
42
42
|
|
|
43
43
|
|
|
44
44
|
def quantum_shannon_decomposition(
|
|
45
|
-
qubits:
|
|
45
|
+
qubits: list[cirq.Qid], u: np.ndarray, atol: float = 1e-8
|
|
46
46
|
) -> Iterable[cirq.Operation]:
|
|
47
47
|
"""Decomposes n-qubit unitary 1-q, 2-q and GlobalPhase gates, preserving global phase.
|
|
48
48
|
|
|
@@ -185,7 +185,7 @@ def _single_qubit_decomposition(qubit: cirq.Qid, u: np.ndarray) -> Iterable[cirq
|
|
|
185
185
|
|
|
186
186
|
|
|
187
187
|
def _msb_demuxer(
|
|
188
|
-
demux_qubits:
|
|
188
|
+
demux_qubits: list[cirq.Qid], u1: np.ndarray, u2: np.ndarray
|
|
189
189
|
) -> Iterable[cirq.Operation]:
|
|
190
190
|
"""Demultiplexes a unitary matrix that is multiplexed in its most-significant-qubit.
|
|
191
191
|
|
|
@@ -248,7 +248,7 @@ def _nth_gray(n: int) -> int:
|
|
|
248
248
|
|
|
249
249
|
|
|
250
250
|
def _multiplexed_cossin(
|
|
251
|
-
cossin_qubits:
|
|
251
|
+
cossin_qubits: list[cirq.Qid], angles: list[float], rot_func: Callable = ops.ry
|
|
252
252
|
) -> Iterable[cirq.Operation]:
|
|
253
253
|
"""Performs a multiplexed rotation over all qubits in this unitary matrix,
|
|
254
254
|
|
|
@@ -17,7 +17,6 @@
|
|
|
17
17
|
from __future__ import annotations
|
|
18
18
|
|
|
19
19
|
import math
|
|
20
|
-
from typing import List, Optional, Tuple
|
|
21
20
|
|
|
22
21
|
import numpy as np
|
|
23
22
|
import sympy
|
|
@@ -41,7 +40,7 @@ def _signed_mod_1(x: float) -> float:
|
|
|
41
40
|
|
|
42
41
|
def single_qubit_matrix_to_pauli_rotations(
|
|
43
42
|
mat: np.ndarray, atol: float = 0
|
|
44
|
-
) ->
|
|
43
|
+
) -> list[tuple[ops.Pauli, float]]:
|
|
45
44
|
"""Implements a single-qubit operation with few rotations.
|
|
46
45
|
|
|
47
46
|
Args:
|
|
@@ -100,7 +99,7 @@ def single_qubit_matrix_to_pauli_rotations(
|
|
|
100
99
|
return [(pauli, ht) for pauli, ht in rotation_list if not is_no_turn(ht)]
|
|
101
100
|
|
|
102
101
|
|
|
103
|
-
def single_qubit_matrix_to_gates(mat: np.ndarray, tolerance: float = 0) ->
|
|
102
|
+
def single_qubit_matrix_to_gates(mat: np.ndarray, tolerance: float = 0) -> list[ops.Gate]:
|
|
104
103
|
"""Implements a single-qubit operation with few gates.
|
|
105
104
|
|
|
106
105
|
Args:
|
|
@@ -116,7 +115,7 @@ def single_qubit_matrix_to_gates(mat: np.ndarray, tolerance: float = 0) -> List[
|
|
|
116
115
|
return [pauli**ht for pauli, ht in rotations]
|
|
117
116
|
|
|
118
117
|
|
|
119
|
-
def single_qubit_op_to_framed_phase_form(mat: np.ndarray) ->
|
|
118
|
+
def single_qubit_op_to_framed_phase_form(mat: np.ndarray) -> tuple[np.ndarray, complex, complex]:
|
|
120
119
|
"""Decomposes a 2x2 unitary M into U^-1 * diag(1, r) * U * diag(g, g).
|
|
121
120
|
|
|
122
121
|
U translates the rotation axis of M to the Z axis.
|
|
@@ -143,7 +142,7 @@ def single_qubit_op_to_framed_phase_form(mat: np.ndarray) -> Tuple[np.ndarray, c
|
|
|
143
142
|
return u, r, g
|
|
144
143
|
|
|
145
144
|
|
|
146
|
-
def _deconstruct_single_qubit_matrix_into_gate_turns(mat: np.ndarray) ->
|
|
145
|
+
def _deconstruct_single_qubit_matrix_into_gate_turns(mat: np.ndarray) -> tuple[float, float, float]:
|
|
147
146
|
"""Breaks down a 2x2 unitary into gate parameters.
|
|
148
147
|
|
|
149
148
|
Args:
|
|
@@ -167,7 +166,7 @@ def _deconstruct_single_qubit_matrix_into_gate_turns(mat: np.ndarray) -> Tuple[f
|
|
|
167
166
|
return (_signed_mod_1(xy_turn), _signed_mod_1(xy_phase_turn), _signed_mod_1(total_z_turn))
|
|
168
167
|
|
|
169
168
|
|
|
170
|
-
def single_qubit_matrix_to_phased_x_z(mat: np.ndarray, atol: float = 0) ->
|
|
169
|
+
def single_qubit_matrix_to_phased_x_z(mat: np.ndarray, atol: float = 0) -> list[ops.Gate]:
|
|
171
170
|
"""Implements a single-qubit operation with a PhasedX and Z gate.
|
|
172
171
|
|
|
173
172
|
If one of the gates isn't needed, it will be omitted.
|
|
@@ -198,7 +197,7 @@ def single_qubit_matrix_to_phased_x_z(mat: np.ndarray, atol: float = 0) -> List[
|
|
|
198
197
|
return result
|
|
199
198
|
|
|
200
199
|
|
|
201
|
-
def single_qubit_matrix_to_phxz(mat: np.ndarray, atol: float = 0) ->
|
|
200
|
+
def single_qubit_matrix_to_phxz(mat: np.ndarray, atol: float = 0) -> ops.PhasedXZGate | None:
|
|
202
201
|
"""Implements a single-qubit operation with a PhasedXZ gate.
|
|
203
202
|
|
|
204
203
|
Under the hood, this uses deconstruct_single_qubit_matrix_into_angles which
|
|
@@ -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
|
import numpy as np
|
|
22
22
|
|
|
@@ -34,7 +34,7 @@ def two_qubit_matrix_to_cz_isometry(
|
|
|
34
34
|
allow_partial_czs: bool = False,
|
|
35
35
|
atol: float = 1e-8,
|
|
36
36
|
clean_operations: bool = True,
|
|
37
|
-
) ->
|
|
37
|
+
) -> list[cirq.Operation]:
|
|
38
38
|
"""Decomposes a 2q operation into at-most 2 CZs + 1q rotations; assuming `q0` is initially |0>.
|
|
39
39
|
|
|
40
40
|
The method implements isometry from one to two qubits; assuming qubit `q0` is always in the |0>
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
|
|
17
17
|
from __future__ import annotations
|
|
18
18
|
|
|
19
|
-
from typing import
|
|
19
|
+
from typing import Sequence
|
|
20
20
|
|
|
21
21
|
import numpy as np
|
|
22
22
|
|
|
@@ -26,7 +26,7 @@ from cirq import ops, transformers as opt
|
|
|
26
26
|
|
|
27
27
|
def three_qubit_matrix_to_operations(
|
|
28
28
|
q0: ops.Qid, q1: ops.Qid, q2: ops.Qid, u: np.ndarray, atol: float = 1e-8
|
|
29
|
-
) ->
|
|
29
|
+
) -> list[ops.Operation]:
|
|
30
30
|
"""Returns operations for a 3 qubit unitary.
|
|
31
31
|
|
|
32
32
|
The algorithm is described in Shende et al.:
|
|
@@ -87,7 +87,7 @@ def three_qubit_matrix_to_operations(
|
|
|
87
87
|
return list(cirq.Circuit(vdh_ops + cs_ops + ud_ops).all_operations())
|
|
88
88
|
|
|
89
89
|
|
|
90
|
-
def _cs_to_ops(q0: ops.Qid, q1: ops.Qid, q2: ops.Qid, theta: np.ndarray) ->
|
|
90
|
+
def _cs_to_ops(q0: ops.Qid, q1: ops.Qid, q2: ops.Qid, theta: np.ndarray) -> list[ops.Operation]:
|
|
91
91
|
"""Converts theta angles based Cosine Sine matrix to operations.
|
|
92
92
|
|
|
93
93
|
Using the optimization as per Appendix A.1, it uses CZ gates instead of
|
|
@@ -126,9 +126,9 @@ def _two_qubit_multiplexor_to_ops(
|
|
|
126
126
|
u1: np.ndarray,
|
|
127
127
|
u2: np.ndarray,
|
|
128
128
|
shift_left: bool = True,
|
|
129
|
-
diagonal:
|
|
129
|
+
diagonal: np.ndarray | None = None,
|
|
130
130
|
atol: float = 1e-8,
|
|
131
|
-
) ->
|
|
131
|
+
) -> tuple[np.ndarray | None, list[ops.Operation]]:
|
|
132
132
|
r"""Converts a two qubit double multiplexor to circuit.
|
|
133
133
|
Input: U_1 ⊕ U_2, with select qubit a (i.e. a = |0> => U_1(b,c),
|
|
134
134
|
a = |1> => U_2(b,c).
|
|
@@ -187,7 +187,7 @@ def _two_qubit_multiplexor_to_ops(
|
|
|
187
187
|
|
|
188
188
|
w = d_v @ w
|
|
189
189
|
|
|
190
|
-
d_w:
|
|
190
|
+
d_w: np.ndarray | None
|
|
191
191
|
|
|
192
192
|
# if it's interesting to extract the diagonal then let's do it
|
|
193
193
|
if shift_left:
|
|
@@ -260,7 +260,7 @@ def _middle_multiplexor_to_ops(q0: ops.Qid, q1: ops.Qid, q2: ops.Qid, eigvals: n
|
|
|
260
260
|
return _optimize_multiplexed_angles_circuit(ops)
|
|
261
261
|
|
|
262
262
|
|
|
263
|
-
def _multiplexed_angles(theta:
|
|
263
|
+
def _multiplexed_angles(theta: Sequence[float] | np.ndarray) -> np.ndarray:
|
|
264
264
|
"""Calculates the angles for a 4-way multiplexed rotation.
|
|
265
265
|
|
|
266
266
|
For example, if we want rz(theta[i]) if the select qubits are in state
|
|
@@ -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
|
import numpy as np
|
|
22
22
|
|
|
@@ -41,7 +41,7 @@ def _1q_matrices_to_ops(g0, g1, q0, q1, include_identity=False):
|
|
|
41
41
|
|
|
42
42
|
def prepare_two_qubit_state_using_sqrt_iswap(
|
|
43
43
|
q0: cirq.Qid, q1: cirq.Qid, state: cirq.STATE_VECTOR_LIKE, *, use_sqrt_iswap_inv: bool = True
|
|
44
|
-
) ->
|
|
44
|
+
) -> list[cirq.Operation]:
|
|
45
45
|
"""Prepares the given 2q state from |00> using at-most 1 √iSWAP gate + single qubit rotations.
|
|
46
46
|
|
|
47
47
|
Entangled states are prepared using exactly 1 √iSWAP gate while product states are prepared
|
|
@@ -76,7 +76,7 @@ def prepare_two_qubit_state_using_sqrt_iswap(
|
|
|
76
76
|
|
|
77
77
|
def prepare_two_qubit_state_using_cz(
|
|
78
78
|
q0: cirq.Qid, q1: cirq.Qid, state: cirq.STATE_VECTOR_LIKE
|
|
79
|
-
) ->
|
|
79
|
+
) -> list[cirq.Operation]:
|
|
80
80
|
"""Prepares the given 2q state from |00> using at-most 1 CZ gate + single qubit rotations.
|
|
81
81
|
|
|
82
82
|
Entangled states are prepared using exactly 1 CZ gate while product states are prepared
|
|
@@ -109,7 +109,7 @@ def prepare_two_qubit_state_using_cz(
|
|
|
109
109
|
|
|
110
110
|
def prepare_two_qubit_state_using_iswap(
|
|
111
111
|
q0: cirq.Qid, q1: cirq.Qid, state: cirq.STATE_VECTOR_LIKE, use_iswap_inv: bool = False
|
|
112
|
-
) ->
|
|
112
|
+
) -> list[cirq.Operation]:
|
|
113
113
|
"""Prepares the given 2q state from |00> using at-most 1 ISWAP gate + single qubit rotations.
|
|
114
114
|
|
|
115
115
|
Entangled states are prepared using exactly 1 ISWAP gate while product states are prepared
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
|
|
17
17
|
from __future__ import annotations
|
|
18
18
|
|
|
19
|
-
from typing import cast, Iterable,
|
|
19
|
+
from typing import cast, Iterable, Sequence, TYPE_CHECKING
|
|
20
20
|
|
|
21
21
|
import numpy as np
|
|
22
22
|
|
|
@@ -34,7 +34,7 @@ if TYPE_CHECKING:
|
|
|
34
34
|
|
|
35
35
|
def _remove_partial_czs_or_fail(
|
|
36
36
|
operations: Iterable[cirq.Operation], atol: float
|
|
37
|
-
) ->
|
|
37
|
+
) -> list[cirq.Operation]:
|
|
38
38
|
result = []
|
|
39
39
|
for op in operations:
|
|
40
40
|
if isinstance(op.gate, ops.CZPowGate):
|
|
@@ -57,7 +57,7 @@ def two_qubit_matrix_to_cz_operations(
|
|
|
57
57
|
allow_partial_czs: bool,
|
|
58
58
|
atol: float = 1e-8,
|
|
59
59
|
clean_operations: bool = True,
|
|
60
|
-
) ->
|
|
60
|
+
) -> list[ops.Operation]:
|
|
61
61
|
"""Decomposes a two-qubit operation into Z/XY/CZ gates.
|
|
62
62
|
|
|
63
63
|
Args:
|
|
@@ -93,7 +93,7 @@ def two_qubit_matrix_to_diagonal_and_cz_operations(
|
|
|
93
93
|
allow_partial_czs: bool = False,
|
|
94
94
|
atol: float = 1e-8,
|
|
95
95
|
clean_operations: bool = True,
|
|
96
|
-
) ->
|
|
96
|
+
) -> tuple[np.ndarray, list[cirq.Operation]]:
|
|
97
97
|
"""Decomposes a 2-qubit unitary to a diagonal and the remaining operations.
|
|
98
98
|
|
|
99
99
|
For a 2-qubit unitary V, return ops, a list of operations and
|
|
@@ -197,7 +197,7 @@ def _kak_decomposition_to_operations(
|
|
|
197
197
|
kak: linalg.KakDecomposition,
|
|
198
198
|
allow_partial_czs: bool,
|
|
199
199
|
atol: float = 1e-8,
|
|
200
|
-
) ->
|
|
200
|
+
) -> list[ops.Operation]:
|
|
201
201
|
"""Assumes that the decomposition is canonical."""
|
|
202
202
|
b0, b1 = kak.single_qubit_operations_before
|
|
203
203
|
pre = [_do_single_on(b0, q0, atol=atol), _do_single_on(b1, q1, atol=atol)]
|
|
@@ -232,7 +232,7 @@ def _is_trivial_angle(rad: float, atol: float) -> bool:
|
|
|
232
232
|
|
|
233
233
|
|
|
234
234
|
def _parity_interaction(
|
|
235
|
-
q0: cirq.Qid, q1: cirq.Qid, rads: float, atol: float, gate:
|
|
235
|
+
q0: cirq.Qid, q1: cirq.Qid, rads: float, atol: float, gate: ops.Gate | None = None
|
|
236
236
|
):
|
|
237
237
|
"""Yields a ZZ interaction framed by the given operation."""
|
|
238
238
|
if abs(rads) < atol:
|
|
@@ -263,7 +263,7 @@ def _do_single_on(u: np.ndarray, q: cirq.Qid, atol: float = 1e-8):
|
|
|
263
263
|
def _non_local_part(
|
|
264
264
|
q0: cirq.Qid,
|
|
265
265
|
q1: cirq.Qid,
|
|
266
|
-
interaction_coefficients:
|
|
266
|
+
interaction_coefficients: tuple[float, float, float],
|
|
267
267
|
allow_partial_czs: bool,
|
|
268
268
|
atol: float = 1e-8,
|
|
269
269
|
):
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
|
|
17
17
|
from __future__ import annotations
|
|
18
18
|
|
|
19
|
-
from typing import Iterable, Iterator,
|
|
19
|
+
from typing import Iterable, Iterator, Sequence, TYPE_CHECKING
|
|
20
20
|
|
|
21
21
|
import numpy as np
|
|
22
22
|
|
|
@@ -27,10 +27,10 @@ if TYPE_CHECKING:
|
|
|
27
27
|
|
|
28
28
|
|
|
29
29
|
def decompose_two_qubit_interaction_into_four_fsim_gates(
|
|
30
|
-
interaction:
|
|
30
|
+
interaction: cirq.SupportsUnitary | np.ndarray,
|
|
31
31
|
*,
|
|
32
|
-
fsim_gate:
|
|
33
|
-
qubits:
|
|
32
|
+
fsim_gate: cirq.FSimGate | cirq.ISwapPowGate,
|
|
33
|
+
qubits: Sequence[cirq.Qid] | None = None,
|
|
34
34
|
) -> cirq.Circuit:
|
|
35
35
|
"""Decomposes operations into an FSimGate near theta=pi/2, phi=0.
|
|
36
36
|
|
|
@@ -100,7 +100,7 @@ def decompose_two_qubit_interaction_into_four_fsim_gates(
|
|
|
100
100
|
return result
|
|
101
101
|
|
|
102
102
|
|
|
103
|
-
def _sticky_0_to_1(v: float, *, atol: float) ->
|
|
103
|
+
def _sticky_0_to_1(v: float, *, atol: float) -> float | None:
|
|
104
104
|
if 0 <= v <= 1:
|
|
105
105
|
return v
|
|
106
106
|
if 1 < v <= 1 + atol:
|
|
@@ -117,7 +117,7 @@ def _decompose_xx_yy_into_two_fsims_ignoring_single_qubit_ops(
|
|
|
117
117
|
canonical_x_kak_coefficient: float,
|
|
118
118
|
canonical_y_kak_coefficient: float,
|
|
119
119
|
atol: float = 1e-8,
|
|
120
|
-
) ->
|
|
120
|
+
) -> list[cirq.Operation]:
|
|
121
121
|
x = canonical_x_kak_coefficient
|
|
122
122
|
y = canonical_y_kak_coefficient
|
|
123
123
|
assert 0 <= y <= x <= np.pi / 4
|
|
@@ -176,10 +176,10 @@ _B = _BGate()
|
|
|
176
176
|
|
|
177
177
|
|
|
178
178
|
def _decompose_two_qubit_interaction_into_two_b_gates(
|
|
179
|
-
interaction:
|
|
179
|
+
interaction: cirq.SupportsUnitary | np.ndarray | cirq.KakDecomposition,
|
|
180
180
|
*,
|
|
181
181
|
qubits: Sequence[cirq.Qid],
|
|
182
|
-
) ->
|
|
182
|
+
) -> list[cirq.Operation]:
|
|
183
183
|
kak = linalg.kak_decomposition(interaction)
|
|
184
184
|
|
|
185
185
|
result = _decompose_interaction_into_two_b_gates_ignoring_single_qubit_ops(
|
|
@@ -195,7 +195,7 @@ def _decompose_two_qubit_interaction_into_two_b_gates(
|
|
|
195
195
|
|
|
196
196
|
def _decompose_b_gate_into_two_fsims(
|
|
197
197
|
*, fsim_gate: cirq.FSimGate, qubits: Sequence[cirq.Qid]
|
|
198
|
-
) ->
|
|
198
|
+
) -> list[cirq.Operation]:
|
|
199
199
|
kak = linalg.kak_decomposition(_B)
|
|
200
200
|
|
|
201
201
|
result = _decompose_xx_yy_into_two_fsims_ignoring_single_qubit_ops(
|
|
@@ -214,7 +214,7 @@ def _decompose_b_gate_into_two_fsims(
|
|
|
214
214
|
|
|
215
215
|
def _decompose_interaction_into_two_b_gates_ignoring_single_qubit_ops(
|
|
216
216
|
qubits: Sequence[cirq.Qid], kak_interaction_coefficients: Iterable[float]
|
|
217
|
-
) ->
|
|
217
|
+
) -> list[cirq.Operation]:
|
|
218
218
|
"""Decompose using a minimal construction of two-qubit operations.
|
|
219
219
|
|
|
220
220
|
References:
|
|
@@ -238,7 +238,7 @@ def _decompose_interaction_into_two_b_gates_ignoring_single_qubit_ops(
|
|
|
238
238
|
|
|
239
239
|
|
|
240
240
|
def _fix_single_qubit_gates_around_kak_interaction(
|
|
241
|
-
*, desired: cirq.KakDecomposition, operations:
|
|
241
|
+
*, desired: cirq.KakDecomposition, operations: list[cirq.Operation], qubits: Sequence[cirq.Qid]
|
|
242
242
|
) -> Iterator[cirq.Operation]:
|
|
243
243
|
"""Adds single qubit operations to complete a desired interaction.
|
|
244
244
|
|
|
@@ -21,7 +21,7 @@ Gate compilation methods implemented here are following the paper below:
|
|
|
21
21
|
|
|
22
22
|
from __future__ import annotations
|
|
23
23
|
|
|
24
|
-
from typing import cast, Iterable,
|
|
24
|
+
from typing import cast, Iterable, TYPE_CHECKING
|
|
25
25
|
|
|
26
26
|
from cirq import linalg, ops, protocols
|
|
27
27
|
from cirq.transformers.analytical_decompositions import single_qubit_decompositions, two_qubit_to_cz
|
|
@@ -34,7 +34,7 @@ if TYPE_CHECKING:
|
|
|
34
34
|
|
|
35
35
|
def two_qubit_matrix_to_ion_operations(
|
|
36
36
|
q0: cirq.Qid, q1: cirq.Qid, mat: np.ndarray, atol: float = 1e-8, clean_operations: bool = True
|
|
37
|
-
) ->
|
|
37
|
+
) -> list[ops.Operation]:
|
|
38
38
|
"""Decomposes a two-qubit operation into MS/single-qubit rotation gates.
|
|
39
39
|
|
|
40
40
|
Args:
|
|
@@ -55,7 +55,7 @@ def two_qubit_matrix_to_ion_operations(
|
|
|
55
55
|
|
|
56
56
|
def _kak_decomposition_to_operations(
|
|
57
57
|
q0: cirq.Qid, q1: cirq.Qid, kak: linalg.KakDecomposition, atol: float = 1e-8
|
|
58
|
-
) ->
|
|
58
|
+
) -> list[ops.Operation]:
|
|
59
59
|
"""Assumes that the decomposition is canonical."""
|
|
60
60
|
b0, b1 = kak.single_qubit_operations_before
|
|
61
61
|
pre = [_do_single_on(b0, q0, atol), _do_single_on(b1, q1, atol)]
|
|
@@ -78,7 +78,7 @@ def _do_single_on(u: np.ndarray, q: cirq.Qid, atol: float = 1e-8):
|
|
|
78
78
|
|
|
79
79
|
|
|
80
80
|
def _parity_interaction(
|
|
81
|
-
q0: cirq.Qid, q1: cirq.Qid, rads: float, atol: float, gate:
|
|
81
|
+
q0: cirq.Qid, q1: cirq.Qid, rads: float, atol: float, gate: ops.Gate | None = None
|
|
82
82
|
):
|
|
83
83
|
"""Yields an XX interaction framed by the given operation."""
|
|
84
84
|
|
|
@@ -98,7 +98,7 @@ def _parity_interaction(
|
|
|
98
98
|
def _non_local_part(
|
|
99
99
|
q0: cirq.Qid,
|
|
100
100
|
q1: cirq.Qid,
|
|
101
|
-
interaction_coefficients:
|
|
101
|
+
interaction_coefficients: tuple[float, float, float],
|
|
102
102
|
atol: float = 1e-8,
|
|
103
103
|
):
|
|
104
104
|
"""Yields non-local operation of KAK decomposition."""
|
|
@@ -22,7 +22,7 @@ References:
|
|
|
22
22
|
|
|
23
23
|
from __future__ import annotations
|
|
24
24
|
|
|
25
|
-
from typing import
|
|
25
|
+
from typing import Sequence, TYPE_CHECKING
|
|
26
26
|
|
|
27
27
|
import numpy as np
|
|
28
28
|
import sympy
|
|
@@ -233,7 +233,7 @@ def two_qubit_matrix_to_sqrt_iswap_operations(
|
|
|
233
233
|
q1: cirq.Qid,
|
|
234
234
|
mat: np.ndarray,
|
|
235
235
|
*,
|
|
236
|
-
required_sqrt_iswap_count:
|
|
236
|
+
required_sqrt_iswap_count: int | None = None,
|
|
237
237
|
use_sqrt_iswap_inv: bool = False,
|
|
238
238
|
atol: float = 1e-8,
|
|
239
239
|
check_preconditions: bool = True,
|
|
@@ -303,7 +303,7 @@ def _kak_decomposition_to_sqrt_iswap_operations(
|
|
|
303
303
|
q0: cirq.Qid,
|
|
304
304
|
q1: cirq.Qid,
|
|
305
305
|
kak: linalg.KakDecomposition,
|
|
306
|
-
required_sqrt_iswap_count:
|
|
306
|
+
required_sqrt_iswap_count: int | None = None,
|
|
307
307
|
use_sqrt_iswap_inv: bool = False,
|
|
308
308
|
atol: float = 1e-8,
|
|
309
309
|
) -> Sequence[cirq.Operation]:
|
|
@@ -328,7 +328,7 @@ def _decomp_to_operations(
|
|
|
328
328
|
q0: cirq.Qid,
|
|
329
329
|
q1: cirq.Qid,
|
|
330
330
|
two_qubit_gate: cirq.Gate,
|
|
331
|
-
single_qubit_operations: Sequence[
|
|
331
|
+
single_qubit_operations: Sequence[tuple[np.ndarray, np.ndarray]],
|
|
332
332
|
u0_before: np.ndarray = np.eye(2),
|
|
333
333
|
u0_after: np.ndarray = np.eye(2),
|
|
334
334
|
atol: float = 1e-8,
|
|
@@ -401,8 +401,8 @@ def _decomp_to_operations(
|
|
|
401
401
|
|
|
402
402
|
|
|
403
403
|
def _single_qubit_matrices_with_sqrt_iswap(
|
|
404
|
-
kak: cirq.KakDecomposition, required_sqrt_iswap_count:
|
|
405
|
-
) ->
|
|
404
|
+
kak: cirq.KakDecomposition, required_sqrt_iswap_count: int | None = None, atol: float = 1e-8
|
|
405
|
+
) -> tuple[Sequence[tuple[np.ndarray, np.ndarray]], complex]:
|
|
406
406
|
"""Computes the sequence of interleaved single-qubit unitary matrices in the
|
|
407
407
|
sqrt-iSWAP decomposition."""
|
|
408
408
|
decomposers = [
|
|
@@ -428,7 +428,7 @@ def _single_qubit_matrices_with_sqrt_iswap(
|
|
|
428
428
|
|
|
429
429
|
|
|
430
430
|
def _in_0_region(
|
|
431
|
-
interaction_coefficients:
|
|
431
|
+
interaction_coefficients: tuple[float, float, float], weyl_tol: float = 1e-8
|
|
432
432
|
) -> bool:
|
|
433
433
|
"""Tests if (x, y, z) ~= (0, 0, 0) assuming x, y, z are canonical."""
|
|
434
434
|
x, y, z = interaction_coefficients
|
|
@@ -436,7 +436,7 @@ def _in_0_region(
|
|
|
436
436
|
|
|
437
437
|
|
|
438
438
|
def _in_1sqrt_iswap_region(
|
|
439
|
-
interaction_coefficients:
|
|
439
|
+
interaction_coefficients: tuple[float, float, float], weyl_tol: float = 1e-8
|
|
440
440
|
) -> bool:
|
|
441
441
|
"""Tests if (x, y, z) ~= (π/8, π/8, 0), assuming x, y, z are canonical."""
|
|
442
442
|
x, y, z = interaction_coefficients
|
|
@@ -444,7 +444,7 @@ def _in_1sqrt_iswap_region(
|
|
|
444
444
|
|
|
445
445
|
|
|
446
446
|
def _in_2sqrt_iswap_region(
|
|
447
|
-
interaction_coefficients:
|
|
447
|
+
interaction_coefficients: tuple[float, float, float], weyl_tol: float = 1e-8
|
|
448
448
|
) -> bool:
|
|
449
449
|
"""Tests if (x, y, z) is inside or within weyl_tol of the volume
|
|
450
450
|
x >= y + |z| assuming x, y, z are canonical.
|
|
@@ -461,7 +461,7 @@ def _in_2sqrt_iswap_region(
|
|
|
461
461
|
|
|
462
462
|
|
|
463
463
|
def _in_3sqrt_iswap_region(
|
|
464
|
-
interaction_coefficients:
|
|
464
|
+
interaction_coefficients: tuple[float, float, float], weyl_tol: float = 1e-8
|
|
465
465
|
) -> bool:
|
|
466
466
|
"""Any two-qubit operation is decomposable into three SQRT_ISWAP gates.
|
|
467
467
|
|
|
@@ -475,7 +475,7 @@ def _in_3sqrt_iswap_region(
|
|
|
475
475
|
|
|
476
476
|
def _decomp_0_matrices(
|
|
477
477
|
kak: cirq.KakDecomposition, atol: float = 1e-8
|
|
478
|
-
) ->
|
|
478
|
+
) -> tuple[Sequence[tuple[np.ndarray, np.ndarray]], complex]:
|
|
479
479
|
"""Returns the single-qubit matrices for the 0-SQRT_ISWAP decomposition.
|
|
480
480
|
|
|
481
481
|
Assumes canonical x, y, z and (x, y, z) = (0, 0, 0) within tolerance.
|
|
@@ -493,7 +493,7 @@ def _decomp_0_matrices(
|
|
|
493
493
|
|
|
494
494
|
def _decomp_1sqrt_iswap_matrices(
|
|
495
495
|
kak: cirq.KakDecomposition, atol: float = 1e-8
|
|
496
|
-
) ->
|
|
496
|
+
) -> tuple[Sequence[tuple[np.ndarray, np.ndarray]], complex]:
|
|
497
497
|
"""Returns the single-qubit matrices for the 1-SQRT_ISWAP decomposition.
|
|
498
498
|
|
|
499
499
|
Assumes canonical x, y, z and (x, y, z) = (π/8, π/8, 0) within tolerance.
|
|
@@ -506,7 +506,7 @@ def _decomp_1sqrt_iswap_matrices(
|
|
|
506
506
|
|
|
507
507
|
def _decomp_2sqrt_iswap_matrices(
|
|
508
508
|
kak: cirq.KakDecomposition, atol: float = 1e-8
|
|
509
|
-
) ->
|
|
509
|
+
) -> tuple[Sequence[tuple[np.ndarray, np.ndarray]], complex]:
|
|
510
510
|
"""Returns the single-qubit matrices for the 2-SQRT_ISWAP decomposition.
|
|
511
511
|
|
|
512
512
|
Assumes canonical x, y, z and x >= y + |z| within tolerance. For x, y, z
|
|
@@ -569,7 +569,7 @@ def _decomp_2sqrt_iswap_matrices(
|
|
|
569
569
|
|
|
570
570
|
def _decomp_3sqrt_iswap_matrices(
|
|
571
571
|
kak: cirq.KakDecomposition, atol: float = 1e-8
|
|
572
|
-
) ->
|
|
572
|
+
) -> tuple[Sequence[tuple[np.ndarray, np.ndarray]], complex]:
|
|
573
573
|
"""Returns the single-qubit matrices for the 3-SQRT_ISWAP decomposition.
|
|
574
574
|
|
|
575
575
|
Assumes any canonical x, y, z. Three sqrt-iSWAP gates are only needed if
|
|
@@ -18,7 +18,7 @@ from __future__ import annotations
|
|
|
18
18
|
|
|
19
19
|
from functools import reduce
|
|
20
20
|
from itertools import cycle
|
|
21
|
-
from typing import
|
|
21
|
+
from typing import TYPE_CHECKING
|
|
22
22
|
|
|
23
23
|
import numpy as np
|
|
24
24
|
|
|
@@ -33,7 +33,7 @@ if TYPE_CHECKING:
|
|
|
33
33
|
import cirq
|
|
34
34
|
|
|
35
35
|
|
|
36
|
-
def _get_dd_sequence_from_schema_name(schema: str) ->
|
|
36
|
+
def _get_dd_sequence_from_schema_name(schema: str) -> tuple[ops.Gate, ...]:
|
|
37
37
|
"""Gets dynamical decoupling sequence from a schema name."""
|
|
38
38
|
match schema:
|
|
39
39
|
case 'DEFAULT':
|
|
@@ -50,14 +50,14 @@ def _get_dd_sequence_from_schema_name(schema: str) -> Tuple[ops.Gate, ...]:
|
|
|
50
50
|
raise ValueError('Invalid schema name.')
|
|
51
51
|
|
|
52
52
|
|
|
53
|
-
def _pauli_up_to_global_phase(gate: ops.Gate) ->
|
|
53
|
+
def _pauli_up_to_global_phase(gate: ops.Gate) -> ops.Pauli | None:
|
|
54
54
|
for pauli_gate in [ops.X, ops.Y, ops.Z]:
|
|
55
55
|
if protocols.equal_up_to_global_phase(gate, pauli_gate):
|
|
56
56
|
return pauli_gate
|
|
57
57
|
return None
|
|
58
58
|
|
|
59
59
|
|
|
60
|
-
def _validate_dd_sequence(dd_sequence:
|
|
60
|
+
def _validate_dd_sequence(dd_sequence: tuple[ops.Gate, ...]) -> None:
|
|
61
61
|
"""Validates a given dynamical decoupling sequence.
|
|
62
62
|
|
|
63
63
|
The sequence should only consists of Pauli gates and is essentially an identity gate.
|
|
@@ -87,8 +87,8 @@ def _validate_dd_sequence(dd_sequence: Tuple[ops.Gate, ...]) -> None:
|
|
|
87
87
|
|
|
88
88
|
|
|
89
89
|
def _parse_dd_sequence(
|
|
90
|
-
schema:
|
|
91
|
-
) ->
|
|
90
|
+
schema: str | tuple[ops.Gate, ...],
|
|
91
|
+
) -> tuple[tuple[ops.Gate, ...], dict[ops.Gate, ops.Pauli]]:
|
|
92
92
|
"""Parses and returns dynamical decoupling sequence and its associated pauli map from schema."""
|
|
93
93
|
dd_sequence = None
|
|
94
94
|
if isinstance(schema, str):
|
|
@@ -98,7 +98,7 @@ def _parse_dd_sequence(
|
|
|
98
98
|
dd_sequence = schema
|
|
99
99
|
|
|
100
100
|
# Map gate to Pauli gate. This is necessary as dd sequence might contain gates like X^-1.
|
|
101
|
-
pauli_map:
|
|
101
|
+
pauli_map: dict[ops.Gate, ops.Pauli] = {}
|
|
102
102
|
for gate in dd_sequence:
|
|
103
103
|
pauli_gate = _pauli_up_to_global_phase(gate)
|
|
104
104
|
if pauli_gate is not None:
|
|
@@ -123,8 +123,8 @@ def _is_clifford_op(op: ops.Operation) -> bool:
|
|
|
123
123
|
|
|
124
124
|
def _calc_busy_moment_range_of_each_qubit(
|
|
125
125
|
circuit: circuits.FrozenCircuit,
|
|
126
|
-
) ->
|
|
127
|
-
busy_moment_range_by_qubit:
|
|
126
|
+
) -> dict[ops.Qid, list[int]]:
|
|
127
|
+
busy_moment_range_by_qubit: dict[ops.Qid, list[int]] = {
|
|
128
128
|
q: [len(circuit), -1] for q in circuit.all_qubits()
|
|
129
129
|
}
|
|
130
130
|
for moment_id, moment in enumerate(circuit):
|
|
@@ -139,7 +139,7 @@ def _is_insertable_moment(moment: circuits.Moment, single_qubit_gate_moments_onl
|
|
|
139
139
|
|
|
140
140
|
|
|
141
141
|
def _merge_single_qubit_ops_to_phxz(
|
|
142
|
-
q: ops.Qid, operations:
|
|
142
|
+
q: ops.Qid, operations: tuple[ops.Operation, ...]
|
|
143
143
|
) -> ops.Operation:
|
|
144
144
|
"""Merges [op1, op2, ...] and returns an equivalent op"""
|
|
145
145
|
if len(operations) == 1:
|
|
@@ -152,7 +152,7 @@ def _merge_single_qubit_ops_to_phxz(
|
|
|
152
152
|
|
|
153
153
|
def _try_merge_single_qubit_ops_of_two_moments(
|
|
154
154
|
m1: circuits.Moment, m2: circuits.Moment
|
|
155
|
-
) ->
|
|
155
|
+
) -> tuple[circuits.Moment, ...]:
|
|
156
156
|
"""Merge single qubit ops of 2 moments if possible, returns 2 moments otherwise."""
|
|
157
157
|
for q in m1.qubits & m2.qubits:
|
|
158
158
|
op1 = m1.operation_at(q)
|
|
@@ -208,8 +208,8 @@ def _need_merge_pulled_through(op_at_q: ops.Operation, is_at_last_busy_moment: b
|
|
|
208
208
|
def add_dynamical_decoupling(
|
|
209
209
|
circuit: cirq.AbstractCircuit,
|
|
210
210
|
*,
|
|
211
|
-
context:
|
|
212
|
-
schema:
|
|
211
|
+
context: cirq.TransformerContext | None = None,
|
|
212
|
+
schema: str | tuple[ops.Gate, ...] = 'DEFAULT',
|
|
213
213
|
single_qubit_gate_moments_only: bool = True,
|
|
214
214
|
) -> cirq.Circuit:
|
|
215
215
|
"""Adds dynamical decoupling gate operations to a given circuit.
|