Backend Sampling#
- backend_sampler(backend)[source]#
Route
sample()andexpectation_value()to a backend.Calls to these functions are executed on a real backend instead of the Jaspify simulator.
Warning
The decorated function must use
sample()orexpectation_value()to trigger quantum execution. Direct quantum operations (gates, measurements) without a surrounding sample/EV call will raise aRuntimeErrorpointing you tojaspify().Warning
Sampling kernels that rely on real-time feedback (e.g. mid-circuit measurements whose outcomes condition subsequent gates) are not supported.
backend_samplerextracts and flattens the quantum circuit into a single static circuit before execution, so any classical control flow that depends on measurement results inside the kernel cannot be captured. Usejaspify()for such workloads.Note
Only the quantum circuit is executed on the backend. All orchestration logic (the code in the decorated function that calls
sample()andexpectation_value(), passes arguments, and combines results) is traced into a Jaspr and compiled viajax.jit(). This means the non-coherence wrapping logic runs at JAX speed, even when orchestrating many sampling calls.- Parameters:
- backendBackend Interface
The backend to execute on. See the Backend Interface documentation for available backends.
- Returns:
- callable
A decorator wrapping a Jasp-compatible function.
- Raises:
- RuntimeError
If the decorated function contains quantum operations without a surrounding
sample()orexpectation_value()call. Usejaspify()for single-shot simulation.- RuntimeError
If a sampling kernel contains real-time feedback (mid-circuit measurements whose outcomes — after classical post-processing — control subsequent quantum gates). The kernel’s quantum circuit must be fully static so it can be extracted and executed once. Use
jaspify()for such workloads.
Examples
Basic sampling through a backend:
from qrisp import QuantumFloat, h, measure from qrisp.jasp import sample, expectation_value, backend_sampler from qrisp.interface import QrispSimulatorBackend backend = QrispSimulatorBackend() @backend_sampler(backend=backend) def main(k): def kernel(k): qf = QuantumFloat(4) h(qf[0]) return measure(qf) return sample(kernel, shots=100)(k) result = main(1) # result is a JAX array of shape (100,) with backend results
Using a different backend – any
Backendworks, for instance Qiskit’sAerSimulator:from qiskit_aer import AerSimulator from qrisp.interface import QiskitBackend backend = QiskitBackend(backend=AerSimulator()) @backend_sampler(backend=backend) def main(): def kernel(): qv = QuantumFloat(3) h(qv) return measure(qv) return sample(kernel, shots=200)() result = main()
Using
expectation_value():@backend_sampler(backend=backend) def main(): def kernel(): qf = QuantumFloat(4) h(qf[0]) h(qf[1]) return measure(qf) return expectation_value(kernel, shots=500)() ev = main() # scalar or vector JAX array
Multiple sample / expectation_value calls in the same function:
@backend_sampler(backend=backend) def main(): def kernel_a(): qf = QuantumFloat(3) h(qf[0]) return measure(qf) def kernel_b(): qf = QuantumFloat(3) h(qf[1]) return measure(qf) samples_a = sample(kernel_a, shots=100)() samples_b = sample(kernel_b, shots=50)() return samples_a, samples_b a, b = main() # Each call is independently routed through the backend.