Microcanonical sampling
TL;DR
Microcanonical (MC) sampling fixes the requested constraints exactly in every sampled network (with one documented hybrid exception: strength+cost). You give MENoBiS constraints, it constructs one feasible state, and samples the target measure on the constraint fiber. No fitting step is required for MC routes.
Practical meaning
A grand-canonical null matches constraints in expectation: every sampled network fluctuates around them. A microcanonical null makes the constrained quantities identical in every realization — a different null hypothesis, not a "better" one. Choose between them by the scientific question (see Choose a model and Ensembles).
Shared philosophy
flowchart TD
C[Requested constraints] --> V[Validate feasibility]
V --> I[Construct a feasible state]
I --> Q{Sampling route}
Q -->|Direct conditional sampler| D[Exact direct draw]
Q -->|MCMC on constrained state space| M[Exact stationary MCMC]
Q -->|Auxiliary chain + return/trace| T[Exact stationary trace kernel]
D --> O[Sampled EdgeTable]
M --> O
T --> O
O --> X[Check exact constraints and diagnostics]
- this is the shared conceptual architecture;
- concrete constructors and kernels differ by constraint;
- construction is not required to be reversible;
- sampling exactness is a property of the sampling law/kernel, not of how the initial feasible state was found.
Current routes
The route table below is generated from the capability registry and is authoritative for backends, required arguments, and exactness:
Microcanonical sampling routes
Registry source SHA: a0b1a12 · generated: 2026-08-31T17:51:54+00:00
| Constraint | Family | Exact / controlled | Backend | Required arguments | Exactness |
|---|---|---|---|---|---|
| strength | ME | strengths exact | microcanonical_fixed_strength |
strength_in, strength_out | exact stationary MCMC; strengths exact |
| strength_cost | ME | strengths exact; cost expected (gamma) | microcanonical_fixed_strength_cost |
coord_x, coord_y, strength_in, strength_out, target_cost | exact stationary MCMC; hybrid (cost expected) |
| strength_edges | ME | strengths, E exact | microcanonical_fixed_strength_edges |
strength_in, strength_out, target_edges | exact stationary MCMC; strengths, E exact |
| strength_degree | ME | strengths, degree sequences exact | microcanonical_fixed_strength_degree |
degree_in, degree_out, strength_in, strength_out | exact stationary MCMC; strengths, degrees exact |
| degree_events | ME | degree sequences, T exact | microcanonical_fixed_kt |
degree_in, degree_out, total_events | exact stationary MCMC; k, T exact |
| edges_events | ME | E, T exact | microcanonical_fixed_et |
node_count, target_edges, total_events | exact direct; E, T exact |
| strength | B | strengths exact | microcanonical_fixed_strength |
strength_in, strength_out | exact stationary MCMC; strengths exact |
| strength_cost | B | strengths exact; cost expected (gamma) | microcanonical_fixed_strength_cost |
coord_x, coord_y, strength_in, strength_out, target_cost | exact stationary MCMC; hybrid (cost expected) |
| strength_edges | B | strengths, E exact | microcanonical_fixed_strength_edges |
strength_in, strength_out, target_edges | exact stationary MCMC; strengths, E exact |
| strength_degree | B | strengths, degree sequences exact | microcanonical_fixed_strength_degree |
degree_in, degree_out, strength_in, strength_out | exact stationary MCMC; strengths, degrees exact |
| degree_events | B | degree sequences, T exact | microcanonical_fixed_kt |
degree_in, degree_out, layers, total_events | exact stationary MCMC; k, T exact |
| edges_events | B | E, T exact | microcanonical_fixed_et |
layers, node_count, target_edges, total_events | exact direct; E, T exact |
| strength | W | strengths exact | microcanonical_fixed_strength |
strength_in, strength_out | exact stationary MCMC; strengths exact |
| strength_cost | W | strengths exact; cost expected (gamma) | microcanonical_fixed_strength_cost |
coord_x, coord_y, strength_in, strength_out, target_cost | exact stationary MCMC; hybrid (cost expected) |
| strength_edges | W | strengths, E exact | microcanonical_fixed_strength_edges |
strength_in, strength_out, target_edges | exact stationary MCMC; strengths, E exact |
| strength_degree | W | strengths, degree sequences exact | microcanonical_fixed_strength_degree |
degree_in, degree_out, strength_in, strength_out | exact stationary MCMC; strengths, degrees exact |
| degree_events | W | degree sequences, T exact | microcanonical_fixed_kt |
degree_in, degree_out, layers, total_events | exact stationary MCMC; k, T exact |
| edges_events | W | E, T exact | microcanonical_fixed_et |
layers, node_count, target_edges, total_events | exact direct; E, T exact |
Conceptually, the routes are:
| Route | Exact / controlled quantities | Initialization | Sampling | Exactness |
|---|---|---|---|---|
(E,T) |
E, T exact | feasible support/occupations | direct conditional sampler | exact direct |
(k,T) |
k, T exact | exact-degree support + occupations | MCMC + occupation allocator | exact stationary MCMC |
s |
strengths exact | compressed feasible table | occupation MCMC | exact stationary MCMC |
(s,E) |
strengths, E exact | exact feasible state | constrained + bridge kernel | exact stationary MCMC |
(s,k) |
strengths, k exact | extras-first constructor | degree-fiber trace | exact stationary MCMC |
s + cost |
strengths exact, cost expected | feasible strength state | cost-biased route | hybrid |
One feasible example per constraint
Constraints must be feasible. The robust way to obtain feasible constraints is to derive them from a valid witness network:
from menobis.models import Constraint, Ensemble, ModelFamily
from menobis.routing import sample_model
from menobis.utilities.synthetic import (
derive_synthetic_constraints,
generate_pa_geographic_network,
)
network = generate_pa_geographic_network(30, average_degree=6.0, seed=7)
c = derive_synthetic_constraints(network)
strength_out = c.strength_out.astype("uint64")
strength_in = c.strength_in.astype("uint64")
degree_out = c.degree_out.astype("uint32")
degree_in = c.degree_in.astype("uint32")
Then, per constraint:
# (E,T): exact occupied-pair count and total events.
sample = sample_model(
ensemble=Ensemble.MICROCANONICAL, family=ModelFamily.ME,
constraint=Constraint.EDGES_EVENTS,
node_count=len(network.x),
target_edges=int(network.edges.num_edges),
total_events=int(network.edges.total_events),
)
# (k,T): exact degree sequences and total events.
sample = sample_model(
ensemble=Ensemble.MICROCANONICAL, family=ModelFamily.ME,
constraint=Constraint.DEGREE_EVENTS,
degree_out=degree_out, degree_in=degree_in,
total_events=int(network.edges.total_events),
)
# fixed strengths.
sample = sample_model(
ensemble=Ensemble.MICROCANONICAL, family=ModelFamily.ME,
constraint=Constraint.STRENGTH,
strength_out=strength_out, strength_in=strength_in,
)
# (s,E): fixed strengths and exact occupied-pair count.
sample = sample_model(
ensemble=Ensemble.MICROCANONICAL, family=ModelFamily.ME,
constraint=Constraint.STRENGTH_EDGES,
strength_out=strength_out, strength_in=strength_in,
target_edges=int(network.edges.num_edges),
)
# (s,k): fixed strengths and exact degree sequences.
sample = sample_model(
ensemble=Ensemble.MICROCANONICAL, family=ModelFamily.ME,
constraint=Constraint.STRENGTH_DEGREE,
strength_out=strength_out, strength_in=strength_in,
degree_out=degree_out, degree_in=degree_in,
)
# s + cost: fixed strengths, cost matched in expectation (hybrid).
sample = sample_model(
ensemble=Ensemble.MICROCANONICAL, family=ModelFamily.ME,
constraint=Constraint.STRENGTH_COST,
strength_out=strength_out, strength_in=strength_in,
coord_x=network.x, coord_y=network.y,
target_cost=float(c.total_cost),
)
For a hand-written example, explicitly assert basic feasibility: an occupation cannot be negative, an occupied pair needs at least one event \(s_i\ge k_i\), and no-self-loop degrees obey \(k_i\le N-1\).
Exactness
(E,T)routes are exact direct: each draw comes from the target constrained distribution, up to ordinary pseudorandom sampling error.- All other routes are exact stationary MCMC: the kernel has exactly the target distribution as its stationary law, but finite runs need burn-in and mixing considerations.
s + costis hybrid: strengths exact, cost expected through \(\gamma\). Itssample_model_detaileddiagnostics report the fitted gamma and expected cost (see below).
sample_model_detailed(..., ensemble=Ensemble.MICROCANONICAL, ...) is the
entry point returning diagnostics:
from menobis.routing import sample_model_detailed
result = sample_model_detailed(
ensemble=Ensemble.MICROCANONICAL, family=ModelFamily.ME,
constraint=Constraint.STRENGTH,
strength_out=strength_out, strength_in=strength_in,
)
print(result.diagnostics.exactness) # e.g. exact_stationary_mcmc
Feasibility
See Constraints: feasibility for the necessary relations. Recall the B \((s,k)\) capacity bound \(s_i\le M k_i\), and for \(M=1\) the Bernoulli invariant \(s=k\).
Diagnostics
For MCMC routes, sample_model_detailed reports the generation method and
exactness on result.diagnostics, and for the strength+cost route also the
gamma fit (converged, gamma, expected_cost, observed_cost,
cost_residual). General guidance on burn-in, mixing, autocorrelation and
effective sample size lives in MCMC diagnostics.
Detailed algorithms
Route-specific kernels and proofs are in the Microcanonical algorithms contributor page, with dedicated pages for fixed (s,E) and fixed (s,k).