Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix AerBackend issues caused by upgrading BackendV2 #1995

Merged
merged 27 commits into from
Nov 24, 2023
Merged
Show file tree
Hide file tree
Changes from 21 commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
4587384
add description if no description is provided, build coupling map if …
doichanj Nov 10, 2023
45cde5b
move import line
doichanj Nov 10, 2023
b94fd93
fix target for simulator backend
doichanj Nov 15, 2023
c20f91b
Merge remote-tracking branch 'upstream/main' into fix_backend_v2
doichanj Nov 15, 2023
55b635b
format
doichanj Nov 15, 2023
acda947
remove unused import
doichanj Nov 15, 2023
e8f43bf
use translation plugin to rebuild gate sets for simulator
doichanj Nov 16, 2023
06f2fe1
Merge remote-tracking branch 'upstream/main' into fix_backend_v2
doichanj Nov 16, 2023
dbb87b4
rename plugin
doichanj Nov 16, 2023
5ea99e3
rebuild of gate sets is eanbled only for opt level 0 and 1
doichanj Nov 16, 2023
8d14345
fix custom pass manager
doichanj Nov 16, 2023
a463e1d
fix pass_manager function
doichanj Nov 16, 2023
e08fc84
added ccx in NAME_MAPPING
doichanj Nov 16, 2023
2162ea8
added missed gates in NAME_MAPPING
doichanj Nov 16, 2023
6c0dc2e
added release note
doichanj Nov 16, 2023
0d62961
add check if opnodes is None
doichanj Nov 16, 2023
d68601b
add check config
doichanj Nov 16, 2023
a2c336e
decrease return
doichanj Nov 16, 2023
e8cf4e7
check opt level
doichanj Nov 16, 2023
5151558
fix searching ops in control flow blocks
doichanj Nov 17, 2023
4b4d466
Merge remote-tracking branch 'upstream/main' into fix_backend_v2
doichanj Nov 21, 2023
c88bdff
Update qiskit_aer/backends/plugin/aer_backend_plugin.py
doichanj Nov 22, 2023
3b0543a
Update qiskit_aer/backends/plugin/aer_backend_plugin.py
doichanj Nov 22, 2023
28e2f06
Merge branch 'main' into fix_backend_v2
doichanj Nov 22, 2023
8afde0b
refer review comments
doichanj Nov 22, 2023
c3f0cc4
remove unused import
doichanj Nov 22, 2023
9618e31
Merge remote-tracking branch 'upstream/main' into fix_backend_v2
doichanj Nov 24, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 26 additions & 4 deletions qiskit_aer/backends/aer_simulator.py
Original file line number Diff line number Diff line change
Expand Up @@ -518,6 +518,7 @@ class AerSimulator(AerBackend):
"continue_loop",
"reset",
"switch_case",
"barrier",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Barrier typically isn't needed in a target because qiskit always assumes barrier is valid for a backend since it's primarily a compiler directive. Was there something specific that was failing

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I removed barrier and add barrier inside plugin.
Adding barrier is needed because barrier can not be found in any name mapping and plugin returns with unsupported operation

]
),
"density_matrix": sorted(
Expand All @@ -542,6 +543,7 @@ class AerSimulator(AerBackend):
"continue_loop",
"reset",
"switch_case",
"barrier",
]
),
"matrix_product_state": sorted(
Expand All @@ -568,6 +570,7 @@ class AerSimulator(AerBackend):
"continue_loop",
"reset",
"switch_case",
"barrier",
]
),
"stabilizer": sorted(
Expand All @@ -591,6 +594,7 @@ class AerSimulator(AerBackend):
"continue_loop",
"reset",
"switch_case",
"barrier",
]
),
"extended_stabilizer": sorted(
Expand All @@ -600,6 +604,7 @@ class AerSimulator(AerBackend):
"roerror",
"save_statevector",
"reset",
"barrier",
]
),
"unitary": sorted(
Expand All @@ -608,6 +613,7 @@ class AerSimulator(AerBackend):
"save_unitary",
"set_unitary",
"reset",
"barrier",
]
),
"superop": sorted(
Expand All @@ -620,6 +626,7 @@ class AerSimulator(AerBackend):
"save_superop",
"set_superop",
"reset",
"barrier",
]
),
"tensor_network": sorted(
Expand All @@ -643,6 +650,7 @@ class AerSimulator(AerBackend):
"set_density_matrix",
"reset",
"switch_case",
"barrier",
]
),
}
Expand Down Expand Up @@ -695,7 +703,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 +727,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 +826,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 +845,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 +857,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 +875,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)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is just a minor comment. Previously, converted target was cached. With this change, it will not be cached. I think frequent access of target property will produce performance regression. Introducing caching may help performance (though setting method may need clear cache of target).

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

because if target is cached and used for transpilation to multiple circuits, basis gates for the first circuit is reused that can be a problem if the second circuit has gate that the first one does not have


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
Loading