From 1c20b8420481eb350a22e54403269980d0a60214 Mon Sep 17 00:00:00 2001 From: Shelly Garion <46566946+ShellyGarion@users.noreply.github.com> Date: Thu, 25 Jan 2024 14:30:14 +0200 Subject: [PATCH] Remove qiskit.transpiler.synthesis for Qiskit 1.0 release (#11570) * deprecate transpiler/synthesis/graysynth.py * style * style * move aqc_plugin to qiskit/transpiler/passes/synthesis * remove code from qiskit/transpiler/synthesis/aqc/aqc_plugin.py * copy qiskit/transpiler/synthesis/aqc to qiskit/synthesis/unitary * move tests from test/python/transpiler/aqc to test/python/synthesis/aqc * update imports in aqc_plugin * add deprecation warning to AQC module * handle cyclic imports * handle cyclic imports * update link in docs * update init in qiskit/transpiler/synthesis/aqc * style * temporary remove deprecation warning test * remove files from qiskit/transpiler/synthesis/aqc * update link in test * add release notes * update docs * update docs/apidocs/synthesis_aqc.rst * add deprecations to qiskit/transpiler/synthesis/__init__.py * fix link * remove qiskit/transpiler/synthesis * add release notes * improve docs * add import aqc to qiskit.synthesis * fix lint errors --- qiskit/transpiler/synthesis/__init__.py | 16 --- qiskit/transpiler/synthesis/aqc/__init__.py | 37 ------ qiskit/transpiler/synthesis/graysynth.py | 123 ------------------ ...transpiler-synthesis-3efbd076905ed141.yaml | 14 ++ test/python/synthesis/aqc/test_aqc.py | 6 - .../synthesis/test_cnot_phase_synthesis.py | 40 ++---- 6 files changed, 22 insertions(+), 214 deletions(-) delete mode 100644 qiskit/transpiler/synthesis/__init__.py delete mode 100644 qiskit/transpiler/synthesis/aqc/__init__.py delete mode 100644 qiskit/transpiler/synthesis/graysynth.py create mode 100644 releasenotes/notes/remove-transpiler-synthesis-3efbd076905ed141.yaml diff --git a/qiskit/transpiler/synthesis/__init__.py b/qiskit/transpiler/synthesis/__init__.py deleted file mode 100644 index b8ac116d2284..000000000000 --- a/qiskit/transpiler/synthesis/__init__.py +++ /dev/null @@ -1,16 +0,0 @@ -# This code is part of Qiskit. -# -# (C) Copyright IBM 2017, 2018. -# -# This code is licensed under the Apache License, Version 2.0. You may -# obtain a copy of this license in the LICENSE.txt file in the root directory -# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0. -# -# Any modifications or derivative works of this code must retain this -# copyright notice, and modified files need to carry a notice indicating -# that they have been altered from the originals. - - -"""Module containing transpiler synthesize.""" - -from .graysynth import graysynth, cnot_synth diff --git a/qiskit/transpiler/synthesis/aqc/__init__.py b/qiskit/transpiler/synthesis/aqc/__init__.py deleted file mode 100644 index f6c51b2c1dd4..000000000000 --- a/qiskit/transpiler/synthesis/aqc/__init__.py +++ /dev/null @@ -1,37 +0,0 @@ -# This code is part of Qiskit. -# -# (C) Copyright IBM 2022. -# -# This code is licensed under the Apache License, Version 2.0. You may -# obtain a copy of this license in the LICENSE.txt file in the root directory -# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0. -# -# Any modifications or derivative works of this code must retain this -# copyright notice, and modified files need to carry a notice indicating -# that they have been altered from the originals. - -""" -============================ -Approximate Quantum Compiler -============================ -""" - -import warnings - -from qiskit.synthesis.unitary.aqc.approximate import ApproximateCircuit, ApproximatingObjective -from qiskit.synthesis.unitary.aqc import AQC -from qiskit.synthesis.unitary.aqc.cnot_structures import make_cnot_network -from qiskit.synthesis.unitary.aqc.cnot_unit_circuit import CNOTUnitCircuit -from qiskit.synthesis.unitary.aqc.cnot_unit_objective import ( - CNOTUnitObjective, - DefaultCNOTUnitObjective, -) -from qiskit.synthesis.unitary.aqc.fast_gradient.fast_gradient import FastCNOTUnitObjective -from qiskit.transpiler.passes.synthesis.aqc_plugin import AQCSynthesisPlugin - -warnings.warn( - "The qiskit.transpiler.synthesis.aqc module is deprecated since Qiskit 0.46.0 " - "and will be removed in Qiskit 1.0.", - stacklevel=2, - category=DeprecationWarning, -) diff --git a/qiskit/transpiler/synthesis/graysynth.py b/qiskit/transpiler/synthesis/graysynth.py deleted file mode 100644 index 5439243d84cd..000000000000 --- a/qiskit/transpiler/synthesis/graysynth.py +++ /dev/null @@ -1,123 +0,0 @@ -# This code is part of Qiskit. -# -# (C) Copyright IBM 2017, 2023. -# -# This code is licensed under the Apache License, Version 2.0. You may -# obtain a copy of this license in the LICENSE.txt file in the root directory -# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0. -# -# Any modifications or derivative works of this code must retain this -# copyright notice, and modified files need to carry a notice indicating -# that they have been altered from the originals. - -# pylint: disable=unused-wildcard-import, wildcard-import - -""" -Implementation of the GraySynth algorithm for synthesizing CNOT-Phase -circuits with efficient CNOT cost, and the Patel-Hayes-Markov algorithm -for optimal synthesis of linear (CNOT-only) reversible circuits. -""" - - -from qiskit.synthesis.linear.cnot_synth import * -from qiskit.synthesis.linear_phase.cnot_phase_synth import * -from qiskit.utils.deprecation import deprecate_func - - -@deprecate_func( - since="0.46.0", - additional_msg="Instead, use the function ``synth_cnot_count_full_pmh`` from the module" - + "``qiskit.synthesis.linear``.", -) -def cnot_synth(state, section_size=2): - """ - Synthesize linear reversible circuits for all-to-all architecture - using Patel, Markov and Hayes method. - - This function is an implementation of the Patel, Markov and Hayes algorithm from [1] - for optimal synthesis of linear reversible circuits for all-to-all architecture, - as specified by an n x n matrix. - - Args: - state (list[list] or ndarray): n x n boolean invertible matrix, describing the state - of the input circuit - section_size (int): the size of each section, used in the - Patel–Markov–Hayes algorithm [1]. section_size must be a factor of num_qubits. - - Returns: - QuantumCircuit: a CX-only circuit implementing the linear transformation. - - Raises: - QiskitError: when variable "state" isn't of type numpy.ndarray - - References: - 1. Patel, Ketan N., Igor L. Markov, and John P. Hayes, - *Optimal synthesis of linear reversible circuits*, - Quantum Information & Computation 8.3 (2008): 282-294. - `arXiv:quant-ph/0302002 [quant-ph] `_ - """ - return synth_cnot_count_full_pmh(state, section_size=section_size) - - -@deprecate_func( - since="0.46.0", - additional_msg="Instead, use the function ``synth_cnot_phase_aam`` from the module" - + "``qiskit.synthesis.linear_phase``.", -) -def graysynth(cnots, angles, section_size=2): - """This function is an implementation of the GraySynth algorithm of - Amy, Azimadeh and Mosca. - - GraySynth is a heuristic algorithm from [1] for synthesizing small parity networks. - It is inspired by Gray codes. Given a set of binary strings S - (called "cnots" bellow), the algorithm synthesizes a parity network for S by - repeatedly choosing an index i to expand and then effectively recursing on - the co-factors S_0 and S_1, consisting of the strings y in S, - with y_i = 0 or 1 respectively. As a subset S is recursively expanded, - CNOT gates are applied so that a designated target bit contains the - (partial) parity ksi_y(x) where y_i = 1 if and only if y'_i = 1 for all - y' in S. If S is a singleton {y'}, then y = y', hence the target bit contains - the value ksi_y'(x) as desired. - - Notably, rather than uncomputing this sequence of CNOT gates when a subset S - is finished being synthesized, the algorithm maintains the invariant - that the remaining parities to be computed are expressed over the current state - of bits. This allows the algorithm to avoid the 'backtracking' inherent in - uncomputing-based methods. - - The algorithm is described in detail in section 4 of [1]. - - Args: - cnots (list[list]): a matrix whose columns are the parities to be synthesized - e.g.:: - - [[0, 1, 1, 1, 1, 1], - [1, 0, 0, 1, 1, 1], - [1, 0, 0, 1, 0, 0], - [0, 0, 1, 0, 1, 0]] - - corresponds to:: - - x1^x2 + x0 + x0^x3 + x0^x1^x2 + x0^x1^x3 + x0^x1 - - angles (list): a list containing all the phase-shift gates which are - to be applied, in the same order as in "cnots". A number is - interpreted as the angle of p(angle), otherwise the elements - have to be 't', 'tdg', 's', 'sdg' or 'z'. - - section_size (int): the size of every section, used in _lwr_cnot_synth(), in the - Patel–Markov–Hayes algorithm. section_size must be a factor of num_qubits. - - Returns: - QuantumCircuit: the decomposed quantum circuit. - - Raises: - QiskitError: when dimensions of cnots and angles don't align. - - References: - 1. Matthew Amy, Parsiad Azimzadeh, and Michele Mosca. - *On the controlled-NOT complexity of controlled-NOT–phase circuits.*, - Quantum Science and Technology 4.1 (2018): 015002. - `arXiv:1712.01859 `_ - """ - return synth_cnot_phase_aam(cnots, angles, section_size=section_size) diff --git a/releasenotes/notes/remove-transpiler-synthesis-3efbd076905ed141.yaml b/releasenotes/notes/remove-transpiler-synthesis-3efbd076905ed141.yaml new file mode 100644 index 000000000000..5161be3756d6 --- /dev/null +++ b/releasenotes/notes/remove-transpiler-synthesis-3efbd076905ed141.yaml @@ -0,0 +1,14 @@ +--- +upgrade: + - | + Removed the ``qiskit.transpiler.synthesis`` module, which has been deprecated since the 0.46 release. + The following objects have been moved: + + * :mod:`qiskit.transpiler.synthesis.aqc` has been moved to :mod:`qiskit.synthesis.unitary.aqc` + (except of :class:`qiskit.synthesis.unitary.aqc.AQCSynthesisPlugin`). + * :class:`qiskit.synthesis.unitary.aqc.AQCSynthesisPlugin` has been moved to + :class:`qiskit.transpiler.passes.synthesis.AQCSynthesisPlugin`. + * :func:`qiskit.transpiler.synthesis.graysynth` has been moved to + :func:`qiskit.synthesis.synth_cnot_phase_aam`. + * :func:`qiskit.transpiler.synthesis.cnot_synth` has been moved to + :func:`qiskit.synthesis.synth_cnot_count_full_pmh`. diff --git a/test/python/synthesis/aqc/test_aqc.py b/test/python/synthesis/aqc/test_aqc.py index 97c70eb3b587..3d153c492181 100644 --- a/test/python/synthesis/aqc/test_aqc.py +++ b/test/python/synthesis/aqc/test_aqc.py @@ -134,12 +134,6 @@ def test_aqc_determinant_minus_one(self): error = 0.5 * (np.linalg.norm(approx_matrix - target_matrix, "fro") ** 2) self.assertTrue(error < 1e-3) - def test_deprecation(self): - """Test that importing this module is deprecated.""" - # pylint: disable = unused-import - with self.assertWarns(DeprecationWarning): - import qiskit.transpiler.synthesis.aqc - if __name__ == "__main__": unittest.main() diff --git a/test/python/synthesis/test_cnot_phase_synthesis.py b/test/python/synthesis/test_cnot_phase_synthesis.py index 8bf6c28a8cc3..39ae60bf6bcd 100644 --- a/test/python/synthesis/test_cnot_phase_synthesis.py +++ b/test/python/synthesis/test_cnot_phase_synthesis.py @@ -21,10 +21,6 @@ from qiskit.quantum_info.operators import Operator from qiskit.synthesis.linear import synth_cnot_count_full_pmh from qiskit.synthesis.linear_phase import synth_cnot_phase_aam -from qiskit.transpiler.synthesis.graysynth import ( - cnot_synth, - graysynth, -) from qiskit.test import QiskitTestCase @@ -32,8 +28,7 @@ class TestGraySynth(QiskitTestCase): """Test the Gray-Synth algorithm.""" - @ddt.data(synth_cnot_phase_aam, graysynth) - def test_gray_synth(self, synth_func): + def test_gray_synth(self): """Test synthesis of a small parity network via gray_synth. The algorithm should take the following matrix as an input: @@ -75,11 +70,7 @@ def test_gray_synth(self, synth_func): [0, 1, 0, 0, 1, 0], ] angles = ["s", "t", "z", "s", "t", "t"] - if synth_func.__name__ == "graysynth": - with self.assertWarns(DeprecationWarning): - c_gray = synth_func(cnots, angles) - else: - c_gray = synth_func(cnots, angles) + c_gray = synth_cnot_phase_aam(cnots, angles) unitary_gray = UnitaryGate(Operator(c_gray)) # Create the circuit displayed above: @@ -108,8 +99,7 @@ def test_gray_synth(self, synth_func): # Check if the two circuits are equivalent self.assertEqual(unitary_gray, unitary_compare) - @ddt.data(synth_cnot_phase_aam, graysynth) - def test_paper_example(self, synth_func): + def test_paper_example(self): """Test synthesis of a diagonal operator from the paper. The diagonal operator in Example 4.2 @@ -137,11 +127,7 @@ def test_paper_example(self, synth_func): """ cnots = [[0, 1, 1, 1, 1, 1], [1, 0, 0, 1, 1, 1], [1, 0, 0, 1, 0, 0], [0, 0, 1, 0, 1, 0]] angles = ["t"] * 6 - if synth_func.__name__ == "graysynth": - with self.assertWarns(DeprecationWarning): - c_gray = synth_func(cnots, angles) - else: - c_gray = synth_func(cnots, angles) + c_gray = synth_cnot_phase_aam(cnots, angles) unitary_gray = UnitaryGate(Operator(c_gray)) # Create the circuit displayed above: @@ -167,8 +153,7 @@ def test_paper_example(self, synth_func): # Check if the two circuits are equivalent self.assertEqual(unitary_gray, unitary_compare) - @ddt.data(synth_cnot_phase_aam, graysynth) - def test_ccz(self, synth_func): + def test_ccz(self): """Test synthesis of the doubly-controlled Z gate. The diagonal operator in Example 4.3 @@ -194,11 +179,7 @@ def test_ccz(self, synth_func): """ cnots = [[1, 0, 0, 1, 1, 0, 1], [0, 1, 0, 1, 0, 1, 1], [0, 0, 1, 0, 1, 1, 1]] angles = ["t", "t", "t", "tdg", "tdg", "tdg", "t"] - if synth_func.__name__ == "graysynth": - with self.assertWarns(DeprecationWarning): - c_gray = synth_func(cnots, angles) - else: - c_gray = synth_func(cnots, angles) + c_gray = synth_cnot_phase_aam(cnots, angles) unitary_gray = UnitaryGate(Operator(c_gray)) # Create the circuit displayed above: @@ -228,8 +209,7 @@ class TestPatelMarkovHayes(QiskitTestCase): """Test the Patel-Markov-Hayes algorithm for synthesizing linear CNOT-only circuits.""" - @ddt.data(synth_cnot_count_full_pmh, cnot_synth) - def test_patel_markov_hayes(self, synth_func): + def test_patel_markov_hayes(self): """Test synthesis of a small linear circuit (example from paper, Figure 3). @@ -264,11 +244,7 @@ def test_patel_markov_hayes(self, synth_func): [1, 1, 0, 1, 1, 1], [0, 0, 1, 1, 1, 0], ] - if synth_func.__name__ == "cnot_synth": - with self.assertWarns(DeprecationWarning): - c_patel = synth_func(state) - else: - c_patel = synth_func(state) + c_patel = synth_cnot_count_full_pmh(state) unitary_patel = UnitaryGate(Operator(c_patel)) # Create the circuit displayed above: