Contributing¶
Contributing to qb-compiler¶
Thank you for your interest in contributing to qb-compiler, the open-source calibration-aware quantum circuit compiler by QubitBoost. This guide covers everything you need to get started.
Getting Started¶
Fork the repository on GitHub.
Clone your fork locally:
git clone https://github.com/<your-username>/qb-compiler.git cd qb-compiler
Set up your development environment:
make devThis installs the package in editable mode with all development dependencies.
Development Setup¶
Requirements:
Python 3.10 or later
A virtual environment is strongly recommended
Manual setup (alternative to make dev):
python -m venv .venv
source .venv/bin/activate
pip install -e ".[dev]"
Pre-commit hooks:
pre-commit install
This enables automatic linting and formatting checks before each commit.
Code Style¶
Linter/formatter: ruff (line-length 100).
Type checking: mypy in strict mode.
Future annotations: Every module must begin with
from __future__ import annotations.Docstrings: Use Google-style docstrings for all public classes and functions.
Imports: Sort with ruff’s isort rules. Prefer absolute imports.
Run checks locally:
make lint # ruff check + ruff format --check
make typecheck # mypy
Testing¶
Run the full test suite:
make test
Pytest markers:
Marker |
Purpose |
|---|---|
|
Fast, isolated unit tests (default) |
|
Tests that exercise multiple components |
|
Performance benchmarks (excluded by default) |
Run a specific marker:
pytest -m unit
pytest -m integration
pytest -m benchmark
Test naming conventions:
Test files:
test_<module>.pyTest functions:
test_<behaviour_under_test>Place tests in
tests/mirroring thesrc/directory structure.
Coverage: Aim for at least 80% line coverage on new code. Check with:
pytest --cov=qb_compiler --cov-report=term-missing
Architecture Overview¶
qb-compiler uses a linear pass pipeline that transforms circuits through well-defined stages:
Input (Qiskit / OpenQASM 2.0)
-> IR conversion (QBCircuit / QBDag)
-> Mapping (CalibrationMapper — VF2 placement)
-> Routing (NoiseAwareRouter — SWAP insertion)
-> Scheduling (NoiseAwareScheduler — ALAP with T1/T2 urgency)
-> Decomposition (GateDecomposition — native basis gates)
-> Analysis (depth, gate count, error budget estimation)
-> Output (QBCircuit / Qiskit QuantumCircuit)
Each pass inherits from BasePass and implements a run(dag: QBDag) -> QBDag
method. Passes are stateless: all configuration is supplied at construction time.
Adding a New Pass¶
Create the pass in
src/qb_compiler/passes/:from __future__ import annotations from qb_compiler.passes.base import BasePass from qb_compiler.ir.dag import QBDag class MyNewPass(BasePass): """One-line description of what this pass does.""" def run(self, dag: QBDag) -> QBDag: # Transform the DAG and return it. return dag
Export the pass from
src/qb_compiler/passes/__init__.py.Write tests in
tests/passes/test_my_new_pass.py. Include at least:A trivial circuit (1-2 qubits) verifying correctness.
An edge case (empty circuit, single gate, barriers).
Integrate the pass into the pipeline in the appropriate position.
Document the pass with a docstring and, if user-facing, update the README.
Adding a Backend¶
Backend configurations live in src/qb_compiler/backends/. To add support for
a new hardware backend:
Create a configuration module (e.g.,
my_backend.py) that defines:Native gate set and gate durations.
Connectivity map (coupling graph).
Default noise parameters (T1, T2, gate fidelities).
Implement a calibration provider if the backend exposes live calibration data, extending
BaseCalibrationProvider.Add decomposition rules in
src/qb_compiler/passes/decomposition.pyfor the backend’s native gate set.Write tests covering mapping, routing, and decomposition for the new backend’s topology.
Add a configuration entry so the CLI and transpiler plugin can reference the backend by name.
ML Models¶
ML models live in src/qb_compiler/ml/. The pipeline has four phases:
Phase |
Module |
Architecture |
Install |
|---|---|---|---|
1 |
|
Training data pipeline |
Core |
2 |
|
XGBoost qubit scorer |
|
3 |
|
Dual-graph GCN |
|
4 |
|
PPO SWAP routing |
|
Model weights are stored in src/qb_compiler/ml/_weights/ with
*.meta.json metadata files. To retrain:
# Phase 2: XGBoost
python -m qb_compiler.ml.train
# Phase 3: GNN
python -c "from qb_compiler.ml.gnn_router import train_gnn_model; train_gnn_model()"
Adding a new ML model:
Create the model in
src/qb_compiler/ml/.Follow the
predict_candidate_qubits(circuit, backend) -> list[int]interface so it’s plug-compatible withCalibrationMapper.Save weights in
_weights/with a.meta.jsonmetadata file.Write tests in
tests/unit/test_ml/.Guard imports behind optional dependency checks (see
ml/__init__.py).
Pull Request Process¶
Branch naming:
feat/<short-description>for new featuresfix/<short-description>for bug fixesdocs/<short-description>for documentation changesrefactor/<short-description>for refactoring
Commit messages: Use conventional commit style:
feat: add Quantinuum H2 backend configuration
fix: correct SWAP count in noise-aware routing
docs: update calibration provider examples
Before opening a PR:
Ensure all checks pass:
make lint && make typecheck && make testAdd or update tests for any changed behaviour.
Update documentation if the public API changed.
PR expectations:
Keep PRs focused on a single concern.
Provide a clear description of what changed and why.
Link any related issues.
Respond to review feedback promptly.
Code of Conduct¶
This project follows the Contributor Covenant Code of Conduct. By participating, you agree to uphold a welcoming and inclusive environment.
Please report unacceptable behaviour to the maintainers.
License¶
By contributing to qb-compiler, you agree that your contributions will be licensed under the Apache License 2.0, the same license that covers the project.