Source code for qiskit_aqt_provider.primitives.estimator

# This code is part of Qiskit.
#
# (C) Copyright Alpine Quantum Technologies GmbH 2023
#
# 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](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.

from __future__ import annotations

from collections.abc import Callable, Iterable
from typing import Any

from qiskit.primitives import (
    BackendEstimatorV2,
    BaseEstimatorV2,
    BasePrimitiveJob,
    PrimitiveResult,
    PubResult,
)
from qiskit.primitives.containers.estimator_pub import EstimatorPubLike
from qiskit.providers import BackendV2, Options

from qiskit_aqt_provider.aqt_provider import AnyAQTResource
from qiskit_aqt_provider.primitives._transpiling_backend import TranspilingBackend

BackendFactory = Callable[[AnyAQTResource], BackendV2]
EstimatorFactory = Callable[[BackendV2, dict[str, Any] | None], BaseEstimatorV2]


[docs] class AQTEstimator(BaseEstimatorV2): """:class:`BaseEstimatorV2 <qiskit.primitives.BaseEstimatorV2>` primitive for AQT backends. As circuit transpilation for AQT backends includes angle wrapping, the transpilation needs to be done after parameter binding. In order for the AQTEstimator to support parameterized circuits, it needs to transpile circuits when it is run. Providing options to the :class:`AQTEstimator` on instantiation will affect all circuit evaluations. Setting options on the backend has the same effect. Passing options in :meth:`AQTEstimator.run <qiskit.primitives.BaseEstimatorV2.run>` restricts the effect to that evaluation. """
[docs] def __init__( self, *, backend: AnyAQTResource, options: dict[str, Any] | None = None, ) -> None: self.backend = backend self._options = options or Options() self.backend_factory: BackendFactory = TranspilingBackend self.estimator_factory: EstimatorFactory = lambda b, o: BackendEstimatorV2(backend=b, options=o)
[docs] def run( self, pubs: Iterable[EstimatorPubLike], *, precision: float | None = None ) -> BasePrimitiveJob[PrimitiveResult[PubResult]]: """Run the given estimator PUBs on the AQT backend. Args: pubs (Iterable): An iterable of estimator PUBs, which may include parameterized circuits and associated parameter values. precision (float | None): The precision to use for the estimation. Defaults to None. Returns: qiskit.primitives.BasePrimitiveJob[qiskit.primitives.PrimitiveResult[qiskit.primitives.PubResult]]: A job representing the execution of the estimator PUBs. """ wrapped_backend = self.backend_factory(self.backend) delegate = self.estimator_factory(wrapped_backend, self._options) return delegate.run(pubs, precision=precision)