States and Backends

State

Construction, initialization, and the opt-in event log.

QuantumCircuitsMPS.SimulationStateType
SimulationState{B<:AbstractBackend}

Main simulation state container holding the numerical backend and metadata.

Fields:

  • backend: the numerical backend (MPSBackend, StateVectorBackend, or CliffordBackend), holding backend-specific state such as the MPS/statevector/tableau, site indices, and SVD truncation parameters. When B == MPSBackend, the property names state.mps, state.sites, state.cutoff, and state.maxdim are SUPPORTED API: they forward transparently (read and write) to state.backend.<name> via getproperty/setproperty! (see Base.getproperty(::SimulationState{MPSBackend}, ::Symbol)).
  • phy_ram: physical site -> RAM index mapping
  • ram_phy: RAM index -> physical site mapping
  • L: system size
  • bc: boundary condition (:open or :periodic)
  • site_type: site index type ("Qubit", "S=1", "Qudit")
  • local_dim: local Hilbert space dimension (default 2 for qubits)
  • rng_registry: RNG streams for reproducibility
  • observables: tracked observable values
  • observable_specs: observable specifications
  • eventlog: typed event log (Nothing unless constructed with logevents=true)
  • eventstep/eventopidx/eventelementidx: current engine execution context (set by simulate! before each execute! call; 0 outside a circuit engine run). Used to thread real indices into events emitted from deep call sites (e.g. MeasurementOutcome from _measuresingle_site!).

Supported site_type values:

  • "Qubit": spin-1/2 (local_dim=2, default)
  • "S=1": spin-1 (local_dim=3)
  • "Qudit": arbitrary dimension (requires local_dim parameter)
source
QuantumCircuitsMPS.initialize!Function
initialize!(state::SimulationState, init::ProductState)

Initialize state with a product state based on specified initialization method. Supports binaryint, binarydecimal, or bitstring. Uses CT.jl MSB ordering: site 1 = MSB, site L = LSB.

source
initialize!(state::SimulationState, init::RandomMPS)

Initialize state with a random MPS. Requires RNGRegistry with :stateinit stream attached to state. The MPS is drawn deterministically from the registry's `:stateinit` stream: the same seed produces an identical MPS.

source
initialize!(state::SimulationState, init::RandomGaussianState)

Generic fallback: RandomGaussianState is only supported on the Gaussian backend (backend=:gaussian). A GaussianBackend-specific override (initialize!(state::SimulationState{GaussianBackend}, init::RandomGaussianState)) is more specific and will win dispatch on that backend; this method fires on MPS/state-vector/Clifford backends and reports an informative error.

source
initialize!(state::SimulationState{StateVectorBackend}, init::ProductState)

Initialize a state-vector-backend SimulationState with a product state, based on the specified initialization method (binaryint, binarydecimal, bitstring, or spinstate). Reuses the EXACT SAME `statenames_physicalcomputation logic as the MPS path (src/State/initialization.jl), but builds a denseVector{ComplexF64}directly instead of anMPS`.

Since ram_phy/phy_ram are the IDENTITY for the state-vector backend (Task 5), no physical-to-RAM reordering is applied here — physical site i directly corresponds to tensor index i.

Site 1 = MSB = slowest-varying tensor index (see _product_state_vector).

source
initialize!(state::SimulationState{StateVectorBackend}, init::RandomStateVector)

Initialize a state-vector-backend SimulationState with a Haar-random unit vector, drawn from the :state_init RNG stream.

source
initialize!(state::SimulationState{CliffordBackend}, init::ProductState)

Initialize a Clifford-backend SimulationState with a computational-basis product state, based on the specified initialization method (binary_int, binary_decimal, or bitstring). Reuses the EXACT SAME bit-pattern-string derivation logic as the MPS/state-vector paths (src/State/initialization.jl / src/StateVector/initialization.jl).

init.spin_state is NOT supported: the Clifford backend is qubit-only (local_dim=2, enforced at construction time in src/State/State.jl), while spin_state is an S=1/qudit-oriented field.

Site 1 = MSB (most significant bit) — identical convention to the MPS/SV backends. Since ram_phy/phy_ram are the IDENTITY for the Clifford backend (Task 7), no physical-to-RAM reordering is applied here — physical site i directly corresponds to qubit i in the tableau.

source
initialize!(state::SimulationState{GaussianBackend}, init::ProductState)

Initialize a Gaussian-backend SimulationState with a computational-basis (occupation-number) product state, based on the specified initialization method (binary_int, binary_decimal, or bitstring). Reuses the EXACT SAME bit-pattern-string derivation logic as the MPS/state-vector/Clifford paths (_bit_pattern_string in src/State/initialization.jl).

init.spin_state is NOT supported: the Gaussian backend is fermionic-mode only (local_dim=2, enforced at construction time in src/State/State.jl), while spin_state is an S=1/qudit-oriented field.

Site 1 = MSB (most significant bit) — identical convention to the other backends. Bit 1 at site i means mode i is OCCUPIED (⟨cᵢ†cᵢ⟩ = 1, covariance block Γ[2i−1,2i] = −1); bit 0 means unoccupied (Γ[2i−1,2i] = +1). Since ram_phy/phy_ram are the IDENTITY for the Gaussian backend, no physical-to-RAM reordering is applied — physical site i directly corresponds to Majorana pair (2i−1, 2i).

Majorana-chain granularity (site_type="Majorana", state.backend.majoranas_per_site == 1): each site is ONE Majorana mode and the product-state covariance is the DIMERIZED pairing ⊕ₖ [[0,1],[−1,0]] over consecutive site pairs (γ_{2k−1}, γ_{2k}), k = 1..L÷2. The bit pattern therefore has length L÷2 (NOT L): bit k sets the parity sign of the pair (γ_{2k−1}, γ_{2k}) — bit 0Γ[2k−1,2k] = +1 (parity iγγ = −1, the "vacuum" sign), bit 1Γ[2k−1,2k] = −1. The pattern is derived by the shared _bit_pattern_string helper with length L÷2, so binary_int is padded to L÷2 binary digits and an explicit bitstring is padded/truncated to exactly L÷2 characters — i.e. the pattern length is always exactly L÷2.

Allocates state.backend.corr (via occupation_covariance; 2L×2L fermionic, L×L Majorana chain) and a zeroed same-size state.backend.scratch buffer. Returns state.

source
initialize!(state::SimulationState{GaussianBackend}, init::RandomGaussianState)

Initialize a Gaussian-backend SimulationState with a Haar-random pure fermionic Gaussian state: draw O ∈ SO(N) exactly Haar-distributed (via haar_orthogonal), with N the total Majorana count (N = 2L fermionic-mode granularity; N = L for the Majorana chain, site_type="Majorana"), and rotate the vacuum covariance matrix, Γ = O·Γ₀·Oᵀ, which preserves purity (Γ² = −I) and antisymmetry.

Requires an RNGRegistry attached to the state; the orthogonal matrix is drawn deterministically from the registry's :state_init stream — the same seed produces a bitwise-identical Γ.

Allocates state.backend.corr and a zeroed 2L×2L state.backend.scratch buffer. Returns state.

source
QuantumCircuitsMPS.ProductStateType
ProductState(; binary_int=nothing, binary_decimal=nothing, bitstring=nothing, spin_state=nothing)

Product state initialization for qubits/qudits. Exactly one parameter must be specified.

Arguments (mutually exclusive)

  • binary_int::Integer: Integer representation (e.g., 0, 1, 5)
  • binary_decimal::AbstractFloat: Binary decimal notation (e.g., 0.101 = "101")
  • bitstring::AbstractString: Explicit bitstring (e.g., "101")
  • spin_state::AbstractString: ITensor state name applied uniformly to all sites, e.g. "Z0" for the S=1 m=0 state

Site ordering

MSB at site 1, LSB at site L (CT.jl convention):

  • binary_int=1 with L=4 → "0001" → site 4 has "1"
  • bitstring="1000" → site 1 has "1"

Examples

# All-zero state (4 qubits)
ProductState(binary_int=0)

# Site 4 has "1", others "0"
ProductState(binary_int=1)

# Binary decimal: "101" (sites 1,3 have "1")
ProductState(binary_decimal=0.101)

# Explicit bitstring
ProductState(bitstring="1010")

# Uniform S=1 m=0 state
ProductState(spin_state="Z0")
source
QuantumCircuitsMPS.RandomStateVectorType
RandomStateVector()

Random Haar-random unit-norm state-vector initialization for the state-vector backend. Mirrors RandomMPS's simplicity (no fields). Requires RNGRegistry with :state_init stream attached to the SimulationState.

source
QuantumCircuitsMPS.RandomGaussianStateType
RandomGaussianState()

Haar-random pure fermionic Gaussian state initialization. Only supported on the Gaussian backend (backend=:gaussian); no fields (mirrors RandomStateVector's simplicity — randomness comes entirely from the :state_init RNG stream at initialize! time via haar_orthogonal). Requires RNGRegistry with :state_init stream attached to the SimulationState.

source
QuantumCircuitsMPS.eventsFunction
events(state::SimulationState) -> Vector{CircuitEvent}

Return all recorded circuit events (gate applications and measurement outcomes) in emission order.

Requires the state to be constructed with log_events=true; otherwise throws an ArgumentError (the log is opt-in — an empty return would be indistinguishable from "nothing happened").

Post-selection recipe

Run each trajectory with logging enabled, then filter on its measurement record:

state = SimulationState(L=L, bc=:periodic, rng=registry, log_events=true)
initialize!(state, ProductState(binary_int=0))
simulate!(circuit, state; n_steps=n)

ms = measurements(state)                # Vector{MeasurementOutcome}
keep = all(m -> m.outcome == 0, ms)     # post-select on all-zero record
keep && push!(accepted_trajectories, state.observables)
source
QuantumCircuitsMPS.measurementsFunction
measurements(state::SimulationState) -> Vector{MeasurementOutcome}

Return only the MeasurementOutcome events from the event log (for post-selection workflows — see events for the full recipe).

Throws ArgumentError if the state was not constructed with log_events=true.

source

Backends

Backend-payload structs are internal (MPSBackend, StateVectorBackend, CliffordBackend are accessed only via state.backend + duck typing, never exported). GaussianBackend is a deliberate exception, exported so state.backend isa GaussianBackend works with a plain using QuantumCircuitsMPS. See the Gaussian Backend page for usage and the Backend Interface Contract for the full struct/method contract.

QuantumCircuitsMPS.GaussianBackendType

Gaussian (free-fermion) backend: holds a Majorana covariance matrix Γ for Gaussian-state simulation of fermionic circuits.

corr is the 2L×2L real antisymmetric Majorana covariance matrix Γ[a,b] = (i/2)⟨[γ_a, γ_b]⟩, satisfying the invariant Γ² = -I for a pure Gaussian state. Mode i (1-indexed, 1 <= i <= L) maps to Majorana indices (2i−1, 2i).

scratch is a preallocated 2L×2L buffer of the same size as corr, used by the Gaussian gate-application kernel to avoid per-gate allocation.

purify_tol is the threshold on ‖Γ² + I‖ (or an equivalent purity diagnostic) above which the backend re-purifies corr to correct floating-point drift from repeated updates (default 1e-10).

majoranas_per_site selects the SITE GRANULARITY (set from site_type in the SimulationState constructor, src/State/State.jl):

  • 2 (default, site_type="Qubit"): each site is one fermionic mode carrying the Majorana pair (2i−1, 2i); Γ is 2L×2L.
  • 1 (site_type="Majorana"): each site IS one Majorana mode (index i); Γ is L×L and L must be even (a pure Gaussian state has an even number of Majoranas). Same covariance-matrix machinery, same gate types — only the site→Majorana index mapping (site_majoranas) changes.
source