qliff
A Clifford stabilizer simulator with support for noisy and mid-circuit measurement-based simulation.
- Clifford stab simulation via the Aaronson–Gottesman tableau
- Noisy sim via stabilizer-channel
decomposition
E = Σ_μ q_μ S_μand stratified importance sampling (arXiv:2512.07304), "nearly as cheap as Pauli noise." - Decoder-ready QEC primitives: detectors, observables, detection-event sampling, a detector error model by Pauli-frame propagation, and exporters (parity-check matrix + priors, matching weights, syndrome/label tensors). These drop directly into MWPM (pymatching), BP, or ML decoders.
- Code factories for surface, toric, color/triangular/kagome, subsystem
(Bacon-Shor, gauge), and qLDPC (hypergraph-product, bivariate-bicycle) families, plus
from_stabilisers/from_gaugesfor arbitrary Pauli codes.
Install
pip install qliff
Docs at plutoniumm.github.io/qliff.
Clifford simulation
from qliff import Simulator
s = Simulator(2).H(0).CX(0, 1)
s.canon() # ['+XX', '+ZZ']
s.peek("ZZ") # +1
s.measure("XX") # (+1, False)
m0, m1 = Simulator(2).H(0).CX(0, 1).M(0, 1) # m0 == m1
Mid-circuit measurement and classical feedback are just Python — the simulator is stateful, so conditionals (teleportation, syndrome correction) need no special API:
s = Simulator(3, seed=0)
s.H(0)
s.H(1).CX(1, 2)
s.CX(0, 1).H(0)
if s.M(1) == 1:
s.X(2)
if s.M(0) == 1:
s.Z(2)
s.peek("__X") # +1
Noise
Build Circuit with gate/noise methods, then sample or estimate.
Circuit.estimate picks the right sampler by default — plain Monte-Carlo when every channel is Pauli, otherwise
stratified importance sampling
from qliff import Circuit
c = Circuit(1)
c.H(0).DEPOLARIZE1(0, 0.1).M(0)
c.sample(1000)
c = Circuit(1)
c.H(0).RZ(0, 0.3)
c.estimate("X", 20000) # ≈ cos(0.3)
c = Circuit(1)
c.X(0).AMPLITUDE_DAMP(0, 0.3)
c.estimate("Z", 60000) # ≈ 2p - 1
Force the variance strategy with c.estimate(obs, shots, stratify=False) (flat) or stratify=True
(stratified), or drive the sampler directly: from qliff.noise import Sampler, then
Sampler(c).expect(obs, shots, stratify=True). Add a custom channel by subclassing
qliff.noise.Channel and dropping it in with c.noise(ch, q).
For deep-tail logical error rates where plain Monte-Carlo needs prohibitively many shots,
from qliff.noise import SplittingEstimator runs a multilevel-splitting (subset-sampling)
estimator that reaches the far tail with orders of magnitude fewer decodes.
Quantum error correction
qliff.qec ships code-circuit generators, so you can go straight to a logical-error-rate
curve. Alongside rotated_surface_code there are unrotated_surface_code, toric_code,
repetition_code, the color family (color_code, hex_color_code, triangular_code,
kagome_code), subsystem codes (bacon_shor_code, from_gauges), and qLDPC codes
(hypergraph_product_code, bivariate_bicycle_code); from_stabilisers builds a full
memory circuit from an arbitrary Pauli stabiliser set. Every family whose code has an
X/Z dual takes memory="Z" or memory="X" to run either basis. Any circuit's detectors
and observables are declared with c.detector(...) / c.observable(...), then turned
into decoder inputs:
from qliff.qec import rotated_surface_code, logical_fidelity
from pymatching import Matching
c = rotated_surface_code(5, 5, 0.01) # distance, rounds, p (square d x d patch)
dem = c.dem()
H, priors, obs_matrix = dem.check_matrix()
m = Matching.from_check_matrix(
H,
weights=dem.weights(),
faults_matrix=obs_matrix
)
dets, flips = c.detector_sampler().sample(20000)
fidelity = logical_fidelity(m.decode_batch(dets), flips)
A memory is blind to noise that commutes with its own basis -- a Z-memory cannot see
Z_ERROR or RZ, and reports a logical error rate of exactly zero at any p. qliff
warns when you build one, and again if the detector error model comes out empty; run the
dual basis instead:
c = rotated_surface_code(3, 3, 0.01, channel="Z_ERROR", memory="X") # sees the noise
Extending
Everything you'd customize lives in Python. Add a noise channel by subclassing
qliff.noise.Channel and returning its stabilizer-channel branches; plug in a custom
sampler or observable; export the DEM to whatever decoder you like. The Rust core stays a thin,
fast tableau engine.
Develop
./do develop # build rust core
./do test
./do lint
./do bench
./do build # all wheels (macOS/Linux/Windows, x86_64 + arm) + sdist, no upload
./do deploy # publish what `build` made to PyPI (no rebuild)
cd docs && npm run build && npm run deploy # docs site -> GitHub Pages
License
MIT
If you are a company using this, please get a grad student to help you with issues. If you are a grad student, please feel free to email me :)
Release files for qliff 0.5.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| qliff-0.5.0.tar.gz | 76.2 kB | Details |
Built distributions (wheels)
| File | Reset | |||
|---|---|---|---|---|
| qliff-0.5.0-cp311-abi3-win_arm64.whl | CPython 3.11 | abi3 | Windows ARM64 | Details |
| qliff-0.5.0-cp311-abi3-win_amd64.whl | CPython 3.11 | abi3 | Windows x86-64 | Details |
| qliff-0.5.0-cp311-abi3-manylinux_2_28_x86_64.whl | CPython 3.11 | abi3 | Linux glibc 2.28+ x86-64 | Details |
| qliff-0.5.0-cp311-abi3-manylinux_2_28_aarch64.whl | CPython 3.11 | abi3 | Linux glibc 2.28+ ARM64 | Details |
| qliff-0.5.0-cp311-abi3-macosx_11_0_x86_64.whl | CPython 3.11 | abi3 | macOS 11.0+ x86-64 | Details |
| qliff-0.5.0-cp311-abi3-macosx_11_0_arm64.whl | CPython 3.11 | abi3 | macOS 11.0+ ARM64 | Details |
Total release size: 2.4 MB
Release files / qliff-0.5.0.tar.gz
| Download URL | qliff-0.5.0.tar.gz |
|---|---|
| Size | 76.2 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
f2e6251d9d923da7f5c261b35f12e08a8d8aed2cb66fb9ab806fa4f8b7a5d981
|
|
BLAKE2b-256 checksum How to use checksums |
65f4f9b32833bde1b58b5a5c4f2ba0da52e60c1468de491b36af92cd6294f731
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.14.3
|
Release files / qliff-0.5.0-cp311-abi3-win_arm64.whl
| Download URL | qliff-0.5.0-cp311-abi3-win_arm64.whl |
|---|---|
| Size | 308.5 kB |
| Tags | CPython 3.11 Windows ARM64 abi3 |
|
SHA-256 checksum How to use checksums |
0ab2cb8b27ba28a158d2c9462bb1ad90c1bfe95336128021a9f477a204f4e5c8
|
|
BLAKE2b-256 checksum How to use checksums |
d4f5c0f1770e165817c1841eb1e71fbd26d6dd1de5a53e4fa8f79ac3a193ee19
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.14.3
|
Release files / qliff-0.5.0-cp311-abi3-win_amd64.whl
| Download URL | qliff-0.5.0-cp311-abi3-win_amd64.whl |
|---|---|
| Size | 326.0 kB |
| Tags | CPython 3.11 Windows x86-64 abi3 |
|
SHA-256 checksum How to use checksums |
2c74a76852f3d3daa3c9ccb1e2470b9d52b7d3ac25890374a88012da55b35be6
|
|
BLAKE2b-256 checksum How to use checksums |
eaeea4925d0169023bd02df1ef07df710a498d893731ca957fb0a922ff244dbb
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.14.3
|
Release files / qliff-0.5.0-cp311-abi3-manylinux_2_28_x86_64.whl
| Download URL | qliff-0.5.0-cp311-abi3-manylinux_2_28_x86_64.whl |
|---|---|
| Size | 453.2 kB |
| Tags | CPython 3.11 Linux glibc 2.28+ x86-64 abi3 |
|
SHA-256 checksum How to use checksums |
9d04b57c53dec984df6075e628d8a49feadb8d6ef35eed0c79612edccf22abef
|
|
BLAKE2b-256 checksum How to use checksums |
02fd94e17275a06433f3297b516bd761d5354a922a7e36e6a97c49f0173a6501
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.14.3
|
Release files / qliff-0.5.0-cp311-abi3-manylinux_2_28_aarch64.whl
| Download URL | qliff-0.5.0-cp311-abi3-manylinux_2_28_aarch64.whl |
|---|---|
| Size | 446.0 kB |
| Tags | CPython 3.11 Linux glibc 2.28+ ARM64 abi3 |
|
SHA-256 checksum How to use checksums |
92041b0ff4b08c94cc376920b0a58d0b8ffc67ad541133a9bf0497a423472e77
|
|
BLAKE2b-256 checksum How to use checksums |
c009d1d7ad8a6c634d230b800f089aea58dc541aa97e68de25bab9859a0a43d8
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.14.3
|
Release files / qliff-0.5.0-cp311-abi3-macosx_11_0_x86_64.whl
| Download URL | qliff-0.5.0-cp311-abi3-macosx_11_0_x86_64.whl |
|---|---|
| Size | 422.4 kB |
| Tags | CPython 3.11 abi3 macOS 11.0+ x86-64 |
|
SHA-256 checksum How to use checksums |
48a2cbcc30ea2f08c0b55528a9a500f48fe049f294441c7501e4d4cd00b5d8f0
|
|
BLAKE2b-256 checksum How to use checksums |
3ae88defca4504afcd0276e550a2d4f706b1da611d301ec33b5a545dc2c2d39a
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.14.3
|
Release files / qliff-0.5.0-cp311-abi3-macosx_11_0_arm64.whl
| Download URL | qliff-0.5.0-cp311-abi3-macosx_11_0_arm64.whl |
|---|---|
| Size | 401.6 kB |
| Tags | CPython 3.11 abi3 macOS 11.0+ ARM64 |
|
SHA-256 checksum How to use checksums |
0f8e7a08626e2a87a603b2ffacbc0a60b4af5ba6a4f7237525c2baa93b0f3a8e
|
|
BLAKE2b-256 checksum How to use checksums |
62c311a9cc11d482bf0652163e6d69f03e5b2cfbfa141141875c8821a2339488
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.14.3
|