Source code for scikit_quri.backend.scaluq_estimator

from typing import Sequence

import numpy as np
from numpy.typing import NDArray
from quri_parts.circuit import ParametricQuantumCircuitProtocol
from quri_parts.core.estimator import Estimatable
from quri_parts.qulacs.estimator import create_qulacs_vector_concurrent_estimator

from quri_parts_scaluq import _backend
from quri_parts_scaluq.estimator import estimate as scaluq_estimate
from quri_parts_scaluq.estimator import estimate_numerical_gradient as scaluq_grad

from .base_estimator import BatchedSimEstimator


[docs]class ScaluqEstimator(BatchedSimEstimator): """Batched expectation-value estimator backed by scaluq. The primary API is ``estimate_batched`` / ``estimate_grad_batched``, which evaluate a single parametric circuit topology over many parameter vectors in one backend call. The non-batched ``estimate(operators, states)`` is implemented as a fallback that defers to qulacs; it is provided so that consumers expecting the ``BaseEstimator`` contract still work, but the batched methods are what give scaluq its speedup. """ def __init__(self) -> None: self._concurrent_estimator = create_qulacs_vector_concurrent_estimator()
[docs] def estimate(self, operators, states): return self._concurrent_estimator(operators, states)
[docs] def estimate_batched( self, operators: Sequence[Estimatable], circuit: ParametricQuantumCircuitProtocol, params: NDArray[np.float64], ) -> list[list[float]]: state = _backend.StateVectorBatched(len(params), circuit.qubit_count) state.set_zero_state() return scaluq_estimate(state, circuit, operators, params)
[docs] def estimate_grad_batched( self, operators: Sequence[Estimatable], circuit: ParametricQuantumCircuitProtocol, shifted_params: NDArray[np.float64], n_samples: int, n_learning_params: int, delta: float = 1e-5, ) -> NDArray[np.float64]: return scaluq_grad(circuit, operators, shifted_params, n_samples, n_learning_params, delta)