Compiler API¶
This page documents the primary user-facing classes for compiling quantum circuits with qb-compiler.
QBCompiler¶
The main entry point. Create an instance via
from_backend() and call
compile() to compile a circuit.
- class qb_compiler.compiler.QBCompiler(backend: str | None = None, calibration: CalibrationProvider | None = None, strategy: str = 'fidelity_optimal', calibration_properties: BackendProperties | None = None, qiskit_target: Any | None = None)¶
Bases:
objectHigh-level compiler for quantum circuits.
- Parameters:
backend – Target backend key (e.g.
"ibm_fez").calibration – Optional live calibration provider for noise-aware compilation.
strategy –
"fidelity_optimal"(default) trades compilation time for estimated output fidelity."depth_optimal"minimises depth."budget_optimal"minimises estimated cost.
- STRATEGIES = frozenset({'budget_optimal', 'depth_optimal', 'fidelity_optimal'})¶
- compile(circuit: QBCircuit, *, strategy: str | None = None, budget_usd: float | None = None, qec_aware: bool = False) CompileResult¶
Compile circuit and return a
CompileResult.- Parameters:
circuit – Input circuit to compile.
strategy – Override the compiler-level strategy for this call.
budget_usd – If set, the compiler raises
BudgetExceededErrorwhen estimated cost at 1024 shots exceeds this amount.qec_aware – Reserve ancilla qubits for QEC syndrome extraction (future).
- compile_enhanced(qiskit_circuit: Any, qiskit_target: Any, *, n_seeds: int = 20, optimization_level: int = 3, dd_type: str | None = None, backend_props: BackendProperties | None = None) EnhancedCompileResult¶
Qiskit-first compilation with DD enhancement.
Let Qiskit handle layout + routing (best of n_seeds at optimization_level), then add Dynamical Decoupling on top. Qiskit does not enable DD at any optimization level by default, so this is a guaranteed improvement.
- Parameters:
qiskit_circuit – Input Qiskit
QuantumCircuit.qiskit_target – Qiskit
Targetfrom the backend (provides gate durations, coupling map, and dt for scheduling).n_seeds – Number of Qiskit transpiler seeds to try.
optimization_level – Qiskit optimization level (default 3 for best routing).
dd_type – DD sequence type:
"XX"or"XY4". IfNone, auto-selects based on calibration data (XY4 if median T2 < 50 µs, else XX).backend_props – Optional calibration data for calibration-aware DD selection and fidelity estimation.
- estimate_cost(circuit: QBCircuit, shots: int) CostEstimate¶
Estimate execution cost in USD for circuit at shots.
Requires a backend to be configured; raises
BackendNotSupportedErrorotherwise.
- estimate_fidelity(circuit: QBCircuit) float¶
Estimate output-state fidelity for circuit on the target backend.
- classmethod from_backend(backend: str, **kwargs: Any) QBCompiler¶
Create a compiler pre-configured for backend.
Validates that the backend is known and passes any extra kwargs through to the constructor.
Compilation Results¶
- class qb_compiler.compiler.CompileResult(compiled_circuit: QBCircuit, original_depth: int, compiled_depth: int, estimated_fidelity: float, pass_log: tuple[PassResult, ...], compilation_time_ms: float, initial_layout: dict[int, int] | None = None)¶
Full result bundle returned by
QBCompiler.compile().When
initial_layoutis present, use it with Qiskit’s transpiler for routing:result = compiler.compile(circuit) transpiled = qiskit.transpile( qiskit_circuit, target=backend.target, initial_layout=result.initial_layout_list, optimization_level=3, )
- property initial_layout_list: list[int] | None¶
Layout as an ordered list suitable for
qiskit.transpile(initial_layout=...).
- pass_log: tuple[PassResult, ...]¶
Cost Estimation¶
- class qb_compiler.compiler.CostEstimator(backend_spec: BackendSpec)¶
Estimates execution cost in USD for a compiled circuit.
Uses the backend’s
cost_per_shotfromBACKEND_CONFIGSas the baseline, then scales for gate count (rough proxy for execution time on pay-per-second platforms).- estimate(depth: int, n_qubits: int, shots: int) CostEstimate¶
Return a
CostEstimatefor the given workload.
Configuration¶
- class qb_compiler.config.CompilerConfig(backend: str | None = None, optimization_level: int = 2, target_basis_gates: tuple[str, ...] | None = None, coupling_map: list[tuple[int, int]] | None = None, calibration_max_age_hours: float = 24.0, enable_calibration_aware: bool = True, enable_noise_aware_scheduling: bool = True, seed: int | None = None)¶
Full configuration for a
QBCompilerrun.- Parameters:
backend (str | None) – Target backend key (must be in
BACKEND_CONFIGSif not None).optimization_level (int) – 0 = no optimisation, 1 = light, 2 = standard, 3 = aggressive.
target_basis_gates (tuple[str, ...] | None) – Override basis gate set. If None, inferred from backend.
coupling_map (list[tuple[int, int]] | None) – Override coupling map as adjacency list
[(i, j), ...]. If None, the compiler assumes all-to-all connectivity.calibration_max_age_hours (float) – Maximum age of calibration data before it is considered stale.
enable_calibration_aware (bool) – Use per-qubit/gate error rates from calibration data to guide routing.
enable_noise_aware_scheduling (bool) – Reorder commuting gates to prefer lower-error time slots.
seed (int | None) – Reproducibility seed for stochastic passes (routing, layout search).
- property backend_spec: BackendSpec | None¶
Resolved
BackendSpec, or None when no backend is set.
- property effective_basis_gates: tuple[str, ...] | None¶
Basis gates to target — explicit override wins, else from backend.
- with_overrides(**kwargs: Any) CompilerConfig¶
Return a shallow copy with selected fields replaced.
- class qb_compiler.config.BackendSpec(provider: str, n_qubits: int, basis_gates: tuple[str, ...], coupling_map: str, cost_per_shot: float, median_cx_error: float, median_readout_error: float, t1_us: float, t2_us: float)¶
Immutable hardware specification for a supported backend.
- qb_compiler.config.BACKEND_CONFIGS: dict[str, BackendSpec] = {'ibm_fez': BackendSpec(provider='ibm', n_qubits=156, basis_gates=('id', 'rz', 'sx', 'x', 'cx', 'reset'), coupling_map='heavy-hex 156q (Heron r2)', cost_per_shot=0.00016, median_cx_error=0.005, median_readout_error=0.01, t1_us=300.0, t2_us=150.0), 'ibm_marrakesh': BackendSpec(provider='ibm', n_qubits=156, basis_gates=('id', 'rz', 'sx', 'x', 'cx', 'reset'), coupling_map='heavy-hex 156q (Heron r2)', cost_per_shot=0.00016, median_cx_error=0.0055, median_readout_error=0.011, t1_us=290.0, t2_us=140.0), 'ibm_torino': BackendSpec(provider='ibm', n_qubits=133, basis_gates=('id', 'rz', 'sx', 'x', 'cx', 'reset'), coupling_map='heavy-hex 133q (Heron r1)', cost_per_shot=0.00014, median_cx_error=0.006, median_readout_error=0.012, t1_us=280.0, t2_us=130.0), 'ionq_aria': BackendSpec(provider='ionq', n_qubits=25, basis_gates=('gpi', 'gpi2', 'ms'), coupling_map='all-to-all 25q (Aria-2)', cost_per_shot=0.3, median_cx_error=0.004, median_readout_error=0.003, t1_us=1000000.0, t2_us=500000.0), 'ionq_forte': BackendSpec(provider='ionq', n_qubits=36, basis_gates=('gpi', 'gpi2', 'ms'), coupling_map='all-to-all 36q (Forte-1)', cost_per_shot=0.3, median_cx_error=0.003, median_readout_error=0.003, t1_us=1000000.0, t2_us=500000.0), 'iqm_emerald': BackendSpec(provider='iqm', n_qubits=5, basis_gates=('prx', 'cz', 'measure'), coupling_map='star topology 5q (Emerald)', cost_per_shot=0.0002, median_cx_error=0.008, median_readout_error=0.015, t1_us=40.0, t2_us=20.0), 'iqm_garnet': BackendSpec(provider='iqm', n_qubits=20, basis_gates=('prx', 'cz', 'measure'), coupling_map='square lattice 20q (Garnet)', cost_per_shot=0.00045, median_cx_error=0.015, median_readout_error=0.02, t1_us=30.0, t2_us=15.0), 'quantinuum_h2': BackendSpec(provider='quantinuum', n_qubits=32, basis_gates=('rz', 'u1q', 'zz'), coupling_map='all-to-all 32q (H2-1)', cost_per_shot=8.0, median_cx_error=0.001, median_readout_error=0.002, t1_us=10000000.0, t2_us=1000000.0), 'rigetti_ankaa': BackendSpec(provider='rigetti', n_qubits=84, basis_gates=('rx', 'rz', 'cz', 'measure'), coupling_map='octagonal lattice 84q (Ankaa-3)', cost_per_shot=0.00035, median_cx_error=0.02, median_readout_error=0.03, t1_us=20.0, t2_us=10.0)}¶
dict() -> new empty dictionary dict(mapping) -> new dictionary initialized from a mapping object’s
(key, value) pairs
- dict(iterable) -> new dictionary initialized as if via:
d = {} for k, v in iterable:
d[k] = v
- dict(**kwargs) -> new dictionary initialized with the name=value pairs
in the keyword argument list. For example: dict(one=1, two=2)
- qb_compiler.config.get_backend_spec(backend: str) BackendSpec¶
Return the
BackendSpecfor backend, raising on unknown names.
Circuit Representation¶
- class qb_compiler.compiler.QBCircuit(n_qubits: int, ops: list[GateOp] | None = None)¶
Minimal quantum circuit representation.
Stores a flat list of
GateOpinstructions and derives depth / gate-count on the fly. This is deliberately backend-agnostic; Qiskit / Cirq interop is handled by converter utilities (not in this module).- add(name: str, qubits: tuple[int, ...], params: tuple[float, ...] = ()) QBCircuit¶
Append a gate and return self for chaining.
- n_qubits¶
Convenience Factory¶
- qb_compiler.passmanager(backend: object = None, *, optimization_level: int = 2) object¶
Return a Qiskit
PassManagerconfigured for backend.Convenience factory that builds a Qiskit
StagedPassManagerwithQBCalibrationPassinjected into the layout stage. Accepts a QiskitBackend,Target, or qb-compiler backend name string.- Parameters:
backend – A Qiskit
Backendinstance, a QiskitTarget, or a qb-compiler backend name (e.g."ibm_fez").optimization_level – Qiskit optimization level (0-3). Default 2.
- Returns:
A Qiskit
StagedPassManagerready to.run()circuits.- Return type:
Examples
>>> from qb_compiler import passmanager >>> pm = passmanager(backend) >>> compiled = pm.run(circuit)
Protocols¶
These runtime-checkable protocols define the extension points that calibration providers and noise models must satisfy.
- class qb_compiler.compiler.CalibrationProvider(*args, **kwargs)¶
Supplies per-qubit / per-gate calibration data for a backend.
Exceptions¶
Exception hierarchy for the qb-compiler package.
All public exceptions inherit from QBCompilerError so callers
can catch the base class for blanket handling.
- exception qb_compiler.exceptions.BackendNotSupportedError(backend: str, available: list[str] | None = None)¶
Bases:
QBCompilerErrorRaised when a requested backend is not in the known configuration.
- exception qb_compiler.exceptions.BudgetExceededError(estimated_usd: float, budget_usd: float, *, shots: int | None = None)¶
Bases:
QBCompilerErrorRaised when estimated execution cost exceeds the caller’s budget.
- exception qb_compiler.exceptions.CalibrationError(message: str, *, detail: str | None = None)¶
Bases:
QBCompilerErrorBase class for calibration-related errors.
- exception qb_compiler.exceptions.CalibrationNotFoundError(backend: str)¶
Bases:
CalibrationErrorRaised when no calibration data exists for the requested backend.
- exception qb_compiler.exceptions.CalibrationStaleError(backend: str, age_hours: float, max_hours: float)¶
Bases:
CalibrationErrorRaised when cached calibration data exceeds the configured max age.
- exception qb_compiler.exceptions.CompilationError(message: str, *, detail: str | None = None)¶
Bases:
QBCompilerErrorRaised when circuit compilation fails.
- exception qb_compiler.exceptions.InvalidCircuitError(message: str, *, gate: str | None = None)¶
Bases:
CompilationErrorRaised when the input circuit is malformed or contains unsupported ops.