Skip to main content

Profiling, analytics, and PDF reporting for the runtime performance of quantum circuit simulators.

Project description

QS_Charter

Profiling, analytics, and bundled-PDF reporting for the runtime performance of quantum circuit simulators.

QS_Charter does not simulate circuits, modify simulators, or visualize circuit diagrams. It measures how a simulator performs — wall time, CPU, memory, and (if available) GPU usage — while it runs, and turns a sweep of runs into scaling-trend analysis, crossover detection, anomaly flags, and a bundled PDF report.

It works with any simulator, with no per-library adapters, because of two design choices:

  1. You wrap your own call to your simulator inside qs_charter.track(...). QS_Charter never imports or calls into the simulator itself.
  2. Measurement is out-of-process / OS-level sampling (via psutil, plus pynvml/nvidia-smi for GPU), not in-Python profiling — so it works correctly whether the simulator is pure Python, a C++/Rust/Julia extension, or running on a GPU.

Install

pip install qs-charter

# optional extras
pip install qs-charter[gpu]       # GPU sampling via pynvml (falls back to nvidia-smi either way)
pip install qs-charter[parquet]   # bulk export to Parquet
pip install qs-charter[dev]       # pytest, etc., for running the test suite

Quickstart

import qs_charter as mq

# 1. Track each run. QS_Charter starts a background sampling thread, lets your
#    code run completely unmodified, and stops sampling when the block exits.
with mq.track(label="qiskit_aer", meta={"qubits": 20, "depth": 50,
                                         "backend_type": "statevector"},
               save_dir="./runs"):
    result = simulator.run(circuit)

# ... repeat across a sweep of qubit counts and/or simulators ...

# 2. Reload every run from disk. This step needs zero simulator-specific
#    context -- it works on a machine with no simulator installed at all.
records = mq.load_all("./runs/")

# 3. Build the report: scaling fits, crossover detection, anomaly flags,
#    charts, and deterministic template-based narrative text, all in one call.
report = mq.report(records, compare_by="label")

# 4. Render the bundled PDF (title page, executive summary, one section per
#    metric, cross-simulator comparison table, appendix of raw stats).
report.save_pdf("benchmark_report.pdf")

Run python examples/sweep_example.py for a complete, runnable end-to-end demo (using a mock simulator, so no real quantum simulator is required) that produces a sample PDF report.

The track() -> load_all() -> report() -> save_pdf() workflow

track() — collect

with mq.track(label, meta=None, interval=0.075, save_dir=None) as t:
    ...your simulator call...

t.record            # the resulting RunRecord, available after the `with` block exits
  • Also works as a decorator: @mq.track(label="my_sim", meta={"qubits": 24}).
  • meta is a free-form dict: put qubits, depth, gate_count, simulator_name, backend_type ("statevector" | "tensor_network" | anything else), or any custom field you want available later in analysis/reporting.
  • save_dir, if given, auto-saves the run as a JSON file there, ready for load_all().
  • If an exception escapes the with block, the run is still recorded, with metadata["failed"] = True and an error message — these show up as critical anomalies in the report rather than crashing your sweep.
  • GPU sampling degrades gracefully: with no GPU (or no pynvml/nvidia-smi), every GPU field is simply None, never an error.

load_all() — reload (replay, no simulator required)

records = mq.load_all("./runs/")        # every *.json in a directory
records = mq.load("./runs/one_run.json")  # a single file

The on-disk JSON is the full-fidelity record (metadata, time-series, summary, and any backend-specific extensions). Bulk CSV/Parquet export is also available via mq.save(records, "runs.csv"), but those formats drop the time-series and are meant for external tools (pandas, Excel), not round-tripping.

report() — analyze + build

report = mq.report(
    records,
    compare_by="label",              # or e.g. "metadata.backend_type"
    metrics=["summary.wall_time", "summary.peak_mem_rss", "summary.mean_cpu_pct"],
    x_field="metadata.qubits",
    title="My Benchmark Report",
)

report.executive_summary   # str
report.findings            # dict of scaling_fits / crossovers / anomalies (JSON-able)

Under the hood this runs qs_charter.analysis (scaling-trend fits, crossover detection, anomaly flags — all structured data, not strings), then qs_charter.visualize (matplotlib charts), then qs_charter.report.narrative (deterministic templates turning the structured findings into captions and an executive summary).

save_pdf() / exports — output

report.save_pdf("benchmark_report.pdf")        # the bundled PDF
report.export_data("./export", fmt="json")     # raw RunRecords (json/csv/parquet)
report.export_charts("./charts")               # every chart as a standalone PNG

Architecture

Module Responsibility
qs_charter.collection track() — background OS-level sampling context manager / decorator
qs_charter.schema RunRecord / Sample — the canonical, JSON-serializable data model
qs_charter.analysis Scaling-trend fits, crossover detection, anomaly flags — structured findings only
qs_charter.visualize matplotlib charts (scaling curves, comparison overlays, time-series, summary tables)
qs_charter.report Ties analysis + visualize + narrative together into a Report (PDF + data exports)

RunRecord is the single contract between these modules — analysis, visualize, and report never talk to each other directly, and none of them know anything about simulators. This is what makes "replay" workflows possible: capture once (with the simulator installed), analyze/report anywhere (without it).

A note on the PDF report's text

Every caption, interpretation, and the executive summary are produced by deterministic string templates in qs_charter.report.narrative, fed only by the structured output of qs_charter.analysis. There is no LLM, no external API call, and no network access involved at any point — the same input data always produces byte-identical report text. See qs_charter/report/narrative.py if you want to extend the template set.

The default PDF backend (qs_charter.report.pdf_backend.ReportLabRenderer) is pure Python (reportlab), specifically to avoid system-level dependencies (Cairo/Pango, etc.) that complicate pip install on Windows. It sits behind the qs_charter.report.base.PDFRenderer interface, so an HTML/CSS-based backend could be added later as an optional extra without restructuring anything upstream.

Running the tests

pip install -e .[dev]
pytest tests/

tests/test_schema.py covers RunRecord/Sample serialization round-tripping (JSON and CSV). tests/test_analysis.py covers the scaling-trend curve-fitting classification (exponential/polynomial/linear/constant, on closed-form synthetic data with known answers) and crossover detection. tests/test_report.py covers narrative determinism and an end-to-end PDF build.

Non-goals (v1)

  • No circuit diagram visualization.
  • No built-in adapters for specific simulator libraries — agnosticism comes from the track() wrapper pattern, not per-library integration.
  • No LLM or external API dependency for report generation, ever — captions/write-ups are template-based only.
  • No GUI/dashboard — output is files (PDF, JSON, PNG) for notebooks or disk.

License

QS_Charter is licensed under the Business Source License 1.1 with a custom Additional Use Grant:

  • Free for any non-commercial use -- personal projects, academic research, non-profit use, evaluation, etc.
  • Commercial use requires a separate license. If you want to use QS_Charter commercially, contact oscinspire@gmail.com to arrange a commercial license agreement.
  • Each version of the Licensed Work converts to the Apache License, Version 2.0 four years after that version is published.

See the LICENSE file for the full terms. This isn't legal advice -- if the licensing terms matter for your use case, have it reviewed by a lawyer.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distributions

No source distribution files available for this release.See tutorial on generating distribution archives.

Built Distribution

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

qs_charter-0.1.0-py3-none-any.whl (38.0 kB view details)

Uploaded Python 3

File details

Details for the file qs_charter-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: qs_charter-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 38.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.2

File hashes

Hashes for qs_charter-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 8cea48fc40487d74ee78058ecf81deb5cff84b72df59a40cce37d644a0bc0e52
MD5 9d5a3ef388c98ba2642e48370a5d8ced
BLAKE2b-256 2b65bfd7f6ec8e0ab4d25286779462f70b2038b96c4faa1d6ad9d763fe5b914a

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