Quantum circuit simulation (statevector + stabilizer) with IQM cloud submission, quantum random numbers from IQM bit pools, and QRNG synthetic data with provable provenance.
Project description
lightrider — quantum circuits, quantum random numbers & QRNG synthetic data
lightrider ships three layers:
- A circuit simulator & cloud runner — build arbitrary circuits with a
qiskit-style
CircuitAPI and run them on one of three backends: a speed-focused dense statevector simulator, a Stim-style stabilizer (Clifford) simulator, or IQM hardware in the cloud via the Light Rider proxy. Every backend declares the gate set it supports. - A QRNG primitive —
IQM_sirius(...)draws quantum random numbers from a bundled IQM bit pool (Hadamard coin-flip circuits across 10 qubits, SHA-256 debiased). Fully offline. - A synthetic-data engine —
Synthesizerfits a Gaussian copula to your tabular data and generates new rows whose every random draw comes from a quantum source, shipping each dataset with a signed provenance manifest.
No torch. No network required (simulators and the QRNG pool are local). Upgrade to IQM hardware or live, signed, multi-source entropy by pointing it at a Light Rider endpoint.
Install
pip install lightrider # numpy only
pip install "lightrider[live]" # + lr-entropy SDK (live EMS entropy)
pip install "lightrider[pandas]" # + DataFrame in/out
Quantum circuit simulation & cloud jobs
from lightrider import Circuit, get_backend
circ = Circuit(2)
circ.h(0)
circ.cx(0, 1)
circ.measure_all()
# local, exact, fast — shots are sampled in one vectorized pass
job = get_backend("statevector").run(circ, shots=100_000, seed=42)
print(job.result().counts) # {'00': 50121, '11': 49879}
# local, Stim-style stabilizer tableau — Clifford circuits at 100s of qubits,
# mid-circuit measurement supported
job = get_backend("stabilizer").run(circ, shots=1000)
# cloud — IQM QPU through the Light Rider proxy (lr_ API key, never IQM tokens)
iqm = get_backend("iqm", endpoint="https://quantum.lightrider.example",
api_key="lr_...")
job = iqm.run(circ, shots=1000) # returns immediately
print(job.status()) # WAITING / PROCESSING / COMPLETED
print(job.result().counts) # polls until terminal
The three backends
| Backend | Where | Gate set | Best for |
|---|---|---|---|
lightrider_statevector (alias statevector) |
local | full set (h x y z s sdg t tdg sx rx ry rz p r u cx cy cz ch swap cp rxx ryy rzz ccx cswap) |
exact simulation ≤ 24 qubits; huge shot counts are ~free |
lightrider_stabilizer (aliases stabilizer, stim) |
local | Clifford subset (x y z h s sdg sx cx cy cz swap) |
Clifford circuits to hundreds of qubits, mid-circuit measurement |
iqm (alias cloud) |
cloud | full set, transpiled server-side to IQM's native r (prx) + cz |
real-hardware runs via the Light Rider IQM proxy |
list_backends() reports each backend's gate set programmatically, and
run() rejects a circuit up front if it uses unsupported gates
(UnsupportedGateError) — a job that submits will also execute.
Custom composite gates expand to primitives at append time:
from lightrider import custom_gate
@custom_gate(num_qubits=2)
def bell_pair(c, qubits, params):
a, b = qubits
c.h(a)
c.cx(a, b)
circ = Circuit(3)
circ.append(bell_pair, [0, 1])
Circuits serialize to the lr-circuit/v1 JSON payload (circ.to_payload())
shared with the Light Rider proxy and lr-entropy SDK, and to a Stim-flavored
text format (circ.to_text() / Circuit.from_text(...)).
Quantum random numbers
from lightrider import IQM_sirius
IQM_sirius(5, 1, 100) # → [42, 7, 88, 13, 56]
IQM_sirius(3, 0.0, 1.0, step=0.1) # → [0.3, 0.8, 0.1]
Numbers are produced by rejection sampling over the debiased quantum bit pool, so output is unbiased on any range.
QRNG synthetic data
from lightrider import Synthesizer
synth = Synthesizer(dataset_id="customers_v3").fit(df) # df: DataFrame / dict / records
rows = synth.generate(10_000) # QRNG-driven synthetic rows
synth.manifest.write("customers_v3.provenance.json") # the certificate
print(synth.certificate())
How it works — the provable pipeline
fit: data ─▶ marginals (empirical CDF / category freqs)
─▶ normal scores z = Φ⁻¹(rank)
─▶ correlation Σ = corr(z), Cholesky Σ = L Lᵀ
gen: QRNG ─▶ U(0,1) (quantum draws, recorded on the manifest)
─▶ Z₀ = Φ⁻¹(U) (iid standard normals)
─▶ Z = Z₀ Lᵀ (impose learned correlation)
─▶ U' = Φ(Z) (back to uniform, per column)
─▶ x = F⁻¹(U') (inverse marginal → synthetic value)
The copula reproduces each column's marginal distribution and the
correlations between columns; the randomness that selects each synthetic row is
quantum, not a PRNG. See docs/qrng-synthetic-data.tex (rendered:
docs/qrng-synthetic-data.pdf) for the full mathematical treatment.
Entropy modes
| Mode | Provider | Provenance |
|---|---|---|
| bundled-qrng (default) | BundledQrng over the packaged IQM pool |
real quantum bits, SHA-256 debiased, offline, unsigned |
| live-attested | EntropySource against a Light Rider EMS |
multi-source extraction over GF(2¹²⁸), 800-90B health-tested, post-quantum-signed receipts |
from lightrider import EntropySource, Synthesizer
src = EntropySource("http://localhost:7081", dataset_id="customers_v3")
synth = Synthesizer(entropy=src).fit(df)
rows = synth.generate(10_000) # every draw carries a signed receipt
EntropySource(allow_failover=True) (the default) falls back to the OS CSPRNG
on any EMS error so a long job never blocks. Failover draws are flagged in the
manifest and excluded from the certificate's source list — the certificate
never overstates its provenance.
Provenance is the product
Each dataset gets a sidecar manifest binding it to the entropy that produced it:
{
"dataset_id": "customers_v3", "model": "qrng-copula",
"rows": 10000, "columns": ["age", "income", "tier", "region"],
"entropy_mode": "live-attested", "fully_attested": true,
"signature_alg": "ML-DSA-65", "post_quantum_signed": true,
"sources_used": ["curby_q_jila_001", "qispace_kds_001"],
"min_quality_score": 90, "health_all_pass": true,
"extractors": ["SHAKE256"], "failover_used": false
}
For the offline default the same manifest reports entropy_mode: "bundled-qrng",
post_quantum_signed: false, and the bundled IQM source — honest by construction.
Demo / tests
python -m lightrider.demo --rows 2000 --out synthetic.csv --manifest cert.json
python -m lightrider.demo --endpoint http://localhost:7081 --rows 2000 # live
pytest tests -q
Data source
The bundled pool is ~2 million bits collected from IQM Hadamard coin-flip
circuits across 10 qubits (capture metadata in
iqm_capture_20260507_181448/metadata.json). Live entropy is sourced from the
Light Rider EMS multi-source pipeline.
Project details
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 lightrider-0.3.0.tar.gz.
File metadata
- Download URL: lightrider-0.3.0.tar.gz
- Upload date:
- Size: 529.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.10.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d54edd0cbee07651287c69b4e5eeffb1386412b33d96a7a20527100e76602bf2
|
|
| MD5 |
68e7fc78d82f74e246408b90e434f7bf
|
|
| BLAKE2b-256 |
5bd8c59ab3e4b15ee048a946bf85d36f30828d8c2d0546d8597790bf6d06d9b3
|
File details
Details for the file lightrider-0.3.0-py3-none-any.whl.
File metadata
- Download URL: lightrider-0.3.0-py3-none-any.whl
- Upload date:
- Size: 655.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.10.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
dbbf9a28c8a0139e9fc2e3f4d2e0e840cf0c1f7a308140309b6e9ab90acdbedb
|
|
| MD5 |
1d7ab0f4aa232ab1cc896effaffaadfa
|
|
| BLAKE2b-256 |
bf97217c2c6ca6b0d7d7932188e84cf2b21b45ac0d3bb49d0688928da1a11c7e
|