# Sampler

Unlike statevector simulation, sampling measurements are necessary in order to estimate expectation value of operators on a quantum computer. In sampling measurements, execution of a quantum circuit and a subsequent measurement of qubits are repeated multiple times. Estimation of expectation value of operators is then performed using statistics of the repeated measurements.

To perform a sampling measurement of a circuit, you can use a Sampler. Here we introduce the definition of Sampler and explain how it can be created or executed.

## Prerequisite​

QURI Parts modules used in this tutorial: quri-parts-circuit, quri-parts-core and quri-parts-qulacs. You can install them as follows:

!pip install "quri-parts[qulacs]"

## Prepare a circuit​

As a preparation, we create a circuit to be sampled:

from math import pifrom quri_parts.circuit import QuantumCircuit# A circuit with 4 qubitscircuit = QuantumCircuit(4)circuit.add_X_gate(0)circuit.add_H_gate(1)circuit.add_Y_gate(2)circuit.add_CNOT_gate(1, 2)circuit.add_RX_gate(3, pi/4)

## Interface​

When performing a sampling measurement for a circuit, you can use a Sampler. In QURI Parts, a Sampler represents a function that samples a specified (non-parametric) circuit by a specified times and returns the count statistics. In the case of an ideal Sampler, the return value corresponds to probabilities multiplied by shot count.

In the case where sampling from multiple circuits is desired, QURI Parts also provide ConcurrentSampler, which is a function that samples from multiple (circuit, shot) pairs.

Sampler and ConcurrentSampler are both abstract interfaces with the following function signatures:

from typing import Callable, Iterable, Mapping, Unionfrom typing_extensions import TypeAliasfrom quri_parts.circuit import NonParametricQuantumCircuit#: MeasurementCounts represents count statistics of repeated measurements of a quantum#: circuit. Keys are observed bit patterns encoded in integers and values are counts#: of observation of the corresponding bit patterns.MeasurementCounts: TypeAlias = Mapping[int, Union[int, float]]#: Sampler represents a function that samples a specified (non-parametric) circuit by#: a specified times and returns the count statistics. In the case of an ideal Sampler,# the return value corresponds to probabilities multiplied by shot count.Sampler: TypeAlias = Callable[[NonParametricQuantumCircuit, int], MeasurementCounts]#: ConcurrentSampler represents a function that samples specified (non-parametric)#: circuits concurrently.ConcurrentSampler: TypeAlias = Callable[    [Iterable[tuple[NonParametricQuantumCircuit, int]]], Iterable[MeasurementCounts]]

The Sampler itself (defined in quri_parts.core.sampling) is an abstract interface and you need a concrete instance to actually perform sampling. There are several implementations of Sampler interface, some of which use a circuit simulator while others use a real quantum computer.

## Create and execute sampler​

Let's create a sampler using state vector simulation with Qulacs and execute sampling with it.

from quri_parts.qulacs.sampler import create_qulacs_vector_sampler# Create the samplersampler = create_qulacs_vector_sampler()sampling_result = sampler(circuit, shots=1000)print(sampling_result)
# output    Counter({5: 423, 3: 419, 13: 90, 11: 68})

MeasurementCounts is actually a python dict with keys are the observed bit patterns and values are counts.

## List of available samplers​

Here is the list of available samplers in QURI Parts. You can set the options for each simulator as the arguments of it's generating function.

ModuleGenerating functionNoiseType
quri-parts-itensorcreate_itensor_mps_sampler(Concurrent)MPS
quri-parts-qulacscreate_qulacs_vector_sampler(Concurrent)
create_qulacs_vector_ideal_sampler
create_qulacs_stochastic_state_vector_sampler(Concurrent)
create_qulacs_density_matrix_sampler(Concurrent)
create_qulacs_density_matrix_ideal_sampler
create_qulacs_noisesimulator_sampler(Concurrent)

Statevector
Statevector
Statevector
Density matrix
Density matrix
NoiseSimulator
quri-parts-stimcreate_stim_clifford_sampler(Concurrent)Clifford

You can also create a Sampler with create_sampler_from_sampling_backend(link) in conjunction with SamplingBackend. Below is the list of SamplingBackend available in QURI Parts:

ModuleBackendClass
quri-parts-braketAWS BraketBraketSamplingBackend
quri-parts-qiskitQiskitQiskitSamplingBackend
QiskitRuntimeSamplingBackend

For more details please refer to the series of tutorials about sampling using real devices: