Ramanujan's mathematics meets the NVIDIA stack: a hand-written CUDA C++ kernel and CUDA-Q/cuQuantum quantum simulation, measured against each other on the same silicon, with NIM/Nemotron writing up what the numbers show.
Version badges describe repository dependency floors. Python 3.14 is the only supported interpreter on every host; CUDA-Q 0.16 pairs it with CuPy 14.x. CUDA-QX is a planned extension.
When G. H. Hardy visited Srinivasa Ramanujan, he remarked that his taxicab's number, 1729, seemed rather dull. Ramanujan replied instantly: "No, it is a very interesting number; it is the smallest number expressible as the sum of two cubes in two different ways" — 1729 = 1³ + 12³ = 9³ + 10³. The q is for quantum. This repo carries that spirit: taking mathematics that looks ordinary from the outside and finding the structure inside it.
The mathematics is not decoration. Ramanujan's 1914 series delivers ~8 correct digits of π per term in exact arithmetic. Independent terms permit parallel evaluation, but unequal term costs, launch overhead and fp64 saturation limit useful GPU scaling:
And the thread doesn't stop at π: the same territory — modular forms, Ramanujan expander graphs — underpins modern quantum LDPC error-correcting codes, which is where this project is ultimately headed (stage 3).
How do a CUDA implementation of Ramanujan's series and a simulated canonical
QAE circuit behave under a declared local timing/accuracy sweep? QAE encodes
the already-known amplitude math.pi / 4; this is a simulator case study,
not an independent π algorithm or a quantum-advantage experiment.
The 2026-08-05 archive contains 27 configurations, five timing repeats each and 4000 shots per QAE estimate, recorded on an RTX 5070 Laptop GPU in turbo mode. A second run was collected under the committed protocol and has human-reviewed findings.
| Selected row | Mean wall time | Reported accuracy |
|---|---|---|
| Classical, 2 terms | 2.714 ms | 15.85 relative-error digits against math.pi |
| QAE, 10 counting qubits | 0.441 s | 5.00 relative-error digits against math.pi |
No crossover was observed within this sweep. These two selected rows differ by about 162.5× in wall time and have different accuracy; this is not a matched-accuracy speedup or a universal claim about the hardware. The observed QAE plateau is consistent with dyadic phase quantization. Sampled GPU utilization alone does not establish a dispatch bottleneck or predict H100 performance. Wrapper work is included in the recorded timings.
Read the reviewed findings for row-level qualifications. The original narrated draft and measured JSON are preserved; the draft's stronger claims are superseded by that review.
The series and QAE arms are distinct computations: QAE estimates the known
amplitude π/4 and is not fed by the series. NIM receives JSON and drafts prose;
the code does not verify its statements, and it never supplies numerical
results. Cloud H100 and multi-GPU execution remain unmeasured. The diagram's
source is assets/architecture/pipeline.mmd.
The three stages below are the research thread. The full evidence-sequenced plan — how each stage is earned, phase by phase — lives in docs/roadmap.md (Stage 1 = Phase 1, Stage 3 = Phase 2). This table is the summary; that document is authoritative for ordering.
| Stage | Focus | Status |
|---|---|---|
| 1 — π benchmark | Ramanujan's 1914 1/π series as a hand-written CUDA kernel vs Quantum Amplitude Estimation with CUDA-Q, on the nvidia (cuStateVec) backend |
Two RTX archives delivered; post-release evidence repairs done 2026-09-23; declared-profile phase study next. Optional H100 unmeasured |
| 2 — community | Upstream contributions to CUDA-Q / CUDA-Q Academic; publish results; invite benchmark submissions from other GPUs (the run-file schema is hardware-agnostic) | Ongoing workstream; publication depends on contribution/evidence gates |
| 3 — Ramanujan graphs → qLDPC | Ramanujan expander graphs underpin modern quantum LDPC codes. Simulate and decode them with CUDA-Q QEC (CUDA-QX) plus custom CUDA kernels | Started: graph construction only; classical decoder and feasible qLDPC study next |
- CUDA C++ — the classical baseline kernel (
classical/ramanujan_kernel.cu), one series term per thread with a shared-memory tree reduction, compiled at runtime through NVRTC (ADR 005) - CUDA-Q — core quantum programming platform (kernels, sampling, target selection)
- CUDA-QX — extension libraries: Solvers (VQE/ADAPT) and QEC (codes + GPU decoders) (stage 3)
- cuQuantum — cuStateVec / cuTensorNet, the simulation engines behind CUDA-Q's backends
- NIM / Nemotron — findings narrator via the NVIDIA NIM chat-completions API (
analysis/narrator.py) - SymPy — exact-rational reference implementation; any float drift in the GPU kernel shows up immediately
Runtime: this repository uses WSL2/Linux for the CUDA-Q and CUDA path. The GPU test suite was re-verified in WSL2 on 2026-09-23 with Python 3.14.7, CUDA-Q 0.16.0.post1 and CuPy 14.2.0: 410 passed, 1 skipped, 100.00% coverage. No new measured run was collected.
- Exact SymPy partial sums provide a reference for the CUDA integration test at 1e-15 relative tolerance. Host reduction avoids atomic accumulation order; this does not guarantee bitwise identity across hardware/toolchains.
- Synthetic sample data is labeled and rejected by the plotter.
- CI requires 100% coverage. The 2026-09-23 Windows no-key suite: 382 passed, 29 skipped, 99.77% coverage; the CUDA-Q diagnostic needs its real runtime. CUDA-Q CPU integration runs in CI; GPU integration requires a GPU.
- The research contract is a requirement; semantic validation, archive protection, schema-3 traceability, a committed measurement protocol and archived aborted runs under a declared time budget (schema 5) are implemented, as are reviews bound to every cited archive and recomputed QAE diagnostics. Remaining limits are recorded in the roadmap.
- ADRs record decisions, including ROCm as a conditional Phase 4 backend and the evidence-first sequence in ADR 007.
classical/ramanujan_kernel.cu— the hand-written CUDA C++ kernel: one series term per thread, shared-memory tree reductionclassical/cuda_kernel.py— compiles, launches and times the kernel; degrades cleanly on hosts without a GPUclassical/ramanujan_series.py— the 1914 series, exact SymPy (ground truth for the kernel)classical/ramanujan_graph.py— LPS Ramanujan expander graphs, spectrally verified against the2√(k−1)bound (ground truth for the Stage 3 / Phase 2 qLDPC experiment; CPU-only, never timed)quantum/qae.py— canonical Quantum Amplitude Estimation of π/4, with the resource-cost caveats stated in the modulequantum/backend.py— CUDA-Q target selection (nvidia-mgpu→nvidia→tensornet→qpp-cpu) + environment diagnosticbenchmarks/harness.py— runs both arms under a declared time budget and emits schema-5 run JSON (complete or aborted) with semantic validation and exclusive output creationbenchmarks/protocol.py— the measurement protocol, committed before data and hashed into every run filebenchmarks/run_file.py— versioned semantic validation of every run file (schemas 1–5; CI's archive check)benchmarks/archive.py— exclusive output creation; evidence is never overwrittenbenchmarks/provenance.py— source hashes, installed distributions and actual execution metadataquantum/quantization.py— closed-form QAE reference (error floor, plateau, outcome distribution); CPU-onlybenchmarks/environment.py— captures hardware, versions, and GPU load during a runbenchmarks/plot.py— theme-aware crossover plots; refuses synthetic and aborted inputbenchmarks/runs/,benchmarks/plots/— measured run files, findings drafts with their human review records, and figuresanalysis/narrator.py— NIM/Nemotron findings narrator (make narrate)analysis/review.py— human findings-review records, hash-bound to the draft and every cited archive; agents never approvescripts/release_check.py— release preflight: tag, version, notes andmainancestrydata/sample_run.json— synthetic sample run file demonstrating the schema; never a measurementmain.py— status check; runs on any host, with or without cudaq / cupy / a NIM keytests/—unit/(any host) +integration/(real CUDA kernel, real CUDA-Q simulation, live NIM; each skips where unavailable)docs/handbook/— principles and research standards (roadmap Phase 0)docs/adr/— architecture decision recordsdocs/sessions.md— dated log of what each work session changed and verifiedassets/architecture/,assets/brand/— theme-aware diagram and banner sources (edit the.mmd/.py, never the SVG)AGENTS.md— cross-tool discipline for keeping this README,CLAUDE.md, and every status-bearing doc in sync before commits and tags
Any host (CPU-safe — classical math, narrator, unit tests, lint):
python -m venv .venv
.\.venv\Scripts\Activate.ps1
pip install -r requirements.txt
python main.py
pytest testsNIM findings narrator (any host; key from build.nvidia.com):
# Export NVIDIA_API_KEY in this shell; .env is not loaded automatically.
# Obtain/set the key privately; do not commit or print it.
make narrate # drafts findings from data/sample_run.jsonGPU work — the CUDA kernel and CUDA-Q (WSL2 / Linux only):
pip install -r requirements.txt
pip install -r requirements-gpu.txt
python -m quantum.backend # diagnostic: which CUDA-Q target initialized
python -m classical.cuda_kernel # diagnostic: which GPU the kernel will use
pytest tests # now includes the real-hardware integration testsReproduction instructions are in benchmarks/README.md.
make benchmark requires POWER_PROFILE and TIME_BUDGET_S and uses a unique
date-plus-UUID filename; the writer refuses existing paths, and a run that stops
early is archived as an aborted audit record rather than lost. Plot defaults are run-specific and both themes are protected.
The default 2000 shots still differs from the archive's 4000; use an explicit
shot count when reproducing it. Schema validation accepts
legacy archives unchanged. Schema 3 retains every timed outcome, count distribution,
source manifest, selected device and target/precision; see run-file details.
New findings require human review records.
make install / make test / make lint / make coverage wrap the commands
in the Makefile. Use separate Windows and Linux virtual environments;
see setup.
| Axis | Evidence |
|---|---|
| Local archive | RTX 5070 Laptop GPU, 8151 MiB; recorded driver 610.88 on 2026-08-05 |
| Current runtime | Same GPU model; driver 616.92, CUDA runtime 13020 (CuPy 14.2.0), CUDA-Q 0.16.0.post1 on nvidia, Python 3.14.7 in WSL2, verified 2026-09-23 |
| H100 / multi-GPU | Planned only; no measured archive |
| NIM | Optional external narrator; no live call in this audit |
Statevector storage grows as bytes-per-amplitude × 2^qubits. Bare fp32 storage is 4 GiB at 29 qubits and 8 GiB at 30, before simulator workspace and other allocations. This is a storage estimate, not a measured usable qubit ceiling. The archive's largest circuit has only 19 total qubits (4 MiB bare fp32 state).
Stage 2 opens this up properly. Until then: issues and benchmark-idea discussions welcome — see CONTRIBUTING.md.
Author: Arjun Ganesh — github.com/iarjunganesh