Skip to content

Architecture

QMBED has two narrow interfaces.

Scientific narrow waist

LinearOperator is the boundary between a physical model and a numerical algorithm. A Hamiltonian may be dense, sparse, parameterized, projected, block structured, or matrix free; eigensolvers and dynamics consume the same action.

basis + typed local terms
 universal operator assembly
     LinearOperator
       ├─ eigensolvers
       ├─ time evolution
       ├─ response functions
       └─ measurements

This is why optimization is capability based. For example, a finite-orbit cache is selected because a basis supplies a finite symmetry action, and a fixed sparse pattern is reused because a parameterized family shares its nonzero structure. No Ising-, Hubbard-, or PXP-specific path is required.

Differentiation boundary

AD rules sit on the same scientific narrow waist:

parameter schema + QuantumOperator + state
             native operation rule
             ├─ exact JVP
             ├─ one-shot VJP
             └─ spectral rule + diagnostics
       optional ChainRules protocol adapter

Sparse assembly and Lanczos iterations are not traced instruction by instruction. The operator-action rule uses the runtime's native forward and adjoint kernels. The ground-state energy rule uses one converged eigenpair and component expectations, and refuses to hide an unresolved degeneracy. ChainRules adapters translate the tested native rule rather than defining a second derivative implementation.

Execution narrow waist

Runtime owns vector storage and coarse operations such as apply, axpy, dot products, and host transfer. The CPU implementation is complete. Accelerator and MPI support can be added behind this boundary without exposing backend buffers in basis or operator APIs.

Language boundary

Rust calls the generic core directly. Python and Julia send the same typed request schema through the C ABI:

Python ─┐
        ├─ typed JSON + opaque handles ─ qmbed-capi ─ Rust core
Julia ──┘

Long-lived frontend objects use opaque handles for model, basis-plan, Krylov, and exponential-action resources. Handles are safe to share at the protocol boundary, never expose Rust addresses, and have explicit release operations.

Python's QuSpin compatibility surface translates old spellings into this protocol. Julia intentionally exposes only the native model.

Numerical backend

Dense eigendecomposition, dense products, and shifted sparse factorization are isolated internally. Iterative algorithms call prepared factorization or matrix kernels rather than redispatching within element or matvec loops. This keeps future backend changes independent of scientific APIs.