Sample with Cirq
examples/cirq_sampler.py
The problem
Section titled “The problem”Run existing Cirq code through cirq.work.Sampler. QubitraSampler is a
cirq.work.Sampler, so code written against Cirq’s sampler interface runs on the
platform by swapping the sampler object and nothing else. The example samples a Bell
pair, then sweeps a rotation over five points as one job.
Needs the extra: pip install 'qubitra-sdk[cirq]'.
The walkthrough
Section titled “The walkthrough”The sampler
Section titled “The sampler”import cirqimport sympy
from qubitra import QubitraClientfrom qubitra.cirq import QubitraSampler with QubitraClient() as client: sampler = QubitraSampler(client, backend_id=backend_id) q0, q1 = cirq.LineQubit.range(2)QubitraSampler wraps a client and a backend id. Everything after this line is
ordinary Cirq.
A Bell pair through run
Section titled “A Bell pair through run” # -- a Bell pair, through cirq's single-run entry point ------------------- bell = cirq.Circuit([cirq.H(q0), cirq.CNOT(q0, q1), cirq.measure(q0, q1, key="m")]) print(f"running a Bell pair on {backend_id} ({SHOTS} shots)") result = sampler.run(bell, repetitions=SHOTS)
histogram = Counter("".join(str(bit) for bit in row) for row in result.measurements["m"]) print() for bits, count in sorted(histogram.items()): bar = "█" * round(40 * count / SHOTS) print(f" {bits} {count:5d} {bar}")sampler.run returns a cirq.Result whose measurements["m"] is one row per shot.
The example folds the rows into a histogram; an even split across 00 and 11 says
the entangling really happened.
A sweep, resolved before export
Section titled “A sweep, resolved before export” # -- a sweep: every point in ONE job -------------------------------------- theta = sympy.Symbol("theta") rotation = cirq.Circuit([cirq.ry(theta)(q0), cirq.measure(q0, key="m")]) sweep = cirq.Linspace("theta", start=0.0, stop=math.pi, length=SWEEP_POINTS)
print(f"\nsweeping theta over {SWEEP_POINTS} points, as one multi-PUB job") results = sampler.run_sweep(rotation, params=sweep, repetitions=SHOTS)The parameter is a sympy.Symbol and the sweep a cirq.Linspace, Cirq’s own sweep
vocabulary. Cirq exports OpenQASM 2, which carries no parameters, so the sampler
resolves each point locally and submits the whole sweep as one multi-PUB job — five
points is one round trip.
Read each point
Section titled “Read each point” print() for point in results: angle = float(point.params.value_of("theta")) p_one = float(point.measurements["m"].mean()) expected = math.sin(angle / 2) ** 2 bar = "█" * round(20 * p_one) print(f" theta={angle:5.3f} P(1)={p_one:.3f} (sin²={expected:.3f}) {bar}") return 0run_sweep returns one result per point, each carrying its parameter binding. Rotating
by theta about Y walks P(1) along sin²(θ/2), a curve you can check by eye.
Running it
Section titled “Running it”QUBITRA_API_KEY=qpk_... python examples/cirq_sampler.pyOutput from a live run:
running a Bell pair on sim-statevector-26q (1024 shots)
00 510 ████████████████████ 11 514 ████████████████████
sweeping theta over 5 points, as one multi-PUB job
theta=0.000 P(1)=0.000 (sin²=0.000) theta=0.785 P(1)=0.171 (sin²=0.146) ███ theta=1.571 P(1)=0.490 (sin²=0.500) ██████████ theta=2.356 P(1)=0.850 (sin²=0.854) █████████████████ theta=3.142 P(1)=1.000 (sin²=1.000) ████████████████████The Bell counts split evenly, and the five sampled probabilities track sin²(θ/2) to within shot noise.
Where to go next
Section titled “Where to go next”- Cirq — the full adapter: export, bit order, and sweep batching.
- Primitives and PUBs — the multi-PUB job the sweep becomes.