Architecture

SimQ is a Cargo workspace of eight crates with a strict, acyclic dependency order. Understanding this layering is the fastest way to find where a change belongs.

Crate dependency graph

                    ┌───────────┐
                    │ simq-core │  types & traits (no deps on other crates)
                    └─────┬─────┘
          ┌───────────────┼────────────────┐
    ┌─────▼─────┐   ┌─────▼──────┐   ┌─────▼───────┐
    │simq-state │   │ simq-gates │   │ simq-macros │ (proc-macros used
    └─────┬─────┘   └─────┬──────┘   └─────────────┘  by simq-gates)
          │               │
          └──────┬────────┘
        ┌────────▼──────┐
        │ simq-compiler │  optimization passes
        └────────┬──────┘
          ┌──────▼───┐
          │ simq-sim │  simulator, gradients, VQE/QAOA
          └──────┬───┘
        ┌────────▼─────┐
        │ simq-backend │  hardware abstraction, transpiler
        └────────┬─────┘
        ┌────────▼───┐      ┌─────────┐
        │    simq    │      │ simq-py │  PyO3 bindings over the stack
        └────────────┘      └─────────┘
          umbrella crate + fluent QuantumCircuit

Crate responsibilities

simq-core — types and traits

The foundation everything else builds on:

  • Circuit, GateOp, QubitId, QuantumError

  • The Gate trait — every gate, standard or custom, implements it

  • Builders: const-generic CircuitBuilder<N>, DynamicCircuitBuilder

  • Parameter / ParameterRegistry for parameterized circuits

  • noise — channels, hardware noise models, Monte-Carlo variants

  • validation, serialization (serde/JSON)

  • Visualization: ascii_renderer, latex_renderer, bloch_sphere, circuit debuggers

Rule of thumb: simq-core depends on no other SimQ crate. If your type is needed by two sibling crates, it probably belongs here.

simq-state — quantum states

Sparse and dense state vectors with adaptive switching, copy-on-write branching, SIMD kernels, density matrices, measurement/sampling, and PauliString/PauliObservable expectation values.

simq-gates — the gate library

Standard gate implementations with SIMD-optimized application and the multi-level compile-time matrix cache. Lookup tables are generated by simq-macros at compile time.

simq-macros — procedural macros

Compile-time code generation (gate matrix tables and related boilerplate). Internal — downstream users never depend on it directly.

simq-compiler — optimization

OptimizationPass implementations (fusion, commutation, dead-code elimination, template matching) and pipelines with cost models, lazy evaluation, and caching. See the compiler guide.

simq-sim — the simulator

The execution engine (adaptive executor, parallel scheduling, kernels, checkpointing, telemetry), Simulator/SimulatorConfig, statistics, gradient methods (finite difference, parameter shift, autodiff), classical optimizers (L-BFGS, Nelder–Mead), convergence monitoring, and VQE/QAOA helpers. Experimental GPU support lives here too.

simq-backend — hardware abstraction

The QuantumBackend trait, capabilities model, transpiler (decomposition, routing, qubit mapping), backend selection, the local simulator backend, and the IBM Quantum client.

simq — the umbrella crate

Re-exports the whole stack module-by-module, defines the fluent QuantumCircuit builder and the prelude. This is the only crate most users depend on.

simq-py — Python bindings

PyO3 extension module (built with maturin) plus pure-Python layers (gates, noise, simulation, visualization). Excluded from plain cargo build/cargo test because extension-module symbols only resolve when loaded by a Python interpreter.

Design principles

  1. Zero-cost abstractions — high-level APIs must not add runtime overhead; prefer compile-time dispatch and pre-computation.

  2. Fail early — invalid circuits are caught at build time (or compile time with CircuitBuilder<N>), never mid-simulation.

  3. Adaptive representations — sparse vs dense, sequential vs parallel: the engine chooses per workload, guided by thresholds in SimulatorConfig.

  4. Exactness by default — cached gate matrices are exact-match only; expectation values and probabilities are computed exactly unless the user asks for shot sampling.