Optimization Level Guide¶
qb-compiler provides four optimization levels (0–3) and three compilation strategies. This guide helps you choose the right settings.
Optimization Levels¶
Each level adds more passes to the compilation pipeline:
Level |
Name |
What It Does |
When to Use |
|---|---|---|---|
0 |
None |
Gate decomposition to native basis only. No optimization. |
Debugging, verifying circuit equivalence. |
1 |
Light |
Decomposition + adjacent gate cancellation (H-H, X-X, CX-CX). |
Quick compilation, large circuits where compilation time matters. |
2 |
Medium (default) |
Level 1 + rotation merging + calibration-aware mapping + noise-aware routing. |
Most workloads. Good balance of quality and speed. |
3 |
Heavy |
Level 2 run twice (second pass catches opportunities exposed by the first). More VF2 candidates explored. |
Maximising fidelity for production experiments. Slower compilation. |
Setting the optimization level:
from qb_compiler import QBCompiler
# Via from_backend
compiler = QBCompiler.from_backend("ibm_fez", optimization_level=3)
# Via config
from qb_compiler.config import CompilerConfig
config = CompilerConfig(backend="ibm_fez", optimization_level=3)
compiler = QBCompiler(config)
Compilation Strategies¶
Strategies control what the compiler optimizes for, independent of the optimization level:
fidelity_optimal(default)Maximise estimated output fidelity. The CalibrationMapper explores more candidate layouts and picks the one with lowest weighted error. Use this when circuit quality is paramount.
depth_optimalMinimise compiled circuit depth. Prioritises parallel gate execution. Useful when decoherence during idle time is the dominant error source.
budget_optimalMinimise execution cost. Uses lighter optimization (level 1 max) and recommends the cheapest viable shot count. Best for parameter sweeps and iterative algorithms like VQE.
compiler = QBCompiler.from_backend("ibm_fez", strategy="budget_optimal")
result = compiler.compile(circuit)
Decision Tree¶
Is this a production experiment?
├── YES → optimization_level=3, strategy="fidelity_optimal"
├── NO, just testing → optimization_level=0 or 1
└── Is budget a concern?
├── YES → strategy="budget_optimal"
└── NO
├── Circuit depth > 100? → strategy="depth_optimal"
└── Otherwise → strategy="fidelity_optimal" (default)
Performance vs Quality¶
Rough compilation time for a 20-qubit circuit with 50 CX gates on a modern laptop:
Level |
Compilation Time |
Fidelity Improvement |
|---|---|---|
0 |
< 10 ms |
Baseline |
1 |
~ 20 ms |
+0.5–1% |
2 |
~ 100 ms |
+2–4% |
3 |
~ 500 ms |
+3–5% |
These are approximate. Actual performance depends on circuit structure, backend size, and available calibration data.
Calibration-Aware vs Topology-Only¶
The biggest fidelity gains come from calibration-aware mapping (level 2+). On IBM Fez (156 qubits), calibration-aware mapping provides +2.4% to +4.5% improvement over topology-only mapping.
This improvement increases with:
More qubits — larger devices have more variation in qubit quality
More 2Q gates — each CX/CZ gate accumulates error
Higher error variance — devices with large error spreads benefit most
The improvement decreases when:
Circuits use most qubits — fewer layout choices available
All qubits are similar quality — calibration adds less signal
Circuits are very shallow — readout error dominates
Combining Level and Strategy¶
# Maximum quality
compiler = QBCompiler.from_backend("ibm_fez",
optimization_level=3,
strategy="fidelity_optimal",
)
# Fast iteration during development
compiler = QBCompiler.from_backend("ibm_fez",
optimization_level=1,
strategy="budget_optimal",
)
# Depth-sensitive circuit (long coherence-limited experiment)
compiler = QBCompiler.from_backend("ibm_fez",
optimization_level=2,
strategy="depth_optimal",
)