Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

3 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Quantum Compiler Analysis

EE798V Course Project — Qiskit Transpiler Pipeline Study

This project benchmarks Qiskit's transpiler pipeline across optimization levels 0–5 on two quantum algorithms (Grover's Search and QFT), measuring how compilation quality affects circuit structure and output fidelity under realistic noise.

Core thesis: Better compilation = sharper probability peaks at correct answer states and fewer noisy gates. The primary quality metric is TVD (Total Variation Distance) between ideal statevector probabilities and noisy simulation output.


Setup

Requirements: Python 3.11+

pip install qiskit>=1.0 qiskit-aer>=0.14 qiskit-ibm-runtime>=0.20 matplotlib numpy

# Optional (for level 5):
pip install z3-solver   # Level 5: HoareOptimizer

Quick Start

Step 1 — Transpile and simulate (generates metrics JSON and QPY files in results/):

# Run for each algorithm and qubit count you want to plot
python compiler/transpile_all.py --algorithm grover --n_qubits 4 --max_level 5
python compiler/transpile_all.py --algorithm qft    --n_qubits 4 --max_level 5

# For qubit scaling plots, also run for 3, 5, 6 qubits
for n in 2 3 4 5 ; do
    python compiler/transpile_all.py --algorithm grover --n_qubits $n --max_level 5
    python compiler/transpile_all.py --algorithm qft    --n_qubits $n --max_level 5
done

Step 2 — Generate all three plots:

python plots/plots.py

Plots

All three plots are generated by plots/plots.py and saved to results/.

Plot Output file Description
1. Histogram results/histogram_4q.png Output state probability distribution for 4 qubits at L0 vs L5. Ideal (blue) vs noisy (red) side by side for both algorithms.
2. Metrics vs Level results/metrics_vs_level.png Gate count and circuit depth vs optimization level (0–5) for both algorithms at 4 qubits.
3. Qubit Scaling results/qubit_scaling.png Gate count, CX count, and circuit depth vs qubit count (3–6) for optimization levels 0, 3, 5.
# With custom qubit count for plots 1 and 2:
python plots/plots.py --n_qubits 5

# Interactive display instead of saving:
python plots/plots.py --show

Optimization Levels

Levels 0–3 use Qiskit's built-in presets. Levels 4–5 are custom extensions that clone Level 3 and add progressively more aggressive passes.

Level Layout Routing Optimization
0 TrivialLayout BasicSwap None
1 Trivial → DenseLayout BasicSwap Optimize1qGates
2 DenseLayout → VF2Layout LookaheadSwap CommutativeCancellation, CXCancellation
3 SabreLayout SabreSwap Full peephole + UnitarySynthesis (KAK)
4 SabreLayout SabreSwap Level 3 + TemplateOptimization + diagonal removal
5 SabreLayout SabreSwap Level 4 + HoareOptimizer (z3-solver required)

All stochastic passes are seeded (seed_transpiler=42, seed_simulator=42) for reproducible results.


Algorithm Suite

Algorithm File Ideal Output
Grover's Search circuits/grover.py Sharp peak at marked state
Quantum Fourier Transform circuits/qft.py Uniform distribution

Both expose build(n_qubits, **kwargs) → QuantumCircuit.


Error Metric: TVD

TVD = 0.5 × Σₛ |P_ideal(s) − P_noisy(s)|
  • TVD = 0 → noisy output matches ideal exactly (perfect compilation)
  • TVD = 1 → no overlap between ideal and noisy distributions

TVD is the primary quality signal because it directly corresponds to how peaked vs spread the probability histogram looks. Secondary structural metrics (gate count, CX count, depth) are proxies that predict TVD.


Hardware Platform

from qiskit_ibm_runtime.fake_provider import FakeNairobiV2  # 7 qubits, real IBM noise data

Basis gate set: ['cx', 'rz', 'sx', 'x']. Statevector simulation is skipped for circuits with more than 20 qubits; those report structural metrics only (TVD = None).


Architecture

circuits/       →  compiler/              →  hardware/        →  analysis/ + plots/
build circuit      transpile_all.py          simulate w/ noise    metrics + figures
                   (levels 0–5, serialise
                    to results/*.qpy)

Each stage is independent. Compiled circuits are serialised to results/*.qpy via qiskit.qpy, so transpilation runs once and plotting reads cached results.


Project Structure

quantum-compiler/
├── circuits/
│   ├── __init__.py          # Registry: build_circuit(algorithm, n_qubits)
│   ├── grover.py            # Grover's search
│   └── qft.py               # Quantum Fourier Transform
├── compiler/
│   ├── __init__.py
│   ├── transpile_all.py     # Top-level runner (CLI entry point)
│   ├── preset_pass_managers.py  # Levels 0–5 PassManagers
│   └── pass_manager.py      # PassManager / AnalysisPass / TransformationPass
├── hardware/
│   ├── __init__.py
│   ├── backends.py          # Backend selection (FakeNairobi / FakeSherbrooke)
│   └── noise_models.py      # Base + scaled noise models
├── analysis/
│   ├── __init__.py
│   ├── metrics.py           # TVD, gate_count, cx_count, depth, compute_all_metrics
│   └── benchmark.py         # Sweep all qubit counts → benchmark_report.json
├── plots/
│   ├── __init__.py
│   └── plots.py             # All three benchmark plots
└── results/                 # Generated outputs (QPY, JSON, PNG)

Output Files

All outputs land in results/:

File pattern Description
<algo>_<n>q_level<l>.qpy Compiled circuit in QPY format
<algo>_<n>q_metrics.json Gate count, CX count, depth, TVD, and probability dicts per level
histogram_<n>q.png State probability histograms: L0 vs L5 for both algorithms
metrics_vs_level.png Gate count + depth vs optimization level for both algorithms
qubit_scaling.png Gate count, CX, depth vs qubit count for both algorithms

About

Optimising Transpiler of Qiskit

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages