Skip to main content

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.

CI PyPI License: MIT Python 3.10+ DOI


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 .db file
  • Versions circuits — git-like tracking of how your circuits evolve over time
  • Benchmarks hardware — a heavy-output (QV-style) benchmark, CLOPS throughput, and algorithmic fidelity (GHZ, QFT)
  • 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

# 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. Benchmarks

suite = db.benchmark(framework="qiskit")

# Heavy-output benchmark (QV-style — see note)
hop = suite.run_quantum_volume(backend=my_backend, max_depth=8)
print(f"Heavy-output depth: {hop.details['achieved_depth']}")

# 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("heavy_output", ["backend_a", "backend_b"])

Note on the heavy-output benchmark: it follows the standard heavy-output protocol (ideal-distribution simulation + 2/3 threshold), but the two-qubit ansatz is a single CNOT with random rotations, not Haar-random SU(4). It is a proxy indicator and is not comparable to spec-compliant Quantum Volume (Cross et al. 2019). True-QV sampling is on the roadmap.

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

MIT

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

qledger-0.1.1.tar.gz (56.0 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

qledger-0.1.1-py3-none-any.whl (59.0 kB view details)

Uploaded Python 3

File details

Details for the file qledger-0.1.1.tar.gz.

File metadata

  • Download URL: qledger-0.1.1.tar.gz
  • Upload date:
  • Size: 56.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.9

File hashes

Hashes for qledger-0.1.1.tar.gz
Algorithm Hash digest
SHA256 2f2d690487434ecb989b89a15223ea6c4c10020a91d082d6bb83878286ee8d4a
MD5 5ff91320a828b14459cb1b7ffb7fa897
BLAKE2b-256 2b0f55ea40f31d52e562ecc6a283d4ecac92bf8dc4e03653fb378dfff3a033ab

See more details on using hashes here.

File details

Details for the file qledger-0.1.1-py3-none-any.whl.

File metadata

  • Download URL: qledger-0.1.1-py3-none-any.whl
  • Upload date:
  • Size: 59.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.9

File hashes

Hashes for qledger-0.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 975a45378a1055ce860269658c562226d6d3e78abb414bcd5fff1a770a8caca0
MD5 e34ad43c43200bfaa4afdb2fa7b2a5cc
BLAKE2b-256 dae84e5e7cafff34d1046e508cd861c8e17dbe71ab3c915c62ecdd5a967cf877

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page