From b65a6214e7eaaf0cbf241802a627ed1aa7097119 Mon Sep 17 00:00:00 2001 From: Matthew Treinish Date: Fri, 17 May 2024 06:14:05 -0400 Subject: [PATCH] Remove qiskit aer translation stage This commit removes the qiskit aer translation plugin. This was added as a workaround for a Qiskit/qiskit#11351. This has been fixed in Qiskit since 0.45.2 and is no longer necessary. The mechanism by which the workaround worked was unsound in practice as it was mutating the target and also explicitly using private attributes of the Target. This is causing real issues now as it only worked by assuming the target wasn't shared between passmanagers which is never guaranteed. Similarly the reliance on internal private attributes of the Target class will cause issues in the future when the target internals change (see Qiskit/qiskit#12292). This commit opts to remove the plugin in its entirity as it's no longer necessary and actively causing issues with Qiskit 1.1 and transpiling targeting aer backends with >1 circuit. As it's private internal detail there isn't a release note. Fixes Qiskit/qiskit#12425 Fixes #2141 --- qiskit_aer/backends/aerbackend.py | 7 - qiskit_aer/backends/plugin/__init__.py | 0 .../backends/plugin/aer_backend_plugin.py | 126 ------------------ setup.py | 7 +- 4 files changed, 1 insertion(+), 139 deletions(-) delete mode 100644 qiskit_aer/backends/plugin/__init__.py delete mode 100644 qiskit_aer/backends/plugin/aer_backend_plugin.py diff --git a/qiskit_aer/backends/aerbackend.py b/qiskit_aer/backends/aerbackend.py index 9d8f14e946..fd0772964e 100644 --- a/qiskit_aer/backends/aerbackend.py +++ b/qiskit_aer/backends/aerbackend.py @@ -737,10 +737,3 @@ def __repr__(self): name = self.__class__.__name__ display = f"'{self.name}'" return f"{name}({display})" - - def get_translation_stage_plugin(self): - """use custom translation method to avoid gate exchange""" - if self._target is None: - return "aer_backend_plugin" - else: - return None diff --git a/qiskit_aer/backends/plugin/__init__.py b/qiskit_aer/backends/plugin/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/qiskit_aer/backends/plugin/aer_backend_plugin.py b/qiskit_aer/backends/plugin/aer_backend_plugin.py deleted file mode 100644 index 73be26fcef..0000000000 --- a/qiskit_aer/backends/plugin/aer_backend_plugin.py +++ /dev/null @@ -1,126 +0,0 @@ -# This code is part of Qiskit. -# -# (C) Copyright IBM 2018, 2019. -# -# 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. -""" -Aer simulator backend transpiler plug-in -""" -from qiskit.transpiler.preset_passmanagers.plugin import PassManagerStagePlugin -from qiskit.transpiler import PassManager, TransformationPass -from qiskit.transpiler.passes import BasisTranslator -from qiskit.transpiler.passes import UnitarySynthesis -from qiskit.transpiler.passes import HighLevelSynthesis -from qiskit.circuit.equivalence_library import SessionEquivalenceLibrary as sel -from qiskit.circuit.library.standard_gates import get_standard_gate_name_mapping -from qiskit.circuit.measure import Measure -from qiskit.circuit.library import Barrier -from qiskit.circuit import ControlFlowOp -from qiskit.converters import circuit_to_dag -from qiskit_aer.backends.name_mapping import NAME_MAPPING - - -class AerBackendRebuildGateSetsFromCircuit(TransformationPass): - """custom translation class to rebuild basis gates with gates in circuit""" - - def __init__(self, config, opt_lvl): - super().__init__() - self.config = config - if opt_lvl is None: - self.optimization_level = 1 - else: - self.optimization_level = opt_lvl - self.qiskit_inst_name_map = get_standard_gate_name_mapping() - self.qiskit_inst_name_map["barrier"] = Barrier - - def _add_ops(self, dag, ops: set): - num_unsupported_ops = 0 - opnodes = dag.op_nodes() - if opnodes is None: - return num_unsupported_ops - - for node in opnodes: - if isinstance(node.op, ControlFlowOp): - for block in node.op.blocks: - num_unsupported_ops += self._add_ops(circuit_to_dag(block), ops) - if node.name in self.qiskit_inst_name_map: - ops.add(node.name) - elif node.name in self.config.target: - ops.add(node.name) - else: - num_unsupported_ops = num_unsupported_ops + 1 - return num_unsupported_ops - - def run(self, dag): - # do nothing for higher optimization level - if self.optimization_level > 1: - return dag - if self.config is None or self.config.target is None: - return dag - - # search ops in supported name mapping - ops = set() - num_unsupported_ops = self._add_ops(dag, ops) - - # if there are some unsupported node (i.e. RealAmplitudes) do nothing - if num_unsupported_ops > 0 or len(ops) < 1: - return dag - - # clear all instructions in target - self.config.target._gate_map.clear() - self.config.target._gate_name_map.clear() - self.config.target._qarg_gate_map.clear() - self.config.target._global_operations.clear() - - # rebuild gate sets from circuit - for name in ops: - if name in self.qiskit_inst_name_map: - self.config.target.add_instruction(self.qiskit_inst_name_map[name], name=name) - else: - self.config.target.add_instruction(NAME_MAPPING[name], name=name) - if "measure" not in ops: - self.config.target.add_instruction(Measure()) - self.config.basis_gates = list(self.config.target.operation_names) - - return dag - - -# This plugin should not be used outside of simulator -# TODO : this plugin should be moved to optimization stage plugin -# if Qiskit will have custom optimizaiton stage plugin interface -# in that case just return pass without Optimize1qGatesDecomposition -class AerBackendPlugin(PassManagerStagePlugin): - """custom passmanager to avoid unnecessary gate changes""" - - def pass_manager(self, pass_manager_config, optimization_level=None) -> PassManager: - return PassManager( - [ - UnitarySynthesis( - pass_manager_config.basis_gates, - approximation_degree=pass_manager_config.approximation_degree, - coupling_map=pass_manager_config.coupling_map, - backend_props=pass_manager_config.backend_properties, - plugin_config=pass_manager_config.unitary_synthesis_plugin_config, - method=pass_manager_config.unitary_synthesis_method, - target=pass_manager_config.target, - ), - HighLevelSynthesis( - hls_config=pass_manager_config.hls_config, - coupling_map=pass_manager_config.coupling_map, - target=pass_manager_config.target, - use_qubit_indices=True, - equivalence_library=sel, - basis_gates=pass_manager_config.basis_gates, - ), - BasisTranslator(sel, pass_manager_config.basis_gates, pass_manager_config.target), - AerBackendRebuildGateSetsFromCircuit( - config=pass_manager_config, opt_lvl=optimization_level - ), - ] - ) diff --git a/setup.py b/setup.py index ba1ef7dcb6..98dad4e2bb 100644 --- a/setup.py +++ b/setup.py @@ -22,7 +22,7 @@ extras_requirements = {"dask": ["dask", "distributed"]} requirements = [ - "qiskit>=0.45.0", + "qiskit>=0.45.2", "numpy>=1.16.3", "scipy>=1.0", "psutil>=5", @@ -114,9 +114,4 @@ cmake_args=cmake_args, keywords="qiskit, simulator, quantum computing, backend", zip_safe=False, - entry_points={ - "qiskit.transpiler.translation": [ - "aer_backend_plugin = qiskit_aer.backends.plugin.aer_backend_plugin:AerBackendPlugin", - ] - }, )