The universal quantum experiment lifecycle platform. Execute circuits across frameworks, track noise, benchmark hardware, and persist everything.
Project description
QLedger
The Universal Quantum Experiment Lifecycle Platform.
Execute circuits across Qiskit, Cirq, and PennyLane. Track noise. Benchmark hardware. Version circuits. Persist everything in a portable SQLite file.
Why QLedger?
The quantum computing ecosystem is fragmented. Every framework has its own circuit format, every backend returns results differently, and there's no standard way to track experiments, compare hardware, or reproduce results.
QLedger fixes this with a single platform that:
- Runs circuits on any framework — Qiskit, Cirq, PennyLane — through a universal adapter layer
- Persists everything — circuits, results, metadata, seeds, timing, noise profiles — in one portable
.dbfile - Versions circuits — git-like tracking of how your circuits evolve over time
- Benchmarks hardware — Quantum Volume, CLOPS, and algorithmic fidelity benchmarks with standardised scoring
- Tracks noise — capture T1/T2, gate fidelities, and readout errors over time to monitor hardware drift
- Enables reproducibility — every seed, every setting, every result is stored for exact replay
Installation
Note: PyPI release pending — until then, install from source (see below). The
pip install qledgercommands will work once the first release is published.
# Core only (no framework dependencies)
pip install qledger
# With specific frameworks
pip install qledger[qiskit]
pip install qledger[cirq]
pip install qledger[pennylane]
pip install qledger[all]
From source:
git clone https://github.com/namashworks/qledger.git
cd qledger
pip install -e ".[dev]"
Quick Start
from qiskit import QuantumCircuit
from qledger import QLedger
with QLedger("my_research.db") as db:
# Create an experiment
exp_id = db.create_experiment("Bell States", tags=["entanglement"])
# Build and run a circuit — everything is saved automatically
qc = QuantumCircuit(2, 2)
qc.h(0)
qc.cx(0, 1)
qc.measure([0, 1], [0, 1])
result = db.run(qc, experiment_id=exp_id, shots=4096, seed_simulator=42)
print(result.counts) # {'00': 2009, '11': 2087}
print(result.probabilities) # {'00': 0.490, '11': 0.510}
print(result.most_frequent()) # '11'
print(result.entropy()) # ~1.000 (near-maximum for 2 equally likely outcomes)
Core Features
1. Universal Circuit IR
Convert between frameworks seamlessly:
# Qiskit -> Universal -> Cirq
cirq_circuit = db.convert(qiskit_circuit, from_framework="qiskit", to_framework="cirq")
The UniversalCircuit is a framework-agnostic intermediate representation with content hashing, validation, and full serialisation support.
2. Cross-Framework Execution
# Run the same circuit on different backends
result_qiskit = db.run(qc, framework="qiskit", shots=4096)
result_cirq = db.run(cirq_circuit, framework="cirq", shots=4096)
3. Circuit Versioning
Track circuit evolution like git tracks code:
# Auto-versioned on every run, or manually:
db.version_circuit(circuit_id, modified_circuit, message="optimised CX count")
# View history
log = db.circuit_log(circuit_id)
# Diff between versions
diff = db.diff_circuit(circuit_id, version_a=1, version_b=3)
print(diff.summary_text()) # "+2 gates, -1 gates, depth: 5 -> 4"
# Restore any version
old_circuit = db.checkout_circuit(circuit_id, version=1)
4. Standardised Benchmarks
suite = db.benchmark(framework="qiskit")
# Quantum Volume
qv = suite.run_quantum_volume(backend=my_backend, max_depth=8)
print(f"Quantum Volume: {qv.details['quantum_volume']}")
# CLOPS (throughput)
clops = suite.run_clops(num_circuits=100, shots=1024)
print(f"CLOPS: {clops.score:.0f}")
# Algorithmic fidelity (GHZ, QFT)
ghz = suite.run_algorithmic(algorithm="ghz", qubit_range=(2, 10))
print(f"Average fidelity: {ghz.score:.4f}")
# Compare backends
comparison = suite.compare_backends("quantum_volume", ["backend_a", "backend_b"])
5. Noise Profiling
# Capture noise from a real backend
snapshot = db.capture_noise(backend, framework="qiskit")
print(f"Median T1: {snapshot.median_t1_us:.1f} us")
print(f"Avg CX error: {snapshot.average_cx_error:.4f}")
print(f"Avg readout error: {snapshot.average_readout_error:.4f}")
# Track drift over time
history = db.get_noise_history("ibm_kyoto")
# Find the best qubits
best = db.best_qubits("ibm_kyoto", count=5, metric="t1")
6. Batch Execution
results = db.run_batch(
[circuit_1, circuit_2, circuit_3],
experiment_name="Parameter Sweep",
names=["theta=0.1", "theta=0.5", "theta=1.0"],
shots=8192,
)
7. Export
# Export full experiment as JSON
data = db.export_experiment(exp_id)
# Includes: experiment metadata, all circuits (as UniversalCircuit JSON),
# all executions (with counts, timing, seeds), version history
CLI
# List experiments
qledger experiments
# Show experiment details
qledger show 1
# List circuits with structural info
qledger circuits 1
# List executions with results
qledger executions --backend aer_simulator
# View circuit version history
qledger versions 1
# View benchmark results
qledger benchmarks --type quantum_volume
# View noise snapshots
qledger noise --backend ibm_kyoto
# Export experiment to JSON
qledger export 1 -o experiment.json
# List available framework adapters
qledger adapters
Database Schema
Everything lives in a single SQLite file:
| Table | Purpose |
|---|---|
experiments |
Named containers with tags and descriptions |
circuits |
UniversalCircuit JSON, content hash, gate counts, depth |
executions |
Counts, probabilities, entropy, backend config, seeds, timing |
circuit_versions |
Version history with diffs and parent hashes |
noise_snapshots |
T1/T2, gate fidelities, readout errors per qubit |
benchmark_results |
QV, CLOPS, algorithmic scores with full parameters |
Foreign keys with ON DELETE CASCADE. WAL mode for concurrent reads.
Architecture
qledger/
schema/ # Universal data models (circuit IR, results, noise)
gates.py # 30+ canonical gates with cross-framework aliases
circuit.py # UniversalCircuit with hashing, validation, depth calc
result.py # ExecutionResult with entropy, fidelity computation
noise.py # NoiseSnapshot, QubitProperties, GateFidelity
adapters/ # Framework adapters (Qiskit, Cirq, PennyLane)
base.py # Abstract adapter interface
registry.py # Lazy auto-discovery registry
storage/ # SQLite persistence layer
versioning/ # Git-like circuit version tracking with diffs
noise/ # Noise profiling and drift analysis
benchmarks/ # Quantum Volume, CLOPS, algorithmic benchmarks
core/ # Main QLedger engine
cli/ # Command-line interface
Development
pip install -e ".[dev]"
pytest # 95 tests
ruff check . # Lint
mypy qledger # Type check
License
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 qledger-0.1.0.tar.gz.
File metadata
- Download URL: qledger-0.1.0.tar.gz
- Upload date:
- Size: 55.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
5e20dae8341a6fc4a155842001077e7508787483d6c7b57bab46d100821118ca
|
|
| MD5 |
14b26e2a74ea0a170ecfda94536f0af4
|
|
| BLAKE2b-256 |
f4f4e1619b631ae536fc85d0b090e25f223dc2bb2e39afbde70f6d64caf26451
|
File details
Details for the file qledger-0.1.0-py3-none-any.whl.
File metadata
- Download URL: qledger-0.1.0-py3-none-any.whl
- Upload date:
- Size: 58.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d891ed9edceb4507d792ecb0c362be65896e0684fdb01464ab208686df0ce522
|
|
| MD5 |
53f657c8f3e2e7ae1627c1639af5faee
|
|
| BLAKE2b-256 |
c7aad80e421c0530fed675c77d8caf4b93c49bb63d59869b7db4d53b1dc9dc48
|