From 4db207e979e88c99a196e9732237f9bcc21bcdd8 Mon Sep 17 00:00:00 2001 From: Tanuj Khattar Date: Thu, 6 Jan 2022 04:53:05 +0530 Subject: [PATCH] Move `optimizers/decompositions.py` to `transformers/analytical_decompositions/single_qubit_decompositions.py` (#4799) Moves the following file from `cirq/optimizers/` to `cirq/transformers/analytical_decompositions/` using `deprecated_submodule`: - decompositions.py --> single_qubit_decompositions.py Part of #4722 --- cirq-core/cirq/__init__.py | 12 ++++++------ .../paulistring/convert_to_clifford_gates.py | 4 ++-- .../convert_to_pauli_string_phasors.py | 4 ++-- cirq-core/cirq/ion/convert_to_ion_gates.py | 4 ++-- cirq-core/cirq/ion/ion_decomposition.py | 4 ++-- .../convert_to_neutral_atom_gates.py | 4 ++-- cirq-core/cirq/optimizers/__init__.py | 17 ++++++++--------- .../cirq/optimizers/eject_phased_paulis.py | 8 +++++--- cirq-core/cirq/optimizers/eject_z.py | 9 +++++---- .../cirq/optimizers/merge_single_qubit_gates.py | 6 +++--- .../cirq/optimizers/two_qubit_decompositions.py | 4 ++-- .../cirq/optimizers/two_qubit_to_sqrt_iswap.py | 6 +++--- cirq-core/cirq/transformers/__init__.py | 6 ++++++ .../analytical_decompositions/__init__.py | 9 +++++++++ .../single_qubit_decompositions.py} | 0 .../single_qubit_decompositions_test.py} | 10 ++++++++++ .../two_qubit_state_preparation.py | 6 ++++-- 17 files changed, 71 insertions(+), 42 deletions(-) rename cirq-core/cirq/{optimizers/decompositions.py => transformers/analytical_decompositions/single_qubit_decompositions.py} (100%) rename cirq-core/cirq/{optimizers/decompositions_test.py => transformers/analytical_decompositions/single_qubit_decompositions_test.py} (97%) diff --git a/cirq-core/cirq/__init__.py b/cirq-core/cirq/__init__.py index 3b09a3f152a..9174b267a0f 100644 --- a/cirq-core/cirq/__init__.py +++ b/cirq-core/cirq/__init__.py @@ -335,17 +335,11 @@ EjectPhasedPaulis, EjectZ, ExpandComposite, - is_negligible_turn, merge_single_qubit_gates_into_phased_x_z, merge_single_qubit_gates_into_phxz, MergeInteractions, MergeInteractionsToSqrtIswap, MergeSingleQubitGates, - single_qubit_matrix_to_gates, - single_qubit_matrix_to_pauli_rotations, - single_qubit_matrix_to_phased_x_z, - single_qubit_matrix_to_phxz, - single_qubit_op_to_framed_phase_form, stratified_circuit, SynchronizeTerminalMeasurements, two_qubit_matrix_to_operations, @@ -360,6 +354,7 @@ decompose_cphase_into_two_fsim, decompose_multi_controlled_x, decompose_multi_controlled_rotation, + is_negligible_turn, map_moments, map_operations, map_operations_and_unroll, @@ -367,6 +362,11 @@ merge_operations, prepare_two_qubit_state_using_cz, prepare_two_qubit_state_using_sqrt_iswap, + single_qubit_matrix_to_gates, + single_qubit_matrix_to_pauli_rotations, + single_qubit_matrix_to_phased_x_z, + single_qubit_matrix_to_phxz, + single_qubit_op_to_framed_phase_form, unroll_circuit_op, unroll_circuit_op_greedy_earliest, unroll_circuit_op_greedy_frontier, diff --git a/cirq-core/cirq/contrib/paulistring/convert_to_clifford_gates.py b/cirq-core/cirq/contrib/paulistring/convert_to_clifford_gates.py index a3a9f181390..fb8dffcb458 100644 --- a/cirq-core/cirq/contrib/paulistring/convert_to_clifford_gates.py +++ b/cirq-core/cirq/contrib/paulistring/convert_to_clifford_gates.py @@ -16,7 +16,7 @@ import numpy as np -from cirq import ops, protocols, optimizers, linalg +from cirq import ops, protocols, transformers, linalg from cirq.circuits.circuit import Circuit from cirq.circuits.optimization_pass import ( PointOptimizationSummary, @@ -67,7 +67,7 @@ def _rotation_to_clifford_gate( return ops.SingleQubitCliffordGate.I def _matrix_to_clifford_op(self, mat: np.ndarray, qubit: 'cirq.Qid') -> Optional[ops.Operation]: - rotations = optimizers.single_qubit_matrix_to_pauli_rotations(mat, self.atol) + rotations = transformers.single_qubit_matrix_to_pauli_rotations(mat, self.atol) clifford_gate = ops.SingleQubitCliffordGate.I for pauli, half_turns in rotations: if linalg.all_near_zero_mod(half_turns, 0.5): diff --git a/cirq-core/cirq/contrib/paulistring/convert_to_pauli_string_phasors.py b/cirq-core/cirq/contrib/paulistring/convert_to_pauli_string_phasors.py index 016b7fc7888..dccb038838a 100644 --- a/cirq-core/cirq/contrib/paulistring/convert_to_pauli_string_phasors.py +++ b/cirq-core/cirq/contrib/paulistring/convert_to_pauli_string_phasors.py @@ -16,7 +16,7 @@ import numpy as np -from cirq import ops, optimizers, protocols, linalg +from cirq import ops, protocols, linalg, transformers from cirq.circuits.circuit import Circuit from cirq.circuits.optimization_pass import ( PointOptimizationSummary, @@ -56,7 +56,7 @@ def __init__( self.atol = atol def _matrix_to_pauli_string_phasors(self, mat: np.ndarray, qubit: 'cirq.Qid') -> ops.OP_TREE: - rotations = optimizers.single_qubit_matrix_to_pauli_rotations(mat, self.atol) + rotations = transformers.single_qubit_matrix_to_pauli_rotations(mat, self.atol) out_ops: List[ops.Operation] = [] for pauli, half_turns in rotations: if self.keep_clifford and linalg.all_near_zero_mod(half_turns, 0.5): diff --git a/cirq-core/cirq/ion/convert_to_ion_gates.py b/cirq-core/cirq/ion/convert_to_ion_gates.py index f3e5708337d..b4e47d32ffa 100644 --- a/cirq-core/cirq/ion/convert_to_ion_gates.py +++ b/cirq-core/cirq/ion/convert_to_ion_gates.py @@ -14,7 +14,7 @@ import numpy as np -from cirq import ops, protocols, optimizers, circuits +from cirq import ops, protocols, optimizers, circuits, transformers from cirq.ion import ms, two_qubit_matrix_to_ion_operations, ion_device @@ -66,7 +66,7 @@ def convert_one(self, op: ops.Operation) -> ops.OP_TREE: # Known matrix mat = protocols.unitary(op, None) if len(op.qubits) <= 2 else None if mat is not None and len(op.qubits) == 1: - gates = optimizers.single_qubit_matrix_to_phased_x_z(mat) + gates = transformers.single_qubit_matrix_to_phased_x_z(mat) return [g.on(op.qubits[0]) for g in gates] if mat is not None and len(op.qubits) == 2: return two_qubit_matrix_to_ion_operations(op.qubits[0], op.qubits[1], mat) diff --git a/cirq-core/cirq/ion/ion_decomposition.py b/cirq-core/cirq/ion/ion_decomposition.py index dd16999728f..0dfeda160b3 100644 --- a/cirq-core/cirq/ion/ion_decomposition.py +++ b/cirq-core/cirq/ion/ion_decomposition.py @@ -23,7 +23,7 @@ import numpy as np -from cirq import ops, linalg, protocols, optimizers, circuits +from cirq import ops, linalg, protocols, optimizers, circuits, transformers from cirq.ion import ms if TYPE_CHECKING: @@ -83,7 +83,7 @@ def _kak_decomposition_to_operations( def _do_single_on(u: np.ndarray, q: 'cirq.Qid', atol: float = 1e-8): - for gate in optimizers.single_qubit_matrix_to_gates(u, atol): + for gate in transformers.single_qubit_matrix_to_gates(u, atol): yield gate(q) diff --git a/cirq-core/cirq/neutral_atoms/convert_to_neutral_atom_gates.py b/cirq-core/cirq/neutral_atoms/convert_to_neutral_atom_gates.py index 36a8c368ce6..b1c61e28890 100644 --- a/cirq-core/cirq/neutral_atoms/convert_to_neutral_atom_gates.py +++ b/cirq-core/cirq/neutral_atoms/convert_to_neutral_atom_gates.py @@ -19,7 +19,7 @@ PointOptimizer, ) from cirq.neutral_atoms import neutral_atom_devices -from cirq import optimizers +from cirq import optimizers, transformers if TYPE_CHECKING: import cirq @@ -57,7 +57,7 @@ def _convert_one(self, op: ops.Operation) -> ops.OP_TREE: # Known matrix? mat = protocols.unitary(op, None) if len(op.qubits) <= 2 else None if mat is not None and len(op.qubits) == 1: - gates = optimizers.single_qubit_matrix_to_phased_x_z(mat) + gates = transformers.single_qubit_matrix_to_phased_x_z(mat) return [g.on(op.qubits[0]) for g in gates] if mat is not None and len(op.qubits) == 2: return optimizers.two_qubit_matrix_to_operations( diff --git a/cirq-core/cirq/optimizers/__init__.py b/cirq-core/cirq/optimizers/__init__.py index 7c1c9bacf87..23d7b9beed8 100644 --- a/cirq-core/cirq/optimizers/__init__.py +++ b/cirq-core/cirq/optimizers/__init__.py @@ -60,15 +60,6 @@ MergeSingleQubitGates, ) -from cirq.optimizers.decompositions import ( - is_negligible_turn, - single_qubit_matrix_to_gates, - single_qubit_matrix_to_pauli_rotations, - single_qubit_matrix_to_phased_x_z, - single_qubit_matrix_to_phxz, - single_qubit_op_to_framed_phase_form, -) - from cirq.optimizers.stratify import ( stratified_circuit, ) @@ -119,3 +110,11 @@ deadline="v0.16", create_attribute=True, ) + +_compat.deprecated_submodule( + new_module_name="cirq.transformers.analytical_decompositions.single_qubit_decompositions", + old_parent="cirq.optimizers", + old_child="decompositions", + deadline="v0.16", + create_attribute=True, +) diff --git a/cirq-core/cirq/optimizers/eject_phased_paulis.py b/cirq-core/cirq/optimizers/eject_phased_paulis.py index 8dbbd1f847c..c6c84ee8587 100644 --- a/cirq-core/cirq/optimizers/eject_phased_paulis.py +++ b/cirq-core/cirq/optimizers/eject_phased_paulis.py @@ -19,7 +19,7 @@ import sympy from cirq import circuits, ops, value, protocols -from cirq.optimizers import decompositions +from cirq.transformers.analytical_decompositions import single_qubit_decompositions if TYPE_CHECKING: import cirq @@ -69,7 +69,9 @@ def optimize_circuit(self, circuit: circuits.Circuit): # Collect, phase, and merge Ws. w = _try_get_known_phased_pauli(op, no_symbolic=not self.eject_parameterized) if w is not None: - if decompositions.is_negligible_turn((w[0] - 1) / 2, self.tolerance): + if single_qubit_decompositions.is_negligible_turn( + (w[0] - 1) / 2, self.tolerance + ): _potential_cross_whole_w(moment_index, op, self.tolerance, state) else: _potential_cross_partial_w(moment_index, op, state) @@ -180,7 +182,7 @@ def _potential_cross_whole_w( # Cancel the gate. del state.held_w_phases[q] t = 2 * (b - a) - if not decompositions.is_negligible_turn(t / 2, tolerance): + if not single_qubit_decompositions.is_negligible_turn(t / 2, tolerance): leftover_phase = ops.Z(q) ** t state.inline_intos.append((moment_index, leftover_phase)) diff --git a/cirq-core/cirq/optimizers/eject_z.py b/cirq-core/cirq/optimizers/eject_z.py index 782686df82e..c0e57cfeec9 100644 --- a/cirq-core/cirq/optimizers/eject_z.py +++ b/cirq-core/cirq/optimizers/eject_z.py @@ -20,7 +20,7 @@ import sympy from cirq import circuits, ops, protocols -from cirq.optimizers import decompositions +from cirq.transformers.analytical_decompositions import single_qubit_decompositions def _is_integer(n): @@ -74,7 +74,7 @@ def dump_tracked_phase(qubits: Iterable[ops.Qid], index: int) -> None: for q in qubits: p = qubit_phase[q] qubit_phase[q] = 0 - if decompositions.is_negligible_turn(p, self.tolerance): + if single_qubit_decompositions.is_negligible_turn(p, self.tolerance): continue dumped = False moment_index = circuit.prev_moment_operating_on([q], index) @@ -111,7 +111,8 @@ def dump_tracked_phase(qubits: Iterable[ops.Qid], index: int) -> None: # If there's no tracked phase, we can move on. phases = [qubit_phase[q] for q in op.qubits] if not isinstance(op.gate, ops.PhasedXZGate) and all( - decompositions.is_negligible_turn(p, self.tolerance) for p in phases + single_qubit_decompositions.is_negligible_turn(p, self.tolerance) + for p in phases ): continue @@ -123,7 +124,7 @@ def dump_tracked_phase(qubits: Iterable[ops.Qid], index: int) -> None: # Try to move the tracked phasing over the operation. phased_op = op for i, p in enumerate(phases): - if not decompositions.is_negligible_turn(p, self.tolerance): + if not single_qubit_decompositions.is_negligible_turn(p, self.tolerance): phased_op = protocols.phase_by(phased_op, -p, i, default=None) if phased_op is not None: gate = phased_op.gate diff --git a/cirq-core/cirq/optimizers/merge_single_qubit_gates.py b/cirq-core/cirq/optimizers/merge_single_qubit_gates.py index c5ec4c27da6..2e168551ec2 100644 --- a/cirq-core/cirq/optimizers/merge_single_qubit_gates.py +++ b/cirq-core/cirq/optimizers/merge_single_qubit_gates.py @@ -19,7 +19,7 @@ import numpy as np from cirq import ops, linalg, protocols, circuits -from cirq.optimizers import decompositions +from cirq.transformers.analytical_decompositions import single_qubit_decompositions if TYPE_CHECKING: import cirq @@ -115,7 +115,7 @@ def merge_single_qubit_gates_into_phased_x_z(circuit: circuits.Circuit, atol: fl """ def synth(qubit: 'cirq.Qid', matrix: np.ndarray) -> List[ops.Operation]: - out_gates = decompositions.single_qubit_matrix_to_phased_x_z(matrix, atol) + out_gates = single_qubit_decompositions.single_qubit_matrix_to_phased_x_z(matrix, atol) return [gate(qubit) for gate in out_gates] MergeSingleQubitGates(synthesizer=synth).optimize_circuit(circuit) @@ -137,7 +137,7 @@ def merge_single_qubit_gates_into_phxz( """ def synth(qubit: 'cirq.Qid', matrix: np.ndarray) -> List[ops.Operation]: - gate = decompositions.single_qubit_matrix_to_phxz(matrix, atol) + gate = single_qubit_decompositions.single_qubit_matrix_to_phxz(matrix, atol) return [gate(qubit)] if gate else [] MergeSingleQubitGates(synthesizer=synth).optimize_circuit(circuit) diff --git a/cirq-core/cirq/optimizers/two_qubit_decompositions.py b/cirq-core/cirq/optimizers/two_qubit_decompositions.py index 9f65bf4c86c..b9c64aa223e 100644 --- a/cirq-core/cirq/optimizers/two_qubit_decompositions.py +++ b/cirq-core/cirq/optimizers/two_qubit_decompositions.py @@ -22,8 +22,8 @@ from cirq.linalg.decompositions import num_cnots_required, extract_right_diag from cirq import ops, linalg, protocols, circuits +from cirq.transformers.analytical_decompositions import single_qubit_decompositions from cirq.optimizers import ( - decompositions, eject_z, eject_phased_paulis, merge_single_qubit_gates, @@ -236,7 +236,7 @@ def _parity_interaction( def _do_single_on(u: np.ndarray, q: 'cirq.Qid', atol: float = 1e-8): - for gate in decompositions.single_qubit_matrix_to_gates(u, atol): + for gate in single_qubit_decompositions.single_qubit_matrix_to_gates(u, atol): yield gate(q) diff --git a/cirq-core/cirq/optimizers/two_qubit_to_sqrt_iswap.py b/cirq-core/cirq/optimizers/two_qubit_to_sqrt_iswap.py index 3a778656957..d4be61459c3 100644 --- a/cirq-core/cirq/optimizers/two_qubit_to_sqrt_iswap.py +++ b/cirq-core/cirq/optimizers/two_qubit_to_sqrt_iswap.py @@ -12,7 +12,7 @@ import numpy as np from cirq import ops, linalg, protocols -from cirq.optimizers import decompositions +from cirq.transformers.analytical_decompositions import single_qubit_decompositions if TYPE_CHECKING: import cirq @@ -144,7 +144,7 @@ def append(matrix0, matrix1, final_layer=False): nonlocal prev_commute # Commute previous Z(q0)**a, Z(q1)**a through earlier sqrt-iSWAP rots1 = list( - decompositions.single_qubit_matrix_to_pauli_rotations( + single_qubit_decompositions.single_qubit_matrix_to_pauli_rotations( np.dot(matrix1, prev_commute), atol=atol ) ) @@ -163,7 +163,7 @@ def append(matrix0, matrix1, final_layer=False): new_commute = new_commute @ p_unitary matrix0 = p_unitary.T.conj() @ matrix0 rots0 = list( - decompositions.single_qubit_matrix_to_pauli_rotations( + single_qubit_decompositions.single_qubit_matrix_to_pauli_rotations( np.dot(matrix0, prev_commute), atol=atol ) ) diff --git a/cirq-core/cirq/transformers/__init__.py b/cirq-core/cirq/transformers/__init__.py index d818e53a000..e92ae3c181d 100644 --- a/cirq-core/cirq/transformers/__init__.py +++ b/cirq-core/cirq/transformers/__init__.py @@ -20,8 +20,14 @@ decompose_clifford_tableau_to_operations, decompose_multi_controlled_x, decompose_multi_controlled_rotation, + is_negligible_turn, prepare_two_qubit_state_using_cz, prepare_two_qubit_state_using_sqrt_iswap, + single_qubit_matrix_to_gates, + single_qubit_matrix_to_pauli_rotations, + single_qubit_matrix_to_phased_x_z, + single_qubit_matrix_to_phxz, + single_qubit_op_to_framed_phase_form, ) from cirq.transformers.transformer_primitives import ( diff --git a/cirq-core/cirq/transformers/analytical_decompositions/__init__.py b/cirq-core/cirq/transformers/analytical_decompositions/__init__.py index c8e0e456bbd..10536dea0ea 100644 --- a/cirq-core/cirq/transformers/analytical_decompositions/__init__.py +++ b/cirq-core/cirq/transformers/analytical_decompositions/__init__.py @@ -28,6 +28,15 @@ decompose_cphase_into_two_fsim, ) +from cirq.transformers.analytical_decompositions.single_qubit_decompositions import ( + is_negligible_turn, + single_qubit_matrix_to_gates, + single_qubit_matrix_to_pauli_rotations, + single_qubit_matrix_to_phased_x_z, + single_qubit_matrix_to_phxz, + single_qubit_op_to_framed_phase_form, +) + from cirq.transformers.analytical_decompositions.two_qubit_state_preparation import ( prepare_two_qubit_state_using_cz, prepare_two_qubit_state_using_sqrt_iswap, diff --git a/cirq-core/cirq/optimizers/decompositions.py b/cirq-core/cirq/transformers/analytical_decompositions/single_qubit_decompositions.py similarity index 100% rename from cirq-core/cirq/optimizers/decompositions.py rename to cirq-core/cirq/transformers/analytical_decompositions/single_qubit_decompositions.py diff --git a/cirq-core/cirq/optimizers/decompositions_test.py b/cirq-core/cirq/transformers/analytical_decompositions/single_qubit_decompositions_test.py similarity index 97% rename from cirq-core/cirq/optimizers/decompositions_test.py rename to cirq-core/cirq/transformers/analytical_decompositions/single_qubit_decompositions_test.py index 5f0c62e272d..5f15a6b87af 100644 --- a/cirq-core/cirq/optimizers/decompositions_test.py +++ b/cirq-core/cirq/transformers/analytical_decompositions/single_qubit_decompositions_test.py @@ -21,6 +21,16 @@ import cirq +ALLOW_DEPRECATION_IN_TEST = 'ALLOW_DEPRECATION_IN_TEST' + + +def test_deprecated_submodule(): + with cirq.testing.assert_deprecated( + "Use cirq.transformers.analytical_decompositions.single_qubit_decompositions instead", + deadline="v0.16", + ): + _ = cirq.optimizers.decompositions.single_qubit_matrix_to_phxz + def assert_gates_implement_unitary( gates: Sequence[cirq.SingleQubitGate], intended_effect: np.ndarray, atol: float diff --git a/cirq-core/cirq/transformers/analytical_decompositions/two_qubit_state_preparation.py b/cirq-core/cirq/transformers/analytical_decompositions/two_qubit_state_preparation.py index 48ccde9068c..3e3ded680e8 100644 --- a/cirq-core/cirq/transformers/analytical_decompositions/two_qubit_state_preparation.py +++ b/cirq-core/cirq/transformers/analytical_decompositions/two_qubit_state_preparation.py @@ -18,7 +18,7 @@ import numpy as np from cirq import ops, qis, circuits -from cirq.optimizers import decompositions +from cirq.transformers.analytical_decompositions import single_qubit_decompositions if TYPE_CHECKING: import cirq @@ -26,7 +26,9 @@ def _1q_matrices_to_ops(g0, g1, q0, q1, include_identity=False): ret = [] - for g, q in zip(map(decompositions.single_qubit_matrix_to_phxz, [g0, g1]), [q0, q1]): + for g, q in zip( + map(single_qubit_decompositions.single_qubit_matrix_to_phxz, [g0, g1]), [q0, q1] + ): if g is not None: ret.append(g.on(q)) elif include_identity: