Skip to content

Submit an IonQ circuit

examples/submit_ionq_circuit.py

Submit a circuit in a provider’s JSON format. Several providers accept the IonQ circuit schema — a gateset, a qubit count and a list of gates — and client.backends.list() reports which backends take it in their supported_formats. The example submits the same Bell pair as submit_bell_pair.py, expressed as that document.

from qubitra import CircuitFormat, QubitraClient
# A Bell pair as an IonQ circuit: `h` on qubit 0, then `x` on qubit 1 controlled by qubit 0.
# `gateset: "qis"` is the standard gate-level set, as against IonQ's native-gate mode.
BELL = {
"gateset": "qis",
"qubits": 2,
"circuit": [
{"gate": "h", "targets": [0]},
{"gate": "x", "targets": [1], "controls": [0]},
],
}
SHOTS = 1024

The document is a Python dict here for readability; what travels is its JSON text. Each entry in "circuit" names a gate, its target qubits, and any control qubits — the CNOT is x with a controls list.

job = client.jobs.submit(
backend_id=backend_id,
circuit=json.dumps(BELL),
circuit_format=CircuitFormat.IONQ_CIRCUIT,
shots=SHOTS,
name="bell-pair (IonQ)",
)
print(f"submitted {job.id} to {backend_id} — {job.status}")

circuit is text whatever the format: the dict passes through json.dumps, and CircuitFormat.IONQ_CIRCUIT tells the platform how to parse it. The platform parses the document at the vendor edge, so the SDK carries it opaquely.

# A live queue can outlast a short wait, and the platform keeps polling either way —
# so this waits longer than the SDK's default rather than reporting a timeout as
# though the job had failed.
job = client.jobs.wait(job.id, timeout=900, poll_interval=5)
print(f"finished {job.id} — {job.status}")

Backends that take this schema are typically vendor hardware with a live queue, so the example waits up to fifteen minutes. wait timing out leaves the job running on the platform; a later client.jobs.get(job.id) picks it back up.

counts = client.jobs.result(job.id).counts or {}
total = sum(counts.values()) or 1
print()
for outcome, count in sorted(counts.items(), key=lambda kv: -kv[1]):
share = 100 * count / total
print(f" {outcome} {count:6} {share:5.1f}% {'█' * round(share / 2)}")
return 0

The result comes back in the same normalized shape as every other job: counts maps bitstrings to frequencies.

The example takes the backend id as a required argument — pick one whose supported_formats includes IONQ_CIRCUIT, from the catalogue list_backends.py prints:

Terminal window
QUBITRA_API_KEY=qpk_... python examples/submit_ionq_circuit.py <backend-id>

Output from a live run at 1024 shots, trimmed to the counts:

11 521 50.9% █████████████████████████
00 503 49.1% █████████████████████████

The same distribution as the OpenQASM run: the document expresses the same circuit.