Source code for qiskit.primitives.base.base_sampler

# This code is part of Qiskit.
# (C) Copyright IBM 2022.
# 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
# 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.

Overview of Sampler

Sampler class calculates probabilities or quasi-probabilities of bitstrings from quantum circuits.

A sampler is initialized with an empty parameter set. The sampler is used to
create a :class:`~qiskit.providers.JobV1`, via the :meth:``
method. This method is called with the following parameters

* quantum circuits (:math:`\psi_i(\theta)`): list of (parameterized) quantum circuits.
  (a list of :class:`~qiskit.circuit.QuantumCircuit` objects)

* parameter values (:math:`\theta_k`): list of sets of parameter values
  to be bound to the parameters of the quantum circuits.
  (list of list of float)

The method returns a :class:`~qiskit.providers.JobV1` object, calling
:meth:`qiskit.providers.JobV1.result()` yields a :class:`~qiskit.primitives.SamplerResult`
object, which contains probabilities or quasi-probabilities of bitstrings,
plus optional metadata like error bars in the samples.

Here is an example of how sampler is used.

.. code-block:: python

    from qiskit.primitives import Sampler
    from qiskit import QuantumCircuit
    from qiskit.circuit.library import RealAmplitudes

    # a Bell circuit
    bell = QuantumCircuit(2)
    bell.h(0), 1)

    # two parameterized circuits
    pqc = RealAmplitudes(num_qubits=2, reps=2)
    pqc2 = RealAmplitudes(num_qubits=2, reps=3)

    theta1 = [0, 1, 1, 2, 3, 5]
    theta2 = [0, 1, 2, 3, 4, 5, 6, 7]

    # initialization of the sampler
    sampler = Sampler()

    # Sampler runs a job on the Bell circuit
    job =[bell], parameter_values=[[]], parameters=[[]])
    job_result = job.result()
    print([q.binary_probabilities() for q in job_result.quasi_dists])

    # Sampler runs a job on the parameterized circuits
    job2 =
        circuits=[pqc, pqc2],
        parameter_values=[theta1, theta2],
        parameters=[pqc.parameters, pqc2.parameters])
    job_result = job2.result()
    print([q.binary_probabilities() for q in job_result.quasi_dists])

from __future__ import annotations

from abc import abstractmethod
from import Sequence
from copy import copy
from typing import Generic, TypeVar

from qiskit.utils.deprecation import deprecate_func
from qiskit.circuit import QuantumCircuit
from qiskit.circuit.parametertable import ParameterView
from qiskit.providers import JobV1 as Job

from .base_primitive import BasePrimitive
from . import validation

T = TypeVar("T", bound=Job)

class BaseSampler(BasePrimitive, Generic[T]):
    """Sampler base class

    Base class of Sampler that calculates quasi-probabilities of bitstrings from quantum circuits.

    __hash__ = None

    def __init__(
        options: dict | None = None,
            options: Default options.
        self._circuits = []
        self._parameters = []

    def run(
        circuits: QuantumCircuit | Sequence[QuantumCircuit],
        parameter_values: Sequence[float] | Sequence[Sequence[float]] | None = None,
    ) -> T:
        """Run the job of the sampling of bitstrings.

            circuits: One of more circuit objects.
            parameter_values: Parameters to be bound to the circuit.
            run_options: Backend runtime options used for circuit execution.

            The job object of the result of the sampler. The i-th result corresponds to
            ``circuits[i]`` evaluated with parameters bound as ``parameter_values[i]``.

            ValueError: Invalid arguments are given.
        # Validation
        circuits, parameter_values = validation._validate_sampler_args(circuits, parameter_values)

        # Options
        run_opts = copy(self.options)

        return self._run(

    def _run(
        circuits: tuple[QuantumCircuit, ...],
        parameter_values: tuple[tuple[float, ...], ...],
    ) -> T:
        raise NotImplementedError("The subclass of BaseSampler must implement `_run` method.")

    def _validate_circuits(
        circuits: Sequence[QuantumCircuit] | QuantumCircuit,
    ) -> tuple[QuantumCircuit, ...]:
        return validation._validate_circuits(circuits, requires_measure=True)

    def circuits(self) -> tuple[QuantumCircuit, ...]:
        """Quantum circuits to be sampled.

            The quantum circuits to be sampled.
        return tuple(self._circuits)

    def parameters(self) -> tuple[ParameterView, ...]:
        """Parameters of quantum circuits.

            List of the parameters in each quantum circuit.
        return tuple(self._parameters)