babylon.engine.invariants
Invariant protocol and concrete invariants for the simulation engine.
Spec 040, Discipline 1: Invariants as First-Class Objects.
Spec 054 extends this with two new bound invariants (ProbabilityInRange,
SimplexPreserved) sitting alongside NonNegativeWealth and
HeatNonNegativity.
Every invariant in the constitution becomes an object implementing the
Invariant protocol. Systems declare which invariants they preserve,
and the test harness checks them automatically via Hypothesis.
Usage:
from babylon.engine.invariants import NonNegativeWealth, Invariant
class VolumeOneProduction:
invariants: ClassVar[list[Invariant]] = [NonNegativeWealth()]
def step(self, state: WorldState) -> Result[WorldState, TransitionError]:
...
Classes
|
Every edge-mode transition along a tick boundary is in the legal arc set. |
Territory heat fields must be >= 0 everywhere. |
|
|
Protocol for simulation invariants. |
|
Outcome of an invariant check. |
No |
|
No entity has negative wealth after a system step. |
|
|
Every Probability-typed field on every entity stays in [0, 1]. |
|
Every TernaryConsciousness on every entity stays on the (r,l,f) simplex. |
- class babylon.engine.invariants.InvariantResult(passed, msg='')[source]
Bases:
objectOutcome of an invariant check.
Use factory methods
InvariantResult.ok()andInvariantResult.violated(msg)rather than constructing directly.- passed
True if the invariant holds, False if violated.
- msg
Descriptive message (empty on success, diagnosis on failure).
- classmethod success()[source]
Create a passing result.
- Return type:
- Returns:
InvariantResult with passed=True.
- class babylon.engine.invariants.Invariant(*args, **kwargs)[source]
Bases:
ProtocolProtocol for simulation invariants.
Every constitution invariant becomes an object implementing this protocol. Systems declare which invariants they preserve via a class-level list. The test harness runs declared invariants on (pre, post) state pairs.
- check(pre, post)[source]
Verify the invariant holds between pre and post states.
- Parameters:
pre (
WorldState) – WorldState before system step.post (
WorldState) – WorldState after system step.
- Return type:
- Returns:
InvariantResult indicating pass or violation.
- __init__(*args, **kwargs)
- class babylon.engine.invariants.NonNegativeWealth[source]
Bases:
objectNo entity has negative wealth after a system step.
This invariant checks all social_class entities in the post-state and fails if any have wealth < 0.
- check(_pre, post)[source]
Check that no entity wealth is negative.
- Parameters:
_pre (
WorldState) – WorldState before step (unused for this invariant).post (
WorldState) – WorldState after step.
- Return type:
- Returns:
InvariantResult — violated if any entity has wealth < 0.
- class babylon.engine.invariants.HeatNonNegativity[source]
Bases:
objectTerritory heat fields must be >= 0 everywhere.
Heat represents state repressive attention. Negative heat is physically meaningless.
- check(_pre, post)[source]
Check that no territory has negative heat.
- Parameters:
_pre (
WorldState) – WorldState before step (unused for this invariant).post (
WorldState) – WorldState after step.
- Return type:
- Returns:
InvariantResult — violated if any territory has heat < 0.
- class babylon.engine.invariants.ProbabilityInRange(field_pairs=<factory>, tolerance=0.0)[source]
Bases:
objectEvery Probability-typed field on every entity stays in [0, 1].
Spec 054 US1 (INV-006). Walks the post-state collections enumerated by
_iter_worldstate_collectionsand asserts0.0 <= value <= 1.0on every(ModelClass, field_name)pair listed infield_pairs.- Parameters:
field_pairs (
Sequence[tuple[type[BaseModel],str]]) – Sequence of (ModelClass, field_name) tuples to check. Defaults to the auto-discovered set fromtests.property.harness.probability_discovery.discover_probability_fields()but is parameterized so production code does not import test modules. The test harness instantiates this class with the discovered pairs.tolerance (
float) – Absolute slack on the bound. Defaults to0.0(exact comparison) per FR-008. The Probability constrained type’s contract is the closed interval[0, 1]; values at the boundary are legal.
- check(_pre, post)[source]
Check that no Probability-typed field escapes [0 - tol, 1 + tol].
- Parameters:
_pre (
WorldState) – WorldState before step (unused for this invariant).post (
WorldState) – WorldState after step.
- Return type:
- Returns:
InvariantResult — violated on first out-of-range field encountered.
- class babylon.engine.invariants.SimplexPreserved(tolerance=0.0001)[source]
Bases:
objectEvery TernaryConsciousness on every entity stays on the (r,l,f) simplex.
Spec 054 US3 (INV-008). Walks every entity in the post-state and, for each one carrying a
consciousnessattribute that is aTernaryConsciousnessinstance, asserts:abs(c.r + c.l + c.f - 1.0) <= tolerance -tolerance <= c.r <= 1.0 + tolerance (same for c.l, c.f)
- Parameters:
tolerance (
float) – Slack on both the simplex sum and per-component bounds. Defaults to1e-4per spec acceptance scenario US3.1.
- check(_pre, post)[source]
Check that every ternary consciousness still lies on the simplex.
- Parameters:
_pre (
WorldState) – WorldState before step (unused for this invariant).post (
WorldState) – WorldState after step.
- Return type:
- Returns:
InvariantResult — violated on first off-simplex consciousness.
- class babylon.engine.invariants.EdgeModeTrajectoryLegal(valid_arcs=<factory>)[source]
Bases:
objectEvery edge-mode transition along a tick boundary is in the legal arc set.
Spec 055 US1 (INV-009). For every relationship in the post-state that carries an
edge_modeattribute, the pair(pre_mode, post_mode)is either invalid_arcs(a real transition) OR equal (trivial no-transition). Trivial pairs are not counted as transitions; the explicit(ANTAGONISTIC, ANTAGONISTIC)persistence arc is invalid_arcsalready.- Parameters:
valid_arcs (
frozenset[tuple[Any,Any]]) – Frozen set of legal(EdgeMode, EdgeMode)arcs. Defaults to_VALID_TRANSITIONSfrombabylon.engine.systems.edge_transition— single source of truth. Tests that want to constrain the arc set can pass an explicit subset.
- check(pre, post)[source]
Check that every (pre_mode, post_mode) pair is legal.
- Parameters:
pre (
WorldState) – WorldState before step (provides previous edge modes).post (
WorldState) – WorldState after step.
- Return type:
- Returns:
InvariantResult — violated on first illegal arc encountered.
- class babylon.engine.invariants.NoCommunityFanOut[source]
Bases:
objectNo
EdgeType.MEMBERSHIPedge has a community-node source.Spec 055 US2 (INV-010). Constitutional commitment II.7 (Edges vs Hyperedges) plus Anti-Pattern VIII.9 (Community as Pairwise Edge): community membership lives in the XGI hyperedge layer; the morphism graph MUST NOT carry community-to-member fan-outs.
Walks every
EdgeType.MEMBERSHIPedge in the post-graph (constructed viapost.to_graph()) and asserts that the source node’s_node_type != "community".- check_graph(graph)[source]
Walk an explicit graph for community-fan-out MEMBERSHIP edges.
Preferred entry point. Tests that inject
_node_type='community'markers via_inject_community_markersMUST pass the live marked graph here — callingcheck(pre, post)instead would round-trip throughpost.to_graph()and strip the markers because community is not yet a first-class WorldState field.- Parameters:
graph (
Any) – NetworkX directed graph carrying the live_node_typemarkers (typically the post-tick graph from a fixture or test setup).- Return type:
- Returns:
InvariantResult — violated on first community-fan-out edge.
- check(_pre, post)[source]
Default Invariant Protocol entry — walks
post.to_graph().Best-effort fallback:
WorldState.to_graph()does not preserve test-injected_node_type='community'markers, so this entry point only catches violations that survive the round-trip. For full coverage, callers should usecheck_graph(live_graph).- Return type:
- Parameters:
_pre (WorldState)
post (WorldState)
- __init__()
- Return type:
None