/
fake_backend.py
158 lines (140 loc) · 5.55 KB
/
fake_backend.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
# This code is part of Qiskit.
#
# (C) Copyright IBM 2019, 2024.
#
# 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=no-name-in-module
"""
Base class for dummy backends.
"""
import warnings
from qiskit import circuit
from qiskit.providers.models import BackendProperties
from qiskit.providers import BackendV1
from qiskit import pulse
from qiskit.exceptions import QiskitError
from qiskit.utils import optionals as _optionals
from qiskit.providers import basic_provider
class _Credentials:
def __init__(self, token="123456", url="https://"):
self.token = token
self.url = url
self.hub = "hub"
self.group = "group"
self.project = "project"
class FakeBackend(BackendV1):
"""This is a dummy backend just for testing purposes."""
def __init__(self, configuration, time_alive=10):
"""FakeBackend initializer.
Args:
configuration (BackendConfiguration): backend configuration
time_alive (int): time to wait before returning result
"""
super().__init__(configuration)
self.time_alive = time_alive
self._credentials = _Credentials()
self.sim = None
def _setup_sim(self):
if _optionals.HAS_AER:
from qiskit_aer import AerSimulator
from qiskit_aer.noise import NoiseModel
self.sim = AerSimulator()
if self.properties():
noise_model = NoiseModel.from_backend(self)
self.sim.set_options(noise_model=noise_model)
# Update fake backend default options too to avoid overwriting
# it when run() is called
self.set_options(noise_model=noise_model)
else:
self.sim = basic_provider.BasicSimulator()
def properties(self):
"""Return backend properties"""
coupling_map = self.configuration().coupling_map
if coupling_map is None:
return None
unique_qubits = list(set().union(*coupling_map))
properties = {
"backend_name": self.name(),
"backend_version": self.configuration().backend_version,
"last_update_date": "2000-01-01 00:00:00Z",
"qubits": [
[
{"date": "2000-01-01 00:00:00Z", "name": "T1", "unit": "\u00b5s", "value": 0.0},
{"date": "2000-01-01 00:00:00Z", "name": "T2", "unit": "\u00b5s", "value": 0.0},
{
"date": "2000-01-01 00:00:00Z",
"name": "frequency",
"unit": "GHz",
"value": 0.0,
},
{
"date": "2000-01-01 00:00:00Z",
"name": "readout_error",
"unit": "",
"value": 0.0,
},
{"date": "2000-01-01 00:00:00Z", "name": "operational", "unit": "", "value": 1},
]
for _ in range(len(unique_qubits))
],
"gates": [
{
"gate": "cx",
"name": "CX" + str(pair[0]) + "_" + str(pair[1]),
"parameters": [
{
"date": "2000-01-01 00:00:00Z",
"name": "gate_error",
"unit": "",
"value": 0.0,
}
],
"qubits": [pair[0], pair[1]],
}
for pair in coupling_map
],
"general": [],
}
return BackendProperties.from_dict(properties)
@classmethod
def _default_options(cls):
if _optionals.HAS_AER:
from qiskit_aer import QasmSimulator
return QasmSimulator._default_options()
else:
return basic_provider.BasicSimulator._default_options()
def run(self, run_input, **kwargs):
"""Main job in simulator"""
circuits = run_input
pulse_job = None
if isinstance(circuits, (pulse.Schedule, pulse.ScheduleBlock)):
pulse_job = True
elif isinstance(circuits, circuit.QuantumCircuit):
pulse_job = False
elif isinstance(circuits, list):
if circuits:
if all(isinstance(x, (pulse.Schedule, pulse.ScheduleBlock)) for x in circuits):
pulse_job = True
elif all(isinstance(x, circuit.QuantumCircuit) for x in circuits):
pulse_job = False
if pulse_job is None:
raise QiskitError(
"Invalid input object %s, must be either a "
"QuantumCircuit, Schedule, or a list of either" % circuits
)
if pulse_job:
raise QiskitError("Pulse simulation is currently not supported for fake backends.")
# circuit job
if not _optionals.HAS_AER:
warnings.warn("Aer not found using BasicAer and no noise", RuntimeWarning)
if self.sim is None:
self._setup_sim()
self.sim._options = self._options
job = self.sim.run(circuits, **kwargs)
return job