Skip to content

Repository files navigation

statevector-sim

A small, fast, header-only C++17 state-vector simulator for quantum circuits.

CI License: MIT C++17


The problem it solves

The state of n qubits is a vector of 2ⁿ complex numbers — the amplitudes. To test or debug a quantum algorithm on an ordinary machine you have to carry that whole vector and evolve it gate by gate.

The naive way to apply a gate is to treat it as a 2ⁿ × 2ⁿ matrix and multiply. That is hopeless almost immediately: at 20 qubits that matrix has ~10¹² entries, and the cost is O(4ⁿ). A textbook implementation stalls around 12–13 qubits.

The trick every real simulator uses: a gate on one or two qubits only ever mixes pairs of amplitudes whose indices differ in those qubit bits. So you sweep the 2ⁿ vector once, updating strided index pairs in place — O(2ⁿ) time and no extra memory, no matrix ever built. The sweep is also embarrassingly parallel.

statevector-sim is a compact, dependency-free implementation of exactly that: the standard gate set, a fluent circuit builder, measurement sampling, OpenMP parallelism, and correctness checks against analytic results (Bell, GHZ, QFT). It is meant for learning, for testing small quantum algorithms, and as a reference point next to production simulators like Qiskit Aer.

Features

  • Header-only, C++17, no external dependencies for the core (#include "svsim/circuit.hpp").
  • Gates: H, X, Y, Z, S, S†, T, T†, RX, RY, RZ, phase, CX, CZ, CPHASE, SWAP, and any user-supplied 2×2.
  • O(2ⁿ) strided-pair gate application; OpenMP-parallel; state vector allocated once, updated in place.
  • Measurement: single-shot sampling and {outcome → count} histograms from |amplitude|².
  • Circuit builder with method chaining; ready-made ghz(n) and qft(n).
  • Catch2 test suite; multi-OS CMake CI (Linux / macOS / Windows, Debug + Release).
  • Optional experimental Python binding via pybind11.

Build & test

cmake -B build -DCMAKE_BUILD_TYPE=Release
cmake --build build --parallel
ctest --test-dir build --output-on-failure

Requires CMake ≥ 3.16 and a C++17 compiler. Catch2 is fetched automatically for the tests; pass -DSVSIM_BUILD_TESTS=OFF to skip it.

Run the demo and the scaling benchmark:

./build/svsim_demo
./build/svsim_bench 26      # optional arg = max qubit count

Quickstart (C++)

#include <iostream>
#include "svsim/circuit.hpp"
#include "svsim/state_vector.hpp"

int main() {
  // Build a Bell pair and sample it.
  svsim::StateVector sv = svsim::Circuit(2).h(0).cx(0, 1).run();

  for (auto [outcome, count] : sv.sample_counts(/*shots=*/1000, /*seed=*/42)) {
    std::cout << svsim::StateVector::to_bitstring(outcome, 2) << ": " << count << '\n';
  }
  // ~ 00: 500   11: 500

  // Or drive the state directly.
  svsim::StateVector q(3);
  q.h(0);
  q.cx(0, 1);
  q.rz(1, 0.5);
  std::cout << "P(|000>) = " << q.probability(0) << '\n';
}

How it works

The core loop, for a gate on target with stride = 1 << target:

for each block of 2*stride consecutive amplitudes:
    for offset in [0, stride):
        i0 = block_base + offset          # target bit = 0
        i1 = i0 + stride                  # target bit = 1
        (amp[i0], amp[i1]) = M * (amp[i0], amp[i1])

Every amplitude is touched exactly once, so one gate is O(2ⁿ). Controlled gates run the same loop and skip pairs whose control bit is 0. CPHASE / CZ and SWAP are single passes over the vector.

Qubits are little-endian: qubit q is bit q of the basis index (qubit 0 is the least-significant bit). to_bitstring prints qubit n-1 on the left.

Benchmark

svsim_bench applies a full layer (a Hadamard on every qubit plus a CX chain, 2n − 1 gates) and reports time per gate as n grows. Representative shape (numbers are machine-dependent; the point is the scaling):

qubits state size time / full layer
20 16 MiB a few ms
24 256 MiB tens of ms
28 4 GiB hundreds of ms

Time per gate grows ~2× per qubit, matching the O(2ⁿ) amplitude count; memory is exactly 2ⁿ × 16 bytes.

Roadmap

  • -Werror / clang-tidy gate in CI
  • Fused gate layers and cache blocking for large n
  • Explicit qubit measurement with state collapse
  • SIMD (AVX2 / NEON) kernels for the 1-qubit sweep
  • pip install-able Python package (scikit-build-core)
  • Benchmark comparison against Qiskit Aer

Context

Built as a companion to a computer-engineering thesis on quantum algorithms (dr-andromeda/Theoretical-Practical-Study-Fundamentals-and-Implementation-of-Quantum-Algorithms), which benchmarked Qiskit / Cirq / PennyLane — this is a from-scratch look at what those libraries do underneath.

License

MIT © 2026 Baltasar Hurtado Jiménez

About

Header-only C++17 state-vector quantum circuit simulator: O(2^n) strided-pair gate application, OpenMP-parallel, verified against analytic Bell/GHZ/QFT

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages