aleph-sim
aleph is a high-performance quantum circuit simulator written in Rust, with pluggable backends: full state-vector (SIMD + multi-threaded), MPS (matrix product state), and stabilizer (tableau). It is benchmarked against Qiskit Aer (state vector + MPS) and Stim (stabilizer) — every parity-matrix cell is at or below 1.2× its reference, most well below 1× (aleph faster); see the parity report.
Install
pip install aleph-sim
The package is named aleph-sim (the name aleph is taken on PyPI); the
Python module is still import aleph. Wheels: Linux x86_64 (manylinux_2_28)
and macOS arm64, Python ≥ 3.10 (abi3). They are also attached to each
GitHub release.
Quickstart
import aleph
c = aleph.Circuit(2)
c.h(0)
c.cx(0, 1)
result = aleph.run(c, shots=1024, seed=0)
print(result.counts()) # {'00': ~512, '11': ~512}
print(result.statevector()) # 4 amplitudes
Threads
Since v0.3 (P3-13) the wheels link rayon: wide-bond MPS operations use a
thread pool sized to the visible CPUs (small-bond operations always run
sequentially via a size threshold). Set RAYON_NUM_THREADS to bound the pool,
e.g. in cgroup-limited containers where the visible CPU count overstates the
quota.
Noise
import aleph
c = aleph.Circuit(2)
c.h(0); c.cx(0, 1)
nm = aleph.NoiseModel()
nm.add_all_qubit_quantum_error(aleph.depolarizing_error(0.01, 1), ["h"])
nm.add_quantum_error(aleph.depolarizing_error(0.02, 2), ["cx"], [0, 1])
nm.add_readout_error([[0.98, 0.02], [0.03, 0.97]], 0)
print(aleph.run(c, shots=100_000, noise=nm, seed=7).counts())
Error factories mirror Qiskit Aer names (depolarizing_error, amplitude_damping_error, phase_damping_error, pauli_error, bit_flip_error, phase_flip_error). Noise runs on the state-vector backend as per-shot Monte-Carlo trajectories. Attach errors by Aer gate mnemonic ("h", "cx"); unknown names raise ValueError.
QEC decoding
aleph ships MWPM, Union-Find, BP, BP-OSD and relay-BP decoders for stim Detector Error Models, usable directly or through sinter:
pip install "aleph-sim[sinter]"
import sinter, stim, aleph.sinter
circ = stim.Circuit.generated("surface_code:rotated_memory_x", distance=5, rounds=5,
after_clifford_depolarization=0.003)
stats = sinter.collect(tasks=[sinter.Task(circuit=circ)], num_workers=4,
decoders=["aleph-mwpm", "aleph-relay-bp-osd", "pymatching"],
custom_decoders=aleph.sinter.decoders(), max_shots=100_000)
aleph's batch decode parallelizes across shots on all cores, so under
sinter.collect(num_workers=N) set RAYON_NUM_THREADS=1 (or a small number)
to avoid running num_workers × cores threads.
Throughput (scripts/python/bench_qec.py, macOS-26.7-arm64-arm-64bit / arm,
Apple Silicon Mac, 10 logical CPUs; surface d=9 reduced to 5,000 shots —
aleph relay-bp-osd is slow enough that 20,000 would take >60s — every other
row is 20,000). Every aleph decoder is measured on all 10 cores and on one
thread (RAYON_NUM_THREADS=1); pymatching's decode_batch runs on one
thread:
| DEM | decoder | threads | shots | shots/s |
|---|---|---|---|---|
| surface d=5 | aleph mwpm | 10 | 20,000 | 2,196,645 |
| surface d=5 | aleph mwpm | 1 | 20,000 | 733,746 |
| surface d=5 | aleph union-find-weighted | 10 | 20,000 | 2,476,563 |
| surface d=5 | aleph union-find-weighted | 1 | 20,000 | 576,536 |
| surface d=5 | aleph bp-osd | 10 | 20,000 | 18,555 |
| surface d=5 | aleph bp-osd | 1 | 20,000 | 2,987 |
| surface d=5 | aleph relay-bp-osd | 10 | 20,000 | 4,530 |
| surface d=5 | aleph relay-bp-osd | 1 | 20,000 | 756 |
| surface d=5 | pymatching | 1 | 20,000 | 1,503,434 |
| surface d=9 | aleph mwpm | 10 | 5,000 | 202,386 |
| surface d=9 | aleph mwpm | 1 | 5,000 | 33,684 |
| surface d=9 | aleph union-find-weighted | 10 | 5,000 | 392,584 |
| surface d=9 | aleph union-find-weighted | 1 | 5,000 | 82,226 |
| surface d=9 | aleph relay-bp-osd | 10 | 5,000 | 323 |
| surface d=9 | aleph relay-bp-osd | 1 | 5,000 | 55 |
| surface d=9 | pymatching | 1 | 5,000 | 204,928 |
| color d=5 | aleph bp-osd | 10 | 20,000 | 27,827 |
| color d=5 | aleph bp-osd | 1 | 20,000 | 4,628 |
| color d=5 | aleph relay-bp | 10 | 20,000 | 6,042 |
| color d=5 | aleph relay-bp | 1 | 20,000 | 1,047 |
| color d=5 | aleph relay-bp-osd | 10 | 20,000 | 5,729 |
| color d=5 | aleph relay-bp-osd | 1 | 20,000 | 1,040 |
Per core, pymatching is faster. Single-threaded, aleph's dense-blossom
mwpm reaches 0.49× pymatching's throughput at d=5 and 0.16× at d=9, and
union-find-weighted 0.38× and 0.40×: aleph's per-shot matching algorithm is
asymptotically slower than PyMatching's Sparse Blossom (see
docs/perf/qec-q1-mwpm.md; the Sparse Blossom rewrite is tracked in
#331 and not yet done).
On the whole machine, aleph is faster or level. With all 10 cores
against pymatching's one thread, mwpm is 1.46× pymatching at d=5 and
level (0.99×) at d=9, and union-find-weighted is 1.65× and 1.92×.
decode_batch_bit_packed releases the GIL and splits shots across cores, so
this is what a single-process caller sees; a sinter run with many workers
already uses the cores and gets the per-core ratio instead.
ldpc's SinterBpOsdDecoder was installed but has no color-code row here:
its compile_decoder_for_dem raises NotImplementedError on this ldpc
version for a non-decomposed (hypergraph) DEM, so the benchmark skips it
rather than fail. aleph's iterative BP-family decoders (bp-osd, relay-bp,
relay-bp-osd) are two to three orders of magnitude lower throughput than
the one-shot matching decoders — expected, since each shot runs multiple BP
iterations (and, for -osd, a post-processing ordered-statistics step)
rather than a single matching pass.
Links
- Repository: https://github.com/aleph-sim/aleph
- Benchmarks: https://github.com/aleph-sim/aleph/blob/main/docs/perf/parity.md
Metadata
Release files for aleph-sim 0.3.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Built distributions (wheels)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| aleph_sim-0.3.0-cp310-abi3-manylinux_2_28_x86_64.whl | CPython 3.10 | abi3 | Linux glibc 2.28+ x86-64 | Details |
| aleph_sim-0.3.0-cp310-abi3-macosx_11_0_arm64.whl | CPython 3.10 | abi3 | macOS 11.0+ ARM64 | Details |
Total release size: 2.7 MB
Release files / aleph_sim-0.3.0-cp310-abi3-manylinux_2_28_x86_64.whl
| Download URL | aleph_sim-0.3.0-cp310-abi3-manylinux_2_28_x86_64.whl |
|---|---|
| Size | 1.7 MB |
| Tags | CPython 3.10 Linux glibc 2.28+ x86-64 abi3 |
|
SHA-256 checksum How to use checksums |
6da8cb847b86111608b80ab0780f3a2cec1630f94981ec25ee04300cc2512891
|
|
BLAKE2b-256 checksum How to use checksums |
3fb6f7b28e0366bebb214e5bdfaff8bd95c7ec014e4f4dafbfed8664ffd7ed98
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 24, 2026.
Transparency logRelease files / aleph_sim-0.3.0-cp310-abi3-macosx_11_0_arm64.whl
| Download URL | aleph_sim-0.3.0-cp310-abi3-macosx_11_0_arm64.whl |
|---|---|
| Size | 1.0 MB |
| Tags | CPython 3.10 abi3 macOS 11.0+ ARM64 |
|
SHA-256 checksum How to use checksums |
33b12a5eb29c4deb54bbcd476421290119e90c52f59a942bed710cd66ab2e251
|
|
BLAKE2b-256 checksum How to use checksums |
97c7255b1c05134ed8cb458545c307bd6de04308216164eb4bc247521fc2fc67
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 24, 2026.
Transparency log