Qiskit Primitives

Overview

This page describes the Sampler and Estimator primitives provided by the Quantum Rings toolkit for Qiskit. Use them to execute Qiskit circuits and retrieve sampled measurement data or expectation values on Quantum Rings backends.

If you are using the Core SDK directly (QuantumRingsLib), you can execute circuits with backend.run(...). See Circuits.

For installation and toolkit setup, see Toolkit for Qiskit. For API signatures, see API Reference.

Primitive Unified Block (PUB)

Sampler PUB

A Sampler primitive unified block (PUB) is a tuple of:

(circuit, <optional> parameter values, <optional> shots)

Estimator PUB

An Estimator primitive unified block (PUB) is a tuple of:

(circuit, observables, <optional> parameter values, <optional> precision)

In both cases, the run(...) method accepts a sequence of PUBs.

Preparing ISA circuits and observables

The toolkit examples prepare circuits and observables using a preset pass manager before passing them to primitives.

Example:

from quantumrings.toolkit.qiskit import QrRuntimeService
from quantumrings.toolkit.qiskit import QrSamplerV2 as Sampler
from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager

service = QrRuntimeService(token=<YOUR_TOKEN_HERE>, name=<YOUR_ACCOUNT_NAME_HERE>)
backend = service.backend(name="scarlet_quantum_rings",
                          precision="single",
                          gpu=0,
                          num_qubits=12)
# Circuit
circuit = QuantumCircuit(2, 2)
circuit.h(0)
circuit.cx(0, 1)
circuit.measure_all()

pm = generate_preset_pass_manager(backend=backend, optimization_level=1)
isa_circuit = pm.run(circuit)

The Estimator example additionally applies the layout to observables:

observable = SparsePauliOp.from_list([("II", -1.052373245772859),("ZZ", -0.01128010425623538)])

isa_observable = observable.apply_layout(isa_circuit.layout)

Sampler V2 (bitstring sampling)

Perform bitstring sampling using QrSamplerV2.

from qiskit import QuantumCircuit
from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager

from quantumrings.toolkit.qiskit import QrRuntimeService
from quantumrings.toolkit.qiskit import QrSamplerV2 as Sampler

# Acquire backend
service = QrRuntimeService(token="<YOUR_TOKEN_HERE>", name="<YOUR_ACCOUNT_NAME_HERE>")
backend = service.backend(name="scarlet_quantum_rings", precision="single", gpu=0, num_qubits=2)

# Circuit
circuit = QuantumCircuit(2, 2)
circuit.h(0)
circuit.cx(0, 1)
circuit.measure_all()

# Transpile to the backend ISA
pm = generate_preset_pass_manager(backend=backend, optimization_level=1)
isa_circuit = pm.run(circuit)

# Run with Sampler V2
sampler = Sampler(backend=backend)
job = sampler.run([isa_circuit])
result = job.result()

pub_result = result[0]
print(pub_result.data.meas.get_bitstrings()[:10])

Note

The toolkit documentation recommends using V2 primitives. If you need quasi-distributions, be aware that the V2 sampler does not provide quasi-distribution outputs directly.

Estimator V2

Compute expectation values for an observable using QrEstimatorV2.

from qiskit import QuantumCircuit
from qiskit.quantum_info import SparsePauliOp
from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager

from quantumrings.toolkit.qiskit import QrRuntimeService
from quantumrings.toolkit.qiskit import QrEstimatorV2 as Estimator

# Acquire backend
service = QrRuntimeService(token="<YOUR_TOKEN_HERE>", name="<YOUR_ACCOUNT_NAME_HERE>")
backend = service.backend(name="scarlet_quantum_rings", precision="double", gpu=0, num_qubits=2)

# Observable
op = SparsePauliOp.from_list(
    [
        ("II", -1.052373245772859),
        ("IZ", 0.39793742484318045),
        ("ZI", -0.39793742484318045),
        ("ZZ", -0.01128010425623538),
        ("XX", 0.18093119978423156),
    ]
)

# State preparation
circuit = QuantumCircuit(2, 2)
circuit.x(0)
circuit.x(1)

# Transpile + align observable to layout
pm = generate_preset_pass_manager(backend=backend, optimization_level=1)
isa_circuit = pm.run(circuit)
isa_observable = op.apply_layout(isa_circuit.layout)

estimator = Estimator(backend=backend)
job = estimator.run([(isa_circuit, isa_observable)])

pub_result = job.result()[0]
print(f"Expectation value: {pub_result.data.evs[0]}")

Options and run_options

Sampler and Estimator accept configuration dictionaries via options and run_options. Documented keys include:

  • backend

  • precision

  • gpu

  • shots

  • mode

  • performance

  • threshold

  • transfer_to_cpu

See Run Settings for execution configuration guidance and API Reference for API details.

Statevector primitives

The toolkit also provides:

  • QrStatevectorSampler

  • QrStatevectorEstimator

These follow the same pattern: create the primitive and call run(pubs, ...).

See also