QuDenoise
A from-scratch, pure-Python Matrix Product State (MPS) quantum circuit simulator with Kraus-channel noise (quantum trajectories) and a quantum-autoencoder (QAE) denoiser. Runs on NumPy everywhere; optionally runs every tensor operation on a GPU through CuPy.
Install
pip install qudenoise # NumPy/SciPy only (CPU)
pip install "qudenoise[viz]" # + matplotlib for plotting examples
GPU (optional)
CuPy publishes one wheel per CUDA version, so QuDenoise does not pin a CuPy variant. Install the one matching your toolkit yourself, e.g.
pip install cupy-cuda12x # CUDA 12.x
pip install cupy-cuda11x # CUDA 11.x
(pip install "qudenoise[gpu]" pulls the generic cupy source package, which needs a local CUDA toolchain.)
CuPy is imported lazily: without it QuDenoise imports and runs with no errors or warnings. With
device="auto" (default) the GPU is used when available and this is logged once
(QuDenoise: running on GPU (CuPy) / running on CPU (NumPy)); force a backend with
Simulator(device="cupy") or device="numpy".
Quick start
from qudenoise import Circuit, Simulator
c = Circuit(20).h(0)
for i in range(19):
c.cnot(i, i + 1)
sim = Simulator(bond_dim=8) # chi cap; also truncation_threshold=...
state = sim.run(c) # -> MPS
print(state.bond_dimensions(), state.fidelity_estimate)
samples, report = sim.sample(c, shots=1000, seed=1)
Non-adjacent two-qubit gates are routed with SWAP chains automatically; every insertion is logged
(logger qudenoise, INFO) and recorded in sim.last_report.routing_log.
Noise
c = Circuit(2).h(0).cnot(0, 1).depolarizing(0, 0.05).amplitude_damping(1, 0.1)
res = Simulator().run_observable(c, lambda m: observables.expectation(m, {0: gates.Z(), 1: gates.Z()}).real,
n_trajectories=2000, seed=0)
print(res.mean, "+/-", res.sem)
Channels: depolarizing (1q/2q), amplitude_damping, phase_damping, bit_flip, phase_flip, or any
KrausChannel. Trajectories are seeded per index (spawn_seeds), so results are identical for any worker
count. CPU runs with 8+ trajectories use a process pool; GPU runs are sequential in-process.
Quantum autoencoder
from qudenoise import QAE
qae = QAE(n_qubits=4, n_latent_qubits=2, ansatz_depth=2, seed=1)
qae.fit(training_states, epochs=60, lr=0.1) # MPS / Circuit / dense vectors
clean_estimate = qae.denoise(noisy_state)
Cost = 1 - mean probability of the trash qubits being |0..0>, computed directly from the MPS. Gradients
use the parameter-shift rule through qudenoise.qae.compute_gradient; pass gradient_fn= to plug in a JAX
([autodiff]) backend without changing the API.
CLI
qudenoise run circuit.json --qubits 20 --bond-dim 32 --shots 1000 [--device auto|numpy|cupy] [-o out.json]
qudenoise train-qae config.yaml
Circuit JSON: {"n_qubits": N, "ops": [{"gate": "h", "qubits": [0]}, {"gate": "rz", "qubits": [1], "params": [0.3]}, {"noise": "depolarizing", "qubits": [0], "param": 0.01}]}. A .py file defining circuit or
build_circuit(n) also works (executed as ordinary Python - only run files you trust). See
examples/qae_config.yaml.
Conventions and limits
- Big-endian qubit order (
|q0 q1 ...>); rotations areexp(-i theta P / 2). MPS.to_dense()refuses above 24 qubits unless forced.qudenoise.reference(dense/density-matrix simulators) exists to validate the MPS code in tests; it is not a supported product feature.- With truncation,
state.truncation_error,state.fidelity_estimate(product of1 - eps_k) andstate.fidelity_lower_boundtrack accuracy loss.
Development
pip install -e ".[test]" && pytest
Tests run on NumPy and, when CuPy + a GPU are present, are repeated on CuPy (backend-parity check).
See docs/design_notes.md.
MIT licensed.
Release files for qudenoise 0.1.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 | |
|---|---|---|---|
| qudenoise-0.1.0.tar.gz | 56.9 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| qudenoise-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 101.0 kB
Release files / qudenoise-0.1.0.tar.gz
| Download URL | qudenoise-0.1.0.tar.gz |
|---|---|
| Size | 56.9 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
c00cfa5477372fce3597540f991ef43b82bc5c32a0fd4a5b2a556ff39d3d419f
|
|
BLAKE2b-256 checksum How to use checksums |
39a885e1780a83a00e74ab3161e471068a5dec8c9877a565fb6b94dc38a8d84d
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.13
|
Release files / qudenoise-0.1.0-py3-none-any.whl
| Download URL | qudenoise-0.1.0-py3-none-any.whl |
|---|---|
| Size | 44.1 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
1e9526a49a23161ed4df8091766bf41547211766d873bff003926933d0af5dbd
|
|
BLAKE2b-256 checksum How to use checksums |
8d098c8ee117c0adbbdf361236b51d92841400fc6b1ea7778289fabe2f2af216
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.13
|