Skip to content

Commit

Permalink
Fix AerBackend issues caused by upgrading BackendV2 (Qiskit#1995)
Browse files Browse the repository at this point in the history
* add description if no description is provided, build coupling map if it is provided

* move import line

* fix target for simulator backend

* format

* remove unused import

* use translation plugin to rebuild gate sets for simulator

* rename plugin

* rebuild of gate sets is eanbled only for opt level 0 and 1

* fix custom pass manager

* fix pass_manager function

* added ccx in NAME_MAPPING

* added missed gates in NAME_MAPPING

* added release note

* add check if opnodes is None

* add check config

* decrease return

* check opt level

* fix searching ops in control flow blocks

* Update qiskit_aer/backends/plugin/aer_backend_plugin.py

Co-authored-by: Matthew Treinish <mtreinish@kortar.org>

* Update qiskit_aer/backends/plugin/aer_backend_plugin.py

Co-authored-by: Matthew Treinish <mtreinish@kortar.org>

* refer review comments

* remove unused import

---------

Co-authored-by: Matthew Treinish <mtreinish@kortar.org>
  • Loading branch information
doichanj and mtreinish committed Nov 24, 2023
1 parent c784592 commit ea70d1c
Show file tree
Hide file tree
Showing 7 changed files with 229 additions and 95 deletions.
22 changes: 18 additions & 4 deletions qiskit_aer/backends/aer_simulator.py
Original file line number Diff line number Diff line change
Expand Up @@ -695,7 +695,9 @@ class AerSimulator(AerBackend):

_AVAILABLE_DEVICES = None

def __init__(self, configuration=None, properties=None, provider=None, **backend_options):
def __init__(
self, configuration=None, properties=None, provider=None, target=None, **backend_options
):
self._controller = aer_controller_execute()

# Update available methods and devices for class
Expand All @@ -717,7 +719,11 @@ def __init__(self, configuration=None, properties=None, provider=None, **backend
self._cached_basis_gates = self._BASIS_GATES["automatic"]

super().__init__(
configuration, properties=properties, provider=provider, backend_options=backend_options
configuration,
properties=properties,
provider=provider,
target=target,
backend_options=backend_options,
)

@classmethod
Expand Down Expand Up @@ -812,6 +818,11 @@ def _name(self):
def from_backend(cls, backend, **options):
"""Initialize simulator from backend."""
if isinstance(backend, BackendV2):
if backend.description is None:
description = "created by AerSimulator.from_backend"
else:
description = backend.description

configuration = QasmBackendConfiguration(
backend_name=f"'aer_simulator({backend.name})",
backend_version=backend.backend_version,
Expand All @@ -826,9 +837,10 @@ def from_backend(cls, backend, **options):
max_shots=int(1e6),
coupling_map=list(backend.coupling_map.get_edges()),
max_experiments=backend.max_circuits,
description=backend.description,
description=description,
)
properties = target_to_backend_properties(backend.target)
target = backend.target
elif isinstance(backend, BackendV1):
# Get configuration and properties from backend
configuration = copy.copy(backend.configuration())
Expand All @@ -837,6 +849,8 @@ def from_backend(cls, backend, **options):
# Customize configuration name
name = configuration.backend_name
configuration.backend_name = f"aer_simulator({name})"

target = None
else:
raise TypeError(
"The backend argument requires a BackendV2 or BackendV1 object, "
Expand All @@ -853,7 +867,7 @@ def from_backend(cls, backend, **options):
options["noise_model"] = noise_model

# Initialize simulator
sim = cls(configuration=configuration, properties=properties, **options)
sim = cls(configuration=configuration, properties=properties, target=target, **options)
return sim

def available_methods(self):
Expand Down
54 changes: 21 additions & 33 deletions qiskit_aer/backends/aerbackend.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
from qiskit.pulse import Schedule, ScheduleBlock
from qiskit.qobj import QasmQobj, PulseQobj
from qiskit.result import Result
from qiskit.transpiler import CouplingMap
from ..aererror import AerError
from ..jobs import AerJob, AerJobSet, split_qobj
from ..noise.noise_model import NoiseModel, QuantumErrorLocation
Expand All @@ -48,7 +49,7 @@ class AerBackend(Backend, ABC):
"""Aer Backend class."""

def __init__(
self, configuration, properties=None, defaults=None, backend_options=None, provider=None
self, configuration, properties=None, provider=None, target=None, backend_options=None
):
"""Aer class for backends.
Expand All @@ -59,8 +60,8 @@ def __init__(
Args:
configuration (BackendConfiguration): backend configuration.
properties (BackendProperties or None): Optional, backend properties.
defaults (PulseDefaults or None): Optional, backend pulse defaults.
provider (Provider): Optional, provider responsible for this backend.
target (Target): initial target for backend
backend_options (dict or None): Optional set custom backend options.
Raises:
Expand All @@ -76,22 +77,24 @@ def __init__(
backend_version=configuration.backend_version,
)

# Initialize backend properties and pulse defaults.
# Initialize backend properties
self._properties = properties
self._defaults = defaults
self._configuration = configuration

# Custom option values for config, properties, and defaults
# Custom option values for config, properties
self._options_configuration = {}
self._options_defaults = {}
self._options_properties = {}
self._target = None
self._target = target
self._mapping = NAME_MAPPING

# Set options from backend_options dictionary
if backend_options is not None:
self.set_options(**backend_options)

# build coupling map
if self.configuration().coupling_map is not None:
self._coupling_map = CouplingMap(self.configuration().coupling_map)

def _convert_circuit_binds(self, circuit, binds, idx_map):
parameterizations = []

Expand Down Expand Up @@ -330,18 +333,6 @@ def properties(self):
setattr(properties, key, val)
return properties

def defaults(self):
"""Return the simulator backend pulse defaults.
Returns:
PulseDefaults: The backend pulse defaults or ``None`` if the
backend does not support pulse.
"""
defaults = copy.copy(self._defaults)
for key, val in self._options_defaults.items():
setattr(defaults, key, val)
return defaults

@property
def max_circuits(self):
if hasattr(self.configuration(), "max_experiments"):
Expand All @@ -351,17 +342,16 @@ def max_circuits(self):

@property
def target(self):
self._target = convert_to_target(
self.configuration(), self.properties(), self.defaults(), self._mapping
)
return self._target
if self._target is not None:
return self._target

return convert_to_target(self.configuration(), self.properties(), None, NAME_MAPPING)

def clear_options(self):
"""Reset the simulator options to default values."""
self._options = self._default_options()
self._options_configuration = {}
self._options_properties = {}
self._options_defaults = {}

def status(self):
"""Return backend status.
Expand Down Expand Up @@ -702,8 +692,6 @@ def set_option(self, key, value):
self._set_configuration_option(key, value)
elif hasattr(self._properties, key):
self._set_properties_option(key, value)
elif hasattr(self._defaults, key):
self._set_defaults_option(key, value)
else:
if not hasattr(self._options, key):
raise AerError(f"Invalid option {key}")
Expand Down Expand Up @@ -735,15 +723,15 @@ def _set_properties_option(self, key, value):
elif key in self._options_properties:
self._options_properties.pop(key)

def _set_defaults_option(self, key, value):
"""Special handling for setting backend defaults options."""
if value is not None:
self._options_defaults[key] = value
elif key in self._options_defaults:
self._options_defaults.pop(key)

def __repr__(self):
"""String representation of an AerBackend."""
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
Loading

0 comments on commit ea70d1c

Please sign in to comment.