Skip to content

MENoBiS architecture

TL;DR — One shared foundation: occupation ontology → shared family/constraint modules → ensemble backends → shared analysis/filtering. Python is a thin validating wrapper over Rust kernels. The authoritative list of supported routes is the generated capability matrix, not any prose table in this file.

Module map (Rust menobis-core)

src/
├── model/                 family/problem/sampling-plan ontology
├── distribution.rs        OccupationFamily, PairDistribution (pair laws)
├── constraints/           PairMask, FixedPairs, FixedContributions,
│                          ResidualConstraints, common validation
├── fitting/               Lagrange multiplier solvers (ME/B/W, partial, conic W)
├── generation/
│   ├── grandcanonical/    independent-pair sampling (fitted multipliers)
│   ├── canonical/         fixed-total multinomial
│   └── microcanonical/
│       ├── route.rs             constraint dispatcher (shared pipeline)
│       ├── occupation_mcmc/     fixed-strength routes
│       │   ├── compressed.rs    compressed fixed-strength state
│       │   ├── chain.rs         occupied-cell (4-cycle) chain
│       │   ├── fixed_edges.rs   fixed-(s,E): local exact-E kernel + censored bridge
│       │   ├── fixed_degrees.rs fixed-(s,k): capped first-return degree trace (K_E)
│       │   ├── fixed_degree_init.rs  extras-first combinatorial constructor
│       │   ├── cost.rs / cost_fit.rs  strength+cost chain and gamma fitting
│       │   └── repair.rs        initialization-only repair
│       ├── conditional/         fixed-total pair-Gibbs chain (E,T; occupations for k,T)
│       ├── binary/              binary support sampling (degree sequences)
│       ├── support/             uniform support sampling (edges-events)
│       └── mcmc/                shared MCMC config, counters, outcome types
├── filter.rs              tail probabilities from the same pair laws
├── graph.rs               OccupiedPair, SparseGraphView
├── stats.rs / clustering.rs  node statistics, clustering (sparse adjacency)
└── pairs.rs               pair-cost and pair-distribution providers

Runtime flow

Python request
    -> capability lookup (menobis/capabilities.py)
    -> route_model verbs (fit | sample | filter)
    -> input normalization + common validation (constraints/)
    -> fixed-pair contributions + residualization (constraints/)
    -> ensemble backend (grandcanonical | canonical | microcanonical)
    -> SampledNetwork / EdgeTable
    -> shared analysis facade
    -> filtering consumes the same shared pair laws

Dependency direction

shared family / constraint / pair-law modules
        -> fitting
        -> generation
        -> filtering
        -> analysis

Filtering never calls generation internally; both consume PairDistribution and the provider abstractions.

Ensembles

Ensemble Constraint treatment Backends
grand-canonical expected (fitted multipliers) independent pairs, filters
canonical one exact global (T) multinomial (ME strength)
microcanonical exact (strengths, E, T, k, T); expected cost (STRENGTH_COST hybrid) occupation MCMC (s), fixed edges + bridge (s,E), extras-first + degree trace (s,k), fixed-total Gibbs (E,T / k,T), uniform support (E,T), cost-biased gamma (s+cost)

Self-loop policies are supported across microcanonical backends; the admissible-pair domain follows the policy.

Exactness

Exactness categories per route are assigned in menobis/routing.py (sample_model_detailed) and surfaced on result.diagnostics.exactness; the generated capability matrix lists them per route. Theoretical claims are always "exact stationary MCMC" (kernel law), never "exact samples" without qualification (Validation).

Contributor documentation