Cirq
QubitraSampler is a cirq.work.Sampler. Code written against Cirq’s sampler
interface — run, run_sweep, sample — executes on a Qubitra backend by swapping in
this sampler object; nothing else changes.
pip install 'qubitra-sdk[cirq]'The base install carries no quantum framework; the cirq extra brings cirq-core in.
Importing qubitra.cirq without it raises an error naming that command.
The Sampler
Section titled “The Sampler”Construct it around an existing QubitraClient, or let it build its own from
QUBITRA_API_KEY / QUBITRA_API_URL (or explicit api_key= / api_url= keywords).
backend_id defaults to sim-statevector-26q, the exact simulator.
import cirqfrom qubitra.cirq import QubitraSampler
sampler = QubitraSampler(backend_id="sim-statevector-26q")
q0, q1 = cirq.LineQubit.range(2)bell = cirq.Circuit([cirq.H(q0), cirq.CNOT(q0, q1), cirq.measure(q0, q1, key="m")])
result = sampler.run(bell, repetitions=1024)print(result.histogram(key="m")) # Counter({0: 512, 3: 512})result is an ordinary cirq.Result: measurements["m"] is the per-repetition array
keyed by your measurement key, exactly where Cirq code expects to find it.
Parameter sweeps: one job
Section titled “Parameter sweeps: one job”run_sweep takes any cirq.Sweepable and submits the whole sweep as one job, one
PUB per parameter set:
import sympy
theta = sympy.Symbol("theta")rotation = cirq.Circuit([cirq.ry(theta)(q0), cirq.measure(q0, key="m")])
results = sampler.run_sweep( rotation, params=cirq.Linspace("theta", start=0.0, stop=3.14159, length=40), repetitions=1024,)The platform’s round trip is dominated by orchestration rather than simulation, so a
40-point sweep submitted as one job costs one round trip instead of forty. Results come
back index-aligned with the sweep, each carrying its resolver in result.params.
How circuits travel
Section titled “How circuits travel”Cirq exports OpenQASM 2, which has no parameters — there is no input declaration for a
symbol to travel through. The sampler therefore resolves each parameter set locally
(cirq.resolve_parameters) and exports each fully-resolved circuit; a symbol the sweep
leaves unbound is rejected by name before submission.
The same boundary applies to gates: an operation with no OpenQASM 2 representation (after
Cirq’s own decomposition) is rejected client-side. Qubit order follows Cirq’s sorted
qubit order, and each measurement key becomes its own classical register, so keys map
back onto result.measurements untouched — including keys OpenQASM identifiers cannot
spell.
What comes back
Section titled “What comes back”The platform returns aggregated counts per circuit, not a shot-by-shot record. The
per-repetition rows in each cirq.Result are synthesized from those counts in
deterministic (sorted-bitstring) order:
- the histogram is real — it is exactly what the backend measured;
- correlations across measurement keys within a row are real — each row expands one measured bitstring covering every key;
- the row order is synthetic — consecutive rows say nothing about consecutive shots.
Do not read order-sensitive structure across repetitions; it was not measured.