diff --git a/cirq-core/cirq/__init__.py b/cirq-core/cirq/__init__.py index 31e2b4745213..03d5f22433ee 100644 --- a/cirq-core/cirq/__init__.py +++ b/cirq-core/cirq/__init__.py @@ -403,6 +403,7 @@ transformer, two_qubit_matrix_to_cz_operations, two_qubit_matrix_to_diagonal_and_cz_operations, + two_qubit_matrix_to_ion_operations, two_qubit_matrix_to_sqrt_iswap_operations, two_qubit_gate_product_tabulation, TwoQubitCompilationTargetGateset, @@ -669,7 +670,7 @@ with_rescoped_keys, ) -from cirq.ion import ConvertToIonGates, IonDevice, two_qubit_matrix_to_ion_operations +from cirq.ion import ConvertToIonGates, IonDevice from cirq.neutral_atoms import ( ConvertToNeutralAtomGates, is_native_neutral_atom_gate, diff --git a/cirq-core/cirq/ion/__init__.py b/cirq-core/cirq/ion/__init__.py index 39e604a16fd5..51b832bc55b8 100644 --- a/cirq-core/cirq/ion/__init__.py +++ b/cirq-core/cirq/ion/__init__.py @@ -16,13 +16,7 @@ from cirq.ops import ms -from cirq.ion.ion_decomposition import two_qubit_matrix_to_ion_operations - -from cirq.ion.ion_device import IonDevice - -from cirq.ion.convert_to_ion_gates import ConvertToIonGates - -from cirq.ion.ion_decomposition import two_qubit_matrix_to_ion_operations +from cirq.transformers import two_qubit_matrix_to_ion_operations from cirq.ion.ion_device import IonDevice diff --git a/cirq-core/cirq/transformers/__init__.py b/cirq-core/cirq/transformers/__init__.py index a1bc125ac3f4..ef820d308440 100644 --- a/cirq-core/cirq/transformers/__init__.py +++ b/cirq-core/cirq/transformers/__init__.py @@ -33,6 +33,7 @@ three_qubit_matrix_to_operations, two_qubit_matrix_to_cz_operations, two_qubit_matrix_to_diagonal_and_cz_operations, + two_qubit_matrix_to_ion_operations, two_qubit_matrix_to_sqrt_iswap_operations, ) diff --git a/cirq-core/cirq/transformers/analytical_decompositions/__init__.py b/cirq-core/cirq/transformers/analytical_decompositions/__init__.py index 3107967d903d..41edc64c1ffa 100644 --- a/cirq-core/cirq/transformers/analytical_decompositions/__init__.py +++ b/cirq-core/cirq/transformers/analytical_decompositions/__init__.py @@ -50,6 +50,10 @@ decompose_two_qubit_interaction_into_four_fsim_gates, ) +from cirq.transformers.analytical_decompositions.two_qubit_to_ms import ( + two_qubit_matrix_to_ion_operations, +) + from cirq.transformers.analytical_decompositions.two_qubit_to_sqrt_iswap import ( parameterized_2q_op_to_sqrt_iswap_operations, two_qubit_matrix_to_sqrt_iswap_operations, diff --git a/cirq-core/cirq/ion/ion_decomposition.py b/cirq-core/cirq/transformers/analytical_decompositions/two_qubit_to_ms.py similarity index 74% rename from cirq-core/cirq/ion/ion_decomposition.py rename to cirq-core/cirq/transformers/analytical_decompositions/two_qubit_to_ms.py index 49a2fdc23b97..3cacff0baae4 100644 --- a/cirq-core/cirq/ion/ion_decomposition.py +++ b/cirq-core/cirq/transformers/analytical_decompositions/two_qubit_to_ms.py @@ -23,15 +23,22 @@ import numpy as np -from cirq import ops, linalg, protocols, circuits, transformers -from cirq.ion import ms +from cirq import ops, linalg, protocols, circuits +from cirq.transformers.analytical_decompositions import single_qubit_decompositions +from cirq.transformers.merge_single_qubit_gates import merge_single_qubit_gates_to_phased_x_and_z +from cirq.transformers.eject_z import eject_z +from cirq.transformers.eject_phased_paulis import eject_phased_paulis if TYPE_CHECKING: import cirq def two_qubit_matrix_to_ion_operations( - q0: 'cirq.Qid', q1: 'cirq.Qid', mat: np.ndarray, atol: float = 1e-8 + q0: 'cirq.Qid', + q1: 'cirq.Qid', + mat: np.ndarray, + atol: float = 1e-8, + clean_operations: bool = True, ) -> List[ops.Operation]: """Decomposes a two-qubit operation into MS/single-qubit rotation gates. @@ -39,22 +46,23 @@ def two_qubit_matrix_to_ion_operations( q0: The first qubit being operated on. q1: The other qubit being operated on. mat: Defines the operation to apply to the pair of qubits. - atol: A limit on the amount of error introduced by the - construction. + atol: A limit on the amount of error introduced by the construction. + clean_operations: Enables optimizing resulting operation list by + merging operations and ejecting phased Paulis and Z operations. Returns: A list of operations implementing the matrix. """ kak = linalg.kak_decomposition(mat, atol=atol) operations = _kak_decomposition_to_operations(q0, q1, kak, atol) - return _cleanup_operations(operations) + return _cleanup_operations(operations) if clean_operations else operations -def _cleanup_operations(operations: List[ops.Operation]): +def _cleanup_operations(operations: List[ops.Operation]) -> List['cirq.Operation']: circuit = circuits.Circuit(operations) - circuit = transformers.merge_single_qubit_gates_to_phased_x_and_z(circuit) - circuit = transformers.eject_phased_paulis(circuit) - circuit = transformers.eject_z(circuit) + circuit = merge_single_qubit_gates_to_phased_x_and_z(circuit) + circuit = eject_phased_paulis(circuit) + circuit = eject_z(circuit) circuit = circuits.Circuit(circuit.all_operations(), strategy=circuits.InsertStrategy.EARLIEST) return list(circuit.all_operations()) @@ -79,7 +87,7 @@ def _kak_decomposition_to_operations( def _do_single_on(u: np.ndarray, q: 'cirq.Qid', atol: float = 1e-8): - for gate in transformers.single_qubit_matrix_to_gates(u, atol): + for gate in single_qubit_decompositions.single_qubit_matrix_to_gates(u, atol): yield gate(q) @@ -95,7 +103,7 @@ def _parity_interaction( g = cast(ops.Gate, gate) yield g.on(q0), g.on(q1) - yield ms(-1 * rads).on(q0, q1) + yield ops.ms(-1 * rads).on(q0, q1) if gate is not None: g = protocols.inverse(gate) diff --git a/cirq-core/cirq/ion/ion_decomposition_test.py b/cirq-core/cirq/transformers/analytical_decompositions/two_qubit_to_ms_test.py similarity index 85% rename from cirq-core/cirq/ion/ion_decomposition_test.py rename to cirq-core/cirq/transformers/analytical_decompositions/two_qubit_to_ms_test.py index 760e4e89323e..02d56fabfc64 100644 --- a/cirq-core/cirq/ion/ion_decomposition_test.py +++ b/cirq-core/cirq/transformers/analytical_decompositions/two_qubit_to_ms_test.py @@ -1,4 +1,17 @@ -# pylint: disable=wrong-or-nonexistent-copyright-notice +# Copyright 2018 The Cirq Developers +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + import random import numpy as np