Source code for pytket.extensions.qiskit.backends.ibmq_emulator

# Copyright 2019-2024 Quantinuum
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

from collections import Counter
from typing import (
    Dict,
    Optional,
    List,
    Sequence,
    Tuple,
    Union,
)

from qiskit_aer.noise.noise_model import NoiseModel  # type: ignore

from qiskit_ibm_provider import IBMProvider  # type: ignore

from pytket.backends import (
    Backend,
    ResultHandle,
    CircuitStatus,
)
from pytket.backends.backendinfo import BackendInfo
from pytket.backends.backendresult import BackendResult
from pytket.backends.resulthandle import _ResultIdTuple
from pytket.circuit import Circuit
from pytket.passes import BasePass
from pytket.predicates import Predicate
from pytket.utils.results import KwargTypes

from .aer import AerBackend
from .ibm import IBMQBackend


[docs]class IBMQEmulatorBackend(Backend): """A backend which uses the AerBackend to loaclly emulate the behaviour of IBMQBackend. Identical to :py:class:`IBMQBackend` except there is no `monitor` parameter. Performs the same compilation and predicate checks as IBMQBackend. Requires a valid IBM account. """ _supports_shots = False _supports_counts = True _supports_contextual_optimisation = True _persistent_handles = False _supports_expectation = False
[docs] def __init__( self, backend_name: str, instance: Optional[str] = None, provider: Optional["IBMProvider"] = None, token: Optional[str] = None, ): super().__init__() self._ibmq = IBMQBackend( backend_name=backend_name, instance=instance, provider=provider, token=token, ) # Get noise model: self._noise_model = NoiseModel.from_backend(self._ibmq._backend) # Construct AerBackend based on noise model: self._aer = AerBackend(noise_model=self._noise_model) # cache of results keyed by job id and circuit index self._ibm_res_cache: Dict[Tuple[str, int], Counter] = dict()
@property def backend_info(self) -> BackendInfo: return self._ibmq._backend_info @property def required_predicates(self) -> List[Predicate]: return self._ibmq.required_predicates
[docs] def default_compilation_pass( self, optimisation_level: int = 2, placement_options: Optional[Dict] = None ) -> BasePass: """ See documentation for :py:meth:`IBMQBackend.default_compilation_pass`. """ return self._ibmq.default_compilation_pass( optimisation_level=optimisation_level, placement_options=placement_options )
@property def _result_id_type(self) -> _ResultIdTuple: return self._aer._result_id_type
[docs] def rebase_pass(self) -> BasePass: return self._ibmq.rebase_pass()
[docs] def process_circuits( self, circuits: Sequence[Circuit], n_shots: Union[None, int, Sequence[Optional[int]]] = None, valid_check: bool = True, **kwargs: KwargTypes, ) -> List[ResultHandle]: """ See :py:meth:`pytket.backends.Backend.process_circuits`. Supported kwargs: `seed`, `postprocess`. """ if valid_check: self._ibmq._check_all_circuits(circuits) return self._aer.process_circuits( circuits, n_shots=n_shots, valid_check=False, **kwargs )
[docs] def cancel(self, handle: ResultHandle) -> None: self._aer.cancel(handle)
[docs] def circuit_status(self, handle: ResultHandle) -> CircuitStatus: return self._aer.circuit_status(handle)
[docs] def get_result(self, handle: ResultHandle, **kwargs: KwargTypes) -> BackendResult: """ See :py:meth:`pytket.backends.Backend.get_result`. Supported kwargs: none. """ return self._aer.get_result(handle)