Circuit Optimization and Compilation
Optimization, transpilation, and compilation are separate stages: optimization removes or combines gates, transpilation rewrites gates into a target basis, and compilation additionally selects a machine and maps the layout. None of these stages submits a hardware job.
from unitarylab import Circuit
qc = Circuit(2)
qc.h(0)
qc.cx(0, 1)
optimized = qc.optimize(optimization_level=1)
transpiled = qc.transpile(basis="default")
compiled = qc.compile(provider="guodun", token="your-provider-token")optimize() and transpile() return Circuit. compile() returns CompilationResult containing the mapped circuit and QCIS; it does not submit a job or consume hardware-run quota. compile() supports local, guodun, and tianyan providers.
| Interface | Return value | Main parameters |
|---|---|---|
optimize(optimization_level=1) | New Circuit | Rule-based optimization level |
transpile(gates_to_unroll=None, basis="default") | New Circuit | Target basis and gates to unroll |
compile(provider="local", machine=None, token=None) | CompilationResult | Compilation target, machine, and credentials |
These calls do not mutate the original circuit. Compiling for a remote machine may require credentials or machine discovery, but does not create a hardware-run job.
Use QCompiler when working with OpenQASM input or detailed configuration:
from unitarylab import QCompiler
compiler = QCompiler()
optimized = compiler.optimize(circuit_or_qasm)
transpiled = compiler.transpile(qc, basis="default")
compiled = compiler.compile(
circuit_or_qasm, provider="guodun", token="your-provider-token",
)QCompiler also accepts CompileConfig, a configuration dictionary, or a configuration-file path to set optimization, mapping, hardware, and execution options. run(source, stop_at=..., start_from=...) selects the start and stop stages of the pipeline.
Rule-based optimization levels
Circuit.optimize(optimization_level=1) accepts levels 0–3; QCompiler.optimize() can override its configuration with the same keyword. Rule-based optimization includes inverse-gate cancellation, rotation and phase merging, multi-controlled gate simplification, and block consolidation; the combination depends on the level. Level 3 includes basis_state_peephole, which assumes an all-zero initial state, so it must not be assumed to preserve unitary-matrix equivalence for arbitrary initial states. To preserve arbitrary-input semantics, exclude this rule with QCompiler({"optimization": {"rule_based": {"optimization_level": 3, "assume_zero_state": False}}}). The execution layer also selects gate simplification automatically, without an extra execute() switch; this serves a different purpose from explicitly returning a new circuit with optimize().
CompilationResult
| Field | Description |
|---|---|
circuit / mapped_circuit | Mapped circuit |
executable | Executable text for the target machine |
executable_format | Executable format, such as QCIS |
optimized_circuit | Optimized circuit before mapping; may be None |
machine | Selected machine information |
layout, final_layout | Initial and final logical-to-physical layouts |
qasm | Intermediate OpenQASM |
stage_metadata | Structured metadata for each stage |
The compilation artifact flow is raw_qasm -> optimized_qasm -> mapped_qcis. To submit to real hardware, see Submitting Hardware Jobs.
Recommendations
- Run the original circuit locally first and save baseline probabilities or expectation values.
- Compare gate count and depth after optimization and transpilation; compare matrices or output distributions for small circuits.
- Hardware basis, coupling map, and machine status can change compilation results; do not treat artifacts as permanently reusable across machines.
- Do not place tokens in documentation, source code, or version control; prefer provider-supported environment variables.