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/ops/controlled_gate_test.py
CHANGED
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
from __future__ import annotations
|
|
16
16
|
|
|
17
17
|
from types import EllipsisType, NotImplementedType
|
|
18
|
-
from typing import Any, cast,
|
|
18
|
+
from typing import Any, cast, Sequence, Union
|
|
19
19
|
|
|
20
20
|
import numpy as np
|
|
21
21
|
import pytest
|
|
@@ -25,7 +25,7 @@ import cirq
|
|
|
25
25
|
|
|
26
26
|
|
|
27
27
|
class GateUsingWorkspaceForApplyUnitary(cirq.testing.SingleQubitGate):
|
|
28
|
-
def _apply_unitary_(self, args: cirq.ApplyUnitaryArgs) ->
|
|
28
|
+
def _apply_unitary_(self, args: cirq.ApplyUnitaryArgs) -> np.ndarray | NotImplementedType:
|
|
29
29
|
args.available_buffer[...] = args.target_tensor
|
|
30
30
|
args.target_tensor[...] = 0
|
|
31
31
|
return args.available_buffer
|
|
@@ -44,10 +44,10 @@ class GateAllocatingNewSpaceForResult(cirq.testing.SingleQubitGate):
|
|
|
44
44
|
def __init__(self):
|
|
45
45
|
self._matrix = cirq.testing.random_unitary(2, random_state=4321)
|
|
46
46
|
|
|
47
|
-
def _apply_unitary_(self, args: cirq.ApplyUnitaryArgs) ->
|
|
47
|
+
def _apply_unitary_(self, args: cirq.ApplyUnitaryArgs) -> np.ndarray | NotImplementedType:
|
|
48
48
|
assert len(args.axes) == 1
|
|
49
49
|
a = args.axes[0]
|
|
50
|
-
seed = cast(
|
|
50
|
+
seed = cast(tuple[Union[int, slice, EllipsisType], ...], (slice(None),))
|
|
51
51
|
zero = seed * a + (0, Ellipsis)
|
|
52
52
|
one = seed * a + (1, Ellipsis)
|
|
53
53
|
result = np.zeros(args.target_tensor.shape, args.target_tensor.dtype)
|
|
@@ -475,7 +475,7 @@ def test_nontrivial_controlled_gate_is_consistent(
|
|
|
475
475
|
def _test_controlled_gate_is_consistent(
|
|
476
476
|
gate: cirq.Gate,
|
|
477
477
|
should_decompose_to_target: bool,
|
|
478
|
-
control_qid_shape:
|
|
478
|
+
control_qid_shape: Sequence[int] | None = None,
|
|
479
479
|
control_values: Any = None,
|
|
480
480
|
):
|
|
481
481
|
cgate = cirq.ControlledGate(
|
cirq/ops/controlled_operation.py
CHANGED
|
@@ -15,18 +15,7 @@
|
|
|
15
15
|
from __future__ import annotations
|
|
16
16
|
|
|
17
17
|
from types import EllipsisType, NotImplementedType
|
|
18
|
-
from typing import
|
|
19
|
-
AbstractSet,
|
|
20
|
-
Any,
|
|
21
|
-
Collection,
|
|
22
|
-
Dict,
|
|
23
|
-
List,
|
|
24
|
-
Optional,
|
|
25
|
-
Sequence,
|
|
26
|
-
Tuple,
|
|
27
|
-
TYPE_CHECKING,
|
|
28
|
-
Union,
|
|
29
|
-
)
|
|
18
|
+
from typing import AbstractSet, Any, Collection, Sequence, TYPE_CHECKING
|
|
30
19
|
|
|
31
20
|
import numpy as np
|
|
32
21
|
|
|
@@ -57,9 +46,7 @@ class ControlledOperation(raw_types.Operation):
|
|
|
57
46
|
self,
|
|
58
47
|
controls: Sequence[cirq.Qid],
|
|
59
48
|
sub_operation: cirq.Operation,
|
|
60
|
-
control_values:
|
|
61
|
-
Union[cv.AbstractControlValues, Sequence[Union[int, Collection[int]]]]
|
|
62
|
-
] = None,
|
|
49
|
+
control_values: cv.AbstractControlValues | Sequence[int | Collection[int]] | None = None,
|
|
63
50
|
):
|
|
64
51
|
"""Initializes the controlled operation.
|
|
65
52
|
|
|
@@ -116,7 +103,7 @@ class ControlledOperation(raw_types.Operation):
|
|
|
116
103
|
self._control_values = self._control_values & sub_operation.control_values
|
|
117
104
|
|
|
118
105
|
@property
|
|
119
|
-
def controls(self) ->
|
|
106
|
+
def controls(self) -> tuple[cirq.Qid, ...]:
|
|
120
107
|
return self._controls
|
|
121
108
|
|
|
122
109
|
@property
|
|
@@ -128,7 +115,7 @@ class ControlledOperation(raw_types.Operation):
|
|
|
128
115
|
return self._sub_operation
|
|
129
116
|
|
|
130
117
|
@property
|
|
131
|
-
def gate(self) ->
|
|
118
|
+
def gate(self) -> cirq.ControlledGate | None:
|
|
132
119
|
if self.sub_operation.gate is None:
|
|
133
120
|
return None
|
|
134
121
|
return controlled_gate.ControlledGate(
|
|
@@ -150,7 +137,7 @@ class ControlledOperation(raw_types.Operation):
|
|
|
150
137
|
def _decompose_(self):
|
|
151
138
|
return self._decompose_with_context_()
|
|
152
139
|
|
|
153
|
-
def _decompose_with_context_(self, context:
|
|
140
|
+
def _decompose_with_context_(self, context: cirq.DecompositionContext | None = None):
|
|
154
141
|
result = protocols.decompose_once_with_qubits(
|
|
155
142
|
self.gate, self.qubits, NotImplemented, flatten=False, context=context
|
|
156
143
|
)
|
|
@@ -183,7 +170,7 @@ class ControlledOperation(raw_types.Operation):
|
|
|
183
170
|
sub_n = len(args.axes) - n
|
|
184
171
|
sub_axes = args.axes[n:]
|
|
185
172
|
for control_vals in self.control_values.expand():
|
|
186
|
-
active:
|
|
173
|
+
active: tuple[EllipsisType | slice, ...] = (
|
|
187
174
|
...,
|
|
188
175
|
*(slice(v, v + 1) for v in control_vals),
|
|
189
176
|
*(slice(None),) * sub_n,
|
|
@@ -209,7 +196,7 @@ class ControlledOperation(raw_types.Operation):
|
|
|
209
196
|
def _has_unitary_(self) -> bool:
|
|
210
197
|
return protocols.has_unitary(self.sub_operation)
|
|
211
198
|
|
|
212
|
-
def _qasm_(self, args: cirq.QasmArgs) ->
|
|
199
|
+
def _qasm_(self, args: cirq.QasmArgs) -> str | None:
|
|
213
200
|
if (
|
|
214
201
|
hasattr(self._sub_operation, "gate")
|
|
215
202
|
and len(self._controls) == 1
|
|
@@ -246,7 +233,7 @@ class ControlledOperation(raw_types.Operation):
|
|
|
246
233
|
tensor[active] = sub_tensor # type: ignore[index]
|
|
247
234
|
return tensor.reshape((np.prod(qid_shape, dtype=np.int64).item(),) * 2)
|
|
248
235
|
|
|
249
|
-
def _unitary_(self) ->
|
|
236
|
+
def _unitary_(self) -> np.ndarray | NotImplementedType:
|
|
250
237
|
sub_matrix = protocols.unitary(self.sub_operation, None)
|
|
251
238
|
if sub_matrix is None:
|
|
252
239
|
return NotImplemented
|
|
@@ -255,7 +242,7 @@ class ControlledOperation(raw_types.Operation):
|
|
|
255
242
|
def _has_mixture_(self) -> bool:
|
|
256
243
|
return protocols.has_mixture(self.sub_operation)
|
|
257
244
|
|
|
258
|
-
def _mixture_(self) ->
|
|
245
|
+
def _mixture_(self) -> list[tuple[float, np.ndarray]] | None:
|
|
259
246
|
sub_mixture = protocols.mixture(self.sub_operation, None)
|
|
260
247
|
if sub_mixture is None:
|
|
261
248
|
return None
|
|
@@ -294,7 +281,7 @@ class ControlledOperation(raw_types.Operation):
|
|
|
294
281
|
new_sub_op = protocols.resolve_parameters(self.sub_operation, resolver, recursive)
|
|
295
282
|
return ControlledOperation(self.controls, new_sub_op, self.control_values)
|
|
296
283
|
|
|
297
|
-
def _trace_distance_bound_(self) ->
|
|
284
|
+
def _trace_distance_bound_(self) -> float | None:
|
|
298
285
|
if self._is_parameterized_():
|
|
299
286
|
return None
|
|
300
287
|
u = protocols.unitary(self.sub_operation, default=None)
|
|
@@ -311,7 +298,7 @@ class ControlledOperation(raw_types.Operation):
|
|
|
311
298
|
|
|
312
299
|
def _circuit_diagram_info_(
|
|
313
300
|
self, args: cirq.CircuitDiagramInfoArgs
|
|
314
|
-
) ->
|
|
301
|
+
) -> protocols.CircuitDiagramInfo | None:
|
|
315
302
|
n = len(self.controls)
|
|
316
303
|
|
|
317
304
|
sub_args = protocols.CircuitDiagramInfoArgs(
|
|
@@ -346,7 +333,7 @@ class ControlledOperation(raw_types.Operation):
|
|
|
346
333
|
exponent_qubit_index=exponent_qubit_index,
|
|
347
334
|
)
|
|
348
335
|
|
|
349
|
-
def _json_dict_(self) ->
|
|
336
|
+
def _json_dict_(self) -> dict[str, Any]:
|
|
350
337
|
return {
|
|
351
338
|
'controls': self.controls,
|
|
352
339
|
'control_values': self.control_values,
|
|
@@ -17,7 +17,7 @@ from __future__ import annotations
|
|
|
17
17
|
import itertools
|
|
18
18
|
import re
|
|
19
19
|
from types import EllipsisType, NotImplementedType
|
|
20
|
-
from typing import cast,
|
|
20
|
+
from typing import cast, Union
|
|
21
21
|
|
|
22
22
|
import numpy as np
|
|
23
23
|
import pytest
|
|
@@ -28,7 +28,7 @@ from cirq import protocols
|
|
|
28
28
|
|
|
29
29
|
|
|
30
30
|
class GateUsingWorkspaceForApplyUnitary(cirq.testing.SingleQubitGate):
|
|
31
|
-
def _apply_unitary_(self, args: cirq.ApplyUnitaryArgs) ->
|
|
31
|
+
def _apply_unitary_(self, args: cirq.ApplyUnitaryArgs) -> np.ndarray | NotImplementedType:
|
|
32
32
|
args.available_buffer[...] = args.target_tensor
|
|
33
33
|
args.target_tensor[...] = 0
|
|
34
34
|
return args.available_buffer
|
|
@@ -47,10 +47,10 @@ class GateAllocatingNewSpaceForResult(cirq.testing.SingleQubitGate):
|
|
|
47
47
|
def __init__(self):
|
|
48
48
|
self._matrix = cirq.testing.random_unitary(2, random_state=1234)
|
|
49
49
|
|
|
50
|
-
def _apply_unitary_(self, args: cirq.ApplyUnitaryArgs) ->
|
|
50
|
+
def _apply_unitary_(self, args: cirq.ApplyUnitaryArgs) -> np.ndarray | NotImplementedType:
|
|
51
51
|
assert len(args.axes) == 1
|
|
52
52
|
a = args.axes[0]
|
|
53
|
-
seed = cast(
|
|
53
|
+
seed = cast(tuple[Union[int, slice, EllipsisType], ...], (slice(None),))
|
|
54
54
|
zero = seed * a + (0, Ellipsis)
|
|
55
55
|
one = seed * a + (1, Ellipsis)
|
|
56
56
|
result = np.zeros(args.target_tensor.shape, args.target_tensor.dtype)
|
|
@@ -157,7 +157,7 @@ def test_str():
|
|
|
157
157
|
|
|
158
158
|
class SingleQubitOp(cirq.Operation):
|
|
159
159
|
@property
|
|
160
|
-
def qubits(self) ->
|
|
160
|
+
def qubits(self) -> tuple[cirq.Qid, ...]:
|
|
161
161
|
return ()
|
|
162
162
|
|
|
163
163
|
def with_qubits(self, *new_qubits: cirq.Qid):
|
cirq/ops/dense_pauli_string.py
CHANGED
|
@@ -22,16 +22,11 @@ from typing import (
|
|
|
22
22
|
Any,
|
|
23
23
|
Callable,
|
|
24
24
|
cast,
|
|
25
|
-
Dict,
|
|
26
25
|
Iterable,
|
|
27
26
|
Iterator,
|
|
28
|
-
List,
|
|
29
|
-
Optional,
|
|
30
27
|
overload,
|
|
31
28
|
Sequence,
|
|
32
|
-
Tuple,
|
|
33
29
|
TYPE_CHECKING,
|
|
34
|
-
Union,
|
|
35
30
|
)
|
|
36
31
|
|
|
37
32
|
import numpy as np
|
|
@@ -47,7 +42,7 @@ if TYPE_CHECKING:
|
|
|
47
42
|
|
|
48
43
|
# Order is important! Index equals numeric value.
|
|
49
44
|
PAULI_CHARS = 'IXYZ'
|
|
50
|
-
PAULI_GATES:
|
|
45
|
+
PAULI_GATES: list[cirq.Pauli | cirq.IdentityGate] = [
|
|
51
46
|
identity.I,
|
|
52
47
|
pauli_gates.X,
|
|
53
48
|
pauli_gates.Y,
|
|
@@ -86,7 +81,7 @@ class BaseDensePauliString(raw_types.Gate, metaclass=abc.ABCMeta):
|
|
|
86
81
|
|
|
87
82
|
def __init__(
|
|
88
83
|
self,
|
|
89
|
-
pauli_mask:
|
|
84
|
+
pauli_mask: Iterable[cirq.PAULI_GATE_LIKE] | np.ndarray,
|
|
90
85
|
*,
|
|
91
86
|
coefficient: cirq.TParamValComplex = 1,
|
|
92
87
|
):
|
|
@@ -105,7 +100,7 @@ class BaseDensePauliString(raw_types.Gate, metaclass=abc.ABCMeta):
|
|
|
105
100
|
values are supported.
|
|
106
101
|
"""
|
|
107
102
|
self._pauli_mask = _as_pauli_mask(pauli_mask)
|
|
108
|
-
self._coefficient:
|
|
103
|
+
self._coefficient: complex | sympy.Expr = (
|
|
109
104
|
coefficient if isinstance(coefficient, sympy.Expr) else complex(coefficient)
|
|
110
105
|
)
|
|
111
106
|
if type(self) != MutableDensePauliString:
|
|
@@ -122,7 +117,7 @@ class BaseDensePauliString(raw_types.Gate, metaclass=abc.ABCMeta):
|
|
|
122
117
|
"""A complex coefficient or symbol."""
|
|
123
118
|
return self._coefficient
|
|
124
119
|
|
|
125
|
-
def _json_dict_(self) ->
|
|
120
|
+
def _json_dict_(self) -> dict[str, Any]:
|
|
126
121
|
return protocols.obj_to_dict_helper(self, ['pauli_mask', 'coefficient'])
|
|
127
122
|
|
|
128
123
|
def _value_equality_values_(self):
|
|
@@ -165,14 +160,14 @@ class BaseDensePauliString(raw_types.Gate, metaclass=abc.ABCMeta):
|
|
|
165
160
|
return False
|
|
166
161
|
return abs(1 - abs(cast(complex, self.coefficient))) < 1e-8
|
|
167
162
|
|
|
168
|
-
def _unitary_(self) ->
|
|
163
|
+
def _unitary_(self) -> np.ndarray | NotImplementedType:
|
|
169
164
|
if not self._has_unitary_():
|
|
170
165
|
return NotImplemented
|
|
171
166
|
return self.coefficient * linalg.kron(
|
|
172
167
|
*[protocols.unitary(PAULI_GATES[p]) for p in self.pauli_mask]
|
|
173
168
|
)
|
|
174
169
|
|
|
175
|
-
def _apply_unitary_(self, args) ->
|
|
170
|
+
def _apply_unitary_(self, args) -> np.ndarray | None | NotImplementedType:
|
|
176
171
|
if not self._has_unitary_():
|
|
177
172
|
return NotImplemented
|
|
178
173
|
from cirq import devices
|
|
@@ -181,7 +176,7 @@ class BaseDensePauliString(raw_types.Gate, metaclass=abc.ABCMeta):
|
|
|
181
176
|
decomposed_ops = cast(Iterable['cirq.OP_TREE'], self._decompose_(qubits))
|
|
182
177
|
return protocols.apply_unitaries(decomposed_ops, qubits, args)
|
|
183
178
|
|
|
184
|
-
def _decompose_(self, qubits: Sequence[cirq.Qid]) ->
|
|
179
|
+
def _decompose_(self, qubits: Sequence[cirq.Qid]) -> NotImplementedType | cirq.OP_TREE:
|
|
185
180
|
if not self._has_unitary_():
|
|
186
181
|
return NotImplemented
|
|
187
182
|
result = [PAULI_GATES[p].on(q) for p, q in zip(self.pauli_mask, qubits) if p]
|
|
@@ -203,7 +198,7 @@ class BaseDensePauliString(raw_types.Gate, metaclass=abc.ABCMeta):
|
|
|
203
198
|
def __pos__(self):
|
|
204
199
|
return self
|
|
205
200
|
|
|
206
|
-
def __pow__(self, power: float) ->
|
|
201
|
+
def __pow__(self, power: float) -> NotImplementedType | Self:
|
|
207
202
|
concrete_class = type(self)
|
|
208
203
|
if isinstance(power, int):
|
|
209
204
|
i_group = [1, +1j, -1, -1j]
|
|
@@ -218,7 +213,7 @@ class BaseDensePauliString(raw_types.Gate, metaclass=abc.ABCMeta):
|
|
|
218
213
|
return NotImplemented
|
|
219
214
|
|
|
220
215
|
@overload
|
|
221
|
-
def __getitem__(self, item: int) ->
|
|
216
|
+
def __getitem__(self, item: int) -> cirq.Pauli | cirq.IdentityGate:
|
|
222
217
|
pass
|
|
223
218
|
|
|
224
219
|
@overload
|
|
@@ -234,7 +229,7 @@ class BaseDensePauliString(raw_types.Gate, metaclass=abc.ABCMeta):
|
|
|
234
229
|
|
|
235
230
|
raise TypeError(f'indices must be integers or slices, not {type(item)}')
|
|
236
231
|
|
|
237
|
-
def __iter__(self) -> Iterator[
|
|
232
|
+
def __iter__(self) -> Iterator[cirq.Pauli | cirq.IdentityGate]:
|
|
238
233
|
for i in range(len(self)):
|
|
239
234
|
yield self[i]
|
|
240
235
|
|
|
@@ -326,7 +321,7 @@ class BaseDensePauliString(raw_types.Gate, metaclass=abc.ABCMeta):
|
|
|
326
321
|
def on(self, *qubits: cirq.Qid) -> cirq.PauliString:
|
|
327
322
|
return self.sparse(qubits)
|
|
328
323
|
|
|
329
|
-
def sparse(self, qubits:
|
|
324
|
+
def sparse(self, qubits: Sequence[cirq.Qid] | None = None) -> cirq.PauliString:
|
|
330
325
|
"""A `cirq.PauliString` version of this dense pauli string.
|
|
331
326
|
|
|
332
327
|
Args:
|
|
@@ -373,9 +368,7 @@ class BaseDensePauliString(raw_types.Gate, metaclass=abc.ABCMeta):
|
|
|
373
368
|
f'coefficient={proper_repr(self.coefficient)})'
|
|
374
369
|
)
|
|
375
370
|
|
|
376
|
-
def _commutes_(
|
|
377
|
-
self, other: Any, *, atol: float = 1e-8
|
|
378
|
-
) -> Union[bool, NotImplementedType, None]:
|
|
371
|
+
def _commutes_(self, other: Any, *, atol: float = 1e-8) -> bool | NotImplementedType | None:
|
|
379
372
|
if isinstance(other, BaseDensePauliString):
|
|
380
373
|
n = min(len(self.pauli_mask), len(other.pauli_mask))
|
|
381
374
|
phase = _vectorized_pauli_mul_phase(self.pauli_mask[:n], other.pauli_mask[:n])
|
|
@@ -403,8 +396,8 @@ class BaseDensePauliString(raw_types.Gate, metaclass=abc.ABCMeta):
|
|
|
403
396
|
@abc.abstractmethod
|
|
404
397
|
def copy(
|
|
405
398
|
self,
|
|
406
|
-
coefficient:
|
|
407
|
-
pauli_mask:
|
|
399
|
+
coefficient: cirq.TParamValComplex | None = None,
|
|
400
|
+
pauli_mask: None | str | Iterable[int] | np.ndarray = None,
|
|
408
401
|
) -> Self:
|
|
409
402
|
"""Returns a copy with possibly modified contents.
|
|
410
403
|
|
|
@@ -459,8 +452,8 @@ class DensePauliString(BaseDensePauliString):
|
|
|
459
452
|
|
|
460
453
|
def copy(
|
|
461
454
|
self,
|
|
462
|
-
coefficient:
|
|
463
|
-
pauli_mask:
|
|
455
|
+
coefficient: cirq.TParamValComplex | None = None,
|
|
456
|
+
pauli_mask: None | str | Iterable[int] | np.ndarray = None,
|
|
464
457
|
) -> DensePauliString:
|
|
465
458
|
if pauli_mask is None and (coefficient is None or coefficient == self.coefficient):
|
|
466
459
|
return self
|
|
@@ -494,9 +487,7 @@ class MutableDensePauliString(BaseDensePauliString):
|
|
|
494
487
|
|
|
495
488
|
@overload
|
|
496
489
|
def __setitem__(
|
|
497
|
-
self,
|
|
498
|
-
key: slice,
|
|
499
|
-
value: Union[Iterable[cirq.PAULI_GATE_LIKE], np.ndarray, BaseDensePauliString],
|
|
490
|
+
self, key: slice, value: Iterable[cirq.PAULI_GATE_LIKE] | np.ndarray | BaseDensePauliString
|
|
500
491
|
) -> Self:
|
|
501
492
|
pass
|
|
502
493
|
|
|
@@ -559,8 +550,8 @@ class MutableDensePauliString(BaseDensePauliString):
|
|
|
559
550
|
|
|
560
551
|
def copy(
|
|
561
552
|
self,
|
|
562
|
-
coefficient:
|
|
563
|
-
pauli_mask:
|
|
553
|
+
coefficient: cirq.TParamValComplex | None = None,
|
|
554
|
+
pauli_mask: None | str | Iterable[int] | np.ndarray = None,
|
|
564
555
|
) -> MutableDensePauliString:
|
|
565
556
|
return MutableDensePauliString(
|
|
566
557
|
coefficient=self.coefficient if coefficient is None else coefficient,
|
|
@@ -574,7 +565,7 @@ class MutableDensePauliString(BaseDensePauliString):
|
|
|
574
565
|
return self.coefficient, tuple(PAULI_CHARS[p] for p in self.pauli_mask)
|
|
575
566
|
|
|
576
567
|
@classmethod
|
|
577
|
-
def inline_gaussian_elimination(cls, rows:
|
|
568
|
+
def inline_gaussian_elimination(cls, rows: list[MutableDensePauliString]) -> None:
|
|
578
569
|
if not rows:
|
|
579
570
|
return
|
|
580
571
|
|
|
@@ -616,13 +607,13 @@ def _pauli_index(val: cirq.PAULI_GATE_LIKE) -> int:
|
|
|
616
607
|
return m[val]
|
|
617
608
|
|
|
618
609
|
|
|
619
|
-
def _as_pauli_mask(val:
|
|
610
|
+
def _as_pauli_mask(val: Iterable[cirq.PAULI_GATE_LIKE] | np.ndarray) -> np.ndarray:
|
|
620
611
|
if isinstance(val, np.ndarray):
|
|
621
612
|
return np.asarray(val, dtype=np.uint8)
|
|
622
613
|
return np.array([_pauli_index(v) for v in val], dtype=np.uint8)
|
|
623
614
|
|
|
624
615
|
|
|
625
|
-
def _attempt_value_to_pauli_index(v: cirq.Operation) ->
|
|
616
|
+
def _attempt_value_to_pauli_index(v: cirq.Operation) -> tuple[int, int] | None:
|
|
626
617
|
if not isinstance(v, raw_types.Operation):
|
|
627
618
|
return None
|
|
628
619
|
|
|
@@ -641,9 +632,7 @@ def _attempt_value_to_pauli_index(v: cirq.Operation) -> Optional[Tuple[int, int]
|
|
|
641
632
|
return pauli_string.PAULI_GATE_LIKE_TO_INDEX_MAP[v.gate], q.x
|
|
642
633
|
|
|
643
634
|
|
|
644
|
-
def _vectorized_pauli_mul_phase(
|
|
645
|
-
lhs: Union[int, np.ndarray], rhs: Union[int, np.ndarray]
|
|
646
|
-
) -> complex:
|
|
635
|
+
def _vectorized_pauli_mul_phase(lhs: int | np.ndarray, rhs: int | np.ndarray) -> complex:
|
|
647
636
|
"""Computes the leading coefficient of a pauli string multiplication.
|
|
648
637
|
|
|
649
638
|
The two inputs must have the same length. They must follow the convention
|
|
@@ -15,7 +15,6 @@
|
|
|
15
15
|
from __future__ import annotations
|
|
16
16
|
|
|
17
17
|
import numbers
|
|
18
|
-
from typing import List
|
|
19
18
|
|
|
20
19
|
import numpy as np
|
|
21
20
|
import pytest
|
|
@@ -547,7 +546,7 @@ def test_copy():
|
|
|
547
546
|
|
|
548
547
|
|
|
549
548
|
def test_gaussian_elimination():
|
|
550
|
-
def table(*rows: str) ->
|
|
549
|
+
def table(*rows: str) -> list[cirq.MutableDensePauliString]:
|
|
551
550
|
coefs = {'i': 1j, '-': -1, '+': 1}
|
|
552
551
|
return [
|
|
553
552
|
cirq.MutableDensePauliString(row[1:].replace('.', 'I'), coefficient=coefs[row[0]])
|
cirq/ops/diagonal_gate.py
CHANGED
|
@@ -20,18 +20,7 @@ passed as a list.
|
|
|
20
20
|
|
|
21
21
|
from __future__ import annotations
|
|
22
22
|
|
|
23
|
-
from typing import
|
|
24
|
-
AbstractSet,
|
|
25
|
-
Any,
|
|
26
|
-
Dict,
|
|
27
|
-
Iterator,
|
|
28
|
-
List,
|
|
29
|
-
Optional,
|
|
30
|
-
Sequence,
|
|
31
|
-
Tuple,
|
|
32
|
-
TYPE_CHECKING,
|
|
33
|
-
Union,
|
|
34
|
-
)
|
|
23
|
+
from typing import AbstractSet, Any, Iterator, Sequence, TYPE_CHECKING
|
|
35
24
|
|
|
36
25
|
import numpy as np
|
|
37
26
|
import sympy
|
|
@@ -44,7 +33,7 @@ if TYPE_CHECKING:
|
|
|
44
33
|
import cirq
|
|
45
34
|
|
|
46
35
|
|
|
47
|
-
def _fast_walsh_hadamard_transform(a:
|
|
36
|
+
def _fast_walsh_hadamard_transform(a: tuple[Any, ...]) -> np.ndarray:
|
|
48
37
|
"""Fast Walsh–Hadamard Transform of an array."""
|
|
49
38
|
h = 1
|
|
50
39
|
a_ = np.array(a)
|
|
@@ -59,7 +48,7 @@ def _fast_walsh_hadamard_transform(a: Tuple[Any, ...]) -> np.ndarray:
|
|
|
59
48
|
return a_
|
|
60
49
|
|
|
61
50
|
|
|
62
|
-
def _gen_gray_code(n: int) -> Iterator[
|
|
51
|
+
def _gen_gray_code(n: int) -> Iterator[tuple[int, int]]:
|
|
63
52
|
"""Generate the Gray Code from 0 to 2^n-1.
|
|
64
53
|
|
|
65
54
|
Each iteration yields a two-tuple, `(gray_code, bit_flip)`. `gray_code` is the decimal
|
|
@@ -94,10 +83,10 @@ class DiagonalGate(raw_types.Gate):
|
|
|
94
83
|
If these values are $(x_0, x_1, \ldots , x_N)$ then the unitary
|
|
95
84
|
has diagonal values $(e^{i x_0}, e^{i x_1}, \ldots, e^{i x_N})$.
|
|
96
85
|
"""
|
|
97
|
-
self._diag_angles_radians:
|
|
86
|
+
self._diag_angles_radians: tuple[cirq.TParamVal, ...] = tuple(diag_angles_radians)
|
|
98
87
|
|
|
99
88
|
@property
|
|
100
|
-
def diag_angles_radians(self) ->
|
|
89
|
+
def diag_angles_radians(self) -> tuple[cirq.TParamVal, ...]:
|
|
101
90
|
return self._diag_angles_radians
|
|
102
91
|
|
|
103
92
|
def _num_qubits_(self):
|
|
@@ -119,7 +108,7 @@ class DiagonalGate(raw_types.Gate):
|
|
|
119
108
|
def _has_unitary_(self) -> bool:
|
|
120
109
|
return not self._is_parameterized_()
|
|
121
110
|
|
|
122
|
-
def _unitary_(self) ->
|
|
111
|
+
def _unitary_(self) -> np.ndarray | None:
|
|
123
112
|
if self._is_parameterized_():
|
|
124
113
|
return None
|
|
125
114
|
return np.diag([np.exp(1j * angle) for angle in self._diag_angles_radians])
|
|
@@ -162,7 +151,7 @@ class DiagonalGate(raw_types.Gate):
|
|
|
162
151
|
|
|
163
152
|
def _decompose_for_basis(
|
|
164
153
|
self, index: int, bit_flip: int, theta: cirq.TParamVal, qubits: Sequence[cirq.Qid]
|
|
165
|
-
) -> Iterator[
|
|
154
|
+
) -> Iterator[cirq.ZPowGate | cirq.CXPowGate]:
|
|
166
155
|
if index == 0:
|
|
167
156
|
return
|
|
168
157
|
largest_digit = self._num_qubits_() - (len(bin(index)) - 2)
|
|
@@ -200,14 +189,14 @@ class DiagonalGate(raw_types.Gate):
|
|
|
200
189
|
# decomposed gates. On its own it is not physically observable. However, if using this
|
|
201
190
|
# diagonal gate for sub-system like controlled gate, it is no longer equivalent. Hence,
|
|
202
191
|
# we add global phase.
|
|
203
|
-
decomposed_circ:
|
|
192
|
+
decomposed_circ: list[Any] = [
|
|
204
193
|
global_phase_op.global_phase_operation(1j ** (2 * hat_angles[0] / np.pi))
|
|
205
194
|
]
|
|
206
195
|
for i, bit_flip in _gen_gray_code(n):
|
|
207
196
|
decomposed_circ.extend(self._decompose_for_basis(i, bit_flip, -hat_angles[i], qubits))
|
|
208
197
|
return decomposed_circ
|
|
209
198
|
|
|
210
|
-
def _json_dict_(self) ->
|
|
199
|
+
def _json_dict_(self) -> dict[str, Any]:
|
|
211
200
|
return protocols.obj_to_dict_helper(self, attribute_names=["diag_angles_radians"])
|
|
212
201
|
|
|
213
202
|
def __repr__(self) -> str:
|
cirq/ops/diagonal_gate_test.py
CHANGED
|
@@ -14,15 +14,13 @@
|
|
|
14
14
|
|
|
15
15
|
from __future__ import annotations
|
|
16
16
|
|
|
17
|
-
from typing import List
|
|
18
|
-
|
|
19
17
|
import numpy as np
|
|
20
18
|
import pytest
|
|
21
19
|
import sympy
|
|
22
20
|
|
|
23
21
|
import cirq
|
|
24
22
|
|
|
25
|
-
_candidate_angles:
|
|
23
|
+
_candidate_angles: list[float] = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53]
|
|
26
24
|
|
|
27
25
|
|
|
28
26
|
@pytest.mark.parametrize(
|
cirq/ops/eigen_gate.py
CHANGED
|
@@ -19,19 +19,7 @@ import fractions
|
|
|
19
19
|
import math
|
|
20
20
|
import numbers
|
|
21
21
|
from types import NotImplementedType
|
|
22
|
-
from typing import
|
|
23
|
-
AbstractSet,
|
|
24
|
-
Any,
|
|
25
|
-
cast,
|
|
26
|
-
Dict,
|
|
27
|
-
Iterable,
|
|
28
|
-
List,
|
|
29
|
-
NamedTuple,
|
|
30
|
-
Optional,
|
|
31
|
-
Tuple,
|
|
32
|
-
TYPE_CHECKING,
|
|
33
|
-
Union,
|
|
34
|
-
)
|
|
22
|
+
from typing import AbstractSet, Any, cast, Iterable, NamedTuple, TYPE_CHECKING
|
|
35
23
|
|
|
36
24
|
import numpy as np
|
|
37
25
|
import sympy
|
|
@@ -219,7 +207,7 @@ class EigenGate(raw_types.Gate):
|
|
|
219
207
|
return args.format_radians(radians=2 * pi * exponent / order)
|
|
220
208
|
|
|
221
209
|
# virtual method
|
|
222
|
-
def _eigen_shifts(self) ->
|
|
210
|
+
def _eigen_shifts(self) -> list[float]:
|
|
223
211
|
"""Describes the eigenvalues of the gate's matrix.
|
|
224
212
|
|
|
225
213
|
By default, this just extracts the shifts by calling
|
|
@@ -235,7 +223,7 @@ class EigenGate(raw_types.Gate):
|
|
|
235
223
|
return [e[0] for e in self._eigen_components()]
|
|
236
224
|
|
|
237
225
|
@abc.abstractmethod
|
|
238
|
-
def _eigen_components(self) ->
|
|
226
|
+
def _eigen_components(self) -> list[EigenComponent | tuple[float, np.ndarray]]:
|
|
239
227
|
"""Describes the eigendecomposition of the gate's matrix.
|
|
240
228
|
|
|
241
229
|
Returns:
|
|
@@ -287,7 +275,7 @@ class EigenGate(raw_types.Gate):
|
|
|
287
275
|
]
|
|
288
276
|
"""
|
|
289
277
|
|
|
290
|
-
def _period(self) ->
|
|
278
|
+
def _period(self) -> float | None:
|
|
291
279
|
"""Determines how the exponent parameter is canonicalized when equating.
|
|
292
280
|
|
|
293
281
|
Returns:
|
|
@@ -300,7 +288,7 @@ class EigenGate(raw_types.Gate):
|
|
|
300
288
|
real_periods = [abs(2 / e) for e in exponents if e != 0]
|
|
301
289
|
return _approximate_common_period(real_periods)
|
|
302
290
|
|
|
303
|
-
def __pow__(self, exponent:
|
|
291
|
+
def __pow__(self, exponent: float | sympy.Symbol) -> EigenGate:
|
|
304
292
|
new_exponent = protocols.mul(self._exponent, exponent, NotImplemented)
|
|
305
293
|
if new_exponent is NotImplemented:
|
|
306
294
|
return NotImplemented # pragma: no cover
|
|
@@ -320,7 +308,7 @@ class EigenGate(raw_types.Gate):
|
|
|
320
308
|
shifts = (f(self._exponent) * f(self._global_shift + e) for e in self._eigen_shifts())
|
|
321
309
|
return tuple(s if symbolic(s) else value.PeriodicValue(f(s), 2) for s in shifts)
|
|
322
310
|
|
|
323
|
-
def _trace_distance_bound_(self) ->
|
|
311
|
+
def _trace_distance_bound_(self) -> float | None:
|
|
324
312
|
if protocols.is_parameterized(self._exponent):
|
|
325
313
|
return None
|
|
326
314
|
angles = np.pi * (np.array(self._eigen_shifts()) * self._exponent % 2)
|
|
@@ -329,7 +317,7 @@ class EigenGate(raw_types.Gate):
|
|
|
329
317
|
def _has_unitary_(self) -> bool:
|
|
330
318
|
return not self._is_parameterized_()
|
|
331
319
|
|
|
332
|
-
def _unitary_(self) ->
|
|
320
|
+
def _unitary_(self) -> np.ndarray | NotImplementedType:
|
|
333
321
|
if self._is_parameterized_():
|
|
334
322
|
return NotImplemented
|
|
335
323
|
e = cast(float, self._exponent)
|
|
@@ -372,7 +360,7 @@ class EigenGate(raw_types.Gate):
|
|
|
372
360
|
other_without_phase._global_shift = 0
|
|
373
361
|
return protocols.approx_eq(self_without_phase, other_without_phase, atol=atol)
|
|
374
362
|
|
|
375
|
-
def _json_dict_(self) ->
|
|
363
|
+
def _json_dict_(self) -> dict[str, Any]:
|
|
376
364
|
return protocols.obj_to_dict_helper(self, ['exponent', 'global_shift'])
|
|
377
365
|
|
|
378
366
|
def _measurement_key_objs_(self):
|
|
@@ -387,8 +375,8 @@ def _lcm(vals: Iterable[int]) -> int:
|
|
|
387
375
|
|
|
388
376
|
|
|
389
377
|
def _approximate_common_period(
|
|
390
|
-
periods:
|
|
391
|
-
) ->
|
|
378
|
+
periods: list[float], approx_denom: int = 60, reject_atol: float = 1e-8
|
|
379
|
+
) -> float | None:
|
|
392
380
|
"""Finds a value that is nearly an integer multiple of multiple periods.
|
|
393
381
|
|
|
394
382
|
The returned value should be the smallest non-negative number with this
|
|
@@ -432,7 +420,7 @@ def _approximate_common_period(
|
|
|
432
420
|
return common
|
|
433
421
|
|
|
434
422
|
|
|
435
|
-
def _common_rational_period(rational_periods:
|
|
423
|
+
def _common_rational_period(rational_periods: list[fractions.Fraction]) -> fractions.Fraction:
|
|
436
424
|
"""Finds the least common integer multiple of some fractions.
|
|
437
425
|
|
|
438
426
|
The solution is the smallest positive integer c such that there
|
cirq/ops/eigen_gate_test.py
CHANGED
|
@@ -14,8 +14,6 @@
|
|
|
14
14
|
|
|
15
15
|
from __future__ import annotations
|
|
16
16
|
|
|
17
|
-
from typing import List, Tuple
|
|
18
|
-
|
|
19
17
|
import numpy as np
|
|
20
18
|
import pytest
|
|
21
19
|
import sympy
|
|
@@ -43,7 +41,7 @@ class CExpZinGate(cirq.EigenGate, cirq.testing.TwoQubitGate):
|
|
|
43
41
|
def _with_exponent(self, exponent):
|
|
44
42
|
return CExpZinGate(exponent)
|
|
45
43
|
|
|
46
|
-
def _eigen_components(self) ->
|
|
44
|
+
def _eigen_components(self) -> list[tuple[float, np.ndarray]]:
|
|
47
45
|
return [
|
|
48
46
|
(0, np.diag([1, 1, 0, 0])),
|
|
49
47
|
(0.5, np.diag([0, 0, 1, 0])),
|
|
@@ -56,7 +54,7 @@ class ZGateDef(cirq.EigenGate, cirq.testing.SingleQubitGate):
|
|
|
56
54
|
def exponent(self):
|
|
57
55
|
return self._exponent
|
|
58
56
|
|
|
59
|
-
def _eigen_components(self) ->
|
|
57
|
+
def _eigen_components(self) -> list[tuple[float, np.ndarray]]:
|
|
60
58
|
return [(0, np.diag([1, 0])), (1, np.diag([0, 1]))]
|
|
61
59
|
|
|
62
60
|
|
|
@@ -210,7 +208,7 @@ def test_period():
|
|
|
210
208
|
self.c = c
|
|
211
209
|
self.d = d
|
|
212
210
|
|
|
213
|
-
def _eigen_components(self) ->
|
|
211
|
+
def _eigen_components(self) -> list[tuple[float, np.ndarray]]:
|
|
214
212
|
return [
|
|
215
213
|
(self.a, np.diag([1, 0, 0, 0])),
|
|
216
214
|
(self.b, np.diag([0, 1, 0, 0])),
|
|
@@ -261,7 +259,7 @@ def test_trace_distance_bound():
|
|
|
261
259
|
def _num_qubits_(self): # pragma: no cover
|
|
262
260
|
return 1
|
|
263
261
|
|
|
264
|
-
def _eigen_components(self) ->
|
|
262
|
+
def _eigen_components(self) -> list[tuple[float, np.ndarray]]:
|
|
265
263
|
return [(0, np.array([[1, 0], [0, 0]])), (12, np.array([[0, 0], [0, 1]]))]
|
|
266
264
|
|
|
267
265
|
for numerator in range(13):
|
|
@@ -353,7 +351,7 @@ def test_resolve_parameters(resolve_fn):
|
|
|
353
351
|
|
|
354
352
|
def test_diagram_period():
|
|
355
353
|
class ShiftyGate(cirq.EigenGate, cirq.testing.SingleQubitGate):
|
|
356
|
-
def _eigen_components(self) ->
|
|
354
|
+
def _eigen_components(self) -> list[tuple[float, np.ndarray]]:
|
|
357
355
|
raise NotImplementedError()
|
|
358
356
|
|
|
359
357
|
def __init__(self, e, *shifts):
|
|
@@ -390,7 +388,7 @@ class WeightedZPowGate(cirq.EigenGate, cirq.testing.SingleQubitGate):
|
|
|
390
388
|
self.weight = weight
|
|
391
389
|
super().__init__(**kwargs)
|
|
392
390
|
|
|
393
|
-
def _eigen_components(self) ->
|
|
391
|
+
def _eigen_components(self) -> list[tuple[float, np.ndarray]]:
|
|
394
392
|
return [(0, np.diag([1, 0])), (self.weight, np.diag([0, 1]))]
|
|
395
393
|
|
|
396
394
|
def _with_exponent(self, exponent):
|