Balancing workflow library for quantum compilation/mitigation benchmarking with Qiskit.
Project description
qBalance
A workflow toolkit for balancing quantum compilation, suppression, and mitigation choices over a dataset of quantum circuits.
At a high level, it provides a reproducible pipeline to:
- load a dataset,
- resolve one or more backend targets,
- evaluate candidate strategies,
- select one strategy per circuit,
- export artifacts for downstream analysis/reporting.
It supports both a Python API and a CLI.
Full documentation lives in docs/, including the API reference, CLI guide, strategy configuration guide, and artifact/report reference.
Why qbalance
Quantum workload tuning is naturally multi-objective. Typical goals conflict:
- lower depth vs. lower compile time,
- fewer two-qubit operations vs. hardware routing constraints,
- suppression/mitigation quality vs. runtime overhead.
qbalance provides a single workflow that keeps these trade-offs explicit and reproducible.
Core capabilities
- Dataset IO: save/load datasets using a JSON index and QPY artifacts with record-level metadata.
- Backend resolution: plugin-based backend specification (
fake:*,aer:*, custom). - Strategy model: immutable
StrategySpecwith compile/suppression/mitigation controls. - Search modes:
grid: evaluate all candidates in sequence.bandit: warmup + adaptive ordering via a Bayesian linear surrogate.
- Selection modes:
- direct objective minimization,
- optional Pareto filtering before tie-break by objective.
- Mitigation/Suppression knobs: Pauli twirling, dynamical decoupling, measurement twirling, M3, ZNE, optional cutting.
- Diagnostics: baseline-vs-selected distribution distances (EMD/CVM/KS).
- Reporting: markdown + optional HTML from matrix JSON.
- Caching: compiled-circuit cache keyed by backend + circuit fingerprint + strategy payload.
Installation
Base
pip install qbalance
Optional extras
pip install "qbalance[aer]" # qiskit-aer integration
pip install "qbalance[runtime]" # IBM runtime integration helpers
pip install "qbalance[mitigation]" # mthree integration
pip install "qbalance[cutting]" # qiskit-addon-cutting integration
pip install "qbalance[report]" # reporting stack (jinja2/matplotlib/pandas)
pip install "qbalance[all]" # all optional dependencies + dev tools
Development install
pip install -e ".[all]"
Python requirement: >=3.10.
Quickstart
Python API
from qbalance import Workload, load_balanced_workload, load_data
# 1) built-in tiny dataset: bell, ghz3, qft4
ds = load_data("tiny")
# 2) choose backend target
wl = Workload.from_dataset(ds).set_target("fake:generic:5")
# 3) run strategy search/selection
balanced = wl.adjust(
search="bandit", # or "grid"
pareto=True, # optional Pareto pre-filtering
max_candidates=24,
execute=False, # compile-only mode
profile=False,
)
# 4) inspect/persist artifacts
print(balanced.summary())
balanced.save("./balanced", overwrite=True)
balanced.to_download("./balanced_bundle.zip", overwrite=True)
# Reload saved results later without recompilation.
reloaded = load_balanced_workload("./balanced")
print(reloaded.summary())
CLI
# Create built-in dataset
python -m qbalance dataset examples --out ./circuits --overwrite
# Run per-circuit adjustment
python -m qbalance adjust ./circuits \
--backend fake:generic:5 \
--out ./balanced \
--search bandit \
--pareto \
--max-candidates 24 \
--strategies ./strategies.json \
--overwrite
# Evaluate fixed strategy matrix across backends
python -m qbalance matrix ./circuits \
--backend fake:generic:5 \
--backend fake:generic:10 \
--out ./matrix.json \
--execute \
--shots 1024 \
--strategies ./strategies.json
# Render markdown/html reports
python -m qbalance report ./matrix.json --out ./report --html
Architecture (execution flow)
CircuitDataset
│
├── Workload.from_dataset(...) / Workload.from_path(...)
│
├── set_target("fake:generic:5" | "aer:..." | custom plugin)
│
└── adjust(...)
├── baseline compile
├── candidate ordering (grid | bandit)
├── compile (+ optional suppression/cutting)
├── optional execution (+ mitigation)
├── objective scoring
└── choose best (optional Pareto pre-filter)
↓
BalancedWorkload
├── summary()
├── save(out_dir)
├── to_download(zip)
└── reload via load_balanced_workload(out_dir)
Data model
Dataset directory layout:
<dataset_root>/
qbalance_dataset.json
<name>.qpy
<name_1>.qpy
...
qbalance_dataset.json indexes records with:
name: circuit identifier,artifact: relative artifact path,format:"qpy"or"qasm",metadata: optional JSON payload.
Programmatic dataset creation:
from pathlib import Path
from qiskit import QuantumCircuit
from qbalance import save_dataset, load_dataset
qc = QuantumCircuit(2, 2, name="bell")
qc.h(0)
qc.cx(0, 1)
qc.measure([0, 1], [0, 1])
save_dataset(Path("./my_dataset"), [qc], metadata=[{"family": "bell"}], overwrite=True)
ds = load_dataset(Path("./my_dataset"))
print(ds.names())
Strategy space
A strategy is an immutable StrategySpec with these groups:
- Compilation knobs:
optimization_level, layout/routing/translation methods, transpiler seed. - Suppression knobs: Pauli twirling, twirl count, dynamical decoupling, measurement twirling, suppression seed.
- Mitigation knobs: M3 toggle, ZNE toggle + factors + polynomial degree.
- Cutting knobs: cutting toggle + max subcircuit qubits.
- Runtime knob: optional resilience level metadata.
Example:
from qbalance import StrategySpec
spec = StrategySpec(
optimization_level=2,
layout_method="qbalance_noise_aware",
routing_method="sabre",
seed_transpiler=0,
pauli_twirling=True,
num_twirls=8,
dynamical_decoupling=False,
measurement_twirling=False,
mthree=False,
zne=False,
)
Mathematical model (objective, Pareto, diagnostics)
1) Weighted objective
Given metric vector $\mathbf{m}$, qbalance minimizes:
J(\mathbf{m}) = \sum_{k \in K} w_k\,m_k
Default terms:
J = 1.0\cdot\text{depth}
+ 2.0\cdot\text{two\_qubit\_ops}
+ 10.0\cdot\text{estimated\_error}
+ 0.1\cdot\text{compile\_time\_s}
Interpretation:
- higher
estimated_erroris penalized strongly (weight 10), - two-qubit operation count has moderate penalty (weight 2),
- compile time contributes but with a small coefficient (0.1).
2) Finite-safe scoring behavior
For each objective term, qbalance ignores a term when the metric is missing, non-numeric, or non-finite. In selection fallback logic, if no finite objective term contributes, the candidate is treated as effectively worst-case (score $+\infty$).
3) Pareto pre-filtering
With pareto=True, qbalance first computes a non-dominated set on:
depth,two_qubit_ops,estimated_error.
Candidate $a$ dominates candidate $b$ iff:
\big(\forall i,\ a_i \le b_i\big)\ \land\ \big(\exists j,\ a_j < b_j\big)
Then qbalance chooses the minimum-objective strategy within that Pareto front.
4) Bandit proposal model
In bandit mode, candidate ordering after warmup uses a Thompson-sampling style linear surrogate:
\mathbf{y} \approx X\mathbf{w},\qquad
\Lambda = \alpha I + \frac{1}{\sigma^2}X^T X,
\qquad
\mu = \Lambda^{-1}\frac{1}{\sigma^2}X^T\mathbf{y}
A sample $\tilde{\mathbf{w}}\sim\mathcal{N}(\mu,\Lambda^{-1})$ is drawn implicitly from the Cholesky factor of $\Lambda$, and candidates are ranked by linear score $\phi(s)^T\tilde{\mathbf{w}}$ (lower is preferred).
5) Distribution diagnostics
For baseline and selected metric samples, qbalance computes:
- KS distance:
D_{KS}=\sup_x |F_1(x)-F_2(x)| - EMD/Wasserstein-1 (1D CDF form):
W_1=\int |F_1(x)-F_2(x)|\,dx - CVM-type distance used here:
\mathrm{CVM}=\int (F_1(x)-F_2(x))^2\,dx
where $F_1, F_2$ are empirical weighted CDFs on aligned support grids.
6) Entropy and top-probability metrics (execution path)
When execution is available, helper metrics may include:
- Shannon entropy over observed counts:
H=-\sum_i p_i\log_2 p_i - top observed probability:
p_{\max}=\max_i p_i
with $p_i = c_i / \sum_j c_j$.
Caching and computational performance
Compiled circuits may be reused via cache key:
\text{key}=\text{SHA256}(\text{backend\_name}:\text{circuit\_fingerprint}:\text{strategy\_json})
This avoids redundant transpilation for repeated (circuit, backend, strategy) tuples.
Additional performance-relevant behavior:
- matrix execution pre-serializes strategy payloads once before inner loops,
- distribution metrics aggregate and align sorted supports efficiently,
- optional
profile=Falseavoids transpiler pass profiling overhead.
Artifacts and output contracts
adjust output directory
dataset/copied dataset index + artifacts,results.jsonselected strategy specs/metrics + baseline metrics + objective weights,summary.txttext summary.
matrix output JSON
{
"version": 1,
"results": [
{
"circuit": "...",
"backend": "...",
"strategy": {"...": "..."},
"metrics": {"...": "..."}
}
]
}
report output directory
report.md,- optional HTML files when
--htmlis used and report dependencies are installed.
CLI reference
dataset
python -m qbalance dataset examples --out ./circuits --overwrite
adjust
python -m qbalance adjust ./circuits \
--backend fake:generic:5 \
--out ./balanced \
--search grid \
--pareto \
--max-candidates 24 \
--strategies ./strategies.json \
--execute \
--shots 1024 \
--profile \
--overwrite
A strategy JSON file may be either one strategy object, a list of strategy objects, or an object with a strategies list:
{
"strategies": [
{"optimization_level": 1, "routing_method": "sabre"},
{"optimization_level": 2, "layout_method": "qbalance_noise_aware", "routing_method": "sabre"}
]
}
matrix
python -m qbalance matrix ./circuits \
--backend fake:generic:5 \
--backend fake:generic:10 \
--out ./matrix.json \
--execute \
--shots 1024 \
--profile \
--strategies ./strategies.json
report
python -m qbalance report ./matrix.json --out ./report --html
plugins
python -m qbalance plugins list
compile
python -m qbalance compile ./circuits \
--backend fake:generic:5 \
--out ./compiled_bundle \
--optimization-level 2 \
--routing-method sabre \
--layout-method qbalance_noise_aware \
--pauli-twirling \
--num-twirls 8 \
--dd \
--meas-twirl \
--overwrite
Plugin system
Entry-point groups:
qbalance.backendsqbalance.objectivesqbalance.reports
Inspect active registrations with:
python -m qbalance plugins list
Edge cases and failure semantics
adjust()without.set_target(...)raisesValueError.- Invalid search mode raises
ValueError. - If no candidate can be evaluated, selection raises
RuntimeError. matrixvalidatesshotsas positive integer and validates integer seed.matrixraisesValueErrorif dataset record count and loaded circuit count mismatch.- Existing output paths require explicit overwrite flags.
- Optional dependency features require installed extras.
- Execution/mitigation exceptions are captured in metrics (e.g.,
exec_error,mthree_error,zne_error) so runs can continue.
Correctness and complexity notes
For a dataset with $N$ circuits and $S$ strategy candidates per circuit:
- Grid search evaluates up to $N\times S$ candidates.
- Bandit search also compiles/evaluates up to $N\times S$ candidates in the worst case, but may discover strong candidates earlier due to adaptive ordering.
- Pareto filtering in practice is close to linear in small fronts, with a quadratic worst-case bound on the number of unique objective vectors.
If a compile cache hit occurs, effective transpilation cost is reduced from repeated compile cost $T_{compile}$ to key lookup + deserialization overhead.
Development
# Install editable package with all extras
pip install -e ".[all]"
# Install hooks once
pre-commit install
# Run tests with warnings promoted to errors
pytest -q -W error
# Run formatting/lint/type hooks
pre-commit run --all-files
Citation
If you use qbalance in your work and wish to refer to it, please use the following BibTeX entry.
@misc{sarkar2026qbalancereproduciblemultiobjectiveworkflow,
title={QBalance: A Reproducible Multi-Objective Workflow for Quantum Compilation, Noise Suppression, and Error-Mitigation Strategy Selection},
author={Soumyadip Sarkar},
year={2026},
eprint={2605.02966},
archivePrefix={arXiv},
primaryClass={quant-ph},
url={https://arxiv.org/abs/2605.02966},
}
License
MIT License. See LICENSE.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file qbalance-0.1.2.tar.gz.
File metadata
- Download URL: qbalance-0.1.2.tar.gz
- Upload date:
- Size: 83.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
de549f9850c01cb10b45d8c33151e71eeb9ec1d536f607adae9cdb4235bdd67d
|
|
| MD5 |
ff867d01b7e7f444c84fe44b44b4375a
|
|
| BLAKE2b-256 |
63f61f34708eb34ef1da44d411b897b553c3c663a21c053f3eb612218229a60e
|
File details
Details for the file qbalance-0.1.2-py3-none-any.whl.
File metadata
- Download URL: qbalance-0.1.2-py3-none-any.whl
- Upload date:
- Size: 72.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
964f911c6c417c98a0314848c68e15eaf8ba7fe133087731e372f4c2c7a58890
|
|
| MD5 |
e93eaf5d11208f36e0863d1764188a14
|
|
| BLAKE2b-256 |
8a578d12d1d9c0a483a5847b15ff7acbda83fb24b3fe1637bc613c16e80d95bb
|