Install
$ pip install limbo-quantum
The SDK itself is pure-Python with no required runtime dependencies. Pull in the circuit framework you'll feed in:
$ pip install 'limbo-quantum[qiskit]' # most common
$ pip install 'limbo-quantum[cirq]'
$ pip install 'limbo-quantum[qasm3]'
To submit directly to a vendor cloud, install the corresponding backend extra:
$ pip install 'limbo-quantum[ibm]' # IBM Quantum $ pip install 'limbo-quantum[aws]' # AWS Braket $ pip install 'limbo-quantum[azure]' # Azure Quantum $ pip install 'limbo-quantum[all]' # everything
Quickstart
DistributedCompilerSDK is the single entry point. Construct once with a provider, call .compile() for every circuit.
from qiskit import QuantumCircuit
from limbo_quantum import DistributedCompilerSDK, LocalSimulationProvider
# Local simulator — zero credentials, zero network.
sdk = DistributedCompilerSDK(
provider=LocalSimulationProvider(),
num_qpus=2,
max_capacity_per_qpu=4,
)
qc = QuantumCircuit(4)
qc.h(0)
for i in range(3):
qc.cx(0, i + 1)
qc.measure_all()
result = sdk.compile(qc, shots=1024)
print(result.counts)
print(result.compiled_qasm[0])
Execution backends
Limbo does not lock you into any one path. The SDK is structured around a narrow QuantumProvider interface with three shipped implementations plus a documented extension point. Pick the path that matches your workflow:
Path A — Local simulator (no account, no network)
from limbo_quantum import DistributedCompilerSDK, LocalSimulationProvider
sdk = DistributedCompilerSDK(
provider=LocalSimulationProvider(),
num_qpus=2, max_capacity_per_qpu=4,
)
Path B — Hosted Limbo backend (one account, multiple vendors)
CloudProductionProvider is an HTTP client for the hosted compile service. The service holds your IBM / AWS Braket / Azure Quantum credentials encrypted server-side and runs the multi-chip-aware partitioner + cross-chip scheduler. You manage one API key; the service brokers the rest. Generate a key from your dashboard.
from limbo_quantum import DistributedCompilerSDK, CloudProductionProvider
sdk = DistributedCompilerSDK(
provider=CloudProductionProvider(
api_key="lmb_live_YOUR_KEY_HERE",
server_url="https://api.limbosys.dev",
),
num_qpus=4, max_capacity_per_qpu=20,
)
For multi-environment workflows, auto_provider() reads LIMBO_API_KEY and LIMBO_SERVER_URL from the environment and falls back to the local simulator when neither is set:
from limbo_quantum import DistributedCompilerSDK, auto_provider sdk = DistributedCompilerSDK(provider=auto_provider())
Path C — Direct to a vendor (IBM / AWS / Azure)
If you already have vendor quotas, the SDK ships first-class wrappers for the three major clouds. Install the right extra and pass an instance to the SDK — no subclassing required.
# IBM Quantum · pip install 'limbo-quantum[ibm]'
from limbo_quantum import DistributedCompilerSDK, IBMProvider
sdk = DistributedCompilerSDK(
provider=IBMProvider(token="...", backend_name="ibm_brisbane"),
num_qpus=1, max_capacity_per_qpu=127,
)
# AWS Braket · pip install 'limbo-quantum[aws]' from limbo_quantum import DistributedCompilerSDK, AWSProvider sdk = DistributedCompilerSDK( provider=AWSProvider( device_arn="arn:aws:braket:::device/quantum-simulator/amazon/sv1", ), num_qpus=1, max_capacity_per_qpu=34, ) # AWS creds: standard boto3 chain — env vars, ~/.aws/credentials, IAM role.
# Azure Quantum · pip install 'limbo-quantum[azure]' from limbo_quantum import DistributedCompilerSDK, AzureProvider sdk = DistributedCompilerSDK( provider=AzureProvider( subscription_id="...", resource_group="quantum-rg", workspace_name="my-workspace", location="eastus", target_name="ionq.qpu", ), num_qpus=1, max_capacity_per_qpu=23, ) # Azure auth: DefaultAzureCredential (az login / managed identity / SP env vars).
All three providers handle QASM → vendor-circuit translation, job submission, status polling, and result decoding for you. They lazy-import their vendor SDK so import limbo_quantum stays fast even if you've installed only one of the extras.
Path D — Bring your own backend
If you're targeting something else (Quantinuum, IonQ direct, Rigetti, a self-hosted Aer cluster, anything), subclass QuantumProvider with three methods:
from limbo_quantum import QuantumProvider, Job, JobResult
class MyBackend(QuantumProvider):
name = "mine"
def submit(self, payload, *, shots=1024, **options) -> Job:
"""Send compiled QASM. Return a Job."""
...
def _fetch_status(self, job_id: str) -> JobResult:
"""Poll. Return JobResult with status in
{queued, running, completed, failed}."""
...
def list_devices(self) -> list[dict]:
"""Optional device catalog for auto-routing. Can be []."""
...
The shipped IBM / AWS / Azure providers (limbo_quantum/vendors.py in the repo) are full reference implementations of this pattern — copy one as a starting point.
Which path to choose
| Scenario | Use |
|---|---|
| Prototyping, CI, anything Aer can run | Path A · LocalSimulationProvider |
| One bill, one credential, multi-chip-aware compile server-side | Path B · CloudProductionProvider |
| You already have IBM / AWS / Azure quotas | Path C · IBMProvider / AWSProvider / AzureProvider |
| Anything else (Quantinuum, IonQ direct, custom) | Path D · subclass QuantumProvider |
Multi-framework ingestion
The same .compile() call accepts Qiskit circuits, Cirq circuits, or raw OpenQASM 3 source strings. Auto-dispatched by input type:
# Qiskit from qiskit import QuantumCircuit qc = QuantumCircuit(3); qc.h(0); qc.cx(0, 1); qc.cx(0, 2) sdk.compile(qc) # Cirq import cirq q0, q1, q2 = cirq.LineQubit.range(3) cq = cirq.Circuit(cirq.H(q0), cirq.CNOT(q0, q1), cirq.CNOT(q0, q2)) sdk.compile(cq) # OpenQASM 3 source string qasm = """ OPENQASM 3.0; include "stdgates.inc"; qubit[3] q; h q[0]; cx q[0], q[1]; cx q[0], q[2]; """ sdk.compile(qasm)
Local linting
The SDK linter runs before any network call. Capacity violations and interaction-graph hotspots are surfaced on your laptop with no cloud round-trip needed:
from limbo_quantum import CircuitParser, LocalStaticLinter, TopologyCapacityError
ir = CircuitParser.from_qiskit(qc)
linter = LocalStaticLinter(ir, num_qpus=2, max_capacity_per_qpu=4)
try:
linter.capacity_audit()
except TopologyCapacityError as exc:
# Caught locally. No paid API call burned.
print(f"needed {exc.num_qubits} qubits, layout had {exc.target_capacity}")
linter.hotspot_detection(threshold_ratio=0.30) # prints dashboard
Variational runtime (VQE / QAOA)
For parametric circuits, ParametricRuntime compiles the template once and binds parameters locally on each subsequent call. The cache key is a SHA-256 of the circuit's structural signature, so different parameter values share a cache entry but a different gate sequence forces a re-compile.
from qiskit import QuantumCircuit
from qiskit.circuit import Parameter
from limbo_quantum import ParametricRuntime, InProcessCompilerClient
theta = Parameter("theta")
qc = QuantumCircuit(2)
qc.ry(theta, 0)
qc.cx(0, 1)
qc.measure_all()
runtime = ParametricRuntime(qc, client=InProcessCompilerClient())
for theta_val in [0.0, 0.1, 0.2, 0.3]:
result = runtime.run({theta: theta_val}, shots=512)
# First call: heavy compile. Subsequent calls: bind-only.
print(theta_val, result.counts)
Telemetry
The TelemetryLogger auto-detects Jupyter vs. terminal and prints a clean per-step timeline:
from limbo_quantum import (
DistributedCompilerSDK, LocalSimulationProvider, TelemetryLogger,
)
sdk = DistributedCompilerSDK(
provider=LocalSimulationProvider(),
num_qpus=2, max_capacity_per_qpu=4,
telemetry=TelemetryLogger(),
)
sdk.compile(qc, shots=1024)
# Prints step durations, payload sizes, and lint outcomes.
Correctness scope
Limbo is a faithful transport for circuits that fit on your chosen target device. If circuit_qubits ≤ device_qubits, the SDK ingests, optionally pre-optimizes (Qiskit passes only), transpiles against the device's coupling map, and submits via the provider's official SDK. The result is semantically identical to what direct Qiskit + the vendor's SDK would produce.
The multi-chip routing path (when your circuit doesn't fit on a single physical device and the SDK partitions across multiple QPUs) is research-grade. There is no commercial cloud QPU today that exposes a multi-chip interconnect, so the cross-chip operations the SDK produces can only be validated on a simulator. Don't ship a num_qpus > 1 configuration to a single-chip cloud backend and expect correct results — the cross-chip entanglement won't be implemented.
API reference
Top-level exports from limbo_quantum:
| Symbol | Purpose |
|---|---|
| DistributedCompilerSDK | Master client; one .compile() call drives the whole pipeline. |
| CompileResult | Dataclass returned by .compile() with counts, QASM, metrics, telemetry. |
| quickstart() | One-liner for laptop dev (LocalSimulationProvider). |
| QuantumProvider | Abstract base for custom execution backends. |
| LocalSimulationProvider | In-process qiskit-aer driver. |
| CloudProductionProvider | HTTP client for the hosted Limbo backend. |
| IBMProvider | Direct IBM Quantum execution via qiskit-ibm-runtime. |
| AWSProvider | Direct AWS Braket execution via amazon-braket-sdk. |
| AzureProvider | Direct Azure Quantum execution via azure-quantum. |
| auto_provider() | Cloud if LIMBO_API_KEY / LIMBO_SERVER_URL set, else local. |
| CircuitParser | Multi-framework parser → standardized JSON IR. |
| IRSchema | Schema descriptor for the JSON IR shape. |
| LocalStaticLinter | Capacity audit + hotspot detection. |
| TopologyCapacityError | Raised when the target layout can't host the circuit. |
| ParametricRuntime | Compile-once-bind-many runtime for variational workloads. |
| TopologicalTemplate | Cached structural compile for parametric circuits. |
| InProcessCompilerClient | Local compile client for ParametricRuntime. |
| HTTPCompilerClient | HTTP compile client for ParametricRuntime against a hosted backend. |
| TelemetryLogger | Jupyter / terminal step-timeline display. |
| Job · JobResult | Handle + result-payload dataclasses returned by providers. |
View on PyPI View on GitHub Join the waitlist for cloud backend access