Skip to content

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.

Terminal window
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.

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 cirq
from 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.

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.

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.

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.