From 3d135f857f9e07b085c1d29810bd8c6a92c99d8f Mon Sep 17 00:00:00 2001 From: Pavol Juhas Date: Wed, 10 Sep 2025 15:45:02 -0700 Subject: [PATCH 1/7] Add return-type to public functions, mostly tests part 5 --- cirq-core/cirq/_doc.py | 7 +- .../protocols/apply_unitary_protocol_test.py | 2 + .../testing/consistent_resolve_parameters.py | 2 +- cirq-core/cirq/testing/consistent_unitary.py | 2 +- .../cirq/testing/consistent_unitary_test.py | 2 +- cirq-core/cirq/testing/equals_tester.py | 4 +- .../cirq/testing/equivalent_basis_map.py | 4 +- cirq-core/cirq/testing/json.py | 2 +- cirq-core/cirq/testing/op_tree.py | 2 +- cirq-core/cirq/testing/order_tester.py | 4 +- cirq-core/cirq/testing/repr_pretty_tester.py | 6 +- cirq-core/cirq/transformers/align_test.py | 26 +++--- .../clifford_decomposition_test.py | 10 +-- .../controlled_gate_decomposition_test.py | 12 +-- .../cphase_to_fsim.py | 2 +- .../cphase_to_fsim_test.py | 19 +++-- .../quantum_shannon_decomposition.py | 10 +-- .../quantum_shannon_decomposition_test.py | 35 ++++---- .../single_qubit_decompositions_test.py | 58 +++++++------ .../single_to_two_qubit_isometry_test.py | 2 +- .../two_qubit_state_preparation_test.py | 23 ++--- .../two_qubit_to_cz.py | 4 +- .../two_qubit_to_cz_test.py | 6 +- .../two_qubit_to_ms_test.py | 4 +- .../two_qubit_to_sqrt_iswap_test.py | 62 +++++++------- .../drop_negligible_operations_test.py | 14 ++-- .../transformers/dynamical_decoupling_test.py | 44 +++++----- .../transformers/eject_phased_paulis_test.py | 2 +- cirq-core/cirq/transformers/eject_z_test.py | 45 +++++----- .../cirq/transformers/expand_composite.py | 2 +- .../transformers/expand_composite_test.py | 28 +++---- .../gauge_compiling/gauge_compiling.py | 2 +- .../gauge_compiling/gauge_compiling_test.py | 26 +++--- .../gauge_compiling_test_utils.py | 6 +- .../gate_tabulation_math_utils_test.py | 12 +-- .../measurement_transformers_test.py | 84 ++++++++++--------- .../transformers/merge_k_qubit_gates_test.py | 2 +- .../merge_single_qubit_gates_test.py | 44 +++++----- .../cirq/transformers/noise_adding_test.py | 4 +- .../optimize_for_target_gateset_test.py | 20 +++-- .../qubit_management_transformers_test.py | 8 +- 41 files changed, 341 insertions(+), 312 deletions(-) diff --git a/cirq-core/cirq/_doc.py b/cirq-core/cirq/_doc.py index 2e9bc1d2d46..540435e4cba 100644 --- a/cirq-core/cirq/_doc.py +++ b/cirq-core/cirq/_doc.py @@ -15,12 +15,13 @@ from __future__ import annotations -from typing import Any +from typing import TypeVar +T = TypeVar('T') RECORDED_CONST_DOCS: dict[int, str] = {} -def document(value: Any, doc_string: str = ''): +def document(value: T, doc_string: str = '') -> T: """Stores documentation details about the given value. This method is used to associate a docstring with global constants. It is @@ -64,7 +65,7 @@ def document(value: Any, doc_string: str = ''): _DOC_PRIVATE = "_tf_docs_doc_private" -def doc_private(obj): +def doc_private(obj: T) -> T: """A decorator: Generates docs for private methods/functions. For example: diff --git a/cirq-core/cirq/protocols/apply_unitary_protocol_test.py b/cirq-core/cirq/protocols/apply_unitary_protocol_test.py index bbde4d78c65..e8dacfa60c0 100644 --- a/cirq-core/cirq/protocols/apply_unitary_protocol_test.py +++ b/cirq-core/cirq/protocols/apply_unitary_protocol_test.py @@ -240,6 +240,7 @@ def assert_is_swap_simple(val: cirq.SupportsConsistentApplyUnitary) -> None: op_indices, tuple(qid_shape[i] for i in op_indices) ) sub_result = val._apply_unitary_(sub_args) + assert isinstance(sub_result, np.ndarray) result = _incorporate_result_into_target(args, sub_args, sub_result) np.testing.assert_allclose(result, expected, atol=1e-8) @@ -258,6 +259,7 @@ def assert_is_swap(val: cirq.SupportsConsistentApplyUnitary) -> None: op_indices, tuple(qid_shape[i] for i in op_indices) ) sub_result = val._apply_unitary_(sub_args) + assert isinstance(sub_result, np.ndarray) result = _incorporate_result_into_target(args, sub_args, sub_result) np.testing.assert_allclose(result, expected, atol=1e-8, verbose=True) diff --git a/cirq-core/cirq/testing/consistent_resolve_parameters.py b/cirq-core/cirq/testing/consistent_resolve_parameters.py index 8da92fe6301..1ad0f6bb906 100644 --- a/cirq-core/cirq/testing/consistent_resolve_parameters.py +++ b/cirq-core/cirq/testing/consistent_resolve_parameters.py @@ -21,7 +21,7 @@ import cirq -def assert_consistent_resolve_parameters(val: Any): +def assert_consistent_resolve_parameters(val: Any) -> None: names = cirq.parameter_names(val) symbols = cirq.parameter_symbols(val) diff --git a/cirq-core/cirq/testing/consistent_unitary.py b/cirq-core/cirq/testing/consistent_unitary.py index b78d514544b..2fa25649472 100644 --- a/cirq-core/cirq/testing/consistent_unitary.py +++ b/cirq-core/cirq/testing/consistent_unitary.py @@ -21,7 +21,7 @@ import cirq -def assert_unitary_is_consistent(val: Any, ignoring_global_phase: bool = False): +def assert_unitary_is_consistent(val: Any, ignoring_global_phase: bool = False) -> None: if not isinstance(val, (cirq.Operation, cirq.Gate)): return diff --git a/cirq-core/cirq/testing/consistent_unitary_test.py b/cirq-core/cirq/testing/consistent_unitary_test.py index 87e0e06f17d..69c7f1bde75 100644 --- a/cirq-core/cirq/testing/consistent_unitary_test.py +++ b/cirq-core/cirq/testing/consistent_unitary_test.py @@ -95,4 +95,4 @@ def test_failed_decomposition() -> None: with pytest.raises(ValueError): cirq.testing.assert_unitary_is_consistent(FailsOnDecompostion()) - _ = cirq.testing.assert_unitary_is_consistent(cirq.Circuit()) + cirq.testing.assert_unitary_is_consistent(cirq.Circuit()) diff --git a/cirq-core/cirq/testing/equals_tester.py b/cirq-core/cirq/testing/equals_tester.py index e4c767c1908..3d64f2f85c8 100644 --- a/cirq-core/cirq/testing/equals_tester.py +++ b/cirq-core/cirq/testing/equals_tester.py @@ -93,7 +93,7 @@ def _verify_equality_group(self, *group_items: Any): "Common problem: returning NotImplementedError instead of NotImplemented. " ) - def add_equality_group(self, *group_items: Any): + def add_equality_group(self, *group_items: Any) -> None: """Tries to add a disjoint equivalence group to the equality tester. This methods asserts that items within the group must all be equal to @@ -114,7 +114,7 @@ def add_equality_group(self, *group_items: Any): # Remember this group, to enable disjoint checks vs later groups. self._groups.append(group_items) - def make_equality_group(self, *factories: Callable[[], Any]): + def make_equality_group(self, *factories: Callable[[], Any]) -> None: """Tries to add a disjoint equivalence group to the equality tester. Uses the factory methods to produce two different objects with the same diff --git a/cirq-core/cirq/testing/equivalent_basis_map.py b/cirq-core/cirq/testing/equivalent_basis_map.py index f7b9a7595e3..009d228c912 100644 --- a/cirq-core/cirq/testing/equivalent_basis_map.py +++ b/cirq-core/cirq/testing/equivalent_basis_map.py @@ -22,7 +22,9 @@ from cirq import circuits -def assert_equivalent_computational_basis_map(maps: dict[int, int], circuit: circuits.Circuit): +def assert_equivalent_computational_basis_map( + maps: dict[int, int], circuit: circuits.Circuit +) -> None: """Ensure equivalence of basis state mapping. Args: diff --git a/cirq-core/cirq/testing/json.py b/cirq-core/cirq/testing/json.py index 3729c685a6f..b3c7e508436 100644 --- a/cirq-core/cirq/testing/json.py +++ b/cirq-core/cirq/testing/json.py @@ -149,7 +149,7 @@ def spec_for(module_name: str) -> ModuleJsonTestSpec: return getattr(test_module, "TestSpec") -def assert_json_roundtrip_works(obj, text_should_be=None, resolvers=None): +def assert_json_roundtrip_works(obj, text_should_be=None, resolvers=None) -> None: """Tests that the given object can serialized and de-serialized Args: diff --git a/cirq-core/cirq/testing/op_tree.py b/cirq-core/cirq/testing/op_tree.py index bc16f4be0a5..e5af5aafafb 100644 --- a/cirq-core/cirq/testing/op_tree.py +++ b/cirq-core/cirq/testing/op_tree.py @@ -17,7 +17,7 @@ from cirq import ops -def assert_equivalent_op_tree(x: ops.OP_TREE, y: ops.OP_TREE): +def assert_equivalent_op_tree(x: ops.OP_TREE, y: ops.OP_TREE) -> None: """Ensures that the two OP_TREEs are equivalent. Args: diff --git a/cirq-core/cirq/testing/order_tester.py b/cirq-core/cirq/testing/order_tester.py index ba057b989a1..b8f5a202ef2 100644 --- a/cirq-core/cirq/testing/order_tester.py +++ b/cirq-core/cirq/testing/order_tester.py @@ -78,7 +78,7 @@ def _verify_not_implemented_vs_unknown(self, item: Any): f"That rule is being violated by this value: {item!r}" ) from ex - def add_ascending(self, *items: Any): + def add_ascending(self, *items: Any) -> None: """Tries to add a sequence of ascending items to the order tester. This methods asserts that items must all be ascending @@ -98,7 +98,7 @@ def add_ascending(self, *items: Any): for item in items: self.add_ascending_equivalence_group(item) - def add_ascending_equivalence_group(self, *group_items: Any): + def add_ascending_equivalence_group(self, *group_items: Any) -> None: """Tries to add an ascending equivalence group to the order tester. Asserts that the group items are equal to each other, but strictly diff --git a/cirq-core/cirq/testing/repr_pretty_tester.py b/cirq-core/cirq/testing/repr_pretty_tester.py index e0d2094c9a2..e77e20df6e2 100644 --- a/cirq-core/cirq/testing/repr_pretty_tester.py +++ b/cirq-core/cirq/testing/repr_pretty_tester.py @@ -34,11 +34,11 @@ class FakePrinter: def __init__(self): self.text_pretty = "" - def text(self, to_print): + def text(self, to_print) -> None: self.text_pretty += to_print -def assert_repr_pretty(val: Any, text: str, cycle: bool = False): +def assert_repr_pretty(val: Any, text: str, cycle: bool = False) -> None: """Assert that the given object has a `_repr_pretty_` method that produces the given text. Args: @@ -57,7 +57,7 @@ def assert_repr_pretty(val: Any, text: str, cycle: bool = False): assert p.text_pretty == text, f"{p.text_pretty} != {text}" -def assert_repr_pretty_contains(val: Any, substr: str, cycle: bool = False): +def assert_repr_pretty_contains(val: Any, substr: str, cycle: bool = False) -> None: """Assert that the given object has a `_repr_pretty_` output that contains the given text. Args: diff --git a/cirq-core/cirq/transformers/align_test.py b/cirq-core/cirq/transformers/align_test.py index b894a1a0155..629574301d8 100644 --- a/cirq-core/cirq/transformers/align_test.py +++ b/cirq-core/cirq/transformers/align_test.py @@ -17,7 +17,7 @@ import cirq -def test_align_basic_no_context(): +def test_align_basic_no_context() -> None: q1 = cirq.NamedQubit('q1') q2 = cirq.NamedQubit('q2') c = cirq.Circuit( @@ -45,7 +45,7 @@ def test_align_basic_no_context(): ) -def test_align_left_no_compile_context(): +def test_align_left_no_compile_context() -> None: q1 = cirq.NamedQubit('q1') q2 = cirq.NamedQubit('q2') cirq.testing.assert_same_circuits( @@ -59,7 +59,7 @@ def test_align_left_no_compile_context(): cirq.measure(*[q1, q2], key='a'), ] ), - context=cirq.TransformerContext(tags_to_ignore=["nocompile"]), + context=cirq.TransformerContext(tags_to_ignore=("nocompile",)), ), cirq.Circuit( [ @@ -73,7 +73,7 @@ def test_align_left_no_compile_context(): ) -def test_align_left_deep(): +def test_align_left_deep() -> None: q1, q2 = cirq.LineQubit.range(2) c_nested = cirq.FrozenCircuit( [ @@ -104,11 +104,11 @@ def test_align_left_deep(): c_nested_aligned, cirq.CircuitOperation(c_nested_aligned).repeat(5).with_tags("preserve_tag"), ) - context = cirq.TransformerContext(tags_to_ignore=["nocompile"], deep=True) + context = cirq.TransformerContext(tags_to_ignore=("nocompile",), deep=True) cirq.testing.assert_same_circuits(cirq.align_left(c_orig, context=context), c_expected) -def test_align_left_subset_of_operations(): +def test_align_left_subset_of_operations() -> None: q1 = cirq.NamedQubit('q1') q2 = cirq.NamedQubit('q2') tag = "op_to_align" @@ -134,7 +134,7 @@ def test_align_left_subset_of_operations(): cirq.toggle_tags( cirq.align_left( cirq.toggle_tags(c_orig, [tag]), - context=cirq.TransformerContext(tags_to_ignore=[tag]), + context=cirq.TransformerContext(tags_to_ignore=(tag,)), ), [tag], ), @@ -142,7 +142,7 @@ def test_align_left_subset_of_operations(): ) -def test_align_right_no_compile_context(): +def test_align_right_no_compile_context() -> None: q1 = cirq.NamedQubit('q1') q2 = cirq.NamedQubit('q2') cirq.testing.assert_same_circuits( @@ -156,7 +156,7 @@ def test_align_right_no_compile_context(): cirq.measure(*[q1, q2], key='a'), ] ), - context=cirq.TransformerContext(tags_to_ignore=["nocompile"]), + context=cirq.TransformerContext(tags_to_ignore=("nocompile",)), ), cirq.Circuit( [ @@ -170,7 +170,7 @@ def test_align_right_no_compile_context(): ) -def test_align_right_deep(): +def test_align_right_deep() -> None: q1, q2 = cirq.LineQubit.range(2) c_nested = cirq.FrozenCircuit( cirq.Moment([cirq.X(q1)]), @@ -199,11 +199,11 @@ def test_align_right_deep(): c_nested_aligned, cirq.CircuitOperation(c_nested_aligned).repeat(5).with_tags("preserve_tag"), ) - context = cirq.TransformerContext(tags_to_ignore=["nocompile"], deep=True) + context = cirq.TransformerContext(tags_to_ignore=("nocompile",), deep=True) cirq.testing.assert_same_circuits(cirq.align_right(c_orig, context=context), c_expected) -def test_classical_control(): +def test_classical_control() -> None: q0, q1 = cirq.LineQubit.range(2) circuit = cirq.Circuit( cirq.H(q0), cirq.measure(q0, key='m'), cirq.X(q1).with_classical_controls('m') @@ -212,7 +212,7 @@ def test_classical_control(): cirq.testing.assert_same_circuits(cirq.align_right(circuit), circuit) -def test_measurement_and_classical_control_same_moment_preserve_order(): +def test_measurement_and_classical_control_same_moment_preserve_order() -> None: q0, q1 = cirq.LineQubit.range(2) circuit = cirq.Circuit() op_measure = cirq.measure(q0, key='m') diff --git a/cirq-core/cirq/transformers/analytical_decompositions/clifford_decomposition_test.py b/cirq-core/cirq/transformers/analytical_decompositions/clifford_decomposition_test.py index 0d6e30048e7..0deb43c5f25 100644 --- a/cirq-core/cirq/transformers/analytical_decompositions/clifford_decomposition_test.py +++ b/cirq-core/cirq/transformers/analytical_decompositions/clifford_decomposition_test.py @@ -21,14 +21,14 @@ from cirq.testing import assert_allclose_up_to_global_phase -def test_misaligned_qubits(): +def test_misaligned_qubits() -> None: qubits = cirq.LineQubit.range(1) tableau = cirq.CliffordTableau(num_qubits=2) with pytest.raises(ValueError): cirq.decompose_clifford_tableau_to_operations(qubits, tableau) -def test_clifford_decompose_one_qubit(): +def test_clifford_decompose_one_qubit() -> None: """Two random instance for one qubit decomposition.""" qubits = cirq.LineQubit.range(1) args = cirq.CliffordTableauSimulationState( @@ -63,7 +63,7 @@ def test_clifford_decompose_one_qubit(): assert_allclose_up_to_global_phase(cirq.unitary(expect_circ), cirq.unitary(circ), atol=1e-7) -def test_clifford_decompose_two_qubits(): +def test_clifford_decompose_two_qubits() -> None: """Two random instance for two qubits decomposition.""" qubits = cirq.LineQubit.range(2) args = cirq.CliffordTableauSimulationState( @@ -98,7 +98,7 @@ def test_clifford_decompose_two_qubits(): assert_allclose_up_to_global_phase(cirq.unitary(expect_circ), cirq.unitary(circ), atol=1e-7) -def test_clifford_decompose_by_unitary(): +def test_clifford_decompose_by_unitary() -> None: """Validate the decomposition of random Clifford Tableau by unitary matrix. Due to the exponential growth in dimension, it cannot validate very large number of qubits. @@ -125,7 +125,7 @@ def test_clifford_decompose_by_unitary(): assert_allclose_up_to_global_phase(cirq.unitary(expect_circ), cirq.unitary(circ), atol=1e-7) -def test_clifford_decompose_by_reconstruction(): +def test_clifford_decompose_by_reconstruction() -> None: """Validate the decomposition of random Clifford Tableau by reconstruction. This approach can validate large number of qubits compared with the unitary one. diff --git a/cirq-core/cirq/transformers/analytical_decompositions/controlled_gate_decomposition_test.py b/cirq-core/cirq/transformers/analytical_decompositions/controlled_gate_decomposition_test.py index be6baf5a188..ef725957cd0 100644 --- a/cirq-core/cirq/transformers/analytical_decompositions/controlled_gate_decomposition_test.py +++ b/cirq-core/cirq/transformers/analytical_decompositions/controlled_gate_decomposition_test.py @@ -20,7 +20,7 @@ import cirq -def test_decompose_x(): +def test_decompose_x() -> None: """Verifies correctness of multi-controlled X decomposition.""" for total_qubits_count in range(1, 8): qubits = cirq.LineQubit.range(total_qubits_count) @@ -83,14 +83,14 @@ def _test_decompose(matrix, controls_count): cirq.testing.assert_allclose_up_to_global_phase(expected_matrix, result_matrix, atol=1e-8) -def test_decompose_specific_matrices(): +def test_decompose_specific_matrices() -> None: for gate in [cirq.X, cirq.Y, cirq.Z, cirq.H, cirq.I, cirq.T, cirq.S]: for controls_count in range(7): _test_decompose(cirq.unitary(gate), controls_count) @cirq.testing.retry_once_with_later_random_values -def test_decompose_random_unitary(): +def test_decompose_random_unitary() -> None: for controls_count in range(5): for _ in range(10): _test_decompose(_random_unitary(), controls_count) @@ -99,7 +99,7 @@ def test_decompose_random_unitary(): @cirq.testing.retry_once_with_later_random_values -def test_decompose_random_special_unitary(): +def test_decompose_random_special_unitary() -> None: for controls_count in range(5): for _ in range(10): _test_decompose(_random_special_unitary(), controls_count) @@ -113,7 +113,7 @@ def _decomposition_size(U, controls_count): return _count_operations(operations) -def test_decompose_size_special_unitary(): +def test_decompose_size_special_unitary() -> None: np.random.seed(0) u = _random_special_unitary() assert _decomposition_size(u, 0) == (1, 0, 0) @@ -126,7 +126,7 @@ def test_decompose_size_special_unitary(): assert _decomposition_size(u, i) == (64 * i - 312, 48 * i - 234, 16) -def test_decompose_size_unitary(): +def test_decompose_size_unitary() -> None: np.random.seed(0) u = _random_unitary() assert _decomposition_size(u, 0) == (1, 0, 0) diff --git a/cirq-core/cirq/transformers/analytical_decompositions/cphase_to_fsim.py b/cirq-core/cirq/transformers/analytical_decompositions/cphase_to_fsim.py index 7e5ab2db08a..ef3fea0303b 100644 --- a/cirq-core/cirq/transformers/analytical_decompositions/cphase_to_fsim.py +++ b/cirq-core/cirq/transformers/analytical_decompositions/cphase_to_fsim.py @@ -100,7 +100,7 @@ def decompose_cphase_into_two_fsim( fsim_gate: cirq.FSimGate, qubits: Sequence[cirq.Qid] | None = None, atol: float = 1e-8, -) -> cirq.OP_TREE: +) -> Sequence[cirq.Operation]: """Decomposes CZPowGate into two FSimGates. This function implements the decomposition described in section VII F I diff --git a/cirq-core/cirq/transformers/analytical_decompositions/cphase_to_fsim_test.py b/cirq-core/cirq/transformers/analytical_decompositions/cphase_to_fsim_test.py index 39780260e1f..41097cd8fb3 100644 --- a/cirq-core/cirq/transformers/analytical_decompositions/cphase_to_fsim_test.py +++ b/cirq-core/cirq/transformers/analytical_decompositions/cphase_to_fsim_test.py @@ -24,7 +24,7 @@ import cirq -def test_symbols(): +def test_symbols() -> None: with pytest.raises(ValueError, match='Symbolic arguments'): cirq.compute_cphase_exponents_for_fsim_decomposition( cirq.FSimGate(theta=sympy.Symbol('t'), phi=sympy.Symbol('phi')) @@ -36,8 +36,9 @@ def __init__(self): super().__init__(theta=np.pi / 2, phi=np.pi / 6) -def test_parameterized_gates(): +def test_parameterized_gates() -> None: t = sympy.Symbol('t') + fsim_gate: cirq.FSimGate with pytest.raises(ValueError): cphase_gate = cirq.CZPowGate(exponent=t) fsim_gate = FakeSycamoreGate() @@ -54,14 +55,14 @@ def test_parameterized_gates(): cirq.decompose_cphase_into_two_fsim(cphase_gate, fsim_gate=fsim_gate) -def test_invalid_qubits(): +def test_invalid_qubits() -> None: with pytest.raises(ValueError): cirq.decompose_cphase_into_two_fsim( cphase_gate=cirq.CZ, fsim_gate=FakeSycamoreGate(), qubits=cirq.LineQubit.range(3) ) -def test_circuit_structure(): +def test_circuit_structure() -> None: syc = FakeSycamoreGate() ops = cirq.decompose_cphase_into_two_fsim(cirq.CZ, fsim_gate=syc) num_interaction_moments = 0 @@ -73,7 +74,7 @@ def test_circuit_structure(): assert num_interaction_moments == 2 -def assert_decomposition_valid(cphase_gate, fsim_gate): +def assert_decomposition_valid(cphase_gate, fsim_gate) -> None: u_expected = cirq.unitary(cphase_gate) ops = cirq.decompose_cphase_into_two_fsim(cphase_gate, fsim_gate=fsim_gate) u_actual = cirq.unitary(cirq.Circuit(ops)) @@ -83,7 +84,7 @@ def assert_decomposition_valid(cphase_gate, fsim_gate): @pytest.mark.parametrize( 'exponent', (-5.5, -3, -1.5, -1, -0.65, -0.2, 0, 0.1, 0.75, 1, 1.5, 2, 5.5) ) -def test_decomposition_to_sycamore_gate(exponent): +def test_decomposition_to_sycamore_gate(exponent) -> None: cphase_gate = cirq.CZPowGate(exponent=exponent) assert_decomposition_valid(cphase_gate, FakeSycamoreGate()) @@ -95,7 +96,7 @@ def test_decomposition_to_sycamore_gate(exponent): (-1.4 * np.pi, -np.pi / 9, np.pi / 11, np.pi / 2, 2.4 * np.pi), ), ) -def test_valid_cphase_exponents(theta, phi): +def test_valid_cphase_exponents(theta, phi) -> None: fsim_gate = cirq.FSimGate(theta=theta, phi=phi) valid_exponent_intervals = cirq.compute_cphase_exponents_for_fsim_decomposition(fsim_gate) assert valid_exponent_intervals @@ -131,7 +132,7 @@ def complement_intervals(intervals: Sequence[tuple[float, float]]) -> Sequence[t (-1.7 * np.pi, -np.pi / 5, np.pi / 7, 2.5 * np.pi), ), ) -def test_invalid_cphase_exponents(theta, phi): +def test_invalid_cphase_exponents(theta, phi) -> None: fsim_gate = cirq.FSimGate(theta=theta, phi=phi) valid_exponent_intervals = cirq.compute_cphase_exponents_for_fsim_decomposition(fsim_gate) invalid_exponent_intervals = complement_intervals(valid_exponent_intervals) @@ -151,6 +152,6 @@ def test_invalid_cphase_exponents(theta, phi): @pytest.mark.parametrize( 'bad_fsim_gate', (cirq.FSimGate(theta=0, phi=0), cirq.FSimGate(theta=np.pi / 4, phi=np.pi / 2)) ) -def test_invalid_fsim_gate(bad_fsim_gate): +def test_invalid_fsim_gate(bad_fsim_gate) -> None: with pytest.raises(ValueError): cirq.decompose_cphase_into_two_fsim(cirq.CZ, fsim_gate=bad_fsim_gate) diff --git a/cirq-core/cirq/transformers/analytical_decompositions/quantum_shannon_decomposition.py b/cirq-core/cirq/transformers/analytical_decompositions/quantum_shannon_decomposition.py index bed6c80da4a..a5cd611b5df 100644 --- a/cirq-core/cirq/transformers/analytical_decompositions/quantum_shannon_decomposition.py +++ b/cirq-core/cirq/transformers/analytical_decompositions/quantum_shannon_decomposition.py @@ -21,7 +21,7 @@ from __future__ import annotations -from typing import Callable, cast, Iterable, TYPE_CHECKING +from typing import Callable, cast, Iterable, Sequence, TYPE_CHECKING import numpy as np from attr import define @@ -47,7 +47,7 @@ class _TwoQubitGate: def quantum_shannon_decomposition( - qubits: list[cirq.Qid], u: np.ndarray, atol: float = 1e-8 + qubits: Sequence[cirq.Qid], u: np.ndarray, atol: float = 1e-8 ) -> Iterable[cirq.Operation]: """Decomposes n-qubit unitary 1-q, 2-q and GlobalPhase gates, preserving global phase. @@ -149,7 +149,7 @@ def quantum_shannon_decomposition( yield from cast(Iterable[ops.Operation], ops.flatten_op_tree(shannon_decomp)) -def _recursive_decomposition(qubits: list[cirq.Qid], u: np.ndarray) -> Iterable[cirq.Operation]: +def _recursive_decomposition(qubits: Sequence[cirq.Qid], u: np.ndarray) -> Iterable[cirq.Operation]: """Recursive step in the quantum shannon decomposition. Decomposes n-qubit unitary into generic 2-qubit gates, CNOT, CZ and 1-qubit gates. @@ -270,7 +270,7 @@ def _single_qubit_decomposition(qubit: cirq.Qid, u: np.ndarray) -> Iterable[cirq def _msb_demuxer( - demux_qubits: list[cirq.Qid], u1: np.ndarray, u2: np.ndarray + demux_qubits: Sequence[cirq.Qid], u1: np.ndarray, u2: np.ndarray ) -> Iterable[cirq.Operation]: """Demultiplexes a unitary matrix that is multiplexed in its most-significant-qubit. @@ -336,7 +336,7 @@ def _nth_gray(n: int) -> int: def _multiplexed_cossin( - cossin_qubits: list[cirq.Qid], angles: list[float], rot_func: Callable = ops.ry + cossin_qubits: Sequence[cirq.Qid], angles: list[float], rot_func: Callable = ops.ry ) -> Iterable[cirq.Operation]: """Performs a multiplexed rotation over all qubits in this unitary matrix, diff --git a/cirq-core/cirq/transformers/analytical_decompositions/quantum_shannon_decomposition_test.py b/cirq-core/cirq/transformers/analytical_decompositions/quantum_shannon_decomposition_test.py index ae713acf013..cb92768ffa6 100644 --- a/cirq-core/cirq/transformers/analytical_decompositions/quantum_shannon_decomposition_test.py +++ b/cirq-core/cirq/transformers/analytical_decompositions/quantum_shannon_decomposition_test.py @@ -33,7 +33,7 @@ @pytest.mark.xfail(reason='#6765') @pytest.mark.parametrize('n_qubits', list(range(1, 8))) -def test_random_qsd_n_qubit(n_qubits): +def test_random_qsd_n_qubit(n_qubits) -> None: U = unitary_group.rvs(2**n_qubits) qubits = [cirq.NamedQubit(f'q{i}') for i in range(n_qubits)] circuit = cirq.Circuit(quantum_shannon_decomposition(qubits, U)) @@ -43,7 +43,7 @@ def test_random_qsd_n_qubit(n_qubits): assert all(cirq.num_qubits(op) <= 2 for op in circuit.all_operations()) -def test_qsd_n_qubit_errors(): +def test_qsd_n_qubit_errors() -> None: qubits = [cirq.NamedQubit(f'q{i}') for i in range(3)] with pytest.raises(ValueError, match="shaped numpy array"): cirq.Circuit(quantum_shannon_decomposition(qubits, np.eye(9))) @@ -51,7 +51,7 @@ def test_qsd_n_qubit_errors(): cirq.Circuit(quantum_shannon_decomposition(qubits, np.ones((8, 8)))) -def test_recursive_decomposition_n_qubit_errors(): +def test_recursive_decomposition_n_qubit_errors() -> None: qubits = [cirq.NamedQubit(f'q{i}') for i in range(3)] with pytest.raises(ValueError, match="shaped numpy array"): cirq.Circuit(_recursive_decomposition(qubits, np.eye(9))) @@ -59,7 +59,7 @@ def test_recursive_decomposition_n_qubit_errors(): cirq.Circuit(_recursive_decomposition(qubits, np.eye(2))) -def test_random_single_qubit_decomposition(): +def test_random_single_qubit_decomposition() -> None: U = unitary_group.rvs(2) qubit = cirq.NamedQubit('q0') circuit = cirq.Circuit(_single_qubit_decomposition(qubit, U)) @@ -69,7 +69,7 @@ def test_random_single_qubit_decomposition(): assert all(cirq.num_qubits(op) <= 2 for op in circuit.all_operations()) -def test_msb_demuxer(): +def test_msb_demuxer() -> None: U1 = unitary_group.rvs(4) U2 = unitary_group.rvs(4) U_full = np.kron([[1, 0], [0, 0]], U1) + np.kron([[0, 0], [0, 1]], U2) @@ -81,13 +81,12 @@ def test_msb_demuxer(): assert all(cirq.num_qubits(op) <= 2 for op in circuit.all_operations()) -def test_multiplexed_cossin(): +def test_multiplexed_cossin() -> None: angle_1 = np.random.random_sample() * 2 * np.pi angle_2 = np.random.random_sample() * 2 * np.pi c1, s1 = np.cos(angle_1), np.sin(angle_1) c2, s2 = np.cos(angle_2), np.sin(angle_2) - multiplexed_ry = [[c1, 0, -s1, 0], [0, c2, 0, -s2], [s1, 0, c1, 0], [0, s2, 0, c2]] - multiplexed_ry = np.array(multiplexed_ry) + multiplexed_ry = np.asarray([[c1, 0, -s1, 0], [0, c2, 0, -s2], [s1, 0, c1, 0], [0, s2, 0, c2]]) qubits = [cirq.NamedQubit(f'q{i}') for i in range(2)] circuit = cirq.Circuit(_multiplexed_cossin(qubits, [angle_1, angle_2])) # Add back the CZ gate removed by the A.1 optimization @@ -126,11 +125,11 @@ def test_multiplexed_cossin(): (15, 8), ], ) -def test_nth_gray(n, gray): +def test_nth_gray(n, gray) -> None: assert _nth_gray(n) == gray -def test_ghz_circuit_decomposes(): +def test_ghz_circuit_decomposes() -> None: # Test case from #6725 ghz_circuit = cirq.Circuit(cirq.H(cirq.q(0)), cirq.CNOT(cirq.q(0), cirq.q(1))) ghz_unitary = cirq.unitary(ghz_circuit) @@ -141,7 +140,7 @@ def test_ghz_circuit_decomposes(): np.testing.assert_allclose(new_unitary, ghz_unitary, atol=1e-6) -def test_qft_decomposes(): +def test_qft_decomposes() -> None: # Test case from #6666 qs = cirq.LineQubit.range(4) qft_circuit = cirq.Circuit(cirq.qft(*qs)) @@ -163,7 +162,7 @@ def test_qft_decomposes(): (cirq.S, 1), # rz & ry ], ) -def test_cliffords(gate, num_ops): +def test_cliffords(gate, num_ops) -> None: desired_unitary = cirq.unitary(gate) shannon_circuit = cirq.Circuit(quantum_shannon_decomposition((cirq.q(0),), desired_unitary)) new_unitary = cirq.unitary(shannon_circuit) @@ -173,7 +172,7 @@ def test_cliffords(gate, num_ops): @pytest.mark.parametrize('gate', [cirq.X, cirq.Y, cirq.Z, cirq.H, cirq.S]) -def test_cliffords_with_global_phase(gate): +def test_cliffords_with_global_phase(gate) -> None: global_phase = np.exp(1j * np.random.choice(np.linspace(0.1, 2 * np.pi, 10))) desired_unitary = cirq.unitary(gate) * global_phase shannon_circuit = cirq.Circuit(quantum_shannon_decomposition((cirq.q(0),), desired_unitary)) @@ -181,7 +180,7 @@ def test_cliffords_with_global_phase(gate): np.testing.assert_allclose(new_unitary, desired_unitary) -def test_global_phase(): +def test_global_phase() -> None: global_phase = np.exp(1j * np.random.choice(np.linspace(0, 2 * np.pi, 10))) shannon_circuit = cirq.Circuit( quantum_shannon_decomposition((cirq.q(0),), np.eye(2) * global_phase) @@ -191,7 +190,7 @@ def test_global_phase(): @pytest.mark.parametrize('gate', [cirq.CZ, cirq.CNOT, cirq.XX, cirq.YY, cirq.ZZ]) -def test_two_qubit_gate(gate): +def test_two_qubit_gate(gate) -> None: global_phase = np.exp(1j * np.random.choice(np.linspace(0, 2 * np.pi, 10))) desired_unitary = cirq.unitary(gate) * global_phase shannon_circuit = cirq.Circuit( @@ -202,7 +201,7 @@ def test_two_qubit_gate(gate): @pytest.mark.parametrize('gate', [cirq.CCNOT, cirq.qft(*cirq.LineQubit.range(3))]) -def test_three_qubit_gate(gate): +def test_three_qubit_gate(gate) -> None: global_phase = np.exp(1j * np.random.choice(np.linspace(0, 2 * np.pi, 10))) desired_unitary = cirq.unitary(gate) * global_phase shannon_circuit = cirq.Circuit( @@ -213,7 +212,7 @@ def test_three_qubit_gate(gate): @pytest.mark.xfail(reason='#6765') -def test_qft5(): +def test_qft5() -> None: global_phase = np.exp(1j * np.random.choice(np.linspace(0, 2 * np.pi, 10))) desired_unitary = cirq.unitary(cirq.qft(*cirq.LineQubit.range(5))) * global_phase shannon_circuit = cirq.Circuit( @@ -223,7 +222,7 @@ def test_qft5(): np.testing.assert_allclose(new_unitary, desired_unitary, atol=1e-6) -def test_random_circuit_decomposition(): +def test_random_circuit_decomposition() -> None: qubits = cirq.LineQubit.range(3) test_circuit = ( random_two_qubit_circuit_with_czs(3, qubits[0], qubits[1]) diff --git a/cirq-core/cirq/transformers/analytical_decompositions/single_qubit_decompositions_test.py b/cirq-core/cirq/transformers/analytical_decompositions/single_qubit_decompositions_test.py index 40292e504f3..3d717bc3b85 100644 --- a/cirq-core/cirq/transformers/analytical_decompositions/single_qubit_decompositions_test.py +++ b/cirq-core/cirq/transformers/analytical_decompositions/single_qubit_decompositions_test.py @@ -25,13 +25,13 @@ def assert_gates_implement_unitary( - gates: Sequence[cirq.testing.SingleQubitGate], intended_effect: np.ndarray, atol: float -): + gates: Sequence[cirq.Gate], intended_effect: np.ndarray, atol: float +) -> None: actual_effect = cirq.dot(*[cirq.unitary(g) for g in reversed(gates)]) cirq.testing.assert_allclose_up_to_global_phase(actual_effect, intended_effect, atol=atol) -def test_is_negligible_turn(): +def test_is_negligible_turn() -> None: assert cirq.is_negligible_turn(0, 1e-5) assert cirq.is_negligible_turn(1e-6, 1e-5) assert cirq.is_negligible_turn(1, 1e-5) @@ -57,37 +57,37 @@ def test_is_negligible_turn(): assert not cirq.is_negligible_turn(sympy.Symbol('a') * 0 + 1.5 - 1e-6, 1e-5) -def test_single_qubit_matrix_to_gates_known_x(): +def test_single_qubit_matrix_to_gates_known_x() -> None: actual = cirq.single_qubit_matrix_to_gates(np.array([[0, 1], [1, 0]]), tolerance=0.01) assert cirq.approx_eq(actual, [cirq.X], atol=1e-9) -def test_single_qubit_matrix_to_gates_known_y(): +def test_single_qubit_matrix_to_gates_known_y() -> None: actual = cirq.single_qubit_matrix_to_gates(np.array([[0, -1j], [1j, 0]]), tolerance=0.01) assert cirq.approx_eq(actual, [cirq.Y], atol=1e-9) -def test_single_qubit_matrix_to_gates_known_z(): +def test_single_qubit_matrix_to_gates_known_z() -> None: actual = cirq.single_qubit_matrix_to_gates(np.array([[1, 0], [0, -1]]), tolerance=0.01) assert cirq.approx_eq(actual, [cirq.Z], atol=1e-9) -def test_single_qubit_matrix_to_gates_known_s(): +def test_single_qubit_matrix_to_gates_known_s() -> None: actual = cirq.single_qubit_matrix_to_gates(np.array([[1, 0], [0, 1j]]), tolerance=0.01) assert cirq.approx_eq(actual, [cirq.Z**0.5], atol=1e-9) -def test_known_s_dag(): +def test_known_s_dag() -> None: actual = cirq.single_qubit_matrix_to_gates(np.array([[1, 0], [0, -1j]]), tolerance=0.01) assert cirq.approx_eq(actual, [cirq.Z**-0.5], atol=1e-9) -def test_known_h(): +def test_known_h() -> None: actual = cirq.single_qubit_matrix_to_gates( np.array([[1, 1], [1, -1]]) * np.sqrt(0.5), tolerance=0.001 ) @@ -109,7 +109,7 @@ def test_known_h(): ] + [cirq.testing.random_unitary(2) for _ in range(10)], ) -def test_single_qubit_matrix_to_gates_cases(intended_effect): +def test_single_qubit_matrix_to_gates_cases(intended_effect) -> None: for atol in [1e-1, 1e-8]: gates = cirq.single_qubit_matrix_to_gates(intended_effect, tolerance=atol / 10) assert len(gates) <= 3 @@ -120,7 +120,7 @@ def test_single_qubit_matrix_to_gates_cases(intended_effect): @pytest.mark.parametrize( 'pre_turns,post_turns', [(random.random(), random.random()) for _ in range(10)] ) -def test_single_qubit_matrix_to_gates_fuzz_half_turns_merge_z_gates(pre_turns, post_turns): +def test_single_qubit_matrix_to_gates_fuzz_half_turns_merge_z_gates(pre_turns, post_turns) -> None: intended_effect = cirq.dot( cirq.unitary(cirq.Z ** (2 * pre_turns)), cirq.unitary(cirq.X), @@ -133,7 +133,7 @@ def test_single_qubit_matrix_to_gates_fuzz_half_turns_merge_z_gates(pre_turns, p assert_gates_implement_unitary(gates, intended_effect, atol=1e-6) -def test_single_qubit_matrix_to_gates_tolerance_z(): +def test_single_qubit_matrix_to_gates_tolerance_z() -> None: z = np.diag([1, np.exp(1j * 0.01)]) optimized_away = cirq.single_qubit_matrix_to_gates(z, tolerance=0.1) @@ -143,7 +143,7 @@ def test_single_qubit_matrix_to_gates_tolerance_z(): assert len(kept) == 1 -def test_single_qubit_matrix_to_gates_tolerance_xy(): +def test_single_qubit_matrix_to_gates_tolerance_xy() -> None: c, s = np.cos(0.01), np.sin(0.01) xy = np.array([[c, -s], [s, c]]) @@ -154,7 +154,7 @@ def test_single_qubit_matrix_to_gates_tolerance_xy(): assert len(kept) == 1 -def test_single_qubit_matrix_to_gates_tolerance_half_turn_phasing(): +def test_single_qubit_matrix_to_gates_tolerance_half_turn_phasing() -> None: a = np.pi / 2 + 0.01 c, s = np.cos(a), np.sin(a) nearly_x = np.array([[c, -s], [s, c]]) @@ -189,13 +189,13 @@ def _random_unitary_with_close_eigenvalues(): ] + [cirq.testing.random_unitary(2) for _ in range(10)], ) -def test_single_qubit_op_to_framed_phase_form_equivalent_on_known_and_random(mat): +def test_single_qubit_op_to_framed_phase_form_equivalent_on_known_and_random(mat) -> None: u, t, g = cirq.single_qubit_op_to_framed_phase_form(mat) z = np.diag([g, g * t]) assert np.allclose(mat, np.conj(u.T).dot(z).dot(u)) -def test_single_qubit_matrix_to_phased_x_z_known(): +def test_single_qubit_matrix_to_phased_x_z_known() -> None: actual = cirq.single_qubit_matrix_to_phased_x_z(np.array([[0, 1], [1, 0]]), atol=0.01) assert cirq.approx_eq(actual, [cirq.PhasedXPowGate(phase_exponent=1.0)], atol=1e-9) @@ -223,7 +223,7 @@ def test_single_qubit_matrix_to_phased_x_z_known(): 'intended_effect', [np.array([[0, 1j], [1, 0]])] + [cirq.testing.random_unitary(2) for _ in range(10)], ) -def test_single_qubit_matrix_to_phased_x_z_cases(intended_effect): +def test_single_qubit_matrix_to_phased_x_z_cases(intended_effect) -> None: gates = cirq.single_qubit_matrix_to_phased_x_z(intended_effect, atol=1e-6) assert len(gates) <= 2 assert_gates_implement_unitary(gates, intended_effect, atol=1e-5) @@ -232,7 +232,9 @@ def test_single_qubit_matrix_to_phased_x_z_cases(intended_effect): @pytest.mark.parametrize( 'pre_turns,post_turns', [(random.random(), random.random()) for _ in range(10)] ) -def test_single_qubit_matrix_to_phased_x_z_fuzz_half_turns_always_one_gate(pre_turns, post_turns): +def test_single_qubit_matrix_to_phased_x_z_fuzz_half_turns_always_one_gate( + pre_turns, post_turns +) -> None: atol = 1e-6 aggr_atol = atol * 10.0 @@ -248,7 +250,7 @@ def test_single_qubit_matrix_to_phased_x_z_fuzz_half_turns_always_one_gate(pre_t assert_gates_implement_unitary(gates, intended_effect, atol=aggr_atol) -def test_single_qubit_matrix_to_phased_x_z_tolerance_z(): +def test_single_qubit_matrix_to_phased_x_z_tolerance_z() -> None: z = np.diag([1, np.exp(1j * 0.01)]) optimized_away = cirq.single_qubit_matrix_to_phased_x_z(z, atol=0.1) @@ -258,7 +260,7 @@ def test_single_qubit_matrix_to_phased_x_z_tolerance_z(): assert len(kept) == 1 -def test_single_qubit_matrix_to_phased_x_z_tolerance_xy(): +def test_single_qubit_matrix_to_phased_x_z_tolerance_xy() -> None: c, s = np.cos(0.01), np.sin(0.01) xy = np.array([[c, -s], [s, c]]) @@ -269,7 +271,7 @@ def test_single_qubit_matrix_to_phased_x_z_tolerance_xy(): assert len(kept) == 1 -def test_single_qubit_matrix_to_phased_x_z_tolerance_half_turn_phasing(): +def test_single_qubit_matrix_to_phased_x_z_tolerance_half_turn_phasing() -> None: a = np.pi / 2 + 0.01 c, s = np.cos(a), np.sin(a) nearly_x = np.array([[c, -s], [s, c]]) @@ -297,15 +299,16 @@ def test_single_qubit_matrix_to_phased_x_z_tolerance_half_turn_phasing(): *[cirq.testing.random_unitary(2) for _ in range(10)], ], ) -def test_single_qubit_matrix_to_phxz_cases(intended_effect): +def test_single_qubit_matrix_to_phxz_cases(intended_effect) -> None: gate = cirq.single_qubit_matrix_to_phxz(intended_effect, atol=1e-6) + assert gate is not None assert_gates_implement_unitary([gate], intended_effect, atol=1e-5) @pytest.mark.parametrize( 'pre_turns,post_turns', [(random.random(), random.random()) for _ in range(10)] ) -def test_single_qubit_matrix_to_phxz_fuzz_half_turns_always_one_gate(pre_turns, post_turns): +def test_single_qubit_matrix_to_phxz_fuzz_half_turns_always_one_gate(pre_turns, post_turns) -> None: atol = 1e-6 aggr_atol = atol * 10.0 @@ -317,11 +320,12 @@ def test_single_qubit_matrix_to_phxz_fuzz_half_turns_always_one_gate(pre_turns, gate = cirq.single_qubit_matrix_to_phxz(intended_effect, atol=atol) + assert gate is not None assert gate.z_exponent == 0 assert_gates_implement_unitary([gate], intended_effect, atol=aggr_atol) -def test_single_qubit_matrix_to_phxz_tolerance_z(): +def test_single_qubit_matrix_to_phxz_tolerance_z() -> None: z = np.diag([1, np.exp(1j * 0.01)]) optimized_away = cirq.single_qubit_matrix_to_phxz(z, atol=0.1) @@ -331,7 +335,7 @@ def test_single_qubit_matrix_to_phxz_tolerance_z(): assert kept is not None -def test_single_qubit_matrix_to_phxz_tolerance_xy(): +def test_single_qubit_matrix_to_phxz_tolerance_xy() -> None: c, s = np.cos(0.01), np.sin(0.01) xy = np.array([[c, -s], [s, c]]) @@ -342,7 +346,7 @@ def test_single_qubit_matrix_to_phxz_tolerance_xy(): assert kept is not None -def test_single_qubit_matrix_to_phxz_tolerance_half_turn_phasing(): +def test_single_qubit_matrix_to_phxz_tolerance_half_turn_phasing() -> None: a = np.pi / 2 + 0.01 c, s = np.cos(a), np.sin(a) nearly_x = np.array([[c, -s], [s, c]]) @@ -351,7 +355,9 @@ def test_single_qubit_matrix_to_phxz_tolerance_half_turn_phasing(): phased_nearly_x = z1.dot(nearly_x).dot(z2) optimized_away = cirq.single_qubit_matrix_to_phxz(phased_nearly_x, atol=0.1) + assert optimized_away is not None assert optimized_away.z_exponent == 0 kept = cirq.single_qubit_matrix_to_phxz(phased_nearly_x, atol=0.0001) + assert kept is not None assert kept.z_exponent != 0 diff --git a/cirq-core/cirq/transformers/analytical_decompositions/single_to_two_qubit_isometry_test.py b/cirq-core/cirq/transformers/analytical_decompositions/single_to_two_qubit_isometry_test.py index 09acdb5e346..b1ca2f81abc 100644 --- a/cirq-core/cirq/transformers/analytical_decompositions/single_to_two_qubit_isometry_test.py +++ b/cirq-core/cirq/transformers/analytical_decompositions/single_to_two_qubit_isometry_test.py @@ -43,7 +43,7 @@ @pytest.mark.parametrize('allow_partial_czs', [True, False]) def test_two_qubit_matrix_to_cz_isometry( initial_state, is_valid, unitary_matrix, allow_partial_czs -): +) -> None: a, b, c = cirq.LineQubit.range(3) decomposed_ops = cirq.two_qubit_matrix_to_cz_isometry( a, b, unitary_matrix, allow_partial_czs=allow_partial_czs diff --git a/cirq-core/cirq/transformers/analytical_decompositions/two_qubit_state_preparation_test.py b/cirq-core/cirq/transformers/analytical_decompositions/two_qubit_state_preparation_test.py index 1adc368c66e..40d344ef7b5 100644 --- a/cirq-core/cirq/transformers/analytical_decompositions/two_qubit_state_preparation_test.py +++ b/cirq-core/cirq/transformers/analytical_decompositions/two_qubit_state_preparation_test.py @@ -17,6 +17,7 @@ from __future__ import annotations import copy +from typing import Iterator import numpy as np import pytest @@ -24,11 +25,11 @@ import cirq -def random_state(seed: float): +def random_state(seed: float) -> np.ndarray: return cirq.testing.random_superposition(4, random_state=seed) -def states_with_phases(st: np.ndarray): +def states_with_phases(st: np.ndarray) -> Iterator[np.ndarray]: """Returns several states similar to st with modified global phases.""" st = np.array(st, dtype="complex64") yield st @@ -61,10 +62,10 @@ def states_with_phases(st: np.ndarray): @pytest.mark.parametrize("state", STATES_TO_PREPARE) -def test_prepare_two_qubit_state_using_cz(state): +def test_prepare_two_qubit_state_using_cz(state) -> None: state = cirq.to_valid_state_vector(state, num_qubits=2) - q = cirq.LineQubit.range(2) - circuit = cirq.Circuit(cirq.prepare_two_qubit_state_using_cz(*q, state)) + q0, q1 = cirq.LineQubit.range(2) + circuit = cirq.Circuit(cirq.prepare_two_qubit_state_using_cz(q0, q1, state)) ops_cz = [*circuit.findall_operations(lambda op: op.gate == cirq.CZ)] ops_2q = [*circuit.findall_operations(lambda op: cirq.num_qubits(op) > 1)] assert ops_cz == ops_2q @@ -76,11 +77,11 @@ def test_prepare_two_qubit_state_using_cz(state): @pytest.mark.parametrize("state", STATES_TO_PREPARE) @pytest.mark.parametrize("use_iswap_inv", [True, False]) -def test_prepare_two_qubit_state_using_iswap(state, use_iswap_inv): +def test_prepare_two_qubit_state_using_iswap(state, use_iswap_inv) -> None: state = cirq.to_valid_state_vector(state, num_qubits=2) - q = cirq.LineQubit.range(2) + q0, q1 = cirq.LineQubit.range(2) circuit = cirq.Circuit( - cirq.prepare_two_qubit_state_using_iswap(*q, state, use_iswap_inv=use_iswap_inv) + cirq.prepare_two_qubit_state_using_iswap(q0, q1, state, use_iswap_inv=use_iswap_inv) ) iswap_gate = cirq.ISWAP_INV if use_iswap_inv else cirq.ISWAP ops_iswap = [*circuit.findall_operations(lambda op: op.gate == iswap_gate)] @@ -94,12 +95,12 @@ def test_prepare_two_qubit_state_using_iswap(state, use_iswap_inv): @pytest.mark.parametrize("state", STATES_TO_PREPARE) @pytest.mark.parametrize("use_sqrt_iswap_inv", [True, False]) -def test_prepare_two_qubit_state_using_sqrt_iswap(state, use_sqrt_iswap_inv): +def test_prepare_two_qubit_state_using_sqrt_iswap(state, use_sqrt_iswap_inv) -> None: state = cirq.to_valid_state_vector(state, num_qubits=2) - q = cirq.LineQubit.range(2) + q0, q1 = cirq.LineQubit.range(2) circuit = cirq.Circuit( cirq.prepare_two_qubit_state_using_sqrt_iswap( - *q, state, use_sqrt_iswap_inv=use_sqrt_iswap_inv + q0, q1, state, use_sqrt_iswap_inv=use_sqrt_iswap_inv ) ) sqrt_iswap_gate = cirq.SQRT_ISWAP_INV if use_sqrt_iswap_inv else cirq.SQRT_ISWAP diff --git a/cirq-core/cirq/transformers/analytical_decompositions/two_qubit_to_cz.py b/cirq-core/cirq/transformers/analytical_decompositions/two_qubit_to_cz.py index a4df4751def..d61b8ed44b1 100644 --- a/cirq-core/cirq/transformers/analytical_decompositions/two_qubit_to_cz.py +++ b/cirq-core/cirq/transformers/analytical_decompositions/two_qubit_to_cz.py @@ -181,7 +181,9 @@ def _xx_yy_zz_interaction_via_full_czs(q0: cirq.Qid, q1: cirq.Qid, x: float, y: yield ops.H(q1) -def cleanup_operations(operations: Sequence[ops.Operation], atol: float = 1e-8): +def cleanup_operations( + operations: Sequence[ops.Operation], atol: float = 1e-8 +) -> list[ops.Operation]: operations = _merge_single_qubit_gates(operations, atol=atol) circuit = circuits.Circuit(operations) circuit = eject_phased_paulis(circuit) diff --git a/cirq-core/cirq/transformers/analytical_decompositions/two_qubit_to_cz_test.py b/cirq-core/cirq/transformers/analytical_decompositions/two_qubit_to_cz_test.py index 1b159bf7c49..a9b97d6367b 100644 --- a/cirq-core/cirq/transformers/analytical_decompositions/two_qubit_to_cz_test.py +++ b/cirq-core/cirq/transformers/analytical_decompositions/two_qubit_to_cz_test.py @@ -95,7 +95,7 @@ def _random_double_full_cz_effect(): ) -def assert_cz_depth_below(operations, threshold, must_be_full): +def assert_cz_depth_below(operations, threshold, must_be_full) -> None: total_cz = 0 for op in operations: @@ -110,7 +110,7 @@ def assert_cz_depth_below(operations, threshold, must_be_full): assert total_cz <= threshold -def assert_ops_implement_unitary(q0, q1, operations, intended_effect, atol=0.01): +def assert_ops_implement_unitary(q0, q1, operations, intended_effect, atol=0.01) -> None: actual_effect = _operations_to_matrix(operations, (q0, q1)) assert cirq.allclose_up_to_global_phase(actual_effect, intended_effect, atol=atol) @@ -273,7 +273,7 @@ def test_decompose_to_diagonal_and_circuit(v) -> None: ) def test_decompose_to_diagonal_and_circuit_returns_circuit_with_expected_number_of_czs( mat, num_czs -): +) -> None: b, c = cirq.LineQubit.range(2) _, ops = two_qubit_matrix_to_diagonal_and_cz_operations(b, c, mat, atol=1e-8) circuit = cirq.Circuit(ops) diff --git a/cirq-core/cirq/transformers/analytical_decompositions/two_qubit_to_ms_test.py b/cirq-core/cirq/transformers/analytical_decompositions/two_qubit_to_ms_test.py index 60294f1af0e..f443a290b5b 100644 --- a/cirq-core/cirq/transformers/analytical_decompositions/two_qubit_to_ms_test.py +++ b/cirq-core/cirq/transformers/analytical_decompositions/two_qubit_to_ms_test.py @@ -60,12 +60,12 @@ def _random_double_MS_effect(): ) -def assert_ops_implement_unitary(q0, q1, operations, intended_effect, atol=0.01): +def assert_ops_implement_unitary(q0, q1, operations, intended_effect, atol=0.01) -> None: actual_effect = _operations_to_matrix(operations, (q0, q1)) assert cirq.allclose_up_to_global_phase(actual_effect, intended_effect, atol=atol) -def assert_ms_depth_below(operations, threshold): +def assert_ms_depth_below(operations, threshold) -> None: total_ms = 0 for op in operations: diff --git a/cirq-core/cirq/transformers/analytical_decompositions/two_qubit_to_sqrt_iswap_test.py b/cirq-core/cirq/transformers/analytical_decompositions/two_qubit_to_sqrt_iswap_test.py index c82dec6e285..67b143ed544 100644 --- a/cirq-core/cirq/transformers/analytical_decompositions/two_qubit_to_sqrt_iswap_test.py +++ b/cirq-core/cirq/transformers/analytical_decompositions/two_qubit_to_sqrt_iswap_test.py @@ -15,6 +15,7 @@ from __future__ import annotations import itertools +from typing import Iterator import numpy as np import pytest @@ -23,11 +24,11 @@ import cirq -def random_unitary(seed): +def random_unitary(seed: cirq.RANDOM_STATE_OR_SEED_LIKE) -> np.ndarray: return cirq.testing.random_unitary(4, random_state=seed) -def random_locals(x, y, z, seed=None): +def random_locals(x: float, y: float, z: float, seed=None) -> np.ndarray: rng = np.random.RandomState(seed) a0 = cirq.testing.random_unitary(2, random_state=rng) a1 = cirq.testing.random_unitary(2, random_state=rng) @@ -42,15 +43,14 @@ def random_locals(x, y, z, seed=None): ) -def perturbations_unitary(u, amount=1e-10): +def perturbations_unitary(u: np.ndarray, amount=1e-10) -> Iterator[np.ndarray]: """Returns several unitaries in the neighborhood of u to test for numerical corner cases near critical values.""" kak = cirq.kak_decomposition(u) yield u for i in range(3): for neg in (-1, 1): - perturb_xyz = list(kak.interaction_coefficients) - perturb_xyz[i] += neg * amount + perturb_xyz = tuple(c + neg * amount for c in kak.interaction_coefficients) yield cirq.unitary( cirq.KakDecomposition( global_phase=kak.global_phase, @@ -61,11 +61,11 @@ def perturbations_unitary(u, amount=1e-10): ) -def perturbations_gate(gate, amount=1e-10): +def perturbations_gate(gate: cirq.SupportsUnitary, amount=1e-10) -> Iterator[np.ndarray]: return perturbations_unitary(cirq.unitary(gate), amount) -def perturbations_weyl(x, y, z, amount=1e-10): +def perturbations_weyl(x: float, y: float, z: float, amount: float = 1e-10) -> Iterator[np.ndarray]: return perturbations_gate(cirq.KakDecomposition(interaction_coefficients=(x, y, z)), amount) @@ -211,7 +211,7 @@ def assert_valid_decomp( atol=1e-6, rtol=0, qubit_order=cirq.LineQubit.range(2), -): +) -> None: # Check expected gates for op in operations: if len(op.qubits) == 0 and isinstance(op.gate, cirq.GlobalPhaseGate): @@ -242,7 +242,7 @@ def assert_valid_decomp( ) -def assert_specific_sqrt_iswap_count(operations, count): +def assert_specific_sqrt_iswap_count(operations, count) -> None: actual = sum(len(op.qubits) == 2 for op in operations) assert actual == count, f'Incorrect sqrt-iSWAP count. Expected {count} but got {actual}.' @@ -255,7 +255,7 @@ def assert_specific_sqrt_iswap_count(operations, count): cirq.CZPowGate(exponent=sympy.Symbol('t')), ], ) -def test_two_qubit_gates_with_symbols(gate: cirq.Gate): +def test_two_qubit_gates_with_symbols(gate: cirq.Gate) -> None: op = gate(*cirq.LineQubit.range(2)) c_new_sqrt_iswap = cirq.Circuit( cirq.parameterized_2q_op_to_sqrt_iswap_operations(op) # type: ignore @@ -279,12 +279,14 @@ def test_two_qubit_gates_with_symbols(gate: cirq.Gate): ) -def test_fsim_gate_with_symbols(): +def test_fsim_gate_with_symbols() -> None: theta, phi = sympy.symbols(['theta', 'phi']) op = cirq.FSimGate(theta=theta, phi=phi).on(*cirq.LineQubit.range(2)) - c_new_sqrt_iswap = cirq.Circuit(cirq.parameterized_2q_op_to_sqrt_iswap_operations(op)) + c_new_sqrt_iswap = cirq.Circuit( + cirq.parameterized_2q_op_to_sqrt_iswap_operations(op) # type: ignore[arg-type] + ) c_new_sqrt_iswap_inv = cirq.Circuit( - cirq.parameterized_2q_op_to_sqrt_iswap_operations(op, use_sqrt_iswap_inv=True) + cirq.parameterized_2q_op_to_sqrt_iswap_operations(op, use_sqrt_iswap_inv=True) # type: ignore[arg-type] ) for theta_val in np.linspace(0, 2 * np.pi, 4): for phi_val in np.linspace(0, 2 * np.pi, 6): @@ -307,7 +309,7 @@ def test_fsim_gate_with_symbols(): @pytest.mark.parametrize('cnt', [-1, 4, 10]) -def test_invalid_required_sqrt_iswap_count(cnt): +def test_invalid_required_sqrt_iswap_count(cnt) -> None: u = TWO_SQRT_ISWAP_UNITARIES[0] q0, q1 = cirq.LineQubit.range(2) with pytest.raises(ValueError, match='required_sqrt_iswap_count'): @@ -315,7 +317,7 @@ def test_invalid_required_sqrt_iswap_count(cnt): @pytest.mark.parametrize('u', ZERO_UNITARIES) -def test_decomp0(u): +def test_decomp0(u) -> None: # Decompose unitaries into zero sqrt-iSWAP gates q0, q1 = cirq.LineQubit.range(2) ops = cirq.two_qubit_matrix_to_sqrt_iswap_operations(q0, q1, u, required_sqrt_iswap_count=0) @@ -326,7 +328,7 @@ def test_decomp0(u): @pytest.mark.parametrize( 'u', ONE_SQRT_ISWAP_UNITARIES + TWO_SQRT_ISWAP_UNITARIES + THREE_SQRT_ISWAP_UNITARIES ) -def test_decomp0_invalid(u): +def test_decomp0_invalid(u) -> None: # Attempt to decompose other unitaries into zero SQRT_ISWAP gates q0, q1 = cirq.LineQubit.range(2) with pytest.raises(ValueError, match='cannot be decomposed into exactly 0 sqrt-iSWAP gates'): @@ -334,7 +336,7 @@ def test_decomp0_invalid(u): @pytest.mark.parametrize('u', ONE_SQRT_ISWAP_UNITARIES) -def test_decomp1(u): +def test_decomp1(u) -> None: q0, q1 = cirq.LineQubit.range(2) ops = cirq.two_qubit_matrix_to_sqrt_iswap_operations(q0, q1, u, required_sqrt_iswap_count=1) assert_valid_decomp(u, ops) @@ -344,14 +346,14 @@ def test_decomp1(u): @pytest.mark.parametrize( 'u', ZERO_UNITARIES + TWO_SQRT_ISWAP_UNITARIES + THREE_SQRT_ISWAP_UNITARIES ) -def test_decomp1_invalid(u): +def test_decomp1_invalid(u) -> None: q0, q1 = cirq.LineQubit.range(2) with pytest.raises(ValueError, match='cannot be decomposed into exactly 1 sqrt-iSWAP gates'): cirq.two_qubit_matrix_to_sqrt_iswap_operations(q0, q1, u, required_sqrt_iswap_count=1) @pytest.mark.parametrize('u', ZERO_UNITARIES + ONE_SQRT_ISWAP_UNITARIES + TWO_SQRT_ISWAP_UNITARIES) -def test_decomp2(u): +def test_decomp2(u) -> None: q0, q1 = cirq.LineQubit.range(2) ops = cirq.two_qubit_matrix_to_sqrt_iswap_operations(q0, q1, u, required_sqrt_iswap_count=2) assert_valid_decomp(u, ops) @@ -359,7 +361,7 @@ def test_decomp2(u): @pytest.mark.parametrize('u', THREE_SQRT_ISWAP_UNITARIES) -def test_decomp2_invalid(u): +def test_decomp2_invalid(u) -> None: q0, q1 = cirq.LineQubit.range(2) with pytest.raises(ValueError, match='cannot be decomposed into exactly 2 sqrt-iSWAP gates'): cirq.two_qubit_matrix_to_sqrt_iswap_operations(q0, q1, u, required_sqrt_iswap_count=2) @@ -372,14 +374,14 @@ def test_decomp2_invalid(u): + TWO_SQRT_ISWAP_UNITARIES + THREE_SQRT_ISWAP_UNITARIES, ) -def test_decomp3(u): +def test_decomp3(u) -> None: q0, q1 = cirq.LineQubit.range(2) ops = cirq.two_qubit_matrix_to_sqrt_iswap_operations(q0, q1, u, required_sqrt_iswap_count=3) assert_valid_decomp(u, ops) assert_specific_sqrt_iswap_count(ops, 3) -def test_decomp3_invalid(): +def test_decomp3_invalid() -> None: # All two-qubit gates can be synthesized with three SQRT_ISWAP gates u = cirq.unitary(cirq.X**0.2) # Pass an invalid size unitary q0, q1 = cirq.LineQubit.range(2) @@ -388,7 +390,7 @@ def test_decomp3_invalid(): @pytest.mark.parametrize('u', TWO_SQRT_ISWAP_UNITARIES[:1]) -def test_qubit_order(u): +def test_qubit_order(u) -> None: q0, q1 = cirq.LineQubit.range(2) ops = cirq.two_qubit_matrix_to_sqrt_iswap_operations(q1, q0, u, required_sqrt_iswap_count=2) assert_valid_decomp(u, ops, qubit_order=(q1, q0)) @@ -396,7 +398,7 @@ def test_qubit_order(u): @pytest.mark.parametrize('u', ZERO_UNITARIES) -def test_decomp_optimal0(u): +def test_decomp_optimal0(u) -> None: q0, q1 = cirq.LineQubit.range(2) ops = cirq.two_qubit_matrix_to_sqrt_iswap_operations(q0, q1, u) assert_valid_decomp(u, ops) @@ -404,7 +406,7 @@ def test_decomp_optimal0(u): @pytest.mark.parametrize('u', ONE_SQRT_ISWAP_UNITARIES) -def test_decomp_optimal1(u): +def test_decomp_optimal1(u) -> None: q0, q1 = cirq.LineQubit.range(2) ops = cirq.two_qubit_matrix_to_sqrt_iswap_operations(q0, q1, u) assert_valid_decomp(u, ops) @@ -412,7 +414,7 @@ def test_decomp_optimal1(u): @pytest.mark.parametrize('u', TWO_SQRT_ISWAP_UNITARIES) -def test_decomp_optimal2(u): +def test_decomp_optimal2(u) -> None: q0, q1 = cirq.LineQubit.range(2) ops = cirq.two_qubit_matrix_to_sqrt_iswap_operations(q0, q1, u) assert_valid_decomp(u, ops) @@ -420,7 +422,7 @@ def test_decomp_optimal2(u): @pytest.mark.parametrize('u', THREE_SQRT_ISWAP_UNITARIES) -def test_decomp_optimal3(u): +def test_decomp_optimal3(u) -> None: q0, q1 = cirq.LineQubit.range(2) ops = cirq.two_qubit_matrix_to_sqrt_iswap_operations(q0, q1, u) assert_valid_decomp(u, ops) @@ -428,7 +430,7 @@ def test_decomp_optimal3(u): @pytest.mark.parametrize('u', ALL_REGION_UNITARIES) -def test_all_weyl_regions(u): +def test_all_weyl_regions(u) -> None: q0, q1 = cirq.LineQubit.range(2) ops = cirq.two_qubit_matrix_to_sqrt_iswap_operations(q0, q1, u, clean_operations=True) assert_valid_decomp(u, ops, single_qubit_gate_types=(cirq.PhasedXZGate,)) @@ -445,13 +447,13 @@ def test_all_weyl_regions(u): THREE_SQRT_ISWAP_UNITARIES[0], ], ) -def test_decomp_sqrt_iswap_inv(u): +def test_decomp_sqrt_iswap_inv(u) -> None: q0, q1 = cirq.LineQubit.range(2) ops = cirq.two_qubit_matrix_to_sqrt_iswap_operations(q0, q1, u, use_sqrt_iswap_inv=True) assert_valid_decomp(u, ops, two_qubit_gate=cirq.SQRT_ISWAP_INV) -def test_valid_check_raises(): +def test_valid_check_raises() -> None: q0 = cirq.LineQubit(0) with pytest.raises(AssertionError, match='Unitaries are completely different'): assert_valid_decomp(np.eye(4), [cirq.X(q0)], single_qubit_gate_types=(cirq.XPowGate,)) diff --git a/cirq-core/cirq/transformers/drop_negligible_operations_test.py b/cirq-core/cirq/transformers/drop_negligible_operations_test.py index ff137384d04..fcbbba6717b 100644 --- a/cirq-core/cirq/transformers/drop_negligible_operations_test.py +++ b/cirq-core/cirq/transformers/drop_negligible_operations_test.py @@ -19,13 +19,13 @@ NO_COMPILE_TAG = "no_compile_tag" -def test_leaves_big(): +def test_leaves_big() -> None: a = cirq.NamedQubit('a') circuit = cirq.Circuit(cirq.Moment(cirq.Z(a) ** 0.1)) cirq.testing.assert_same_circuits(cirq.drop_negligible_operations(circuit, atol=0.001), circuit) -def test_clears_small(): +def test_clears_small() -> None: a = cirq.NamedQubit('a') circuit = cirq.Circuit(cirq.Moment(cirq.Z(a) ** 0.000001)) cirq.testing.assert_same_circuits( @@ -33,7 +33,7 @@ def test_clears_small(): ) -def test_does_not_clear_small_no_compile(): +def test_does_not_clear_small_no_compile() -> None: a = cirq.NamedQubit('a') circuit = cirq.Circuit(cirq.Moment((cirq.Z(a) ** 0.000001).with_tags(NO_COMPILE_TAG))) cirq.testing.assert_same_circuits( @@ -44,7 +44,7 @@ def test_does_not_clear_small_no_compile(): ) -def test_clears_known_empties_even_at_zero_tolerance(): +def test_clears_known_empties_even_at_zero_tolerance() -> None: a, b = cirq.LineQubit.range(2) circuit = cirq.Circuit( cirq.Z(a) ** 0, cirq.Y(a) ** 0.0000001, cirq.X(a) ** -0.0000001, cirq.CZ(a, b) ** 0 @@ -63,7 +63,7 @@ def test_clears_known_empties_even_at_zero_tolerance(): ) -def test_recursively_runs_inside_circuit_ops_deep(): +def test_recursively_runs_inside_circuit_ops_deep() -> None: a = cirq.NamedQubit('a') small_op = cirq.Z(a) ** 0.000001 nested_circuit = cirq.FrozenCircuit( @@ -92,13 +92,13 @@ def test_recursively_runs_inside_circuit_ops_deep(): ), cirq.Moment(), ) - context = cirq.TransformerContext(tags_to_ignore=[NO_COMPILE_TAG], deep=True) + context = cirq.TransformerContext(tags_to_ignore=(NO_COMPILE_TAG,), deep=True) cirq.testing.assert_same_circuits( cirq.drop_negligible_operations(c_orig, context=context, atol=0.001), c_expected ) -def test_ignores_large_ops(): +def test_ignores_large_ops() -> None: qnum = 20 qubits = cirq.LineQubit.range(qnum) subcircuit = cirq.FrozenCircuit(cirq.X.on_each(*qubits)) diff --git a/cirq-core/cirq/transformers/dynamical_decoupling_test.py b/cirq-core/cirq/transformers/dynamical_decoupling_test.py index 410d4beaaa8..eb60cd38edb 100644 --- a/cirq-core/cirq/transformers/dynamical_decoupling_test.py +++ b/cirq-core/cirq/transformers/dynamical_decoupling_test.py @@ -23,7 +23,7 @@ from cirq import add_dynamical_decoupling, CNOT, CZ, CZPowGate, H, X, Y, Z -def assert_sim_eq(circuit1: cirq.AbstractCircuit, circuit2: cirq.AbstractCircuit): +def assert_sim_eq(circuit1: cirq.AbstractCircuit, circuit2: cirq.AbstractCircuit) -> None: # Simulate 2 circuits and compare final states. sampler = cirq.Simulator(dtype=np.complex128) psi0 = sampler.simulate(cirq.drop_terminal_measurements(circuit1)).final_state_vector @@ -37,7 +37,7 @@ def assert_dd( expected_circuit: str | cirq.AbstractCircuit, schema: str | tuple[cirq.Gate, ...] = 'DEFAULT', single_qubit_gate_moments_only: bool = True, -): +) -> None: transformed_circuit = add_dynamical_decoupling( input_circuit, schema=schema, single_qubit_gate_moments_only=single_qubit_gate_moments_only ).freeze() @@ -53,7 +53,7 @@ def assert_dd( assert_sim_eq(input_circuit, transformed_circuit) -def test_no_insertion(): +def test_no_insertion() -> None: """Test case diagrams. Input: a: ───H───@─────── @@ -81,7 +81,7 @@ def test_no_insertion(): 'schema,inserted_gates', [('XX_PAIR', (X, X)), ('X_XINV', (X, X**-1)), ('YY_PAIR', (Y, Y)), ('Y_YINV', (Y, Y**-1))], ) -def test_insert_provided_schema(schema: str, inserted_gates: Sequence[cirq.Gate]): +def test_insert_provided_schema(schema: str, inserted_gates: Sequence[cirq.Gate]) -> None: """Test case diagrams. Input: a: ───H───@───────────M─── @@ -113,7 +113,7 @@ def test_insert_provided_schema(schema: str, inserted_gates: Sequence[cirq.Gate] assert_dd(input_circuit, expected_circuit, schema=schema, single_qubit_gate_moments_only=False) -def test_insert_by_customized_dd_sequence(): +def test_insert_by_customized_dd_sequence() -> None: """Test case diagrams. Input: a: ───H───@───────────────────H─── @@ -151,13 +151,13 @@ def test_insert_by_customized_dd_sequence(): cirq.Moment(CNOT(b, c), Y(a)), cirq.Moment([H(qubit) for qubit in [a, b, c]]), ), - schema=[X, X, Y, Y], + schema=(X, X, Y, Y), single_qubit_gate_moments_only=False, ) @pytest.mark.parametrize('single_qubit_gate_moments_only', [True, False]) -def test_pull_through_h_gate_case1(single_qubit_gate_moments_only: bool): +def test_pull_through_h_gate_case1(single_qubit_gate_moments_only: bool) -> None: """Test case diagrams. Input: a: ───H───────H───────@─── @@ -193,7 +193,7 @@ def test_pull_through_h_gate_case1(single_qubit_gate_moments_only: bool): @pytest.mark.parametrize('single_qubit_gate_moments_only', [True, False]) -def test_pull_through_h_gate_case2(single_qubit_gate_moments_only: bool): +def test_pull_through_h_gate_case2(single_qubit_gate_moments_only: bool) -> None: """Test case diagrams. Input: a: ───H───────H───────H─── @@ -246,14 +246,14 @@ def test_pull_through_h_gate_case2(single_qubit_gate_moments_only: bool): ), ], ) -def test_invalid_dd_schema(schema: str | tuple[cirq.Gate, ...], error_msg_regex): +def test_invalid_dd_schema(schema: str | tuple[cirq.Gate, ...], error_msg_regex) -> None: a = cirq.NamedQubit('a') input_circuit = cirq.Circuit(H(a)) with pytest.raises(ValueError, match=error_msg_regex): add_dynamical_decoupling(input_circuit, schema=schema, single_qubit_gate_moments_only=False) -def test_single_qubit_gate_moments_only_no_updates_succeeds(): +def test_single_qubit_gate_moments_only_no_updates_succeeds() -> None: qubits = cirq.LineQubit.range(9) input_circuit = cirq.Circuit( cirq.Moment([H(qubits[i]) for i in [3, 4, 5]]), @@ -269,7 +269,7 @@ def test_single_qubit_gate_moments_only_no_updates_succeeds(): add_dynamical_decoupling(input_circuit, schema='X_XINV', single_qubit_gate_moments_only=True) -def test_scattered_circuit(): +def test_scattered_circuit() -> None: """Test case diagrams. Input: 0: ───────────────────────────────H───@───H─── @@ -424,7 +424,7 @@ def test_scattered_circuit(): ) -def test_scattered_circuit2(): +def test_scattered_circuit2() -> None: """Test case diagrams. Input: 0: ───────────────────@─── @@ -484,7 +484,7 @@ def test_scattered_circuit2(): ) -def test_pull_through_chain(): +def test_pull_through_chain() -> None: """Test case diagrams. Input: 0: ───X───────×───────────X─── @@ -526,7 +526,7 @@ def test_pull_through_chain(): ) -def test_multiple_clifford_pieces_case1(): +def test_multiple_clifford_pieces_case1() -> None: """Test case diagrams. Input: a: ───H───────H───────@───────────H───────H─── @@ -560,7 +560,7 @@ def test_multiple_clifford_pieces_case1(): ) -def test_multiple_clifford_pieces_case2(): +def test_multiple_clifford_pieces_case2() -> None: """Test case diagrams. Input: a: ───@───PhXZ(a=0.3,x=0.2,z=0)───PhXZ(a=0.3,x=0.2,z=0)───PhXZ(a=0.3,x=0.2,z=0)───@─── @@ -596,7 +596,7 @@ def test_multiple_clifford_pieces_case2(): ) -def test_insert_new_moment(): +def test_insert_new_moment() -> None: """Test case diagrams. Input: a: ───H───────H───@───@─────── @@ -637,7 +637,7 @@ def test_insert_new_moment(): ) -def test_with_non_clifford_measurements(): +def test_with_non_clifford_measurements() -> None: """Test case diagrams. Input: 0: ───────────H───@───H───M─── @@ -672,7 +672,7 @@ def test_with_non_clifford_measurements(): ) -def test_cross_clifford_pieces_filling_merge(): +def test_cross_clifford_pieces_filling_merge() -> None: """Test case diagrams. Input: 0: ─────────────────────────────────PhXZ(a=0.2,x=0.2,z=0.1)───@─────────────────────────PhXZ(a=0.2,x=0.2,z=0.1)───@───PhXZ(a=0.2,x=0.2,z=0.1)───H─── @@ -738,7 +738,7 @@ def test_cross_clifford_pieces_filling_merge(): ) -def test_pull_through_phxz_gate_case1(): +def test_pull_through_phxz_gate_case1() -> None: """Test case diagrams. Input: a: ───H───────PhXZ(a=0.25,x=-1,z=0)───────@─── @@ -767,7 +767,7 @@ def test_pull_through_phxz_gate_case1(): ) -def test_pull_through_phxz_gate_case2(): +def test_pull_through_phxz_gate_case2() -> None: """Test case diagrams. Input: a: ───H───────PhXZ(a=0.2,x=-1,z=0)───────@─── @@ -796,7 +796,7 @@ def test_pull_through_phxz_gate_case2(): ) -def test_merge_before_non_cliffords(): +def test_merge_before_non_cliffords() -> None: """Test case diagrams. Input circuit: 0: ───X──────────────────────────────────────────────────M─── @@ -860,7 +860,7 @@ def test_merge_before_non_cliffords(): ) def test_single_qubit_gate_moments_only_true_vs_false( single_qubit_gate_moments_only, expected_diagram -): +) -> None: q0, q1, q2 = cirq.LineQubit.range(3) input_circuit = cirq.Circuit( cirq.Moment([X(q) for q in [q0, q1, q2]]), diff --git a/cirq-core/cirq/transformers/eject_phased_paulis_test.py b/cirq-core/cirq/transformers/eject_phased_paulis_test.py index bfbcd0bb45d..5398aa2fa91 100644 --- a/cirq-core/cirq/transformers/eject_phased_paulis_test.py +++ b/cirq-core/cirq/transformers/eject_phased_paulis_test.py @@ -31,7 +31,7 @@ def assert_optimizes( eject_parameterized: bool = False, *, with_context: bool = False, -): +) -> None: context = cirq.TransformerContext(tags_to_ignore=("nocompile",)) if with_context else None circuit = cirq.eject_phased_paulis( before, eject_parameterized=eject_parameterized, context=context diff --git a/cirq-core/cirq/transformers/eject_z_test.py b/cirq-core/cirq/transformers/eject_z_test.py index 39e00b287f6..b77c47b69b3 100644 --- a/cirq-core/cirq/transformers/eject_z_test.py +++ b/cirq-core/cirq/transformers/eject_z_test.py @@ -30,7 +30,7 @@ def assert_optimizes( eject_parameterized: bool = False, *, with_context: bool = False, -): +) -> None: if cirq.has_unitary(before): cirq.testing.assert_circuits_with_terminal_measurements_are_equivalent( before, expected, atol=1e-8 @@ -72,7 +72,7 @@ def assert_optimizes( cirq.testing.assert_same_circuits(c_nested, c_expected) -def assert_removes_all_z_gates(circuit: cirq.Circuit, eject_parameterized: bool = True): +def assert_removes_all_z_gates(circuit: cirq.Circuit, eject_parameterized: bool = True) -> None: optimized = cirq.eject_z(circuit, eject_parameterized=eject_parameterized) for op in optimized.all_operations(): # assert _try_get_known_z_half_turns(op, eject_parameterized) is None @@ -96,7 +96,7 @@ def assert_removes_all_z_gates(circuit: cirq.Circuit, eject_parameterized: bool ) -def test_single_z_stays(): +def test_single_z_stays() -> None: q = cirq.NamedQubit('q') assert_optimizes( before=cirq.Circuit([cirq.Moment([cirq.Z(q) ** 0.5])]), @@ -104,13 +104,13 @@ def test_single_z_stays(): ) -def test_single_phased_xz_stays(): +def test_single_phased_xz_stays() -> None: gate = cirq.PhasedXZGate(axis_phase_exponent=0.2, x_exponent=0.3, z_exponent=0.4) q = cirq.NamedQubit('q') assert_optimizes(before=cirq.Circuit(gate(q)), expected=cirq.Circuit(gate(q))) -def test_ignores_xz_and_cz(): +def test_ignores_xz_and_cz() -> None: a = cirq.NamedQubit('a') b = cirq.NamedQubit('b') assert_optimizes( @@ -135,7 +135,7 @@ def test_ignores_xz_and_cz(): ) -def test_early_z(): +def test_early_z() -> None: q = cirq.NamedQubit('q') assert_optimizes( before=cirq.Circuit([cirq.Moment([cirq.Z(q) ** 0.5]), cirq.Moment(), cirq.Moment()]), @@ -143,7 +143,7 @@ def test_early_z(): ) -def test_multi_z_merges(): +def test_multi_z_merges() -> None: q = cirq.NamedQubit('q') assert_optimizes( before=cirq.Circuit([cirq.Moment([cirq.Z(q) ** 0.5]), cirq.Moment([cirq.Z(q) ** 0.25])]), @@ -151,7 +151,7 @@ def test_multi_z_merges(): ) -def test_z_pushes_past_xy_and_phases_it(): +def test_z_pushes_past_xy_and_phases_it() -> None: q = cirq.NamedQubit('q') assert_optimizes( before=cirq.Circuit([cirq.Moment([cirq.Z(q) ** 0.5]), cirq.Moment([cirq.Y(q) ** 0.25])]), @@ -161,7 +161,7 @@ def test_z_pushes_past_xy_and_phases_it(): ) -def test_z_pushes_past_cz(): +def test_z_pushes_past_cz() -> None: a = cirq.NamedQubit('a') b = cirq.NamedQubit('b') assert_optimizes( @@ -174,7 +174,7 @@ def test_z_pushes_past_cz(): ) -def test_measurement_consumes_zs(): +def test_measurement_consumes_zs() -> None: q = cirq.NamedQubit('q') assert_optimizes( before=cirq.Circuit( @@ -188,7 +188,7 @@ def test_measurement_consumes_zs(): ) -def test_unphaseable_causes_earlier_merge_without_size_increase(): +def test_unphaseable_causes_earlier_merge_without_size_increase() -> None: class UnknownGate(cirq.testing.SingleQubitGate): pass @@ -222,7 +222,7 @@ class UnknownGate(cirq.testing.SingleQubitGate): @pytest.mark.parametrize('sym', [sympy.Symbol('a'), sympy.Symbol('a') + 1]) -def test_symbols_block(sym): +def test_symbols_block(sym) -> None: q = cirq.NamedQubit('q') assert_optimizes( before=cirq.Circuit( @@ -239,7 +239,7 @@ def test_symbols_block(sym): @pytest.mark.parametrize('sym', [sympy.Symbol('a'), sympy.Symbol('a') + 1]) -def test_symbols_eject(sym): +def test_symbols_eject(sym) -> None: q = cirq.NamedQubit('q') assert_optimizes( before=cirq.Circuit( @@ -256,7 +256,7 @@ def test_symbols_eject(sym): ) -def test_removes_zs(): +def test_removes_zs() -> None: a = cirq.NamedQubit('a') b = cirq.NamedQubit('b') @@ -295,7 +295,7 @@ def test_removes_zs(): ) -def test_unknown_operation_blocks(): +def test_unknown_operation_blocks() -> None: q = cirq.NamedQubit('q') class UnknownOp(cirq.Operation): @@ -314,7 +314,7 @@ def with_qubits(self, *new_qubits): ) -def test_tagged_nocompile_operation_blocks(): +def test_tagged_nocompile_operation_blocks() -> None: q = cirq.NamedQubit('q') u = cirq.Z(q).with_tags("nocompile") assert_optimizes( @@ -324,7 +324,7 @@ def test_tagged_nocompile_operation_blocks(): ) -def test_swap(): +def test_swap() -> None: a, b = cirq.LineQubit.range(2) original = cirq.Circuit([cirq.rz(0.123).on(a), cirq.SWAP(a, b)]) optimized = original.copy() @@ -341,13 +341,13 @@ def test_swap(): @pytest.mark.parametrize('exponent', (0, 2, 1.1, -2, -1.6)) -def test_not_a_swap(exponent): +def test_not_a_swap(exponent) -> None: a, b = cirq.LineQubit.range(2) assert not _is_swaplike(cirq.SWAP(a, b) ** exponent) @pytest.mark.parametrize('theta', (np.pi / 2, -np.pi / 2, np.pi / 2 + 5 * np.pi)) -def test_swap_fsim(theta): +def test_swap_fsim(theta) -> None: a, b = cirq.LineQubit.range(2) original = cirq.Circuit([cirq.rz(0.123).on(a), cirq.FSimGate(theta=theta, phi=0.123).on(a, b)]) optimized = original.copy() @@ -364,13 +364,12 @@ def test_swap_fsim(theta): @pytest.mark.parametrize('theta', (0, 5 * np.pi, -np.pi)) -def test_not_a_swap_fsim(theta): - a, b = cirq.LineQubit.range(2) - assert not _is_swaplike(cirq.FSimGate(theta=theta, phi=0.456).on(a, b)) +def test_not_a_swap_fsim(theta) -> None: + assert not _is_swaplike(cirq.FSimGate(theta=theta, phi=0.456)) @pytest.mark.parametrize('exponent', (1, -1)) -def test_swap_iswap(exponent): +def test_swap_iswap(exponent) -> None: a, b = cirq.LineQubit.range(2) original = cirq.Circuit([cirq.rz(0.123).on(a), cirq.ISWAP(a, b) ** exponent]) optimized = original.copy() diff --git a/cirq-core/cirq/transformers/expand_composite.py b/cirq-core/cirq/transformers/expand_composite.py index 5d3868960d4..a72991b468a 100644 --- a/cirq-core/cirq/transformers/expand_composite.py +++ b/cirq-core/cirq/transformers/expand_composite.py @@ -31,7 +31,7 @@ def expand_composite( *, context: cirq.TransformerContext | None = None, no_decomp: Callable[[ops.Operation], bool] = (lambda _: False), -): +) -> cirq.Circuit: """A transformer that expands composite operations via `cirq.decompose`. For each operation in the circuit, this pass examines if the operation can diff --git a/cirq-core/cirq/transformers/expand_composite_test.py b/cirq-core/cirq/transformers/expand_composite_test.py index 34201b023e8..96db7ee7eb0 100644 --- a/cirq-core/cirq/transformers/expand_composite_test.py +++ b/cirq-core/cirq/transformers/expand_composite_test.py @@ -19,24 +19,24 @@ import cirq -def assert_equal_mod_empty(expected, actual): +def assert_equal_mod_empty(expected, actual) -> None: actual = cirq.drop_empty_moments(actual) cirq.testing.assert_same_circuits(actual, expected) -def test_empty_circuit(): +def test_empty_circuit() -> None: circuit = cirq.Circuit() circuit = cirq.expand_composite(circuit) assert_equal_mod_empty(cirq.Circuit(), circuit) -def test_empty_moment(): +def test_empty_moment() -> None: circuit = cirq.Circuit([]) circuit = cirq.expand_composite(circuit) assert_equal_mod_empty(cirq.Circuit([]), circuit) -def test_ignore_non_composite(): +def test_ignore_non_composite() -> None: q0, q1 = cirq.LineQubit.range(2) circuit = cirq.Circuit() circuit.append([cirq.X(q0), cirq.Y(q1), cirq.CZ(q0, q1), cirq.Z(q0)]) @@ -45,7 +45,7 @@ def test_ignore_non_composite(): assert_equal_mod_empty(expected, circuit) -def test_composite_default(): +def test_composite_default() -> None: q0, q1 = cirq.LineQubit.range(2) cnot = cirq.CNOT(q0, q1) circuit = cirq.Circuit() @@ -56,7 +56,7 @@ def test_composite_default(): assert_equal_mod_empty(expected, circuit) -def test_multiple_composite_default(): +def test_multiple_composite_default() -> None: q0, q1 = cirq.LineQubit.range(2) cnot = cirq.CNOT(q0, q1) circuit = cirq.Circuit() @@ -68,7 +68,7 @@ def test_multiple_composite_default(): assert_equal_mod_empty(expected, circuit) -def test_mix_composite_non_composite(): +def test_mix_composite_non_composite() -> None: q0, q1 = cirq.LineQubit.range(2) circuit = cirq.Circuit(cirq.X(q0), cirq.CNOT(q0, q1), cirq.X(q1)) @@ -85,7 +85,7 @@ def test_mix_composite_non_composite(): assert_equal_mod_empty(expected, circuit) -def test_recursive_composite(): +def test_recursive_composite() -> None: q0, q1 = cirq.LineQubit.range(2) swap = cirq.SWAP(q0, q1) circuit = cirq.Circuit() @@ -106,7 +106,7 @@ def test_recursive_composite(): assert_equal_mod_empty(expected, circuit) -def test_decompose_returns_not_flat_op_tree(): +def test_decompose_returns_not_flat_op_tree() -> None: class ExampleGate(cirq.testing.SingleQubitGate): def _decompose_(self, qubits): (q0,) = qubits @@ -121,7 +121,7 @@ def _decompose_(self, qubits): assert_equal_mod_empty(expected, circuit) -def test_decompose_returns_deep_op_tree(): +def test_decompose_returns_deep_op_tree() -> None: class ExampleGate(cirq.testing.TwoQubitGate): def _decompose_(self, qubits): q0, q1 = qubits @@ -162,7 +162,7 @@ def generator(depth): assert_equal_mod_empty(expected, circuit) -def test_non_recursive_expansion(): +def test_non_recursive_expansion() -> None: qubits = [cirq.NamedQubit(s) for s in 'xy'] no_decomp = lambda op: (isinstance(op, cirq.GateOperation) and op.gate == cirq.ISWAP) unexpanded_circuit = cirq.Circuit(cirq.ISWAP(*qubits)) @@ -184,14 +184,14 @@ def test_non_recursive_expansion(): assert actual_text_diagram == expected_text_diagram -def test_do_not_decompose_no_compile(): +def test_do_not_decompose_no_compile() -> None: q0, q1 = cirq.LineQubit.range(2) c = cirq.Circuit(cirq.CNOT(q0, q1).with_tags("no_compile")) context = cirq.TransformerContext(tags_to_ignore=("no_compile",)) assert_equal_mod_empty(c, cirq.expand_composite(c, context=context)) -def test_expands_composite_recursively_preserving_structure(): +def test_expands_composite_recursively_preserving_structure() -> None: q = cirq.LineQubit.range(2) c_nested = cirq.FrozenCircuit( cirq.SWAP(*q[:2]), cirq.SWAP(*q[:2]).with_tags("ignore"), cirq.SWAP(*q[:2]) @@ -256,7 +256,7 @@ def test_expands_composite_recursively_preserving_structure(): c_nested_expanded, ) - context = cirq.TransformerContext(tags_to_ignore=["ignore"], deep=True) + context = cirq.TransformerContext(tags_to_ignore=("ignore",), deep=True) c_expanded = cirq.expand_composite( c_orig, no_decomp=lambda op: op.gate == cirq.CNOT, context=context ) diff --git a/cirq-core/cirq/transformers/gauge_compiling/gauge_compiling.py b/cirq-core/cirq/transformers/gauge_compiling/gauge_compiling.py index c9bfe84159d..25525e23d2c 100644 --- a/cirq-core/cirq/transformers/gauge_compiling/gauge_compiling.py +++ b/cirq-core/cirq/transformers/gauge_compiling/gauge_compiling.py @@ -260,7 +260,7 @@ def as_sweep( N: int, context: transformer_api.TransformerContext | None = None, prng: np.random.Generator | None = None, - ) -> tuple[circuits.AbstractCircuit, cirq.Sweepable]: + ) -> tuple[circuits.AbstractCircuit, cirq.Sweep]: """Generates a parameterized circuit with *N* sets of sweepable parameters. Args: diff --git a/cirq-core/cirq/transformers/gauge_compiling/gauge_compiling_test.py b/cirq-core/cirq/transformers/gauge_compiling/gauge_compiling_test.py index 755e57bfd61..79f67331abf 100644 --- a/cirq-core/cirq/transformers/gauge_compiling/gauge_compiling_test.py +++ b/cirq-core/cirq/transformers/gauge_compiling/gauge_compiling_test.py @@ -33,29 +33,31 @@ from cirq.transformers.gauge_compiling.sqrt_cz_gauge import SqrtCZGauge -def test_deep_transformation_not_supported(): +def test_deep_transformation_not_supported() -> None: + + empty_selector = GaugeSelector(gauges=()) with pytest.raises(ValueError, match="cannot be used with deep=True"): - _ = GaugeTransformer(target=cirq.CZ, gauge_selector=lambda _: None)( + _ = GaugeTransformer(target=cirq.CZ, gauge_selector=empty_selector)( cirq.Circuit(), context=cirq.TransformerContext(deep=True) ) with pytest.raises(ValueError, match="cannot be used with deep=True"): - _ = GaugeTransformer(target=cirq.CZ, gauge_selector=lambda _: None).as_sweep( + _ = GaugeTransformer(target=cirq.CZ, gauge_selector=empty_selector).as_sweep( cirq.Circuit(), context=cirq.TransformerContext(deep=True), N=1 ) -def test_ignore_tags(): +def test_ignore_tags() -> None: c = cirq.Circuit(cirq.CZ(*cirq.LineQubit.range(2)).with_tags('foo')) - assert c == CZGaugeTransformer(c, context=cirq.TransformerContext(tags_to_ignore={"foo"})) + assert c == CZGaugeTransformer(c, context=cirq.TransformerContext(tags_to_ignore=("foo",))) parameterized_circuit, _ = CZGaugeTransformer.as_sweep( - c, context=cirq.TransformerContext(tags_to_ignore={"foo"}), N=1 + c, context=cirq.TransformerContext(tags_to_ignore=("foo",)), N=1 ) assert c == parameterized_circuit -def test_target_can_be_gateset(): +def test_target_can_be_gateset() -> None: qs = cirq.LineQubit.range(2) c = cirq.Circuit(cirq.CZ(*qs)) transformer = GaugeTransformer( @@ -65,7 +67,7 @@ def test_target_can_be_gateset(): assert transformer(c, prng=np.random.default_rng(0)) == want -def test_as_sweep_multi_pre_or_multi_post(): +def test_as_sweep_multi_pre_or_multi_post() -> None: transformer = GaugeTransformer( target=cirq.CZ, gauge_selector=GaugeSelector( @@ -91,7 +93,7 @@ def test_as_sweep_multi_pre_or_multi_post(): ) -def test_as_sweep_invalid_gauge_sequence(): +def test_as_sweep_invalid_gauge_sequence() -> None: transfomer = GaugeTransformer( target=cirq.CZ, gauge_selector=GaugeSelector( @@ -112,7 +114,7 @@ def test_as_sweep_invalid_gauge_sequence(): transfomer.as_sweep(c, N=1) -def test_as_sweep_convert_to_phxz_failed(): +def test_as_sweep_convert_to_phxz_failed() -> None: qs = cirq.LineQubit.range(2) c = cirq.Circuit(cirq.CZ(*qs)) @@ -128,7 +130,7 @@ def test_as_sweep_convert_to_phxz_failed(): _ = CZGaugeTransformer.as_sweep(c, context=cirq.TransformerContext(), N=1) -def test_symbolize_2_qubits_gate_failed(): +def test_symbolize_2_qubits_gate_failed() -> None: qs = cirq.LineQubit.range(2) c = cirq.Circuit(cirq.CZPowGate(exponent=0.5).on(*qs)) @@ -142,7 +144,7 @@ def test_symbolize_2_qubits_gate_failed(): _ = SqrtCZGaugeTransformer.as_sweep(c, N=1) -def test_symbolize_2_qubits_gate_failed_unmatched_symbol_length(): +def test_symbolize_2_qubits_gate_failed_unmatched_symbol_length() -> None: symbolizer = TwoQubitGateSymbolizer(symbolizer_fn=lambda gate, _: (gate, {}), n_symbols=2) with pytest.raises(ValueError, match="Expect 2 symbols, but got 1 symbols"): symbolizer(cirq.CZ, [sympy.Symbol('x')]) diff --git a/cirq-core/cirq/transformers/gauge_compiling/gauge_compiling_test_utils.py b/cirq-core/cirq/transformers/gauge_compiling/gauge_compiling_test_utils.py index 6f6cbc343fd..b86a0beb9cc 100644 --- a/cirq-core/cirq/transformers/gauge_compiling/gauge_compiling_test_utils.py +++ b/cirq-core/cirq/transformers/gauge_compiling/gauge_compiling_test_utils.py @@ -33,7 +33,7 @@ class GaugeTester: ['generation_seed', 'transformation_seed'], np.random.RandomState(0).randint(2**31, size=(5, 2)).tolist(), ) - def test_gauge_transformer(self, generation_seed, transformation_seed): + def test_gauge_transformer(self, generation_seed, transformation_seed) -> None: c = cirq.Circuit() while not any(op.gate == self.two_qubit_gate for op in c.all_operations()): c = cirq.testing.random_circuit( @@ -57,7 +57,7 @@ def test_gauge_transformer(self, generation_seed, transformation_seed): @patch('cirq.transformers.gauge_compiling.gauge_compiling._select', autospec=True) @pytest.mark.parametrize('seed', range(5)) - def test_all_gauges(self, mock_select, seed): + def test_all_gauges(self, mock_select, seed) -> None: assert isinstance( self.gauge_transformer.gauge_selector, GaugeSelector ), 'When using a custom selector, please override this method to properly test all gauges' @@ -74,7 +74,7 @@ def test_all_gauges(self, mock_select, seed): else: _check_equivalent_with_error_message(c, nc, gauge) - def test_sweep(self): + def test_sweep(self) -> None: qubits = cirq.LineQubit.range(3) input_circuit = cirq.Circuit( diff --git a/cirq-core/cirq/transformers/heuristic_decompositions/gate_tabulation_math_utils_test.py b/cirq-core/cirq/transformers/heuristic_decompositions/gate_tabulation_math_utils_test.py index 1668bf84d9d..a7b0849281e 100644 --- a/cirq-core/cirq/transformers/heuristic_decompositions/gate_tabulation_math_utils_test.py +++ b/cirq-core/cirq/transformers/heuristic_decompositions/gate_tabulation_math_utils_test.py @@ -14,15 +14,15 @@ ) -def test_weyl_chamber_mesh_spacing_too_small_throws_error(): +def test_weyl_chamber_mesh_spacing_too_small_throws_error() -> None: with pytest.raises(ValueError, match='may cause system to crash'): weyl_chamber_mesh(spacing=5e-4) -def test_kak_vector_infidelity_ignore_equivalent_nontrivial(): +def test_kak_vector_infidelity_ignore_equivalent_nontrivial() -> None: x, y, z = np.pi / 4, 1, 0.5 - kak_0 = cirq.kak_canonicalize_vector(x, y, z).interaction_coefficients - kak_1 = cirq.kak_canonicalize_vector(x - 1e-3, y, z).interaction_coefficients + kak_0 = np.asarray(cirq.kak_canonicalize_vector(x, y, z).interaction_coefficients) + kak_1 = np.asarray(cirq.kak_canonicalize_vector(x - 1e-3, y, z).interaction_coefficients) inf_check_equivalent = kak_vector_infidelity(kak_0, kak_1, False) inf_ignore_equivalent = kak_vector_infidelity(kak_0, kak_1, True) @@ -30,7 +30,7 @@ def test_kak_vector_infidelity_ignore_equivalent_nontrivial(): assert inf_check_equivalent < inf_ignore_equivalent -def test_random_qubit_unitary_shape(): +def test_random_qubit_unitary_shape() -> None: rng = value.parse_random_state(11) actual = random_qubit_unitary((3, 4, 5), True, rng).ravel() rng = value.parse_random_state(11) @@ -38,7 +38,7 @@ def test_random_qubit_unitary_shape(): np.testing.assert_almost_equal(actual, expected) -def test_random_qubit_default(): +def test_random_qubit_default() -> None: rng = value.parse_random_state(11) actual = random_qubit_unitary(randomize_global_phase=True, rng=rng).ravel() rng = value.parse_random_state(11) diff --git a/cirq-core/cirq/transformers/measurement_transformers_test.py b/cirq-core/cirq/transformers/measurement_transformers_test.py index 844ec4196c2..1439a9717ad 100644 --- a/cirq-core/cirq/transformers/measurement_transformers_test.py +++ b/cirq-core/cirq/transformers/measurement_transformers_test.py @@ -23,7 +23,7 @@ from cirq.transformers.measurement_transformers import _ConfusionChannel, _MeasurementQid, _mod_add -def assert_equivalent_to_deferred(circuit: cirq.Circuit): +def assert_equivalent_to_deferred(circuit: cirq.Circuit) -> None: qubits = list(circuit.all_qubits()) sim = cirq.Simulator() num_qubits = len(qubits) @@ -40,7 +40,7 @@ def assert_equivalent_to_deferred(circuit: cirq.Circuit): np.testing.assert_equal(result.measurements, result1.measurements) -def test_basic(): +def test_basic() -> None: q0, q1 = cirq.LineQubit.range(2) circuit = cirq.Circuit( cirq.measure(q0, key='a'), @@ -61,7 +61,7 @@ def test_basic(): ) -def test_qudits(): +def test_qudits() -> None: q0, q1 = cirq.LineQid.range(2, dimension=3) circuit = cirq.Circuit( cirq.measure(q0, key='a'), @@ -82,7 +82,7 @@ def test_qudits(): ) -def test_sympy_control(): +def test_sympy_control() -> None: q0, q1 = cirq.LineQubit.range(2) circuit = cirq.Circuit( cirq.measure(q0, key='a'), @@ -103,7 +103,7 @@ def test_sympy_control(): ) -def test_sympy_qudits(): +def test_sympy_qudits() -> None: q0, q1 = cirq.LineQid.range(2, dimension=3) circuit = cirq.Circuit( cirq.measure(q0, key='a'), @@ -124,7 +124,7 @@ def test_sympy_qudits(): ) -def test_sympy_control_complex(): +def test_sympy_control_complex() -> None: q0, q1, q2 = cirq.LineQubit.range(3) circuit = cirq.Circuit( cirq.measure(q0, key='a'), @@ -151,7 +151,7 @@ def test_sympy_control_complex(): ) -def test_sympy_control_complex_qudit(): +def test_sympy_control_complex_qudit() -> None: q0, q1, q2 = cirq.LineQid.for_qid_shape((4, 2, 2)) circuit = cirq.Circuit( cirq.measure(q0, key='a'), @@ -180,7 +180,7 @@ def test_sympy_control_complex_qudit(): ) -def test_multiple_sympy_control_complex(): +def test_multiple_sympy_control_complex() -> None: q0, q1, q2 = cirq.LineQubit.range(3) circuit = cirq.Circuit( cirq.measure(q0, key='a'), @@ -209,7 +209,7 @@ def test_multiple_sympy_control_complex(): ) -def test_sympy_and_key_control(): +def test_sympy_and_key_control() -> None: q0, q1 = cirq.LineQubit.range(2) circuit = cirq.Circuit( cirq.measure(q0, key='a'), @@ -230,7 +230,7 @@ def test_sympy_and_key_control(): ) -def test_sympy_control_multiqubit(): +def test_sympy_control_multiqubit() -> None: q0, q1, q2 = cirq.LineQubit.range(3) circuit = cirq.Circuit( cirq.measure(q0, q1, key='a'), @@ -255,7 +255,7 @@ def test_sympy_control_multiqubit(): ) -def test_nocompile_context(): +def test_nocompile_context() -> None: q0, q1 = cirq.LineQubit.range(2) circuit = cirq.Circuit( cirq.measure(q0, key='a').with_tags('nocompile'), @@ -268,7 +268,7 @@ def test_nocompile_context(): cirq.testing.assert_same_circuits(deferred, circuit) -def test_nocompile_context_leaves_invalid_circuit(): +def test_nocompile_context_leaves_invalid_circuit() -> None: q0, q1 = cirq.LineQubit.range(2) circuit = cirq.Circuit( cirq.measure(q0, key='a').with_tags('nocompile'), @@ -281,7 +281,7 @@ def test_nocompile_context_leaves_invalid_circuit(): ) -def test_pauli(): +def test_pauli() -> None: q0, q1 = cirq.LineQubit.range(2) circuit = cirq.Circuit( cirq.PauliMeasurementGate(cirq.DensePauliString('Y'), key='a').on(q0), @@ -303,7 +303,7 @@ def test_pauli(): ) -def test_extra_measurements(): +def test_extra_measurements() -> None: q0, q1 = cirq.LineQubit.range(2) circuit = cirq.Circuit( cirq.measure(q0, key='a'), @@ -326,7 +326,7 @@ def test_extra_measurements(): ) -def test_extra_controlled_bits(): +def test_extra_controlled_bits() -> None: q0, q1 = cirq.LineQubit.range(2) circuit = cirq.Circuit( cirq.measure(q0, key='a'), @@ -347,7 +347,7 @@ def test_extra_controlled_bits(): ) -def test_extra_control_bits(): +def test_extra_control_bits() -> None: q0, q1 = cirq.LineQubit.range(2) circuit = cirq.Circuit( cirq.measure(q0, key='a'), @@ -372,7 +372,7 @@ def test_extra_control_bits(): ) -def test_subcircuit(): +def test_subcircuit() -> None: q0, q1 = cirq.LineQubit.range(2) circuit = cirq.Circuit( cirq.CircuitOperation( @@ -397,7 +397,7 @@ def test_subcircuit(): ) -def test_multi_qubit_measurements(): +def test_multi_qubit_measurements() -> None: q0, q1 = cirq.LineQubit.range(2) circuit = cirq.Circuit( cirq.measure(q0, q1, key='a'), @@ -422,7 +422,7 @@ def test_multi_qubit_measurements(): ) -def test_multi_qubit_control(): +def test_multi_qubit_control() -> None: q0, q1, q2 = cirq.LineQubit.range(3) circuit = cirq.Circuit( cirq.measure(q0, q1, key='a'), @@ -448,7 +448,7 @@ def test_multi_qubit_control(): @pytest.mark.parametrize('index', [-3, -2, -1, 0, 1, 2]) -def test_repeated(index: int): +def test_repeated(index: int) -> None: q0, q1 = cirq.LineQubit.range(2) circuit = cirq.Circuit( cirq.measure(q0, key='a'), # The control measurement when `index` is 0 or -2 @@ -481,7 +481,7 @@ def test_repeated(index: int): ) -def test_diagram(): +def test_diagram() -> None: q0, q1, q2, q3 = cirq.LineQubit.range(4) circuit = cirq.Circuit( cirq.measure(q0, q2, key='a'), @@ -515,7 +515,7 @@ def test_diagram(): ) -def test_repr(): +def test_repr() -> None: def test_repr(qid: _MeasurementQid): cirq.testing.assert_equivalent_repr(qid, global_vals={'_MeasurementQid': _MeasurementQid}) @@ -526,7 +526,7 @@ def test_repr(qid: _MeasurementQid): test_repr(_MeasurementQid('0:1:a', cirq.LineQid(9, 4))) -def test_confusion_map(): +def test_confusion_map() -> None: q0, q1 = cirq.LineQubit.range(2) circuit = cirq.Circuit( cirq.H(q0), @@ -549,7 +549,7 @@ def test_confusion_map(): assert np.all(result['a'] == result['b']) -def test_confusion_map_density_matrix(): +def test_confusion_map_density_matrix() -> None: q0, q1 = cirq.LineQubit.range(2) p_q0 = 0.3 # probability to measure 1 for q0 confusion = np.array([[0.8, 0.2], [0.1, 0.9]]) @@ -573,20 +573,20 @@ def test_confusion_map_density_matrix(): assert np.allclose(cirq.partial_trace(rho, [2]), expected) -def test_confusion_map_invert_mask_ordering(): +def test_confusion_map_invert_mask_ordering() -> None: q0 = cirq.LineQubit(0) # Confusion map sets the measurement to zero, and the invert mask changes it to one. # If these are run out of order then the result would be zero. circuit = cirq.Circuit( cirq.measure( - q0, key='a', confusion_map={(0,): np.array([[1, 0], [1, 0]])}, invert_mask=(1,) + q0, key='a', confusion_map={(0,): np.array([[1, 0], [1, 0]])}, invert_mask=(True,) ), cirq.I(q0), ) assert_equivalent_to_deferred(circuit) -def test_confusion_map_qudits(): +def test_confusion_map_qudits() -> None: q0 = cirq.LineQid(0, dimension=3) # First op takes q0 to superposed state, then confusion map measures 2 regardless. circuit = cirq.Circuit( @@ -599,7 +599,7 @@ def test_confusion_map_qudits(): assert_equivalent_to_deferred(circuit) -def test_multi_qubit_confusion_map(): +def test_multi_qubit_confusion_map() -> None: q0, q1, q2 = cirq.LineQubit.range(3) circuit = cirq.Circuit( cirq.measure( @@ -638,7 +638,7 @@ def test_multi_qubit_confusion_map(): assert np.sum(result['b']) == 100 -def test_confusion_map_errors(): +def test_confusion_map_errors() -> None: q0, q1 = cirq.LineQubit.range(2) circuit = cirq.Circuit( cirq.measure(q0, key='a', confusion_map={(0,): np.array([1])}), @@ -676,7 +676,7 @@ def test_confusion_map_errors(): _ = cirq.defer_measurements(circuit) -def test_dephase(): +def test_dephase() -> None: q0, q1 = cirq.LineQubit.range(2) circuit = cirq.Circuit( cirq.CircuitOperation( @@ -704,7 +704,7 @@ def test_dephase(): ) -def test_dephase_classical_conditions(): +def test_dephase_classical_conditions() -> None: q0, q1 = cirq.LineQubit.range(2) circuit = cirq.Circuit( cirq.measure(q0, key='a'), @@ -715,7 +715,7 @@ def test_dephase_classical_conditions(): _ = cirq.dephase_measurements(circuit) -def test_dephase_nocompile_context(): +def test_dephase_nocompile_context() -> None: q0, q1 = cirq.LineQubit.range(2) circuit = cirq.Circuit( cirq.CircuitOperation( @@ -745,11 +745,13 @@ def test_dephase_nocompile_context(): ) -def test_drop_terminal(): +def test_drop_terminal() -> None: q0, q1 = cirq.LineQubit.range(2) circuit = cirq.Circuit( cirq.CircuitOperation( - cirq.FrozenCircuit(cirq.CX(q0, q1), cirq.measure(q0, q1, key='a~b', invert_mask=[0, 1])) + cirq.FrozenCircuit( + cirq.CX(q0, q1), cirq.measure(q0, q1, key='a~b', invert_mask=(False, True)) + ) ) ) dropped = cirq.drop_terminal_measurements(circuit) @@ -761,10 +763,12 @@ def test_drop_terminal(): ) -def test_drop_terminal_qudit(): +def test_drop_terminal_qudit() -> None: q0, q1 = cirq.LineQid.range(2, dimension=3) circuit = cirq.Circuit( - cirq.CircuitOperation(cirq.FrozenCircuit(cirq.measure(q0, q1, key='m', invert_mask=[0, 1]))) + cirq.CircuitOperation( + cirq.FrozenCircuit(cirq.measure(q0, q1, key='m', invert_mask=(False, True))) + ) ) dropped = cirq.drop_terminal_measurements(circuit) expected_inversion_matrix = np.array([[0, 1, 0], [1, 0, 0], [0, 0, 1]]) @@ -796,11 +800,13 @@ def test_drop_terminal_qudit(): assert np.all(d2.measurements['m'] == [2, 2]) -def test_drop_terminal_nonterminal_error(): +def test_drop_terminal_nonterminal_error() -> None: q0, q1 = cirq.LineQubit.range(2) circuit = cirq.Circuit( cirq.CircuitOperation( - cirq.FrozenCircuit(cirq.measure(q0, q1, key='a~b', invert_mask=[0, 1]), cirq.CX(q0, q1)) + cirq.FrozenCircuit( + cirq.measure(q0, q1, key='a~b', invert_mask=(False, True)), cirq.CX(q0, q1) + ) ) ) with pytest.raises(ValueError, match='Circuit contains a non-terminal measurement'): @@ -813,7 +819,7 @@ def test_drop_terminal_nonterminal_error(): _ = cirq.drop_terminal_measurements(circuit, context=None) -def test_confusion_channel_consistency(): +def test_confusion_channel_consistency() -> None: two_d_chan = _ConfusionChannel(np.array([[0.5, 0.5], [0.4, 0.6]]), shape=(2,)) cirq.testing.assert_has_consistent_apply_channel(two_d_chan) three_d_chan = _ConfusionChannel( diff --git a/cirq-core/cirq/transformers/merge_k_qubit_gates_test.py b/cirq-core/cirq/transformers/merge_k_qubit_gates_test.py index c2e98902167..2de0346803b 100644 --- a/cirq-core/cirq/transformers/merge_k_qubit_gates_test.py +++ b/cirq-core/cirq/transformers/merge_k_qubit_gates_test.py @@ -20,7 +20,7 @@ import cirq -def assert_optimizes(optimized: cirq.AbstractCircuit, expected: cirq.AbstractCircuit): +def assert_optimizes(optimized: cirq.AbstractCircuit, expected: cirq.AbstractCircuit) -> None: # Ignore differences that would be caught by follow-up optimizations. followup_transformers: list[cirq.TRANSFORMER] = [ cirq.drop_negligible_operations, diff --git a/cirq-core/cirq/transformers/merge_single_qubit_gates_test.py b/cirq-core/cirq/transformers/merge_single_qubit_gates_test.py index 10a78a5830e..c7f0e0a58b8 100644 --- a/cirq-core/cirq/transformers/merge_single_qubit_gates_test.py +++ b/cirq-core/cirq/transformers/merge_single_qubit_gates_test.py @@ -21,7 +21,7 @@ import cirq -def assert_optimizes(optimized: cirq.AbstractCircuit, expected: cirq.AbstractCircuit): +def assert_optimizes(optimized: cirq.AbstractCircuit, expected: cirq.AbstractCircuit) -> None: # Ignore differences that would be caught by follow-up optimizations. followup_transformers: list[cirq.TRANSFORMER] = [ cirq.drop_negligible_operations, @@ -34,7 +34,7 @@ def assert_optimizes(optimized: cirq.AbstractCircuit, expected: cirq.AbstractCir cirq.testing.assert_same_circuits(optimized, expected) -def test_merge_single_qubit_gates_to_phased_x_and_z(): +def test_merge_single_qubit_gates_to_phased_x_and_z() -> None: a, b = cirq.LineQubit.range(2) c = cirq.Circuit( cirq.X(a), @@ -58,7 +58,7 @@ def test_merge_single_qubit_gates_to_phased_x_and_z(): ) -def test_merge_single_qubit_gates_to_phased_x_and_z_deep(): +def test_merge_single_qubit_gates_to_phased_x_and_z_deep() -> None: a = cirq.NamedQubit("a") c_nested = cirq.FrozenCircuit(cirq.H(a), cirq.Z(a), cirq.H(a).with_tags("ignore")) c_nested_merged = cirq.FrozenCircuit( @@ -80,7 +80,7 @@ def test_merge_single_qubit_gates_to_phased_x_and_z_deep(): c_nested_merged, cirq.CircuitOperation(c_nested_merged).repeat(6), ) - context = cirq.TransformerContext(tags_to_ignore=["ignore"], deep=True) + context = cirq.TransformerContext(tags_to_ignore=("ignore",), deep=True) c_new = cirq.merge_single_qubit_gates_to_phased_x_and_z(c_orig, context=context) cirq.testing.assert_same_circuits(c_new, c_expected) @@ -89,7 +89,7 @@ def _phxz(a: float | sympy.Symbol, x: float | sympy.Symbol, z: float | sympy.Sym return cirq.PhasedXZGate(axis_phase_exponent=a, x_exponent=x, z_exponent=z) -def test_merge_single_qubit_gates_to_phxz(): +def test_merge_single_qubit_gates_to_phxz() -> None: a, b = cirq.LineQubit.range(2) c = cirq.Circuit( cirq.X(a), @@ -113,7 +113,7 @@ def test_merge_single_qubit_gates_to_phxz(): ) -def test_merge_single_qubit_gates_to_phxz_deep(): +def test_merge_single_qubit_gates_to_phxz_deep() -> None: a = cirq.NamedQubit("a") c_nested = cirq.FrozenCircuit(cirq.H(a), cirq.Z(a), cirq.H(a).with_tags("ignore")) c_nested_merged = cirq.FrozenCircuit(_phxz(-0.5, 0.5, 0).on(a), cirq.H(a).with_tags("ignore")) @@ -133,12 +133,12 @@ def test_merge_single_qubit_gates_to_phxz_deep(): c_nested_merged, cirq.CircuitOperation(c_nested_merged).repeat(6), ) - context = cirq.TransformerContext(tags_to_ignore=["ignore"], deep=True) + context = cirq.TransformerContext(tags_to_ignore=("ignore",), deep=True) c_new = cirq.merge_single_qubit_gates_to_phxz(c_orig, context=context) cirq.testing.assert_same_circuits(c_new, c_expected) -def test_merge_single_qubit_moments_to_phxz(): +def test_merge_single_qubit_moments_to_phxz() -> None: q = cirq.LineQubit.range(3) c_orig = cirq.Circuit( cirq.Moment(cirq.X.on_each(*q[:2])), @@ -182,7 +182,7 @@ def test_merge_single_qubit_moments_to_phxz(): ) -def test_merge_single_qubit_moments_to_phxz_deep(): +def test_merge_single_qubit_moments_to_phxz_deep() -> None: q = cirq.LineQubit.range(3) x_t_y = cirq.FrozenCircuit( cirq.Moment(cirq.X.on_each(*q[:2])), @@ -218,20 +218,20 @@ def test_merge_single_qubit_moments_to_phxz_deep(): c_nested_merged, cirq.CircuitOperation(c_nested_merged).repeat(6), ) - context = cirq.TransformerContext(tags_to_ignore=["ignore"], deep=True) + context = cirq.TransformerContext(tags_to_ignore=("ignore",), deep=True) c_new = cirq.merge_single_qubit_moments_to_phxz(c_orig, context=context) cirq.testing.assert_allclose_up_to_global_phase( c_new.unitary(), c_expected.unitary(), atol=1e-7 ) -def test_merge_single_qubit_gates_to_phxz_global_phase(): +def test_merge_single_qubit_gates_to_phxz_global_phase() -> None: c = cirq.Circuit(cirq.GlobalPhaseGate(1j).on()) c2 = cirq.merge_single_qubit_gates_to_phxz(c) assert c == c2 -def test_merge_single_qubit_gates_to_phased_x_and_z_global_phase(): +def test_merge_single_qubit_gates_to_phased_x_and_z_global_phase() -> None: c = cirq.Circuit(cirq.GlobalPhaseGate(1j).on()) c2 = cirq.merge_single_qubit_gates_to_phased_x_and_z(c) assert c == c2 @@ -240,7 +240,7 @@ def test_merge_single_qubit_gates_to_phased_x_and_z_global_phase(): class TestMergeSingleQubitGatesSymbolized(TestCase): """Test suite for merge_single_qubit_gates_to_phxz_symbolized.""" - def test_case1(self): + def test_case1(self) -> None: """Test case diagram. Input circuit: 0: ───X─────────@────────H[ignore]─H──X──PhXZ(a=a0,x=x0,z=z0)──X──PhXZ(a=a1,x=x1,z=z1)─── @@ -265,7 +265,7 @@ def test_case1(self): cirq.Moment(cirq.X(a)), cirq.Moment(_phxz(sa1, sx1, sz1).on(a)), ) - context = cirq.TransformerContext(tags_to_ignore=["ignore"]) + context = cirq.TransformerContext(tags_to_ignore=("ignore",)) sweep = cirq.Zip( cirq.Points(key="h_exp", points=[0, 1]), cirq.Points(key="cz_exp", points=[0, 1]), @@ -295,7 +295,7 @@ def test_case1(self): {q: q for q in input_circuit.all_qubits()}, ) - def test_with_gauge_compiling_as_sweep_success(self): + def test_with_gauge_compiling_as_sweep_success(self) -> None: qubits = cirq.LineQubit.range(7) c = cirq.Circuit( cirq.Moment(cirq.H(qubits[0]), cirq.H(qubits[3])), @@ -318,7 +318,7 @@ def test_with_gauge_compiling_as_sweep_success(self): {q: q for q in qubits}, ) - def test_case_non_parameterized_singles(self): + def test_case_non_parameterized_singles(self) -> None: """Test merge_single_qubit_gates_to_phxz_symbolized when all single qubit gates are not parameterized.""" @@ -330,7 +330,7 @@ def test_case_non_parameterized_singles(self): ) assert_optimizes(output_circuit, expected_circuit) - def test_fail_different_structures_error(self): + def test_fail_different_structures_error(self) -> None: """Tests that the function raises a ValueError if merged structures of the circuit differ for different parameterizations.""" q0, q1 = cirq.LineQubit.range(2) @@ -347,7 +347,7 @@ def test_fail_different_structures_error(self): with pytest.raises(ValueError, match="Expect a PhasedXZGate or IdentityGate.*"): cirq.merge_single_qubit_gates_to_phxz_symbolized(circuit, sweep=sweep) - def test_fail_unexpected_gate_error(self): + def test_fail_unexpected_gate_error(self) -> None: """Tests that the function raises a RuntimeError of unexpected gate.""" a, b = cirq.LineQubit.range(2) circuit = cirq.Circuit( @@ -373,7 +373,7 @@ def test_fail_unexpected_gate_error(self): cirq.merge_single_qubit_gates_to_phxz_symbolized(circuit, sweep=sweep) -def test_merge_single_qubit_moments_to_phxz_with_global_phase_in_first_moment(): +def test_merge_single_qubit_moments_to_phxz_with_global_phase_in_first_moment() -> None: q0 = cirq.LineQubit(0) c_orig = cirq.Circuit( cirq.Moment(cirq.Y(q0) ** 0.5, cirq.GlobalPhaseGate(1j**0.5).on()), cirq.Moment(cirq.X(q0)) @@ -384,12 +384,12 @@ def test_merge_single_qubit_moments_to_phxz_with_global_phase_in_first_moment(): cirq.GlobalPhaseGate(1j**0.5).on(), ) ) - context = cirq.TransformerContext(tags_to_ignore=["ignore"]) + context = cirq.TransformerContext(tags_to_ignore=("ignore",)) c_new = cirq.merge_single_qubit_moments_to_phxz(c_orig, context=context) assert c_new == c_expected -def test_merge_single_qubit_moments_to_phxz_with_global_phase_in_second_moment(): +def test_merge_single_qubit_moments_to_phxz_with_global_phase_in_second_moment() -> None: q0 = cirq.LineQubit(0) c_orig = cirq.Circuit( cirq.Moment(cirq.Y(q0) ** 0.5), cirq.Moment(cirq.X(q0), cirq.GlobalPhaseGate(1j**0.5).on()) @@ -400,6 +400,6 @@ def test_merge_single_qubit_moments_to_phxz_with_global_phase_in_second_moment() cirq.GlobalPhaseGate(1j**0.5).on(), ) ) - context = cirq.TransformerContext(tags_to_ignore=["ignore"]) + context = cirq.TransformerContext(tags_to_ignore=("ignore",)) c_new = cirq.merge_single_qubit_moments_to_phxz(c_orig, context=context) assert c_new == c_expected diff --git a/cirq-core/cirq/transformers/noise_adding_test.py b/cirq-core/cirq/transformers/noise_adding_test.py index f50fbb3ecc0..774d46ac946 100644 --- a/cirq-core/cirq/transformers/noise_adding_test.py +++ b/cirq-core/cirq/transformers/noise_adding_test.py @@ -20,7 +20,7 @@ from cirq import circuits, devices, ops -def test_noise_adding(): +def test_noise_adding() -> None: qubits = devices.LineQubit.range(4) one_layer = circuits.Circuit(ops.CZ(*qubits[:2]), ops.CZ(*qubits[2:])) circuit = one_layer * 10 @@ -48,7 +48,7 @@ def test_noise_adding(): # test that supplying a dictionary for p works transformed_circuit_p_dict = na.DepolarizingNoiseTransformer( - {tuple(qubits[:2]): 1.0, tuple(qubits[2:]): 0.0} + {(qubits[0], qubits[1]): 1.0, (qubits[2], qubits[3]): 0.0} )(circuit) assert len(transformed_circuit_p_dict) == 20 # depth should be doubled assert transformed_circuit_p_dict[1::2].all_qubits() == frozenset( diff --git a/cirq-core/cirq/transformers/optimize_for_target_gateset_test.py b/cirq-core/cirq/transformers/optimize_for_target_gateset_test.py index 2cc515bedd9..db87b97e2d7 100644 --- a/cirq-core/cirq/transformers/optimize_for_target_gateset_test.py +++ b/cirq-core/cirq/transformers/optimize_for_target_gateset_test.py @@ -25,7 +25,7 @@ from cirq.protocols.decompose_protocol import DecomposeResult -def test_decompose_operations_raises_on_stuck(): +def test_decompose_operations_raises_on_stuck() -> None: c_orig = cirq.Circuit(cirq.X(cirq.NamedQubit("q")).with_tags("ignore")) gateset = cirq.Gateset(cirq.Y) with pytest.raises(ValueError, match="Unable to convert"): @@ -41,7 +41,7 @@ def test_decompose_operations_raises_on_stuck(): cirq.testing.assert_same_circuits(c_orig, c_new) -def test_decompose_operations_to_target_gateset_default(): +def test_decompose_operations_to_target_gateset_default() -> None: q = cirq.LineQubit.range(2) c_orig = cirq.Circuit( cirq.T(q[0]), @@ -77,7 +77,7 @@ def test_decompose_operations_to_target_gateset_default(): ) -def test_decompose_operations_to_target_gateset(): +def test_decompose_operations_to_target_gateset() -> None: q = cirq.LineQubit.range(2) c_orig = cirq.Circuit( cirq.T(q[0]), @@ -130,7 +130,7 @@ def decompose_to_target_gateset(self, op: cirq.Operation, _) -> DecomposeResult: return cirq.MatrixGate(cirq.unitary(op), name="M").on(*op.qubits) -def test_optimize_for_target_gateset_default(): +def test_optimize_for_target_gateset_default() -> None: q = cirq.LineQubit.range(2) c_orig = cirq.Circuit( cirq.T(q[0]), cirq.SWAP(*q), cirq.T(q[0]), cirq.SWAP(*q).with_tags("ignore") @@ -148,7 +148,7 @@ def test_optimize_for_target_gateset_default(): cirq.testing.assert_circuits_with_terminal_measurements_are_equivalent(c_orig, c_new, atol=1e-6) -def test_optimize_for_target_gateset(): +def test_optimize_for_target_gateset() -> None: q = cirq.LineQubit.range(4) c_orig = cirq.Circuit( cirq.QuantumFourierTransformGate(4).on(*q), @@ -201,7 +201,7 @@ def test_optimize_for_target_gateset(): ) -def test_optimize_for_target_gateset_deep(): +def test_optimize_for_target_gateset_deep() -> None: q0, q1 = cirq.LineQubit.range(2) c_nested = cirq.FrozenCircuit(cirq.CX(q0, q1)) c_orig = cirq.Circuit( @@ -209,10 +209,12 @@ def test_optimize_for_target_gateset_deep(): cirq.FrozenCircuit(cirq.H(q0), cirq.CircuitOperation(c_nested).repeat(3)) ).repeat(5) ) + phxz_from_h_unitary = cirq.single_qubit_matrix_to_phxz(cirq.unitary(cirq.H(q0))) + assert phxz_from_h_unitary is not None c_expected = cirq.Circuit( cirq.CircuitOperation( cirq.FrozenCircuit( - cirq.single_qubit_matrix_to_phxz(cirq.unitary(cirq.H(q0))).on(q0), + phxz_from_h_unitary.on(q0), cirq.CircuitOperation( cirq.FrozenCircuit( cirq.MatrixGate(c_nested.unitary(qubit_order=[q0, q1]), name="M").on(q0, q1) @@ -252,7 +254,7 @@ def test_optimize_for_target_gateset_deep(): @pytest.mark.parametrize('max_num_passes', [2, None]) -def test_optimize_for_target_gateset_multiple_passes(max_num_passes: int | None): +def test_optimize_for_target_gateset_multiple_passes(max_num_passes: int | None) -> None: gateset = cirq.CZTargetGateset() input_circuit = cirq.Circuit( @@ -332,7 +334,7 @@ def test_optimize_for_target_gateset_multiple_passes(max_num_passes: int | None) @pytest.mark.parametrize('max_num_passes', [2, None]) def test_optimize_for_target_gateset_multiple_passes_dont_preserve_moment_structure( max_num_passes: int | None, -): +) -> None: gateset = cirq.CZTargetGateset(preserve_moment_structure=False) input_circuit = cirq.Circuit( diff --git a/cirq-core/cirq/transformers/qubit_management_transformers_test.py b/cirq-core/cirq/transformers/qubit_management_transformers_test.py index fa948eb46e6..057c71cd136 100644 --- a/cirq-core/cirq/transformers/qubit_management_transformers_test.py +++ b/cirq-core/cirq/transformers/qubit_management_transformers_test.py @@ -14,6 +14,8 @@ from __future__ import annotations +from typing import Callable + import cirq @@ -57,8 +59,10 @@ def _decompose_with_context_(self, qubits, context): qm.qfree(qa + qb) -def get_decompose_func(gate_type, qm): - def decompose_func(op: cirq.Operation, _): +def get_decompose_func( + gate_type: type[cirq.Gate], qm: cirq.QubitManager +) -> Callable[[cirq.Operation, int], cirq.OP_TREE]: + def decompose_func(op: cirq.Operation, _: int) -> cirq.OP_TREE: return ( cirq.decompose_once(op, context=cirq.DecompositionContext(qm)) if isinstance(op.gate, gate_type) From 07e32205e100b572b9fcdcc8ea3916b589837c66 Mon Sep 17 00:00:00 2001 From: Pavol Juhas Date: Thu, 2 Oct 2025 15:43:35 -0700 Subject: [PATCH 2/7] Add no-op method `Operation.__pow__` to support typing Let mypy type check accept `cirq.Operation ** exponent`. --- cirq-core/cirq/ops/fourier_transform_test.py | 6 ++---- cirq-core/cirq/ops/raw_types.py | 3 +++ 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/cirq-core/cirq/ops/fourier_transform_test.py b/cirq-core/cirq/ops/fourier_transform_test.py index fd490197f2c..75066f96ba9 100644 --- a/cirq-core/cirq/ops/fourier_transform_test.py +++ b/cirq-core/cirq/ops/fourier_transform_test.py @@ -107,9 +107,7 @@ def test_qft() -> None: arr = np.array([[1, 1, 1, 1], [1, -1j, -1, 1j], [1, -1, 1, -1], [1, 1j, -1, -1j]]) / 2 np.testing.assert_allclose( - cirq.unitary(cirq.qft(*cirq.LineQubit.range(2)) ** -1), # type: ignore[operator] - arr, # type: ignore[arg-type] - atol=1e-8, + cirq.unitary(cirq.qft(*cirq.LineQubit.range(2)) ** -1), arr, atol=1e-8 ) for k in range(4): @@ -121,7 +119,7 @@ def test_qft() -> None: def test_inverse() -> None: a, b, c = cirq.LineQubit.range(3) - assert cirq.qft(a, b, c, inverse=True) == cirq.qft(a, b, c) ** -1 # type: ignore[operator] + assert cirq.qft(a, b, c, inverse=True) == cirq.qft(a, b, c) ** -1 assert cirq.qft(a, b, c, inverse=True, without_reverse=True) == cirq.inverse( cirq.qft(a, b, c, without_reverse=True) ) diff --git a/cirq-core/cirq/ops/raw_types.py b/cirq-core/cirq/ops/raw_types.py index 1043eb2f81f..4f5e49543b1 100644 --- a/cirq-core/cirq/ops/raw_types.py +++ b/cirq-core/cirq/ops/raw_types.py @@ -528,6 +528,9 @@ def _num_qubits_(self) -> int: def _qid_shape_(self) -> tuple[int, ...]: return protocols.qid_shape(self.qubits) + def __pow__(self, exponent: Any) -> Operation: + return NotImplemented + @abc.abstractmethod def with_qubits(self, *new_qubits: cirq.Qid) -> cirq.Operation: """Returns the same operation, but applied to different qubits. From eade55374b1f0796a38a37b153999e973c42cb2f Mon Sep 17 00:00:00 2001 From: Pavol Juhas Date: Tue, 16 Sep 2025 12:03:52 -0700 Subject: [PATCH 3/7] Replace list[Qid] --> Sequence[Qid] which is covariant --- .../clifford_decomposition.py | 16 +++++++------- .../controlled_gate_decomposition.py | 22 +++++++++---------- 2 files changed, 19 insertions(+), 19 deletions(-) diff --git a/cirq-core/cirq/transformers/analytical_decompositions/clifford_decomposition.py b/cirq-core/cirq/transformers/analytical_decompositions/clifford_decomposition.py index c27de1d7298..23199b23271 100644 --- a/cirq-core/cirq/transformers/analytical_decompositions/clifford_decomposition.py +++ b/cirq-core/cirq/transformers/analytical_decompositions/clifford_decomposition.py @@ -17,7 +17,7 @@ from __future__ import annotations import functools -from typing import TYPE_CHECKING +from typing import Sequence, TYPE_CHECKING import numpy as np @@ -31,7 +31,7 @@ def _X( q: int, args: sim.CliffordTableauSimulationState, operations: list[ops.Operation], - qubits: list[cirq.Qid], + qubits: Sequence[cirq.Qid], ): protocols.act_on(ops.X, args, qubits=[qubits[q]], allow_decompose=False) operations.append(ops.X(qubits[q])) @@ -41,7 +41,7 @@ def _Z( q: int, args: sim.CliffordTableauSimulationState, operations: list[ops.Operation], - qubits: list[cirq.Qid], + qubits: Sequence[cirq.Qid], ): protocols.act_on(ops.Z, args, qubits=[qubits[q]], allow_decompose=False) operations.append(ops.Z(qubits[q])) @@ -51,7 +51,7 @@ def _Sdg( q: int, args: sim.CliffordTableauSimulationState, operations: list[ops.Operation], - qubits: list[cirq.Qid], + qubits: Sequence[cirq.Qid], ): # Apply the tableau with S^\{dagger} protocols.act_on(ops.S**-1, args, qubits=[qubits[q]], allow_decompose=False) @@ -62,7 +62,7 @@ def _H( q: int, args: sim.CliffordTableauSimulationState, operations: list[ops.Operation], - qubits: list[cirq.Qid], + qubits: Sequence[cirq.Qid], ): protocols.act_on(ops.H, args, qubits=[qubits[q]], allow_decompose=False) operations.append(ops.H(qubits[q])) @@ -73,7 +73,7 @@ def _CNOT( q2: int, args: sim.CliffordTableauSimulationState, operations: list[ops.Operation], - qubits: list[cirq.Qid], + qubits: Sequence[cirq.Qid], ): protocols.act_on(ops.CNOT, args, qubits=[qubits[q1], qubits[q2]], allow_decompose=False) operations.append(ops.CNOT(qubits[q1], qubits[q2])) @@ -84,14 +84,14 @@ def _SWAP( q2: int, args: sim.CliffordTableauSimulationState, operations: list[ops.Operation], - qubits: list[cirq.Qid], + qubits: Sequence[cirq.Qid], ): protocols.act_on(ops.SWAP, args, qubits=[qubits[q1], qubits[q2]], allow_decompose=False) operations.append(ops.SWAP(qubits[q1], qubits[q2])) def decompose_clifford_tableau_to_operations( - qubits: list[cirq.Qid], clifford_tableau: qis.CliffordTableau + qubits: Sequence[cirq.Qid], clifford_tableau: qis.CliffordTableau ) -> list[ops.Operation]: """Decompose an n-qubit Clifford Tableau into a list of one/two qubit operations. diff --git a/cirq-core/cirq/transformers/analytical_decompositions/controlled_gate_decomposition.py b/cirq-core/cirq/transformers/analytical_decompositions/controlled_gate_decomposition.py index 560739dd34c..c5f9b1dc090 100644 --- a/cirq-core/cirq/transformers/analytical_decompositions/controlled_gate_decomposition.py +++ b/cirq-core/cirq/transformers/analytical_decompositions/controlled_gate_decomposition.py @@ -15,7 +15,7 @@ from __future__ import annotations import itertools -from typing import TYPE_CHECKING +from typing import Sequence, TYPE_CHECKING import numpy as np @@ -114,7 +114,7 @@ def _ccnot_congruent(c0: cirq.Qid, c1: cirq.Qid, target: cirq.Qid) -> list[cirq. def decompose_multi_controlled_x( - controls: list[cirq.Qid], target: cirq.Qid, free_qubits: list[cirq.Qid] + controls: Sequence[cirq.Qid], target: cirq.Qid, free_qubits: Sequence[cirq.Qid] ) -> list[cirq.Operation]: """Implements action of multi-controlled Pauli X gate. @@ -152,11 +152,11 @@ def decompose_multi_controlled_x( elif len(free_qubits) >= 1: # See [1], Lemma 7.3. m1 = n // 2 - free1 = controls[m1:] + [target] + free_qubits[1:] + free1 = [*controls[m1:], target, *free_qubits[1:]] ctrl1 = controls[:m1] part1 = decompose_multi_controlled_x(ctrl1, free_qubits[0], free1) - free2 = controls[:m1] + free_qubits[1:] - ctrl2 = controls[m1:] + [free_qubits[0]] + free2 = [*controls[:m1], *free_qubits[1:]] + ctrl2 = [*controls[m1:], free_qubits[0]] part2 = decompose_multi_controlled_x(ctrl2, target, free2) return [*part1, *part2, *part1, *part2] else: @@ -167,7 +167,7 @@ def decompose_multi_controlled_x( def _decompose_su( - matrix: np.ndarray, controls: list[cirq.Qid], target: cirq.Qid + matrix: np.ndarray, controls: Sequence[cirq.Qid], target: cirq.Qid ) -> list[cirq.Operation]: """Decomposes controlled special unitary gate into elementary gates. @@ -193,9 +193,9 @@ def _decompose_su( def _decompose_recursive( matrix: np.ndarray, power: float, - controls: list[cirq.Qid], + controls: Sequence[cirq.Qid], target: cirq.Qid, - free_qubits: list[cirq.Qid], + free_qubits: Sequence[cirq.Qid], ) -> list[cirq.Operation]: """Decomposes controlled unitary gate into elementary gates. @@ -205,20 +205,20 @@ def _decompose_recursive( if len(controls) == 1: return _decompose_single_ctrl(_unitary_power(matrix, power), controls[0], target) - cnots = decompose_multi_controlled_x(controls[:-1], controls[-1], free_qubits + [target]) + cnots = decompose_multi_controlled_x(controls[:-1], controls[-1], [*free_qubits, target]) return [ *_decompose_single_ctrl(_unitary_power(matrix, 0.5 * power), controls[-1], target), *cnots, *_decompose_single_ctrl(_unitary_power(matrix, -0.5 * power), controls[-1], target), *cnots, *_decompose_recursive( - matrix, 0.5 * power, controls[:-1], target, [controls[-1]] + free_qubits + matrix, 0.5 * power, controls[:-1], target, [controls[-1], *free_qubits] ), ] def decompose_multi_controlled_rotation( - matrix: np.ndarray, controls: list[cirq.Qid], target: cirq.Qid + matrix: np.ndarray, controls: Sequence[cirq.Qid], target: cirq.Qid ) -> list[cirq.Operation]: """Implements action of multi-controlled unitary gate. From cf6b01e3a69a467e03fbdf05f2972ada9ca1bd5a Mon Sep 17 00:00:00 2001 From: Pavol Juhas Date: Thu, 25 Sep 2025 15:28:43 -0700 Subject: [PATCH 4/7] Make KakDecomposition and FSimGate match the SupportsUnitary type --- cirq-core/cirq/linalg/decompositions.py | 3 +++ cirq-core/cirq/protocols/unitary_protocol.py | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/cirq-core/cirq/linalg/decompositions.py b/cirq-core/cirq/linalg/decompositions.py index 4a5f0d6e8fa..adf444bd70f 100644 --- a/cirq-core/cirq/linalg/decompositions.py +++ b/cirq-core/cirq/linalg/decompositions.py @@ -472,6 +472,9 @@ def __repr__(self) -> str: f' global_phase={self.global_phase!r})' ) + def _has_unitary_(self) -> bool: + return True + def _unitary_(self) -> np.ndarray: """Returns the decomposition's two-qubit unitary matrix. diff --git a/cirq-core/cirq/protocols/unitary_protocol.py b/cirq-core/cirq/protocols/unitary_protocol.py index 2e5a731b4ea..e7b241ff8f4 100644 --- a/cirq-core/cirq/protocols/unitary_protocol.py +++ b/cirq-core/cirq/protocols/unitary_protocol.py @@ -38,7 +38,7 @@ class SupportsUnitary(Protocol): """An object that may be describable by a unitary matrix.""" @doc_private - def _unitary_(self) -> np.ndarray | NotImplementedType: + def _unitary_(self) -> np.ndarray | NotImplementedType | None: """A unitary matrix describing this value, e.g. the matrix of a gate. This method is used by the global `cirq.unitary` method. If this method From 8ae9a4d03f176cde53474cd22323064ca1073632 Mon Sep 17 00:00:00 2001 From: Pavol Juhas Date: Thu, 25 Sep 2025 15:36:11 -0700 Subject: [PATCH 5/7] Loosen return type of the `_kraus_` method from Sequence to Iterable The value is converted to tuple in `protocols.kraus()` anyway. This makes PhaseDampingChannel match the SupportsKraus type. --- cirq-core/cirq/protocols/kraus_protocol.py | 6 +++--- cirq-core/cirq/protocols/kraus_protocol_test.py | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/cirq-core/cirq/protocols/kraus_protocol.py b/cirq-core/cirq/protocols/kraus_protocol.py index f6238debed8..e8daca186e8 100644 --- a/cirq-core/cirq/protocols/kraus_protocol.py +++ b/cirq-core/cirq/protocols/kraus_protocol.py @@ -18,7 +18,7 @@ import warnings from types import NotImplementedType -from typing import Any, Protocol, Sequence, TypeVar +from typing import Any, Iterable, Protocol, TypeVar import numpy as np @@ -31,7 +31,7 @@ # This is a special indicator value used by the channel method to determine # whether or not the caller provided a 'default' argument. It must be of type -# Sequence[np.ndarray] to ensure the method has the correct type signature in +# Iterable[np.ndarray] to ensure the method has the correct type signature in # that case. It is checked for using `is`, so it won't have a false positive # if the user provides a different (np.array([]),) value. RaiseTypeErrorIfNotProvided: tuple[np.ndarray] = (np.array([]),) @@ -44,7 +44,7 @@ class SupportsKraus(Protocol): """An object that may be describable as a quantum channel.""" @doc_private - def _kraus_(self) -> Sequence[np.ndarray] | NotImplementedType: + def _kraus_(self) -> Iterable[np.ndarray] | NotImplementedType: r"""A list of Kraus matrices describing the quantum channel. These matrices are the terms in the operator sum representation of a diff --git a/cirq-core/cirq/protocols/kraus_protocol_test.py b/cirq-core/cirq/protocols/kraus_protocol_test.py index cd1492cf00c..e7b794ede7e 100644 --- a/cirq-core/cirq/protocols/kraus_protocol_test.py +++ b/cirq-core/cirq/protocols/kraus_protocol_test.py @@ -16,7 +16,7 @@ from __future__ import annotations -from typing import Iterable, Sequence +from typing import Iterable import numpy as np import pytest @@ -89,7 +89,7 @@ def test_explicit_kraus() -> None: c = (a0, a1) class ReturnsKraus: - def _kraus_(self) -> Sequence[np.ndarray]: + def _kraus_(self) -> Iterable[np.ndarray]: return c assert cirq.kraus(ReturnsKraus()) is c From efb0cd9bc825523cd78d927a0a81bed9af7df221 Mon Sep 17 00:00:00 2001 From: Pavol Juhas Date: Thu, 2 Oct 2025 16:43:42 -0700 Subject: [PATCH 6/7] Fix argument to `_is_swaplike` which needs to be of Gate type --- cirq-core/cirq/transformers/eject_z.py | 4 ++-- cirq-core/cirq/transformers/eject_z_test.py | 5 ++--- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/cirq-core/cirq/transformers/eject_z.py b/cirq-core/cirq/transformers/eject_z.py index 03bb02dd790..6d7426bda60 100644 --- a/cirq-core/cirq/transformers/eject_z.py +++ b/cirq-core/cirq/transformers/eject_z.py @@ -29,11 +29,11 @@ import cirq -def _is_integer(n): +def _is_integer(n) -> bool: return np.isclose(n, np.round(n)) -def _is_swaplike(gate: cirq.Gate): +def _is_swaplike(gate: cirq.Gate) -> bool: if isinstance(gate, ops.SwapPowGate): return gate.exponent == 1 diff --git a/cirq-core/cirq/transformers/eject_z_test.py b/cirq-core/cirq/transformers/eject_z_test.py index b77c47b69b3..9da2d3c250e 100644 --- a/cirq-core/cirq/transformers/eject_z_test.py +++ b/cirq-core/cirq/transformers/eject_z_test.py @@ -341,9 +341,8 @@ def test_swap() -> None: @pytest.mark.parametrize('exponent', (0, 2, 1.1, -2, -1.6)) -def test_not_a_swap(exponent) -> None: - a, b = cirq.LineQubit.range(2) - assert not _is_swaplike(cirq.SWAP(a, b) ** exponent) +def test_not_a_swap(exponent: float) -> None: + assert not _is_swaplike(cirq.SWAP**exponent) @pytest.mark.parametrize('theta', (np.pi / 2, -np.pi / 2, np.pi / 2 + 5 * np.pi)) From 014a7b38d32d3a9f6d101431b7fa21ea2faf0546 Mon Sep 17 00:00:00 2001 From: Pavol Juhas Date: Thu, 2 Oct 2025 17:35:54 -0700 Subject: [PATCH 7/7] Cover uncovered lines --- cirq-core/cirq/linalg/decompositions_test.py | 1 + cirq-core/cirq/ops/raw_types.py | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/cirq-core/cirq/linalg/decompositions_test.py b/cirq-core/cirq/linalg/decompositions_test.py index 9259ee5d0af..d7d268c57ef 100644 --- a/cirq-core/cirq/linalg/decompositions_test.py +++ b/cirq-core/cirq/linalg/decompositions_test.py @@ -259,6 +259,7 @@ def test_kak_plot_empty() -> None: ) def test_kak_decomposition(target) -> None: kak = cirq.kak_decomposition(target) + assert cirq.has_unitary(kak) np.testing.assert_allclose(cirq.unitary(kak), target, atol=1e-8) diff --git a/cirq-core/cirq/ops/raw_types.py b/cirq-core/cirq/ops/raw_types.py index 4f5e49543b1..86b147ef56f 100644 --- a/cirq-core/cirq/ops/raw_types.py +++ b/cirq-core/cirq/ops/raw_types.py @@ -529,7 +529,7 @@ def _qid_shape_(self) -> tuple[int, ...]: return protocols.qid_shape(self.qubits) def __pow__(self, exponent: Any) -> Operation: - return NotImplemented + return NotImplemented # pragma: no cover @abc.abstractmethod def with_qubits(self, *new_qubits: cirq.Qid) -> cirq.Operation: