Balancing workflow library for quantum compilation/mitigation benchmarking with Qiskit.
Project description
qbalance
qbalance is 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.
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.
- 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_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)
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 \
--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
# 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)
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 \
--execute \
--shots 1024 \
--profile \
--overwrite
matrix
python -m qbalance matrix ./circuits \
--backend fake:generic:5 \
--backend fake:generic:10 \
--out ./matrix.json \
--execute \
--shots 1024 \
--profile
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.
Development
# Install editable package with all extras
pip install -e ".[all]"
# Run tests
pytest -q -W error
# Run formatting/lint/type hooks
pre-commit run --all-files
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.0.tar.gz.
File metadata
- Download URL: qbalance-0.1.0.tar.gz
- Upload date:
- Size: 62.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
77c99f5402941ceadadd76ba75fbe00d89dfe2a728491ef6153838ed58b2a18b
|
|
| MD5 |
83583b8ccd8d7c0023e807daadd55037
|
|
| BLAKE2b-256 |
062261360f8c3d3820951de1f06041505325975539f0d8b75a80ddab347810c2
|
File details
Details for the file qbalance-0.1.0-py3-none-any.whl.
File metadata
- Download URL: qbalance-0.1.0-py3-none-any.whl
- Upload date:
- Size: 63.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
96b4d15ef21f171a9e5bd819e02711fc2962db438e4f20c95b4ca3e29bcca242
|
|
| MD5 |
580f758749cc0cf68abe9682ae6aa151
|
|
| BLAKE2b-256 |
8b3a52b72967eddc0b46649837b8072ca61d99090152a89edc675927365169d6
|