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

Update backend.configuration() to use BackendConfiguration #1323

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
5 changes: 4 additions & 1 deletion CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,10 @@ Changed
- `IBMQ.save_account()` now takes an `overwrite` option to replace an existing
account on disk. Default is False (#1295).
- Backend and Provider methods defined in the specification use model objects
rather than dicts, along with validation against schemas (#1249, #1277).
rather than dicts, along with validation against schemas (#1249, #1277). The
updated methods include:
- ``backend.status()``(#1301).
- ``backend.configuration()`` (and ``__init__``) (#1323).
- ``backend.provider()`` is now a method instead of a property (#1312).
- Remove local backend (Aer) fallback (#1303)

Expand Down
11 changes: 2 additions & 9 deletions qiskit/backends/aer/aerprovider.py
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ def _verify_aer_backends(self):
for backend_cls in AER_STANDARD_BACKENDS:
try:
backend_instance = self._get_backend_instance(backend_cls)
backend_name = backend_instance.configuration()['name']
backend_name = backend_instance.name()
ret[backend_name] = backend_instance
except QISKitError as err:
# Ignore backends that could not be initialized.
Expand All @@ -132,8 +132,7 @@ def _get_backend_instance(self, backend_cls):
Returns:
BaseBackend: a backend instance.
Raises:
QISKitError: if the backend could not be instantiated or does not
provide a valid configuration containing a name.
QISKitError: if the backend could not be instantiated.
"""
# Verify that the backend can be instantiated.
try:
Expand All @@ -142,12 +141,6 @@ def _get_backend_instance(self, backend_cls):
raise QISKitError('Backend %s could not be instantiated: %s' %
(backend_cls, err))

# Verify that the instance has a minimal valid configuration.
try:
_ = backend_instance.configuration()['name']
except (LookupError, TypeError):
raise QISKitError('Backend %s has an invalid configuration')

return backend_instance

def __str__(self):
Expand Down
55 changes: 34 additions & 21 deletions qiskit/backends/aer/qasm_simulator.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@

import numpy as np

from qiskit.backends.models import BackendConfiguration
from qiskit.result._utils import copy_qasm_from_qobj_into_result, result_from_old_style_dict
from qiskit.backends import BaseBackend
from qiskit.backends.aer.aerjob import AerJob
Expand All @@ -46,34 +47,40 @@ class QasmSimulator(BaseBackend):
"""C++ quantum circuit simulator with realistic noise"""

DEFAULT_CONFIGURATION = {
'name': 'qasm_simulator',
'backend_name': 'qasm_simulator',
'backend_version': '1.0.0',
'n_qubits': -1,
'url': 'https://github.com/QISKit/qiskit-terra/src/qasm-simulator-cpp',
'simulator': True,
'local': True,
'description': 'A C++ realistic noise simulator for qobj files',
'coupling_map': 'all-to-all',
"basis_gates": 'u0,u1,u2,u3,cx,cz,id,x,y,z,h,s,sdg,t,tdg,rzz,' +
'snapshot,wait,noise,save,load'
'conditional': True,
'open_pulse': False,
'description': 'A C++ realistic noise simulator for qasm experiments',
'basis_gates': ['u0', 'u1', 'u2', 'u3', 'cx', 'cz', 'id', 'x', 'y', 'z',
'h', 's', 'sdg', 't', 'tdg', 'rzz', 'snapshot', 'wait',
'noise', 'save', 'load'],
'gates': [{'name': 'TODO', 'parameters': [], 'qasm_def': 'TODO'}]
}

def __init__(self, configuration=None, provider=None):
super().__init__(configuration=configuration or self.DEFAULT_CONFIGURATION.copy(),
super().__init__(configuration=(configuration or
BackendConfiguration.from_dict(self.DEFAULT_CONFIGURATION)),
provider=provider)

# Try to use the default executable if not specified.
if self._configuration.get('exe'):
paths = [self._configuration.get('exe')]
if 'exe' in self._configuration:
paths = [self._configuration.exe]
else:
paths = DEFAULT_SIMULATOR_PATHS

# Ensure that the executable is available.
try:
self._configuration['exe'] = next(
self._configuration.exe = next(
path for path in paths if (os.path.exists(path) and
os.path.getsize(path) > 100))
except StopIteration:
raise FileNotFoundError('Simulator executable not found (using %s)' %
self._configuration.get('exe', 'default locations'))
getattr(self._configuration, 'exe', 'default locations'))

def run(self, qobj):
"""Run a qobj on the backend."""
Expand All @@ -84,7 +91,7 @@ def run(self, qobj):

def _run_job(self, job_id, qobj):
self._validate(qobj)
result = run(qobj, self._configuration['exe'])
result = run(qobj, self._configuration.exe)
result['job_id'] = job_id
copy_qasm_from_qobj_into_result(qobj, result)

Expand All @@ -104,33 +111,39 @@ class CliffordSimulator(BaseBackend):
""""C++ Clifford circuit simulator with realistic noise."""

DEFAULT_CONFIGURATION = {
'name': 'clifford_simulator',
'url': 'https://github.com/QISKit/qiskit-terra/src/qasm-simulator',
'backend_name': 'clifford_simulator',
'backend_version': '1.0.0',
'n_qubits': -1,
'url': 'https://github.com/QISKit/qiskit-terra/src/qasm-simulator-cpp',
'simulator': True,
'local': True,
'conditional': True,
'open_pulse': False,
'description': 'A C++ Clifford simulator with approximate noise',
'coupling_map': 'all-to-all',
'basis_gates': 'cx,id,x,y,z,h,s,sdg,snapshot,wait,noise,save,load'
'basis_gates': ['cx', 'id', 'x', 'y', 'z', 'h', 's', 'sdg', 'snapshot',
'wait', 'noise', 'save', 'load'],
'gates': [{'name': 'TODO', 'parameters': [], 'qasm_def': 'TODO'}]
}

def __init__(self, configuration=None, provider=None):
super().__init__(configuration=configuration or self.DEFAULT_CONFIGURATION.copy(),
super().__init__(configuration=(configuration or
BackendConfiguration.from_dict(self.DEFAULT_CONFIGURATION)),
provider=provider)

# Try to use the default executable if not specified.
if self._configuration.get('exe'):
paths = [self._configuration.get('exe')]
if 'exe' in self._configuration:
paths = [self._configuration.exe]
else:
paths = DEFAULT_SIMULATOR_PATHS

# Ensure that the executable is available.
try:
self._configuration['exe'] = next(
self._configuration.exe = next(
path for path in paths if (os.path.exists(path) and
os.path.getsize(path) > 100))
except StopIteration:
raise FileNotFoundError('Simulator executable not found (using %s)' %
self._configuration.get('exe', 'default locations'))
getattr(self._configuration, 'exe', 'default locations'))

def run(self, qobj):
"""Run a Qobj on the backend.
Expand Down Expand Up @@ -159,7 +172,7 @@ def _run_job(self, job_id, qobj):
qobj_dict['config'] = {'simulator': 'clifford'}

qobj = Qobj.from_dict(qobj_dict)
result = run(qobj, self._configuration['exe'])
result = run(qobj, self._configuration.exe)
result['job_id'] = job_id

return result_from_old_style_dict(
Expand Down
20 changes: 13 additions & 7 deletions qiskit/backends/aer/qasm_simulator_py.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@

import numpy as np

from qiskit.backends.models import BackendConfiguration
from qiskit.result._utils import copy_qasm_from_qobj_into_result, result_from_old_style_dict
from qiskit.backends import BaseBackend
from qiskit.backends.aer.aerjob import AerJob
Expand All @@ -90,17 +91,22 @@ class QasmSimulatorPy(BaseBackend):
"""Python implementation of a qasm simulator."""

DEFAULT_CONFIGURATION = {
'name': 'qasm_simulator_py',
'backend_name': 'qasm_simulator_py',
'backend_version': '2.0.0',
'n_qubits': -1,
'url': 'https://github.com/QISKit/qiskit-terra',
'simulator': True,
'local': True,
'description': 'A python simulator for qasm files',
'coupling_map': 'all-to-all',
'basis_gates': 'u1,u2,u3,cx,id,snapshot'
'conditional': True,
'open_pulse': False,
'description': 'A python simulator for qasm experiments',
'basis_gates': ['u1', 'u2', 'u3', 'cx', 'id', 'snapshot'],
'gates': [{'name': 'TODO', 'parameters': [], 'qasm_def': 'TODO'}]
}

def __init__(self, configuration=None, provider=None):
super().__init__(configuration=configuration or self.DEFAULT_CONFIGURATION.copy(),
super().__init__(configuration=(configuration or
BackendConfiguration.from_dict(self.DEFAULT_CONFIGURATION)),
provider=provider)

self._local_random = random.Random()
Expand Down Expand Up @@ -243,7 +249,7 @@ def _run_job(self, job_id, qobj):
for circuit in qobj.experiments:
result_list.append(self.run_circuit(circuit))
end = time.time()
result = {'backend': self._configuration['name'],
result = {'backend': self.name(),
'id': qobj.qobj_id,
'job_id': job_id,
'result': result_list,
Expand Down Expand Up @@ -342,7 +348,7 @@ def run_circuit(self, circuit):
params = operation.params
self._add_qasm_snapshot(params[0])
else:
backend = self._configuration['name']
backend = self.name()
err_msg = '{0} encountered unrecognized operation "{1}"'
raise SimulatorError(err_msg.format(backend,
operation.name))
Expand Down
18 changes: 13 additions & 5 deletions qiskit/backends/aer/statevector_simulator.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
import logging
import uuid

from qiskit.backends.models import BackendConfiguration
from qiskit.qobj import QobjInstruction
from .qasm_simulator import QasmSimulator
from ._simulatorerror import SimulatorError
Expand All @@ -26,17 +27,24 @@ class StatevectorSimulator(QasmSimulator):
"""C++ statevector simulator"""

DEFAULT_CONFIGURATION = {
'name': 'statevector_simulator',
'backend_name': 'statevector_simulator',
'backend_version': '1.0.0',
'n_qubits': -1,
'url': 'https://github.com/QISKit/qiskit-terra/src/qasm-simulator-cpp',
'simulator': True,
'local': True,
'description': 'A C++ statevector simulator for qobj files',
'coupling_map': 'all-to-all',
'basis_gates': 'u1,u2,u3,cx,cz,id,x,y,z,h,s,sdg,t,tdg,rzz,load,save,snapshot'
'conditional': False,
'open_pulse': False,
'description': 'A single-shot C++ statevector simulator for the |0> state evolution',
'basis_gates': ['u1', 'u2', 'u3', 'cx', 'cz', 'id', 'x', 'y', 'z', 'h',
's', 'sdg', 't', 'tdg', 'rzz', 'load', 'save',
'snapshot'],
'gates': [{'name': 'TODO', 'parameters': [], 'qasm_def': 'TODO'}]
}

def __init__(self, configuration=None, provider=None):
super().__init__(configuration=configuration or self.DEFAULT_CONFIGURATION.copy(),
super().__init__(configuration=(configuration or
BackendConfiguration.from_dict(self.DEFAULT_CONFIGURATION)),
provider=provider)

def run(self, qobj):
Expand Down
14 changes: 10 additions & 4 deletions qiskit/backends/aer/statevector_simulator_py.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@

from qiskit.backends.aer.aerjob import AerJob
from qiskit.backends.aer._simulatorerror import SimulatorError
from qiskit.backends.models import BackendConfiguration
from qiskit.qobj import QobjInstruction
from .qasm_simulator_py import QasmSimulatorPy

Expand All @@ -33,17 +34,22 @@ class StatevectorSimulatorPy(QasmSimulatorPy):
"""Python statevector simulator."""

DEFAULT_CONFIGURATION = {
'name': 'statevector_simulator_py',
'backend_name': 'statevector_simulator_py',
'backend_version': '1.0.0',
'n_qubits': -1,
'url': 'https://github.com/QISKit/qiskit-terra',
'simulator': True,
'local': True,
'conditional': False,
'open_pulse': False,
'description': 'A Python statevector simulator for qobj files',
'coupling_map': 'all-to-all',
'basis_gates': 'u1,u2,u3,cx,id,snapshot'
'basis_gates': ['u1', 'u2', 'u3', 'cx', 'id', 'snapshot'],
'gates': [{'name': 'TODO', 'parameters': [], 'qasm_def': 'TODO'}]
}

def __init__(self, configuration=None, provider=None):
super().__init__(configuration=configuration or self.DEFAULT_CONFIGURATION.copy(),
super().__init__(configuration=(configuration or
BackendConfiguration.from_dict(self.DEFAULT_CONFIGURATION)),
provider=provider)

def run(self, qobj):
Expand Down
18 changes: 12 additions & 6 deletions qiskit/backends/aer/unitary_simulator_py.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@

import numpy as np

from qiskit.backends.models import BackendConfiguration
from qiskit.result._utils import copy_qasm_from_qobj_into_result, result_from_old_style_dict
from qiskit.backends import BaseBackend
from qiskit.backends.aer.aerjob import AerJob
Expand All @@ -103,17 +104,22 @@ class UnitarySimulatorPy(BaseBackend):
"""Python implementation of a unitary simulator."""

DEFAULT_CONFIGURATION = {
'name': 'unitary_simulator_py',
'backend_name': 'unitary_simulator_py',
'backend_version': '1.0.0',
'n_qubits': -1,
'url': 'https://github.com/QISKit/qiskit-terra',
'simulator': True,
'local': True,
'description': 'A python simulator for unitary matrix',
'coupling_map': 'all-to-all',
'basis_gates': 'u1,u2,u3,cx,id'
'conditional': False,
'open_pulse': False,
'description': 'A python simulator for unitary matrix corresponding to a circuit',
'basis_gates': ['u1', 'u2', 'u3', 'cx', 'id'],
'gates': [{'name': 'TODO', 'parameters': [], 'qasm_def': 'TODO'}]
}

def __init__(self, configuration=None, provider=None):
super().__init__(configuration=configuration or self.DEFAULT_CONFIGURATION.copy(),
super().__init__(configuration=(configuration or
BackendConfiguration.from_dict(self.DEFAULT_CONFIGURATION)),
provider=provider)

# Define attributes inside __init__.
Expand Down Expand Up @@ -189,7 +195,7 @@ def _run_job(self, job_id, qobj):
for circuit in qobj.experiments:
result_list.append(self.run_circuit(circuit))
end = time.time()
result = {'backend': self._configuration['name'],
result = {'backend': self.name(),
'id': qobj.qobj_id,
'job_id': job_id,
'result': result_list,
Expand Down
20 changes: 13 additions & 7 deletions qiskit/backends/basebackend.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,15 +28,13 @@ def __init__(self, configuration, provider=None):
not available.

Args:
configuration (dict): configuration dictionary
configuration (BackendConfiguration): backend configuration
provider (BaseProvider): provider responsible for this backend

Raises:
FileNotFoundError if backend executable is not available.
QISKitError: if there is no name in the configuration
"""
if 'name' not in configuration:
raise qiskit.QISKitError('backend does not have a name.')
self._configuration = configuration
self._provider = provider

Expand All @@ -46,7 +44,11 @@ def run(self, qobj):
pass

def configuration(self):
"""Return backend configuration"""
"""Return the backend configuration.

Returns:
BackendConfiguration: the configuration fot the backend.
"""
return self._configuration

def properties(self):
Expand All @@ -57,7 +59,7 @@ def provider(self):
"""Return the backend Provider.

Returns:
BaseProvider: the Provider responsible for this backend.
BaseProvider: the Provider responsible for the backend.
"""
return self._provider

Expand All @@ -74,8 +76,12 @@ def status(self):
status_msg='')

def name(self):
"""Return backend name"""
return self._configuration['name']
"""Return backend name.

Returns:
str: the name of the backend.
"""
return self._configuration.backend_name

def __str__(self):
return self.name()
Expand Down
Loading