-
Notifications
You must be signed in to change notification settings - Fork 12
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 TketBackend
to derive from BackendV2
#389
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -12,36 +12,41 @@ | |
# See the License for the specific language governing permissions and | ||
# limitations under the License. | ||
|
||
import inspect | ||
from typing import Optional, Any | ||
from qiskit.circuit.library.standard_gates import get_standard_gate_name_mapping # type: ignore | ||
from qiskit.circuit.quantumcircuit import QuantumCircuit # type: ignore | ||
from qiskit.providers.backend import BackendV1 # type: ignore | ||
from qiskit.providers.models import QasmBackendConfiguration # type: ignore | ||
from qiskit.providers.backend import BackendV2 # type: ignore | ||
from qiskit.providers import Options # type: ignore | ||
from qiskit.transpiler import CouplingMap, Target # type: ignore | ||
from pytket.extensions.qiskit import AerStateBackend, AerUnitaryBackend | ||
from pytket.extensions.qiskit.qiskit_convert import qiskit_to_tk, _gate_str_2_optype_rev | ||
from pytket.extensions.qiskit.tket_job import TketJob, JobInfo | ||
from pytket.backends import Backend | ||
from pytket.passes import BasePass | ||
from pytket.predicates import ( | ||
NoClassicalControlPredicate, | ||
GateSetPredicate, | ||
CompilationUnit, | ||
) | ||
from pytket.predicates import GateSetPredicate, CompilationUnit | ||
from pytket.architecture import FullyConnected | ||
|
||
|
||
def _extract_basis_gates(backend: Backend) -> list[str]: | ||
standard_gate_mapping = get_standard_gate_name_mapping() | ||
for pred in backend.required_predicates: | ||
if type(pred) == GateSetPredicate: | ||
return [ | ||
_gate_str_2_optype_rev[optype] | ||
for optype in pred.gate_set | ||
if optype in _gate_str_2_optype_rev.keys() | ||
] | ||
if type(pred) is GateSetPredicate: | ||
basis_gates = [] | ||
# Restrict to the gate set accepted by the backend, the converters, | ||
# and the Target.from_configuration() method. | ||
for optype in pred.gate_set: | ||
if optype in _gate_str_2_optype_rev.keys(): | ||
gate_name = _gate_str_2_optype_rev[optype] | ||
if gate_name in standard_gate_mapping: | ||
gate_obj = standard_gate_mapping[gate_name] | ||
if gate_obj.num_qubits in [1, 2] or inspect.isclass(gate_obj): | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. See https://github.com/Qiskit/qiskit/blob/2ef371ae0d159a6dfd643805f3e5e5fdec37ab88/qiskit/transpiler/target.py#L1066 -- have to restrict the gateset to match what is accepted by the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do I understand correctly that the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, some gates such as CCX were rejected when I omitted this check. I am not sure when |
||
basis_gates.append(gate_name) | ||
return basis_gates | ||
return [] | ||
|
||
|
||
class TketBackend(BackendV1): | ||
class TketBackend(BackendV2): | ||
"""Wraps a :py:class:`Backend` as a :py:class:`qiskit.providers.BaseBackend` for use | ||
within the Qiskit software stack. | ||
|
||
|
@@ -87,31 +92,27 @@ def __init__(self, backend: Backend, comp_pass: Optional[BasePass] = None): | |
[[n.index[0], m.index[0]] for n, m in arch.coupling] if arch else None | ||
) | ||
|
||
config = QasmBackendConfiguration( | ||
backend_name=("statevector_" if backend.supports_state else "") | ||
super().__init__( | ||
name=("statevector_" if backend.supports_state else "") | ||
+ "pytket/" | ||
+ str(type(backend)), | ||
backend_version="0.0.1", | ||
n_qubits=len(arch.nodes) if arch and arch.nodes else 40, | ||
basis_gates=_extract_basis_gates(backend), | ||
gates=[], | ||
local=False, | ||
simulator=False, | ||
conditional=not any( | ||
( | ||
type(pred) == NoClassicalControlPredicate | ||
for pred in backend.required_predicates | ||
) | ||
), | ||
open_pulse=False, | ||
memory=backend.supports_shots, | ||
max_shots=10000, | ||
coupling_map=coupling, | ||
max_experiments=10000, | ||
) | ||
super().__init__(configuration=config, provider=None) | ||
self._backend = backend | ||
self._comp_pass = comp_pass | ||
self._target = Target.from_configuration( | ||
basis_gates=_extract_basis_gates(backend), | ||
num_qubits=len(arch.nodes) if arch and arch.nodes else 40, | ||
coupling_map=CouplingMap(coupling), | ||
) | ||
|
||
@property | ||
def target(self) -> Target: | ||
return self._target | ||
|
||
@property | ||
def max_circuits(self) -> int: | ||
return 10000 | ||
|
||
@classmethod | ||
def _default_options(cls) -> Options: | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Perhaps worth adding a comment explaining what these "if" statements are for?