Catch silently-wrong quantum circuits: assertions, statistical checks, and regression tests for quantum programs.
Project description
Veriqa
Catch silently-wrong quantum circuits.
Quantum programs output probability distributions, not values — so you can't
write assert result == expected. A circuit can run, return perfectly normal
counts, and still be wrong: a misplaced gate, a transpiler that rewrote your
circuit, hardware that drifted overnight. Veriqa gives you assertions,
statistical checks, and regression tests that catch those silent failures —
and they drop straight into the pytest you already use.
pip install veriqa
Status: v0.1 (alpha). Qiskit + Aer simulator. Multi-framework backends (PennyLane, Cirq) and real-hardware monitoring are on the roadmap.
Quick start
from qiskit import QuantumCircuit
import veriqa as vq
qc = QuantumCircuit(2)
qc.h(0)
qc.cx(0, 1) # a Bell state
# 1. Does it produce the right distribution? (shot-noise aware)
vq.assert_distribution_close(qc, {"00": 0.5, "11": 0.5})
# 2. Did an "optimised" rewrite change behaviour? (regression test)
vq.assert_circuits_equivalent(qc, my_optimised_qc)
Failures raise QuantumAssertionError (a subclass of AssertionError), so they
show up in pytest exactly like any other failed assertion.
The five checks in v0.1
| Function | What it verifies | How |
|---|---|---|
assert_distribution_close |
output distribution matches expected | chi-squared goodness-of-fit (shot-noise aware) or TVD threshold |
assert_state_equal |
circuit prepares a target statevector | fidelity, up to global phase |
assert_unitary_equal |
circuit implements an intended operation | full-unitary overlap, up to global phase |
assert_circuits_equivalent |
two circuits do the same thing | unitary equivalence — the regression workhorse |
assert_deterministic |
circuit collapses to one outcome | for oracles / reversible logic |
Every check returns an AssertionResult carrying numeric metrics
(p-values, distances, fidelities), so reporters and dashboards can trend them.
Why it works: a circuit that looks fine but isn't
examples/mutation_demo.py builds a correct 3-qubit GHZ state, then deletes a
single CX (a classic mutation-testing bug). A naive eyeball check passes the
broken circuit. Veriqa catches it:
MUTANT circuit (one CX silently deleted)
naive_check(mutant): P('000') = 0.505 -> PASS (looks fine)
veriqa.assert_distribution_close(mutant): [FAIL] output distribution differs (p_value=0.0, tvd=0.5)
veriqa.assert_circuits_equivalent(correct, mutant): [FAIL] circuits are NOT equivalent
The bug lives in the correlations, not the marginal you happened to look at. That gap is exactly what Veriqa exists to close.
Configuration
import veriqa as vq
vq.configure(shots=8192, seed=42, alpha=0.05) # set once per session
Development
pip install -e ".[dev]"
pytest -v
License
MIT © 2026 Abhishek Singh
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 veriqa-0.1.1.tar.gz.
File metadata
- Download URL: veriqa-0.1.1.tar.gz
- Upload date:
- Size: 15.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e77b0e4eda856d1e54714ac80e7c2b534394b32afef252cc2e744bea35e7e882
|
|
| MD5 |
adf3b5b1fc1a8a7dbec37597568d7ada
|
|
| BLAKE2b-256 |
92d182d2c625bd2ebf81b9f90d1f0e09e93930067a21da18b534aa4f52aae18e
|
File details
Details for the file veriqa-0.1.1-py3-none-any.whl.
File metadata
- Download URL: veriqa-0.1.1-py3-none-any.whl
- Upload date:
- Size: 18.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d68efc480cae3946680e3c0ad62ba493852df32c3c6d22b3d917ba5ae3214329
|
|
| MD5 |
2f3abccddac127262792b6f67fa3a3fe
|
|
| BLAKE2b-256 |
7b8ba31fdb3f3a7ccfa39b0bc32c91b03198cf016b0464ac2be990a8a37fd697
|