Models

Core data models and types used throughout Babylon.

Pydantic models for the Babylon simulation engine.

This package contains the type system foundation: - enums: Categorical types (SocialRole, EdgeType, etc.) - types: Constrained value types (Probability, Currency, etc.) - entities: Game objects (Effect, Contradiction, Trigger, etc.) - components: Entity-Component system (Material, Vitality, Spatial, etc.)

All game state flows through these validated types.

class babylon.models.SocialRole(*values)[source]

Bases: StrEnum

Class position in the world system.

Based on Marxist-Leninist-Maoist Third Worldist (MLM-TW) theory, classes are defined by their relationship to production AND their position in the imperial hierarchy.

Values:

CORE_BOURGEOISIE: Owns means of production in imperial core PERIPHERY_PROLETARIAT: Sells labor in exploited periphery LABOR_ARISTOCRACY: Core workers benefiting from imperial rent PETTY_BOURGEOISIE: Small owners, professionals, shopkeepers LUMPENPROLETARIAT: Outside formal economy, precarious existence COMPRADOR_BOURGEOISIE: Intermediary class in periphery, collaborates with imperial core INTERNAL_PROLETARIAT: Core workers outside LA (precariat, unemployed, incarcerated) CARCERAL_ENFORCER: Guards, cops, prison staff (repressive apparatus)

Terminal Crisis Dynamics (ai-docs/terminal-crisis-dynamics.md):

When peripheral extraction fails and super-wages deplete, the Labor Aristocracy decomposes into CARCERAL_ENFORCER (30%) and INTERNAL_PROLETARIAT (70%). This models the carceral turn from productive to coercive labor.

CORE_BOURGEOISIE = 'core_bourgeoisie'
PERIPHERY_PROLETARIAT = 'periphery_proletariat'
LABOR_ARISTOCRACY = 'labor_aristocracy'
PETTY_BOURGEOISIE = 'petty_bourgeoisie'
LUMPENPROLETARIAT = 'lumpenproletariat'
COMPRADOR_BOURGEOISIE = 'comprador_bourgeoisie'
INTERNAL_PROLETARIAT = 'internal_proletariat'
CARCERAL_ENFORCER = 'carceral_enforcer'
class babylon.models.EdgeType(*values)[source]

Bases: StrEnum

Nature of relationships between entities.

These are the fundamental relationship types that form edges in the simulation’s NetworkX graph.

Values:

EXPLOITATION: Value extraction (imperial rent flows along these edges) SOLIDARITY: Mutual support and class consciousness REPRESSION: State violence directed at a class COMPETITION: Market rivalry between entities TRIBUTE: Value flow from periphery comprador to core (comprador keeps cut) WAGES: Core bourgeoisie paying core workers (super-wages from imperial rent) CLIENT_STATE: Imperial subsidy to maintain client state stability TENANCY: Occupant -> Territory relationship (Sprint 3.5.1) ADJACENCY: Territory -> Territory spatial connectivity (Sprint 3.5.1) TRANSACTIONAL: Service-for-support exchange (org-community, Feature 032) SOLIDARISTIC: Deep mutual commitment (org-community, Feature 032) ANTAGONISTIC: Manufactured conflict between orgs (Feature 039)

EXPLOITATION = 'exploitation'
SOLIDARITY = 'solidarity'
REPRESSION = 'repression'
COMPETITION = 'competition'
TRIBUTE = 'tribute'
WAGES = 'wages'
CLIENT_STATE = 'client_state'
TENANCY = 'tenancy'
ADJACENCY = 'adjacency'
MEMBERSHIP = 'membership'
RECRUITMENT = 'recruitment'
EMPLOYMENT = 'employment'
COMMAND = 'command'
PRESENCE = 'presence'
TRANSACTIONAL = 'transactional'
SOLIDARISTIC = 'solidaristic'
ANTAGONISTIC = 'antagonistic'
TARGETS = 'targets'
OWNED_BY = 'owned_by'
JURISDICTION = 'jurisdiction'
HOUSES = 'houses'
class babylon.models.IntensityLevel(*values)[source]

Bases: StrEnum

Intensity scale for contradictions and tensions.

Contradictions exist on a spectrum from dormant (latent potential) to critical (imminent rupture). This enum provides discrete levels for game mechanics while the underlying simulation may use continuous float values.

Values:

DORMANT: Contradiction exists but not yet manifest LOW: Minor tensions, easily managed MEDIUM: Noticeable conflict, requires attention HIGH: Serious crisis, intervention needed CRITICAL: Rupture imminent, phase transition likely

DORMANT = 'dormant'
LOW = 'low'
MEDIUM = 'medium'
HIGH = 'high'
CRITICAL = 'critical'
class babylon.models.ResolutionType(*values)[source]

Bases: StrEnum

How contradictions can resolve.

Based on dialectical materialism, contradictions resolve through one of three mechanisms. The resolution type determines what happens to the system after a contradiction reaches critical intensity.

Values:

SYNTHESIS: Dialectical resolution - opposites unite at higher level RUPTURE: Revolutionary break - system undergoes fundamental change SUPPRESSION: Forced dormancy - contradiction remains but is contained

SYNTHESIS = 'synthesis'
RUPTURE = 'rupture'
SUPPRESSION = 'suppression'
class babylon.models.SimulationConfig(**data)[source]

Bases: BaseModel

Global configuration for the simulation engine.

All formula coefficients and world parameters are stored here. The config is immutable (frozen) to ensure determinism during simulation runs.

Parameters:
extraction_efficiency

Alpha (α) in imperial rent formula. Controls how efficiently the core extracts value from periphery. Range: [0, 1], Default: 0.8

consciousness_sensitivity

k in consciousness drift formula. Controls how quickly consciousness responds to material conditions. Range: [0, 1], Default: 0.5

subsistence_threshold

Poverty line for acquiescence calculation. Below this wealth level, survival through compliance becomes impossible. Range: [0, inf), Default: 0.3

survival_steepness

Controls sigmoid sharpness in acquiescence probability. Higher values mean sharper transition around subsistence threshold. Range: (0, inf), Default: 10.0

repression_level

State capacity for violence. Reduces revolution probability in P(S|R) = cohesion / repression. Range: [0, 1], Default: 0.5

initial_worker_wealth

Starting wealth for periphery worker entities. Range: [0, inf), Default: 0.5

initial_owner_wealth

Starting wealth for core owner entities. Range: [0, inf), Default: 0.5

loss_aversion_lambda

Kahneman-Tversky loss aversion coefficient. Humans feel losses ~2.25x more strongly than equivalent gains. Range: (0, inf), Default: 2.25

model_config: ClassVar[ConfigDict] = {'frozen': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

extraction_efficiency: Annotated[float]
consciousness_sensitivity: Annotated[float]
consciousness_decay_lambda: Annotated[float]
subsistence_threshold: Annotated[float]
survival_steepness: Annotated[float]
repression_level: Annotated[float]
initial_worker_wealth: Annotated[float]
initial_owner_wealth: Annotated[float]
loss_aversion_lambda: Annotated[float]
tension_accumulation_rate: Annotated[float]
comprador_cut: Annotated[float]
super_wage_rate: Annotated[float]
subsidy_conversion_rate: Annotated[float]
subsidy_trigger_threshold: Annotated[float]
solidarity_activation_threshold: Annotated[float]
mass_awakening_threshold: Annotated[float]
heat_decay_rate: Annotated[float]
high_profile_heat_gain: Annotated[float]
eviction_heat_threshold: Annotated[float]
rent_spike_multiplier: Annotated[float]
displacement_rate: Annotated[float]
heat_spillover_rate: Annotated[float]
clarity_profile_coefficient: Annotated[float]
initial_rent_pool: Annotated[float]
pool_high_threshold: Annotated[float]
pool_low_threshold: Annotated[float]
pool_critical_threshold: Annotated[float]
min_wage_rate: Annotated[float]
max_wage_rate: Annotated[float]
superwage_ppp_impact: Annotated[float]
concentration_camp_decay_rate: Annotated[float]
displacement_priority_mode: DisplacementPriorityMode
elimination_rent_threshold: Annotated[float]
elimination_tension_threshold: Annotated[float]
containment_rent_threshold: Annotated[float]
containment_tension_threshold: Annotated[float]
class babylon.models.ScenarioConfig(**data)[source]

Bases: BaseModel

Configuration for multiverse scenario injection.

ScenarioConfig defines modifiers that transform a base WorldState and SimulationConfig into a specific counterfactual scenario. This enables deterministic exploration of parameter space without random sampling.

The model is frozen (immutable) to ensure scenarios remain constant throughout simulation runs.

Parameters:
name

Human-readable scenario identifier, must be unique within a multiverse run. Format: “{SWLevel}_{SolidarityLevel}_{RepressionLevel}”

superwage_multiplier

Multiplier for extraction_efficiency in SimulationConfig. Default 1.0 (no change). Range: [0, inf). - 0.3 = Low superwage (periphery retains more value) - 1.5 = High superwage (aggressive extraction) Theory: “Superwage” refers to core worker wages above value produced, subsidized by imperial rent extraction.

solidarity_index

Base strength for SOLIDARITY edges in topology. Default 0.5. Constrained to [0, 1] via Coefficient type. - 0.2 = Low solidarity (atomized workers) - 0.8 = High solidarity (strong worker networks)

repression_capacity

State violence capacity modifier. Updates repression_faced on entities and repression_level in config. Default 0.5. Constrained to [0, 1] via Coefficient type. - 0.2 = Low repression (weak state) - 0.8 = High repression (police state)

model_config: ClassVar[ConfigDict] = {'frozen': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

name: str
superwage_multiplier: float
solidarity_index: Coefficient
repression_capacity: Coefficient
class babylon.models.WorldState(**data)[source]

Bases: BaseModel

Immutable snapshot of the simulation at a specific tick.

WorldState follows the Data/Logic separation principle: - State holds WHAT exists (pure data) - Engine determines HOW it transforms (pure logic)

This enables: - Determinism: Same state + same engine = same output - Replayability: Save initial state, replay entire history - Counterfactuals: Modify a parameter, run forward, compare - Testability: Feed state in, assert on state out

Parameters:
tick

Current turn number (0-indexed)

entities

Map of entity ID to SocialClass (the nodes)

territories

Map of territory ID to Territory (Layer 0 nodes)

relationships

List of Relationship edges (the edges)

event_log

Recent events for narrative/debugging (string format)

events

Structured simulation events for analysis (Sprint 3.1)

economy

Global economic state for dynamic balance (Sprint 3.4.4)

add_entity(entity)[source]

Return new state with entity added.

Parameters:

entity (SocialClass) – SocialClass to add

Return type:

WorldState

Returns:

New WorldState with the entity included.

Example

new_state = state.add_entity(worker)

add_event(event)[source]

Return new state with event appended to log.

Parameters:

event (str) – Event description string

Return type:

WorldState

Returns:

New WorldState with event in log.

Example

new_state = state.add_event(“Worker crossed poverty threshold”)

add_relationship(relationship)[source]

Return new state with relationship added.

Parameters:

relationship (Relationship) – Relationship edge to add

Return type:

WorldState

Returns:

New WorldState with the relationship included.

Example

new_state = state.add_relationship(exploitation_edge)

add_territory(territory)[source]

Return new state with territory added.

Parameters:

territory (Territory) – Territory to add (Layer 0 node)

Return type:

WorldState

Returns:

New WorldState with the territory included.

Example

new_state = state.add_territory(university_district)

classmethod from_graph(G, tick, event_log=None, events=None)[source]

Reconstruct WorldState from NetworkX DiGraph.

Parameters:
  • G – NetworkX DiGraph with node/edge data

  • tick – The tick number for the new state

  • event_log – Optional event log to preserve (backward compatibility)

  • events – Optional structured events to include (Sprint 3.1)

Returns:

New WorldState with entities, territories, and relationships from graph.

Return type:

WorldState

Example

G = state.to_graph() # … modify graph … new_state = WorldState.from_graph(G, tick=state.tick + 1)

model_config: ClassVar[ConfigDict] = {'frozen': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

property overshoot_ratio: float

Global ecological overshoot ratio.

to_graph()[source]

Convert state to NetworkX DiGraph for formula application.

Nodes are entity/territory IDs with all fields as attributes. A _node_type marker distinguishes between node types: - _node_type=’social_class’ for SocialClass nodes - _node_type=’territory’ for Territory nodes

Edges are relationships with all Relationship fields as attributes.

Graph metadata (G.graph) contains: - economy: GlobalEconomy state (Sprint 3.4.4)

Returns:

NetworkX DiGraph with nodes and edges from this state.

Example:

G = state.to_graph()
for node_id, data in G.nodes(data=True):
    if data["_node_type"] == "social_class":
        data["wealth"] += 10  # Modify entity
new_state = WorldState.from_graph(G, tick=state.tick + 1)
property total_biocapacity: Annotated[float, FieldInfo(annotation=NoneType, required=True, description='Non-negative economic value (wealth, wages, rent, GDP)', metadata=[Ge(ge=0.0)]), AfterValidator(func=quantize)]

Global sum of territory biocapacity.

property total_consumption: Annotated[float, FieldInfo(annotation=NoneType, required=True, description='Non-negative economic value (wealth, wages, rent, GDP)', metadata=[Ge(ge=0.0)]), AfterValidator(func=quantize)]

Global sum of consumption needs.

tick: int
entities: dict[str, SocialClass]
territories: dict[str, Territory]
relationships: list[Relationship]
event_log: list[str]
events: list[SimulationEvent]
economy: GlobalEconomy
state_finances: dict[str, StateFinance]
contradiction_frames: dict[str, ContradictionFrame]
organizations: dict[str, OrganizationType]
key_figures: dict[str, KeyFigure]
institutions: dict[str, Institution]
institution_relations: list[InstitutionOrgRelation]
industries: dict[str, IndustryHyperedge]
class babylon.models.SocialClass(**data)[source]

Bases: BaseModel

A social class in the world system.

The fundamental unit of the simulation. Classes are defined by their relationship to production and their position in the imperial hierarchy.

This model uses Sprint 1 constrained types for automatic validation: - Currency: [0, inf) for wealth, subsistence_threshold - IdeologicalProfile: Multi-dimensional consciousness model (Sprint 3.4.3) - Probability: [0, 1] for survival probabilities and organization/repression

Parameters:
id

Unique identifier matching pattern ^C[0-9]{3}$

name

Human-readable name for the class

role

Position in the world system (SocialRole enum)

description

Optional detailed description

wealth

Economic resources (Currency, default 10.0)

ideology

Multi-dimensional ideological profile (IdeologicalProfile)

p_acquiescence

P(S|A) - survival probability through acquiescence (Probability)

p_revolution

P(S|R) - survival probability through revolution (Probability)

subsistence_threshold

Minimum wealth for survival (Currency, default 5.0)

organization

Collective cohesion/class consciousness (Probability, default 0.1)

repression_faced

State violence directed at this class (Probability, default 0.5)

Legacy Compatibility:

If a float value is passed for ideology, it will be automatically converted to an IdeologicalProfile using from_legacy_ideology().

property consumption_needs: Annotated[float, FieldInfo(annotation=NoneType, required=True, description='Non-negative economic value (wealth, wages, rent, GDP)', metadata=[Ge(ge=0.0)]), AfterValidator(func=quantize)]

Total consumption required per tick (Wealth-independent demand).

property economic: EconomicComponent

Return economic component view (computed, not live).

property material_conditions: MaterialConditionsComponent

Return material conditions component view (computed, not live).

model_config: ClassVar[ConfigDict] = {'extra': 'forbid', 'str_strip_whitespace': True, 'validate_assignment': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

property survival: SurvivalComponent

Return survival component view (computed, not live).

classmethod unpack_components_and_convert_legacy(data)[source]

Unpack component objects and convert legacy ideology to IdeologicalProfile.

Return type:

Any

Parameters:

data (Any)

id: str
name: str
role: SocialRole
description: str
wealth: Annotated[float]
ideology: IdeologicalProfile
p_acquiescence: Annotated[float]
p_revolution: Annotated[float]
subsistence_threshold: Annotated[float]
organization: Annotated[float]
repression_faced: Annotated[float]
effective_wealth: Annotated[float]
unearned_increment: Annotated[float]
ppp_multiplier: float
active: bool
s_bio: Annotated[float]
s_class: Annotated[float]
subsistence_multiplier: float
population: int
inequality: Annotated[float]
community_memberships: list[Any]
community_cost_modifier: float
class babylon.models.Relationship(**data)[source]

Bases: BaseModel

A directed edge between two entities.

Represents flows of value, solidarity, or repression between classes. In Phase 1, the primary relationship is exploitation: value flows from the periphery worker (source) to the core owner (target).

This model uses Sprint 1 constrained types for automatic validation: - Currency: [0, inf) for value_flow - Intensity: [0, 1] for tension

Parameters:
source_id

Origin entity ID (value/action flows FROM here)

target_id

Destination entity ID (value/action flows TO here)

edge_type

Nature of the relationship (EdgeType enum)

value_flow

Imperial rent or value transfer amount (Currency, default 0.0)

tension

Dialectical tension/contradiction intensity (Intensity, default 0.0)

description

Optional description of the relationship

property edge_data: dict[str, object]

Return edge attributes dict for NetworkX, excluding IDs.

Usage:

G.add_edge(*relationship.edge_tuple, **relationship.edge_data)
property edge_tuple: tuple[str, str]

Return (source_id, target_id) tuple for NetworkX edge creation.

Usage:

G.add_edge(*relationship.edge_tuple, **relationship.edge_data)
property flow: FlowComponent

Return flow component view (computed, not live).

model_config: ClassVar[ConfigDict] = {'extra': 'forbid', 'str_strip_whitespace': True, 'validate_assignment': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

classmethod unpack_flow_component(data)[source]

Unpack flow component into flat fields if provided.

Return type:

Any

Parameters:

data (Any)

validate_no_self_loop()[source]

Ensure entities cannot have a relationship with themselves.

Return type:

Relationship

source_id: str
target_id: str
edge_type: EdgeType
value_flow: Annotated[float]
tension: Annotated[float]
description: str
subsidy_cap: Annotated[float]
solidarity_strength: Annotated[float]
class babylon.models.IdeologicalProfile(**data)[source]

Bases: BaseModel

Multi-dimensional ideological state of a social class.

Sprint 3.4.3 (George Jackson Refactor): This model replaces the scalar ideology field with a multi-dimensional consciousness model.

The key insight: “Fascism is the defensive form of capitalism.” - Agitation + Solidarity -> Class Consciousness (Revolutionary Path) - Agitation + No Solidarity -> National Identity (Fascist Path)

Parameters:
class_consciousness

Relationship to Capital [0.0=False, 1.0=Revolutionary] How clearly the class understands its position relative to capital.

national_identity

Relationship to State/Tribe [0.0=Internationalist, 1.0=Fascist] How strongly the class identifies with nation/race over class.

agitation

Raw political energy from crisis [0.0, inf) Accumulated energy from falling wages, crisis conditions. Routes to either axis based on solidarity_pressure.

classmethod from_legacy_ideology(ideology_value)[source]

Convert legacy scalar ideology [-1, 1] to IdeologicalProfile.

Legacy mapping: - ideology=-1 (revolutionary) -> class_consciousness=1.0, national_identity=0.0 - ideology=0 (neutral) -> class_consciousness=0.5, national_identity=0.5 - ideology=+1 (reactionary) -> class_consciousness=0.0, national_identity=1.0

Parameters:

ideology_value (float) – Legacy ideology scalar in range [-1.0, 1.0]

Return type:

IdeologicalProfile

Returns:

IdeologicalProfile with mapped values

model_config: ClassVar[ConfigDict] = {'frozen': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

to_legacy_ideology()[source]

Convert IdeologicalProfile back to legacy scalar ideology [-1, 1].

This provides backward compatibility for systems still using the scalar ideology representation.

Return type:

float

Returns:

Legacy ideology scalar in range [-1.0, 1.0]

class_consciousness: Annotated[float]
national_identity: Annotated[float]
agitation: Annotated[float]
class babylon.models.GlobalEconomy(**data)[source]

Bases: BaseModel

System-wide economic state for dynamic balance mechanics.

The GlobalEconomy model tracks the “Gas Tank” (imperial rent pool) and the “Driver” parameters (wage rate, repression level) that the bourgeoisie can adjust based on pool levels and tension.

Parameters:
imperial_rent_pool

Accumulated imperial rent available for redistribution. Fed by TRIBUTE inflows, depleted by WAGES and CLIENT_STATE outflows. Default: 100.0 Currency.

current_super_wage_rate

Dynamic wage rate for WAGES edges. Adjusts based on pool level and tension via decision heuristics. Range: [0.05, 0.35]. Default: 0.20 (20%).

current_repression_level

System-wide repression modifier. Blended with per-class repression_faced values. Increases during austerity/crisis periods. Range: [0.0, 1.0]. Default: 0.5.

Pool Flow Logic:

inflow = sum(tribute reaching Core Bourgeoisie after comprador cut) outflow = wages_paid + subsidy_paid delta = inflow - outflow new_pool = old_pool + delta

Decision Thresholds (Aggressive):

pool_ratio >= 0.7: PROSPERITY (can increase wages) pool_ratio < 0.3: AUSTERITY (cut wages or increase repression) pool_ratio < 0.1: CRISIS (emergency measures, emit event)

model_config: ClassVar[ConfigDict] = {'frozen': True, 'populate_by_name': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

imperial_rent_pool: Annotated[float]
current_super_wage_rate: Annotated[float]
current_repression_level: Annotated[float]
class babylon.models.Effect(**data)[source]

Bases: BaseModel

A modification to game state.

Effects are the atoms of change - they modify single attributes on single targets by specific amounts. Every state change in the simulation should be expressible as one or more Effects.

Parameters:
  • target_id (str)

  • attribute (str)

  • operation (Literal['increase', 'decrease', 'set', 'multiply'])

  • magnitude (float)

  • description (str)

target_id

ID of the entity to modify

attribute

Name of the attribute to change

operation

How to modify the value

magnitude

Amount of change (interpretation depends on operation)

description

Human-readable explanation of why this effect occurs

apply_to(current_value)[source]

Calculate the new value after applying this effect.

Parameters:

current_value (float) – The current value of the attribute

Return type:

float

Returns:

The new value after the effect is applied

model_config: ClassVar[ConfigDict] = {'extra': 'forbid'}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

target_id: str
attribute: str
operation: Literal['increase', 'decrease', 'set', 'multiply']
magnitude: float
description: str
class babylon.models.ContradictionFrame(**data)[source]

Bases: BaseModel

The 2x2 contradiction matrix at a given scale and moment.

Models the principal and secondary contradictions for a specific scope.

Parameters:
model_config: ClassVar[ConfigDict] = {'extra': 'forbid'}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

principal: Contradiction
secondary: Contradiction
class babylon.models.Contradiction(**data)[source]

Bases: BaseModel

A structural contradiction at a specific scale.

Instead of hardcoding the fractal, this uses a dynamic aspect mapping.

Parameters:
model_config: ClassVar[ConfigDict] = {'extra': 'forbid'}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

id: str
type: ContradictionType
aspect_a: str
aspect_b: str
principal_aspect: Literal['a', 'b']
identity: Annotated[float]
intensity: Annotated[float]
aspect_balance: float
form_of_struggle: EdgeMode
is_antagonistic: bool
class babylon.models.Trigger(**data)[source]

Bases: BaseModel

A condition that can trigger game events.

Triggers define when events should occur based on game state. They can have multiple conditions that must all be met (AND logic) or any one met (OR logic).

Parameters:
id

Unique identifier

description

Human-readable description

trigger_type

Category of trigger (economic, political, social, etc.)

conditions

List of conditions to evaluate

logic

How to combine conditions (all must pass or any must pass)

parameters

Optional parameters for condition evaluation

cooldown_turns

Minimum turns between activations (0 = no cooldown)

last_triggered_turn

Turn when this was last triggered

evaluate(game_state, current_turn=0)[source]

Evaluate if the trigger condition is met.

Parameters:
  • game_state (dict[str, Any]) – The current game state to evaluate against

  • current_turn (int) – The current turn number (for cooldown checking)

Return type:

bool

Returns:

True if the trigger condition is met, False otherwise

mark_triggered(current_turn)[source]

Mark this trigger as having been triggered.

Parameters:

current_turn (int) – The current turn number

Return type:

None

model_config: ClassVar[ConfigDict] = {'extra': 'forbid'}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

id: str
description: str
trigger_type: str | None
conditions: list[TriggerCondition]
logic: Literal['all', 'any']
parameters: dict[str, Any]
cooldown_turns: int
last_triggered_turn: int | None
class babylon.models.TriggerCondition(**data)[source]

Bases: BaseModel

A single condition that can be evaluated against game state.

Conditions specify what to check, how to compare, and what threshold to use. Multiple conditions can be combined in a Trigger.

Parameters:
  • path (str)

  • operator (Literal['>=', '<=', '>', '<', '==', '!='])

  • threshold (float)

  • description (str)

path

Dot-notation path to the value in game state (e.g., “economy.gini_coefficient”)

operator

Comparison operator

threshold

Value to compare against

description

Human-readable explanation

evaluate(game_state)[source]

Evaluate this condition against the game state.

Parameters:

game_state (dict[str, Any]) – The current game state dictionary

Return type:

bool

Returns:

True if the condition is met, False otherwise

model_config: ClassVar[ConfigDict] = {'extra': 'forbid'}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

path: str
operator: Literal['>=', '<=', '>', '<', '==', '!=']
threshold: float
description: str
class babylon.models.Component(*args, **kwargs)[source]

Bases: Protocol

Protocol defining the interface for all component types.

All components in the Babylon simulation must implement this protocol. The protocol requires a component_type property that returns a string identifier for the component type.

This protocol is runtime-checkable, meaning you can use isinstance() to verify that an object implements the Component interface.

Example

>>> class MyComponent(BaseModel):
...     model_config = ConfigDict(frozen=True)
...     @property
...     def component_type(self) -> str:
...         return "my_component"
...
>>> instance = MyComponent()
>>> isinstance(instance, Component)
True
__init__(*args, **kwargs)
property component_type: str

Return the component type identifier.

Returns:

A string identifying the type of this component. For example: “material”, “vitality”, “spatial”, etc.

class babylon.models.MaterialComponent(**data)[source]

Bases: BaseModel

Material conditions of an entity.

Tracks the economic and material state of an entity including: - Accumulated wealth (Currency) - Available resources (Currency) - Control over means of production (Probability)

All values use constrained types for automatic validation: - wealth, resources: Currency [0, inf) - means_of_production: Probability [0, 1]

This component is immutable (frozen) to ensure state integrity.

Parameters:
wealth

Accumulated economic resources (default: 10.0)

resources

Available material resources (default: 0.0)

means_of_production

Control over productive apparatus [0, 1] (default: 0.0)

property component_type: str

Return the component type identifier.

Returns:

The string ‘material’ identifying this component type.

model_config: ClassVar[ConfigDict] = {'frozen': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

wealth: Annotated[float]
resources: Annotated[float]
means_of_production: Annotated[float]
class babylon.models.VitalityComponent(**data)[source]

Bases: BaseModel

Population and survival needs of an entity.

Tracks the demographic and subsistence state of an entity: - Population size (Currency) - Minimum resources required for survival (Currency)

All values use constrained types for automatic validation: - population, subsistence_needs: Currency [0, inf)

This component is immutable (frozen) to ensure state integrity.

Parameters:
population

Size of the population (default: 1.0)

subsistence_needs

Resources needed for survival (default: 5.0)

property component_type: str

Return the component type identifier.

Returns:

The string ‘vitality’ identifying this component type.

model_config: ClassVar[ConfigDict] = {'frozen': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

population: Annotated[float]
subsistence_needs: Annotated[float]
class babylon.models.SpatialComponent(**data)[source]

Bases: BaseModel

Location and mobility of an entity.

Tracks the spatial state of an entity: - Geographic/topological location identifier (string) - Ability to relocate (Probability)

All numeric values use constrained types for automatic validation: - mobility: Probability [0, 1]

This component is immutable (frozen) to ensure state integrity.

Parameters:
location_id

Geographic or topological location identifier (default: “”)

mobility

Ability to relocate [0=immobile, 1=fully mobile] (default: 0.5)

property component_type: str

Return the component type identifier.

Returns:

The string ‘spatial’ identifying this component type.

model_config: ClassVar[ConfigDict] = {'frozen': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

location_id: str
mobility: Annotated[float]
class babylon.models.OrganizationComponent(**data)[source]

Bases: BaseModel

Organizational capacity of an entity.

Tracks the organizational state of an entity: - Internal unity and coordination (Probability) - Quality of organizational leadership (Probability)

All values use constrained types for automatic validation: - cohesion: Probability [0, 1] - cadre_level: Probability [0, 1]

This component is immutable (frozen) to ensure state integrity.

Parameters:
cohesion

Internal unity and coordination [0=atomized, 1=unified] (default: 0.1)

cadre_level

Quality of organizational leadership [0=none, 1=elite] (default: 0.0)

property component_type: str

Return the component type identifier.

Returns:

The string ‘organization’ identifying this component type.

model_config: ClassVar[ConfigDict] = {'frozen': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

cohesion: Annotated[float]
cadre_level: Annotated[float]
class babylon.models.TopologySnapshot(**data)[source]

Bases: BaseModel

Metrics snapshot of the solidarity subgraph at a specific tick.

Captures the topological state of SOLIDARITY edges in the social graph, enabling detection of phase transitions from atomized (gaseous) to condensed (liquid) movement states.

Parameters:
tick

Simulation tick when snapshot was taken

num_components

Number of disconnected subgraphs (solidarity cells)

max_component_size

Size of the largest connected component (L_max)

total_nodes

Total number of social_class nodes (N)

percolation_ratio

L_max / N, measures giant component dominance

potential_liquidity

Count of SOLIDARITY edges > 0.1 (sympathizers)

actual_liquidity

Count of SOLIDARITY edges > 0.5 (cadre)

is_resilient

Whether movement survives 20% purge (optional)

Interpretation (4-Phase Model):
  • percolation_ratio < 0.1: Gaseous (atomized, no coordination)

  • 0.1 <= percolation_ratio < 0.5: Transitional (emerging structure)

  • percolation_ratio >= 0.5 AND cadre_density < 0.5: Liquid (mass movement)

  • percolation_ratio >= 0.5 AND cadre_density >= 0.5: Solid (vanguard party)

  • potential >> actual: Broad but brittle (lacks cadre discipline)

model_config: ClassVar[ConfigDict] = {'frozen': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

tick: int
num_components: int
max_component_size: int
total_nodes: int
percolation_ratio: Probability
potential_liquidity: int
actual_liquidity: int
cadre_density: float
is_resilient: bool | None
class babylon.models.ResilienceResult(**data)[source]

Bases: BaseModel

Result of purge simulation (Sword of Damocles test).

Tests whether the solidarity network survives targeted removal of a percentage of nodes. A resilient network maintains its giant component after losing key members.

Parameters:
is_resilient

True if post-purge L_max > threshold of original L_max

original_max_component

Size of L_max before purge

post_purge_max_component

Size of L_max after purge

removal_rate

Fraction of nodes removed (e.g., 0.2 = 20%)

survival_threshold

Required fraction of original L_max to survive

seed

RNG seed for reproducibility (None if random)

Interpretation:
  • is_resilient=True: Network can survive targeted repression

  • is_resilient=False: “Sword of Damocles” - purge would destroy movement

model_config: ClassVar[ConfigDict] = {'frozen': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

is_resilient: bool
original_max_component: int
post_purge_max_component: int
removal_rate: float
survival_threshold: float
seed: int | None
class babylon.models.EntityMetrics(**data)[source]

Bases: BaseModel

Metrics snapshot for a single entity at a specific tick.

Captures wealth, consciousness, and survival probabilities for analysis and visualization.

Parameters:
model_config: ClassVar[ConfigDict] = {'frozen': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

wealth: Currency
consciousness: Probability
national_identity: Probability
agitation: float
p_acquiescence: Probability
p_revolution: Probability
organization: Probability
population: int
class babylon.models.EdgeMetrics(**data)[source]

Bases: BaseModel

Metrics snapshot for relationship edges at a specific tick.

Captures tension, value flows, and solidarity strength for analysis and visualization.

Parameters:
model_config: ClassVar[ConfigDict] = {'frozen': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

exploitation_tension: Probability
exploitation_rent: Currency
tribute_flow: Currency
wages_paid: Currency
solidarity_strength: Probability
class babylon.models.TickMetrics(**data)[source]

Bases: BaseModel

Complete metrics snapshot for a single simulation tick.

Aggregates entity and edge metrics for comprehensive tick analysis.

Parameters:
model_config: ClassVar[ConfigDict] = {'frozen': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

tick: int
p_w: EntityMetrics | None
p_c: EntityMetrics | None
c_b: EntityMetrics | None
c_w: EntityMetrics | None
edges: EdgeMetrics
imperial_rent_pool: Currency
global_tension: Probability
current_super_wage_rate: float
current_repression_level: Probability
pool_ratio: Probability
topology: TopologySummary | None
consciousness_gap: float
wealth_gap: float
overshoot_ratio: float
total_biocapacity: Currency
total_consumption: Currency
class babylon.models.SweepSummary(**data)[source]

Bases: BaseModel

Summary statistics for a completed simulation run.

Aggregates metrics across all ticks for parameter sweep analysis.

Parameters:
model_config: ClassVar[ConfigDict] = {'frozen': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

ticks_survived: int
outcome: Literal['SURVIVED', 'DIED', 'ERROR']
final_p_w_wealth: Currency
final_p_c_wealth: Currency
final_c_b_wealth: Currency
final_c_w_wealth: Currency
max_tension: Probability
crossover_tick: int | None
cumulative_rent: Currency
peak_p_w_consciousness: Probability
peak_c_w_consciousness: Probability
class babylon.models.GraphNode(**data)[source]

Bases: BaseModel

Type-safe graph node representation.

Frozen Pydantic model for node data at the protocol boundary. Adapters convert to/from their internal representation.

Parameters:
id

Unique node identifier.

node_type

Discriminator for polymorphism (e.g., ‘social_class’, ‘territory’).

attributes

Type-specific attributes stored as dict.

Example

>>> node = GraphNode(id="C001", node_type="social_class", attributes={"wealth": 100.0})
>>> node.wealth
100.0
get_attr(key, default=None)[source]

Get attribute with default.

Parameters:
  • key (str) – Attribute name to retrieve.

  • default (Any) – Value to return if attribute not present.

Return type:

Any

Returns:

The attribute value or default.

model_config: ClassVar[ConfigDict] = {'frozen': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

property wealth: float

Convenience accessor for wealth attribute.

Returns:

Wealth value or 0.0 if not present.

id: str
node_type: str
attributes: dict[str, Any]
class babylon.models.GraphEdge(**data)[source]

Bases: BaseModel

Type-safe graph edge representation.

Frozen Pydantic model for edge data at the protocol boundary. Adapters convert to/from their internal representation.

Parameters:
source_id

Origin node ID.

target_id

Destination node ID.

edge_type

Edge category (e.g., ‘SOLIDARITY’, ‘EXPLOITATION’).

weight

Generic weight (default 1.0).

attributes

Type-specific attributes stored as dict.

Example

>>> edge = GraphEdge(source_id="C001", target_id="C002", edge_type="SOLIDARITY")
>>> edge.weight
1.0
model_config: ClassVar[ConfigDict] = {'frozen': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

property tension: float

Convenience accessor for tension attribute.

Returns:

Tension value or 0.0 if not present.

property value_flow: float

Convenience accessor for value_flow attribute.

Returns:

Value flow or 0.0 if not present.

source_id: str
target_id: str
edge_type: str
weight: float
attributes: dict[str, Any]
class babylon.models.EdgeFilter(**data)[source]

Bases: BaseModel

Filter specification for edge traversal.

Used to select which edges to traverse during graph operations. All fields are optional - None means no filter (match all).

Parameters:
  • edge_types (set[str] | None)

  • min_weight (float | None)

  • max_weight (float | None)

edge_types

Set of edge types to include (None = all types).

min_weight

Minimum weight threshold (inclusive).

max_weight

Maximum weight threshold (inclusive).

Example

>>> f = EdgeFilter(edge_types={"SOLIDARITY"}, min_weight=0.5)
>>> f.edge_types
{'SOLIDARITY'}
model_config: ClassVar[ConfigDict] = {'frozen': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

edge_types: set[str] | None
min_weight: float | None
max_weight: float | None
class babylon.models.NodeFilter(**data)[source]

Bases: BaseModel

Filter specification for node inclusion.

Used to select which nodes to include during graph operations. All fields are optional - None means no filter (match all).

Parameters:
node_types

Set of node types to include (None = all types).

attribute_predicates

Dict of attribute equality filters.

Example

>>> f = NodeFilter(node_types={"social_class"})
>>> f.node_types
{'social_class'}
model_config: ClassVar[ConfigDict] = {'frozen': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

node_types: set[str] | None
attribute_predicates: dict[str, Any] | None
class babylon.models.TraversalQuery(**data)[source]

Bases: BaseModel

Generic traversal query specification.

Specifies what traversal to execute and what to collect. This is the generic hook for complex operations like percolation analysis, pathfinding, and component detection.

Parameters:
  • query_type (Literal['bfs', 'dfs', 'shortest_path', 'connected_components', 'percolation', 'reachability'])

  • start_nodes (list[str] | None)

  • target_nodes (list[str] | None)

  • edge_filter (EdgeFilter | None)

  • node_filter (NodeFilter | None)

  • max_depth (int | None)

  • collect (list[str])

query_type

Type of traversal algorithm to use.

start_nodes

Starting node IDs (None = all nodes).

target_nodes

Target node IDs (for shortest_path, reachability).

edge_filter

Filter which edges to traverse.

node_filter

Filter which nodes to include.

max_depth

Maximum traversal depth.

collect

What to include in result.

Example

>>> query = TraversalQuery(query_type="bfs", start_nodes=["C001"])
>>> query.query_type
'bfs'
model_config: ClassVar[ConfigDict] = {'frozen': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

query_type: Literal['bfs', 'dfs', 'shortest_path', 'connected_components', 'percolation', 'reachability']
start_nodes: list[str] | None
target_nodes: list[str] | None
edge_filter: EdgeFilter | None
node_filter: NodeFilter | None
max_depth: int | None
collect: list[str]
class babylon.models.TraversalResult(**data)[source]

Bases: BaseModel

Result of traversal query execution.

Contains all data collected during traversal based on query.collect.

Parameters:
nodes

Node IDs in traversal result.

edges

Edge tuples (source, target, type) in result.

paths

Paths found (for shortest_path queries).

components

Connected components (for component queries).

component_sizes

Sizes of connected components (sorted descending).

metadata

Query-specific metadata.

Example

>>> result = TraversalResult(component_sizes=[10, 5, 3])
>>> result.largest_component_size
10
property largest_component_size: int

Size of the largest (giant) component.

Returns:

Size of first component or 0 if no components.

model_config: ClassVar[ConfigDict] = {'frozen': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

property percolation_ratio: float

Fraction of nodes in the largest component.

This is the key metric for phase transition detection. A ratio near 1.0 indicates full percolation (connectivity).

Returns:

Ratio of largest_component_size to total nodes, or 0.0 if empty.

nodes: list[str]
edges: list[tuple[str, str, str]]
paths: list[list[str]]
components: list[list[str]]
component_sizes: list[int]
metadata: dict[str, Any]
babylon.models.role_to_entity_id(role)[source]

Convert a SocialRole enum to its canonical entity ID.

Parameters:

role (SocialRole) – SocialRole enum value

Return type:

str

Returns:

Entity ID string (e.g., “C001”)

Raises:

KeyError – If the role has no entity ID mapping (e.g., LUMPENPROLETARIAT)

Example

>>> role_to_entity_id(SocialRole.PERIPHERY_PROLETARIAT)
'C001'
babylon.models.entity_id_to_role(entity_id)[source]

Convert an entity ID to its SocialRole enum.

Parameters:

entity_id (str) – Entity ID string (e.g., “C001”)

Return type:

SocialRole

Returns:

SocialRole enum value

Raises:

KeyError – If the entity ID is not recognized

Example

>>> entity_id_to_role("C001")
<SocialRole.PERIPHERY_PROLETARIAT: 'periphery_proletariat'>
babylon.models.get_slot_name(entity_id)[source]

Get the short slot name for an entity ID.

Slot names are used for CSV column prefixes and metrics keys.

Parameters:

entity_id (str) – Entity ID string (e.g., “C001”)

Return type:

str

Returns:

Short slot name (e.g., “p_w”)

Raises:

KeyError – If the entity ID is not recognized

Example

>>> get_slot_name("C001")
'p_w'
class babylon.models.HexState(**data)[source]

Bases: BaseModel

Immutable geographic cell snapshot.

Hexes are the invariant substrate - they don’t change during simulation. For MVP, HexState contains only the H3 index. Future versions may add physical properties (terrain, resources).

Parameters:

h3_index (str)

h3_index

H3 cell index (15-char hex string, resolution 5).

model_config: ClassVar[ConfigDict] = {'frozen': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

classmethod validate_h3_index(v)[source]

Validate H3 index is 15-char lowercase hex.

Return type:

str

Parameters:

v (str)

h3_index: str
class babylon.models.EdgeState(**data)[source]

Bases: BaseModel

Relationship snapshot between entities at a specific tick.

Parameters:
source_id

ID of the source entity.

target_id

ID of the target entity.

edge_type

Relationship type.

weight

Edge weight (default 1.0).

model_config: ClassVar[ConfigDict] = {'frozen': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

source_id: str
target_id: str
edge_type: SnapshotEdgeType
weight: float
class babylon.models.TerritoryState(**data)[source]

Bases: BaseModel

Territory state snapshot at a specific tick.

This is the GUI-facing representation of a territory.

Parameters:
territory_id

Unique identifier (FIPS code for counties).

controlling_polity

Current controller (equals territory_id for MVP).

hex_claims

Set of H3 indices this territory claims.

tick

Tick number when this snapshot was taken.

profit_rate

Current profit rate, range [0.0, 1.0].

equilibrium_r

Territory-specific equilibrium (= initial_r at hydration).

classmethod convert_hex_claims(v)[source]

Convert hex_claims to frozenset for immutability.

Return type:

frozenset[str]

Parameters:

v (set[str] | frozenset[str] | list[str])

model_config: ClassVar[ConfigDict] = {'frozen': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

validate_hex_claims_patterns()[source]

Validate all H3 indices in hex_claims match pattern.

Return type:

TerritoryState

classmethod validate_territory_id(v)[source]

Validate territory_id is a 5-digit FIPS code.

Return type:

str

Parameters:

v (str)

classmethod with_clamped_profit_rate(territory_id, controlling_polity, hex_claims, tick, profit_rate, equilibrium_r, tensor_year=None)[source]

Create TerritoryState with profit_rate clamped to [0.0, 1.0].

If profit_rate is outside valid range, it is clamped and a warning is logged.

Parameters:
  • territory_id (str) – FIPS code.

  • controlling_polity (str) – Controller ID.

  • hex_claims (set[str] | frozenset[str]) – Set of H3 indices.

  • tick (int) – Current tick.

  • profit_rate (float) – Computed profit rate (may be out of range).

  • equilibrium_r (float) – Territory-specific equilibrium.

  • tensor_year (int | None) – Year for tensor lookup (may differ from tick). None if no tensor data.

Return type:

TerritoryState

Returns:

TerritoryState with clamped profit_rate.

territory_id: str
controlling_polity: str
hex_claims: frozenset[str]
tick: int
profit_rate: float
equilibrium_r: float
tensor_year: int | None
class babylon.models.SimulationSnapshot(**data)[source]

Bases: BaseModel

Complete simulation state at a specific tick.

This is the top-level container returned by get_snapshot().

Parameters:
tick

Current tick number.

territories

Map of territory_id to TerritoryState.

hexes

Map of h3_index to HexState (invariant substrate).

edges

List of EdgeState relationships (empty for MVP).

tensor_registry

Optional reference to TensorRegistry for cached tensor data access without database queries.

model_config: ClassVar[ConfigDict] = {'arbitrary_types_allowed': True, 'frozen': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

validate_hex_references()[source]

Validate all hex_claims reference existing hexes.

Return type:

SimulationSnapshot

tick: int
territories: dict[str, TerritoryState]
hexes: dict[str, HexState]
edges: list[EdgeState]
tensor_registry: Any
class babylon.models.SnapshotEdgeType(*values)[source]

Bases: str, Enum

Edge types for simulation snapshots.

Maps to constitution I.6 edge modes.

ADJACENCY = 'ADJACENCY'
EXTRACTION = 'EXTRACTION'
SOLIDARITY = 'SOLIDARITY'
ANTAGONISTIC = 'ANTAGONISTIC'
class babylon.models.CommunityType(*values)[source]

Bases: StrEnum

Community types for hypergraph membership (Constitution II.7).

Three structurally distinct categories — NOT a spectrum.

Category 1 — Contradiction Pairs (both sides real hyperedges):

SETTLER: Settler nation (hegemonic). Institutions: HOAs, police unions, border militias. NEW_AFRIKAN: New Afrikan / Black internal nation (marginalized) FIRST_NATIONS: Indigenous / First Nations peoples (marginalized) CHICANO: Chicano / Mexican-American nation (marginalized) PATRIARCHAL: Patriarchal order (hegemonic). Institutions: gendered wage systems, family structure. WOMEN: Women — reproductive labor allocation (marginalized) TRANS: Transgender / gender non-conforming (marginalized)

Category 2 — Institutional Exclusion (only marginalized side):

DISABLED: Disabled community. Built environment assumes able-bodiedness. QUEER: Queer / LGBQ. Institutional heteronormativity. UNDOCUMENTED: Undocumented. Legal exclusion from protections. INCARCERATED: Incarcerated. Carceral system, civil death.

Category 3 — Lifecycle Phases (D-P-D’ Circuit):

YOUTH: D phase. Pre-productive, dependent, receives socialization. ADULT: P phase. Sells labor-power. Where C-M-C and M-C-M’ operate. ELDER: D’ phase. Post-productive. Legitimation bargain (pensions, Social Security).

SETTLER = 'settler'
PATRIARCHAL = 'patriarchal'
NEW_AFRIKAN = 'new_afrikan'
FIRST_NATIONS = 'first_nations'
CHICANO = 'chicano'
WOMEN = 'women'
TRANS = 'trans'
DISABLED = 'disabled'
QUEER = 'queer'
UNDOCUMENTED = 'undocumented'
INCARCERATED = 'incarcerated'
YOUTH = 'youth'
ADULT = 'adult'
ELDER = 'elder'
class babylon.models.LegalStatus(*values)[source]

Bases: StrEnum

Legal designation status for community-level state repression.

Hypergraph Community Layer (Feature 022): Escalation is strictly one-way for state action. De-escalation requires political struggle (player action). Each level increases the threat multiplier applied to community members.

Values:

LEGAL: Normal status, minimal state attention (multiplier 0.1) SURVEILLED: Active monitoring (multiplier 0.5) DESIGNATED_EXTREMIST: Formal extremist designation (multiplier 1.0) DESIGNATED_TERRORIST: Formal terrorist designation (multiplier 2.0) CRIMINALIZED: Membership itself criminalized (multiplier 3.0)

LEGAL = 'legal'
SURVEILLED = 'surveilled'
DESIGNATED_EXTREMIST = 'designated_extremist'
DESIGNATED_TERRORIST = 'designated_terrorist'
CRIMINALIZED = 'criminalized'
class babylon.models.MembershipRole(*values)[source]

Bases: StrEnum

Agent integration level within a community.

Hypergraph Community Layer (Feature 022): Determines membership strength weight and visibility profile for threat score computation.

Values:

CORE_ORGANIZER: Infrastructure maintainers, visible leaders (weight 1.0) ACTIVE: Regular participants, known within community (weight 0.7) PARTICIPANT: Occasional engagement (weight 0.4) PERIPHERAL: Marginal connection (weight 0.2) SYMPATHIZER: External ally, not legible as member (weight 0.1)

CORE_ORGANIZER = 'core_organizer'
ACTIVE = 'active'
PARTICIPANT = 'participant'
PERIPHERAL = 'peripheral'
SYMPATHIZER = 'sympathizer'
class babylon.models.CommunityState(**data)[source]

Bases: BaseModel

State of a community, independent of its members.

Each community has collective attributes tracking state attention, internal cohesion, organizational infrastructure, and material modifiers applied to all members.

Parameters:
  • community_type (CommunityType) – Identity of this community.

  • heat (Annotated[float, Ge(ge=0.0), Le(le=1.0), AfterValidator(func=~babylon.utils.math.quantize)]) – State attention/surveillance intensity [0, 1].

  • legal_status (LegalStatus) – Current legal designation (one-way escalation).

  • cohesion (Annotated[float, Ge(ge=0.0), Le(le=1.0), AfterValidator(func=~babylon.utils.math.quantize)]) – Internal trust and mutual aid effectiveness [0, 1].

  • infrastructure (Annotated[float, Ge(ge=0.0), Le(le=1.0), AfterValidator(func=~babylon.utils.math.quantize)]) – Organizational capacity (meeting spaces, comms) [0, 1].

  • visibility (Annotated[float, Ge(ge=0.0), Le(le=1.0), AfterValidator(func=~babylon.utils.math.quantize)]) – Community legibility to state surveillance [0, 1].

  • reproduction_cost_modifier (Annotated[float, Ge(ge=0)]) – Multiplier on V_reproduction for members.

  • rent_access_modifier (Annotated[float, Ge(ge=0.0), Le(le=1.0), AfterValidator(func=~babylon.utils.math.quantize)]) – Multiplier on imperial rent received by members.

  • category (HyperedgeCategory)

  • consciousness (TernaryConsciousness)

  • education_pressure (Annotated[float, Ge(ge=0)])

property infiltration_resistance: float

Community resistance to state infiltration.

Formula: CI * 0.6 + cohesion * 0.3 + CI * cohesion * 0.1

Returns:

Resistance score in [0.0, 1.0].

property is_cross_class_bridge: bool

Whether this community can span contradiction axes.

Only INSTITUTIONAL_EXCLUSION communities bridge across axes because their members can come from both hegemonic and marginalized sides.

Returns:

True if the community is an institutional exclusion type.

model_config: ClassVar[ConfigDict] = {'frozen': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

community_type: CommunityType
category: HyperedgeCategory
heat: Probability
legal_status: LegalStatus
cohesion: Probability
infrastructure: Probability
visibility: Probability
reproduction_cost_modifier: float
rent_access_modifier: Coefficient
consciousness: CommunityConsciousness
education_pressure: float
class babylon.models.CommunityMembership(**data)[source]

Bases: BaseModel

An agent’s membership in a community.

Represents the relationship between an individual agent and a community hyperedge. Each membership has a role determining integration level and a visibility determining legibility to state.

Parameters:
  • agent_id (str) – Identifier of the member agent.

  • community_type (CommunityType) – Which community this membership is in.

  • role (MembershipRole) – Integration level within the community.

  • strength (Annotated[float, Ge(ge=0.0), Le(le=1.0), AfterValidator(func=~babylon.utils.math.quantize)]) – Membership weight [0, 1], derived from role default.

  • visibility (Annotated[float, Ge(ge=0.0), Le(le=1.0), AfterValidator(func=~babylon.utils.math.quantize)]) – Base legibility to state [0, 1].

  • overt (bool) – Publicly identified — overrides visibility to 1.0.

property effective_visibility: float

Effective visibility accounting for overt flag.

Returns:

1.0 if overt, otherwise the base visibility value.

model_config: ClassVar[ConfigDict] = {'frozen': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

agent_id: str
community_type: CommunityType
role: MembershipRole
strength: Coefficient
visibility: Probability
overt: bool
class babylon.models.HyperedgeCategory(*values)[source]

Bases: StrEnum

Structural category for community hyperedges (Feature 029, Constitution II.7).

Three qualitatively distinct categories with different material bases, relationships to oppression, and modeling requirements.

Values:
CONTRADICTION_PAIR: Both hegemonic and marginalized sides exist as real

hyperedges with extraction flows between them.

INSTITUTIONAL_EXCLUSION: Only marginalized side exists. Oppression flows

through institutional defaults, not a paired oppressor community.

LIFECYCLE_PHASE: Temporal positions in D-P-D’ intergenerational lifecycle.

Universal, temporally permeable, defined by relationship to production.

ECONOMIC_SECTOR: Industry sectors represented by 2-digit NAICS codes. Used

for tracking economic metabolism, business coordination, and profit equalization.

CONTRADICTION_PAIR = 'contradiction_pair'
INSTITUTIONAL_EXCLUSION = 'institutional_exclusion'
LIFECYCLE_PHASE = 'lifecycle_phase'
ECONOMIC_SECTOR = 'economic_sector'
class babylon.models.ConsciousnessTendency(*values)[source]

Bases: StrEnum

Dominant ideological tendency within a community (Feature 029).

Represents the prevailing direction of collective consciousness — the default drift without active organizing.

Values:
LIBERAL: Seeks inclusion in existing institutions without transforming

them. Organizational vehicle: liberal CSOs, Democratic Party.

FASCIST: Collaboration with hegemonic order for individual escape.

Strategy: shrink the marginalized definition, exclude the most marginal.

REVOLUTIONARY: Oppositional collective identity, independent power.

The contradiction is material, not a misunderstanding.

LIBERAL = 'liberal'
FASCIST = 'fascist'
REVOLUTIONARY = 'revolutionary'
babylon.models.CommunityConsciousness

alias of TernaryConsciousness

class babylon.models.ContradictionType(*values)[source]

Bases: StrEnum

Main axes of structural contradiction (Constitutional Framework).

Moving away from hardcoded models towards a dynamic Maoist contradiction framework. Defines the principal and secondary axes at a given scale.

NATIONAL = 'national'
CLASS = 'class'
GENDER = 'gender'
IMPERIAL = 'imperial'
ECOLOGICAL = 'ecological'
class babylon.models.TernaryConsciousness(**data)[source]

Bases: BaseModel

A point in the 2-simplex representing community consciousness.

Three components (r, l, f) sum to 1.0: - r: Revolutionary consciousness (distance from assimilation). - l: Liberal consciousness (reform within existing order). - f: Fascist consciousness (exclusionary reaction).

Supports two construction paths: 1. Native: TernaryConsciousness(r=0.5, l=0.3, f=0.2) 2. Legacy: ``TernaryConsciousness(collective_identity=0.5,

dominant_tendency=LIBERAL, ideological_contestation=0.4)``

Both produce valid simplex points with backward-compatible properties.

Parameters:
  • r (Annotated[float, Ge(ge=0.0), Le(le=1.0), AfterValidator(func=~babylon.utils.math.quantize)]) – Revolutionary component [0, 1].

  • l (Annotated[float, Ge(ge=0.0), Le(le=1.0), AfterValidator(func=~babylon.utils.math.quantize)]) – Liberal component [0, 1].

  • f (Annotated[float, Ge(ge=0.0), Le(le=1.0), AfterValidator(func=~babylon.utils.math.quantize)]) – Fascist component [0, 1].

  • contestation_stored (float | None) – Preserved legacy contestation value, or None for natively constructed instances (uses Shannon entropy).

property assimilation_ratio: float

f / (l + f).

Measures how much of the non-revolutionary consciousness is fascist. When l + f is near zero (fully revolutionary), returns 0.5 (neutral).

Returns:

Ratio in [0, 1]. 0 = pure liberal, 1 = pure fascist.

Type:

Position along the liberal-fascist base

property collective_identity: float

Oppositional consciousness [0, 1]. Equals r component.

Returns:

The revolutionary component, semantically identical to the old CommunityConsciousness.collective_identity.

property dominant_tendency: ConsciousnessTendency

Prevailing ideological direction (argmax of r, l, f).

Ties are broken in favor of liberal (structural advantage of the status quo — you have to actively organize to leave liberalism).

Returns:

ConsciousnessTendency corresponding to the largest component.

property ideological_contestation: float

Active debate between tendencies [0, 1].

If contestation_stored is set (legacy construction), returns that value for backward compatibility. Otherwise computes normalized Shannon entropy of (r, l, f): H(r,l,f) / log(3).

Returns:

Contestation level. 0 = monopoly, 1 = maximum contestation.

model_config: ClassVar[ConfigDict] = {'frozen': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

r: Probability
l: Probability
f: Probability
contestation_stored: float | None
class babylon.models.SubstrateFloor(**data)[source]

Bases: BaseModel

Per-community-type minimum revolutionary consciousness with provenance.

The substrate floor is consciousness that persists even when all organizations are destroyed — the grandmother teaching not to talk to cops, survival knowledge transmitted through socialization.

Parameters:
  • community_type (CommunityType) – Which community this floor applies to.

  • floor_value (Annotated[float, Ge(ge=0.0), Le(le=1.0), AfterValidator(func=~babylon.utils.math.quantize)]) – Minimum r regardless of org landscape [0, 1].

  • confidence (ProvenanceLevel) – Data quality indicator.

  • data_sources (list[str]) – Named data sources used.

  • computation_method (str) – How floor was derived from proxies.

model_config: ClassVar[ConfigDict] = {'frozen': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

community_type: CommunityType
floor_value: Probability
confidence: ProvenanceLevel
data_sources: list[str]
computation_method: str
class babylon.models.ProvenanceLevel(*values)[source]

Bases: StrEnum

Data quality indicator for substrate floor computation.

Values:

HIGH: Derived from 2+ independent proxy data sources. MEDIUM: Derived from 1 proxy data source. LOW: Estimated from related data, not direct proxy. SYNTHETIC: Stipulated placeholder with no data path.

HIGH = 'high'
MEDIUM = 'medium'
LOW = 'low'
SYNTHETIC = 'synthetic'
class babylon.models.OrgContribution(**data)[source]

Bases: BaseModel

An organization’s weighted contribution to community consciousness.

Used as input to the compute_ternary_consciousness function.

Parameters:
  • tendency (ConsciousnessTendency) – Which vertex this org pulls toward.

  • membership_density (Annotated[float, Ge(ge=0.0), Le(le=1.0), AfterValidator(func=~babylon.utils.math.quantize)]) – Members in community / community population [0, 1].

  • cadre_level (Annotated[float, Ge(ge=0.0), Le(le=1.0), AfterValidator(func=~babylon.utils.math.quantize)]) – Organizational development level [0, 1].

  • cohesion (Annotated[float, Ge(ge=0.0), Le(le=1.0), AfterValidator(func=~babylon.utils.math.quantize)]) – Internal organizational cohesion [0, 1].

model_config: ClassVar[ConfigDict] = {'frozen': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

tendency: ConsciousnessTendency
membership_density: Probability
cadre_level: Probability
cohesion: Probability

Types

Constrained value types for the Babylon simulation.

These Annotated type aliases provide runtime validation for numeric values. Using Pydantic v2’s Annotated pattern allows these types to be used directly in any BaseModel field.

Types defined:

Probability: [0.0, 1.0] - for P(S|A), P(S|R), tension Ideology: [-1.0, 1.0] - revolutionary to reactionary spectrum Currency: [0.0, inf) - wealth, wages, rent, GDP Intensity: [0.0, 1.0] - contradiction intensity Coefficient: [0.0, 1.0] - formula parameters (alpha, lambda, k) Ratio: (0.0, inf) - wage ratios, exchange ratios EntityProtocol: Protocol for entities with lifecycle state (Sprint 1.X D2)

Usage:

from babylon.models.types import Probability, Currency

class SurvivalState(BaseModel):

p_acquiescence: Probability # Automatically validated [0, 1] wealth: Currency # Automatically validated [0, inf)

All types serialize to plain floats in JSON for compatibility with the Ledger (SQLite) and NetworkX graph storage.

Epoch 0 Physics Hardening (Gatekeeper Pattern):

All constrained types apply SnapToGrid quantization via AfterValidator. Values are snapped to a 10^-5 grid (0.00001 resolution) to prevent floating-point drift accumulation over long simulations.

babylon.models.types.Probability

[0.0, 1.0]

A probability represents the likelihood of an event occurring. Used for: - P(S|A): Probability of survival through acquiescence - P(S|R): Probability of survival through revolution - tension: Contradiction tension level

Boundary values: - 0.0 = impossible event - 1.0 = certain event

Note: Values are quantized to 10^-5 precision via SnapToGrid.

Type:

Probability

alias of Annotated[float, FieldInfo(annotation=NoneType, required=True, description=’Value in range [0.0, 1.0] representing likelihood’, metadata=[Ge(ge=0.0), Le(le=1.0)]), AfterValidator(func=quantize)]

babylon.models.types.Ideology

[-1.0, 1.0]

A class’s ideological position on the revolutionary-reactionary spectrum. Based on consciousness drift formula: dPsi_c/dt = k(1 - Wc/Vc) - lambda*Psi_c

Boundary values: - -1.0 = fully revolutionary (class conscious, anti-capitalist) - +1.0 = fully reactionary (false consciousness, pro-status-quo) - 0.0 = neutral/apolitical

Note: Values are quantized to 10^-5 precision via SnapToGrid.

Type:

Ideology

alias of Annotated[float, FieldInfo(annotation=NoneType, required=True, description=’Ideological position from revolutionary (-1) to reactionary (+1)’, metadata=[Ge(ge=-1.0), Le(le=1.0)]), AfterValidator(func=quantize)]

babylon.models.types.Currency

[0.0, inf)

Economic value that cannot be negative. Used for: - wealth: Accumulated resources - wages: Payment for labor - rent: Imperial rent (Phi) - GDP: Aggregate output

Note: Debt is not modeled as negative currency but as a separate relationship/obligation between entities.

Note: Values are quantized to 10^-5 precision via SnapToGrid.

Type:

Currency

alias of Annotated[float, FieldInfo(annotation=NoneType, required=True, description=’Non-negative economic value (wealth, wages, rent, GDP)’, metadata=[Ge(ge=0.0)]), AfterValidator(func=quantize)]

babylon.models.types.Intensity

[0.0, 1.0]

The intensity of a dialectical contradiction. When intensity reaches 1.0, the contradiction triggers a phase transition (synthesis, rupture, or suppression).

Boundary values: - 0.0 = dormant (contradiction exists but not manifest) - 1.0 = rupture threshold (phase transition imminent)

Note: Values are quantized to 10^-5 precision via SnapToGrid.

Type:

Intensity

alias of Annotated[float, FieldInfo(annotation=NoneType, required=True, description=’Contradiction intensity from dormant (0) to rupture (1)’, metadata=[Ge(ge=0.0), Le(le=1.0)]), AfterValidator(func=quantize)]

babylon.models.types.Coefficient

[0.0, 1.0]

A parameter that modifies the strength of an effect in formulas. Used for: - alpha: Extraction efficiency in imperial rent - lambda: Decay rate in consciousness drift - k: Sensitivity coefficient in survival calculus

Boundary values: - 0.0 = no effect - 1.0 = maximum effect

Note: Values are quantized to 10^-5 precision via SnapToGrid.

Type:

Coefficient

alias of Annotated[float, FieldInfo(annotation=NoneType, required=True, description=’Formula parameter in range [0, 1]’, metadata=[Ge(ge=0.0), Le(le=1.0)]), AfterValidator(func=quantize)]

babylon.models.types.Ratio

(0.0, inf)

A ratio comparing two quantities. Zero is invalid because ratios typically represent division results.

Used for: - Wc/Vc: Labor aristocracy ratio (wages to value produced) - epsilon: Exchange ratio in unequal exchange

Interpretation: - Ratio = 1.0: Equal exchange / fair wages - Ratio > 1.0: Core receives more than it gives (exploitation) - Ratio < 1.0: Core receives less than it gives

Note: Values are quantized to 10^-5 precision via SnapToGrid.

Type:

Ratio

alias of Annotated[float, FieldInfo(annotation=NoneType, required=True, description=’Positive ratio comparing two quantities’, metadata=[Gt(gt=0.0)]), AfterValidator(func=quantize)]

babylon.models.types.LaborHours

[0.0, inf)

Labor-time measurement in hours. Used for the fundamental tensor primitive where all economic values are expressed in labor-time, not monetary units.

Used for: - Primitive tensor cells (c, v, s components) - Aggregated labor-time values - SNLT-converted wage data

The distinction from Currency is semantic: Currency represents monetary value, LaborHours represents socially necessary labor time (SNLT).

Note: Values are quantized to 10^-6 precision via SnapToGrid.

Type:

LaborHours

alias of Annotated[float, FieldInfo(annotation=NoneType, required=True, description=’Non-negative labor-time measurement in hours’, metadata=[Ge(ge=0.0)]), AfterValidator(func=quantize)]

babylon.models.types.SignedLaborHours

(-inf, +inf)

Labor-time measurement that can be negative. Used for derived tensors where negative values have economic meaning.

Used for: - Imperial rent (Φ): Positive = core (receiving rent), Negative = periphery (donating rent) - Net value flows between territories - Derived economic calculations

Unlike LaborHours, this type permits negative values because: - Negative imperial rent indicates periphery status (donating more value than receiving) - Net flows can be negative (outflow > inflow)

Note: Values are quantized to 10^-6 precision via SnapToGrid.

Type:

SignedLaborHours

alias of Annotated[float, FieldInfo(annotation=NoneType, required=True, description=’Labor-time measurement allowing negative values’), AfterValidator(func=quantize)]

babylon.models.types.Gini

[0.0, 1.0]

Intra-class inequality coefficient (Mass Line Refactor). Determines what fraction of wealth the marginal worker (bottom 40%) receives.

Used for: - inequality: Intra-class wealth distribution within a demographic block

Boundary values: - 0.0 = Perfect equality (mean = median, everyone gets equal share) - 1.0 = Maximum tyranny (Pareto extreme: bottom majority has nothing)

The Grinding Attrition Formula uses this to calculate marginal wealth:

marginal_wealth = per_capita_wealth × (1 - gini)

At gini=0: marginal_wealth = average (all survive if average suffices) At gini=1: marginal_wealth = 0 (marginal workers always starve)

Note: Values are quantized to 10^-5 precision via SnapToGrid.

Type:

Gini

alias of Annotated[float, FieldInfo(annotation=NoneType, required=True, description=’Gini coefficient measuring intra-class inequality’, metadata=[Ge(ge=0.0), Le(le=1.0)]), AfterValidator(func=quantize)]

class babylon.models.types.EntityProtocol(*args, **kwargs)[source]

Bases: Protocol

Protocol for entities with lifecycle state.

Any object implementing this protocol can be checked for death using is_dead() or similar lifecycle functions. This prevents type errors where floats, dicts, or other non-entity types are accidentally passed to lifecycle functions.

Implementors:
  • SocialClass: Has active field (True = alive, False = dead)

Sprint 1.X D2 Pain Point #3: Loose typing allowed bugs like is_dead(float) instead of is_dead(Entity).

Example

>>> from babylon.models.types import EntityProtocol
>>> from babylon.models import SocialClass
>>>
>>> worker = SocialClass(id="C001", name="Worker", ...)
>>> isinstance(worker, EntityProtocol)  # True
>>> is_dead(worker)  # Works
>>>
>>> is_dead(0.5)  # TypeError: expected EntityProtocol
__init__(*args, **kwargs)
property active: bool

Whether the entity is alive/active.

Returns:

True if the entity is alive, False if dead.

World State

WorldState model for the Babylon simulation.

WorldState is an immutable snapshot of the entire simulation at a specific tick. It encapsulates: - All entities (social classes) as nodes - All territories (strategic sectors) as nodes - All relationships (value flows, tensions) as edges - A tick counter for temporal tracking - An event log for narrative/debugging

The state is designed for functional transformation:

new_state = step(old_state, config)

Sprint 4: Phase 2 game loop state container with NetworkX integration. Sprint 3.5.3: Territory integration for Layer 0.

class babylon.models.world_state.WorldState(**data)[source]

Bases: BaseModel

Immutable snapshot of the simulation at a specific tick.

WorldState follows the Data/Logic separation principle: - State holds WHAT exists (pure data) - Engine determines HOW it transforms (pure logic)

This enables: - Determinism: Same state + same engine = same output - Replayability: Save initial state, replay entire history - Counterfactuals: Modify a parameter, run forward, compare - Testability: Feed state in, assert on state out

Parameters:
tick

Current turn number (0-indexed)

entities

Map of entity ID to SocialClass (the nodes)

territories

Map of territory ID to Territory (Layer 0 nodes)

relationships

List of Relationship edges (the edges)

event_log

Recent events for narrative/debugging (string format)

events

Structured simulation events for analysis (Sprint 3.1)

economy

Global economic state for dynamic balance (Sprint 3.4.4)

model_config: ClassVar[ConfigDict] = {'frozen': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

tick: int
entities: dict[str, SocialClass]
territories: dict[str, Territory]
relationships: list[Relationship]
event_log: list[str]
events: list[SimulationEvent]
economy: GlobalEconomy
state_finances: dict[str, StateFinance]
contradiction_frames: dict[str, ContradictionFrame]
organizations: dict[str, OrganizationType]
key_figures: dict[str, KeyFigure]
institutions: dict[str, Institution]
institution_relations: list[InstitutionOrgRelation]
industries: dict[str, IndustryHyperedge]
to_graph()[source]

Convert state to NetworkX DiGraph for formula application.

Nodes are entity/territory IDs with all fields as attributes. A _node_type marker distinguishes between node types: - _node_type=’social_class’ for SocialClass nodes - _node_type=’territory’ for Territory nodes

Edges are relationships with all Relationship fields as attributes.

Graph metadata (G.graph) contains: - economy: GlobalEconomy state (Sprint 3.4.4)

Returns:

NetworkX DiGraph with nodes and edges from this state.

Example:

G = state.to_graph()
for node_id, data in G.nodes(data=True):
    if data["_node_type"] == "social_class":
        data["wealth"] += 10  # Modify entity
new_state = WorldState.from_graph(G, tick=state.tick + 1)
classmethod from_graph(G, tick, event_log=None, events=None)[source]

Reconstruct WorldState from NetworkX DiGraph.

Parameters:
  • G – NetworkX DiGraph with node/edge data

  • tick – The tick number for the new state

  • event_log – Optional event log to preserve (backward compatibility)

  • events – Optional structured events to include (Sprint 3.1)

Returns:

New WorldState with entities, territories, and relationships from graph.

Return type:

WorldState

Example

G = state.to_graph() # … modify graph … new_state = WorldState.from_graph(G, tick=state.tick + 1)

add_entity(entity)[source]

Return new state with entity added.

Parameters:

entity (SocialClass) – SocialClass to add

Return type:

WorldState

Returns:

New WorldState with the entity included.

Example

new_state = state.add_entity(worker)

add_territory(territory)[source]

Return new state with territory added.

Parameters:

territory (Territory) – Territory to add (Layer 0 node)

Return type:

WorldState

Returns:

New WorldState with the territory included.

Example

new_state = state.add_territory(university_district)

add_relationship(relationship)[source]

Return new state with relationship added.

Parameters:

relationship (Relationship) – Relationship edge to add

Return type:

WorldState

Returns:

New WorldState with the relationship included.

Example

new_state = state.add_relationship(exploitation_edge)

add_event(event)[source]

Return new state with event appended to log.

Parameters:

event (str) – Event description string

Return type:

WorldState

Returns:

New WorldState with event in log.

Example

new_state = state.add_event(“Worker crossed poverty threshold”)

property total_biocapacity: Annotated[float, FieldInfo(annotation=NoneType, required=True, description='Non-negative economic value (wealth, wages, rent, GDP)', metadata=[Ge(ge=0.0)]), AfterValidator(func=quantize)]

Global sum of territory biocapacity.

property total_consumption: Annotated[float, FieldInfo(annotation=NoneType, required=True, description='Non-negative economic value (wealth, wages, rent, GDP)', metadata=[Ge(ge=0.0)]), AfterValidator(func=quantize)]

Global sum of consumption needs.

property overshoot_ratio: float

Global ecological overshoot ratio.

Configuration

Simulation configuration for the Babylon engine.

SimulationConfig holds all global coefficients and parameters used by the formulas in babylon.formulas. This model provides: - Type-safe validation of all parameters - Sensible defaults matching ai-docs/game-loop-architecture.yaml - Immutability during simulation runs - JSON serialization for save/load

Sprint 3: Phase 2 game loop configuration.

class babylon.models.config.SimulationConfig(**data)[source]

Bases: BaseModel

Global configuration for the simulation engine.

All formula coefficients and world parameters are stored here. The config is immutable (frozen) to ensure determinism during simulation runs.

Parameters:
extraction_efficiency

Alpha (α) in imperial rent formula. Controls how efficiently the core extracts value from periphery. Range: [0, 1], Default: 0.8

consciousness_sensitivity

k in consciousness drift formula. Controls how quickly consciousness responds to material conditions. Range: [0, 1], Default: 0.5

subsistence_threshold

Poverty line for acquiescence calculation. Below this wealth level, survival through compliance becomes impossible. Range: [0, inf), Default: 0.3

survival_steepness

Controls sigmoid sharpness in acquiescence probability. Higher values mean sharper transition around subsistence threshold. Range: (0, inf), Default: 10.0

repression_level

State capacity for violence. Reduces revolution probability in P(S|R) = cohesion / repression. Range: [0, 1], Default: 0.5

initial_worker_wealth

Starting wealth for periphery worker entities. Range: [0, inf), Default: 0.5

initial_owner_wealth

Starting wealth for core owner entities. Range: [0, inf), Default: 0.5

loss_aversion_lambda

Kahneman-Tversky loss aversion coefficient. Humans feel losses ~2.25x more strongly than equivalent gains. Range: (0, inf), Default: 2.25

model_config: ClassVar[ConfigDict] = {'frozen': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

extraction_efficiency: Annotated[float]
consciousness_sensitivity: Annotated[float]
consciousness_decay_lambda: Annotated[float]
subsistence_threshold: Annotated[float]
survival_steepness: Annotated[float]
repression_level: Annotated[float]
initial_worker_wealth: Annotated[float]
initial_owner_wealth: Annotated[float]
loss_aversion_lambda: Annotated[float]
tension_accumulation_rate: Annotated[float]
comprador_cut: Annotated[float]
super_wage_rate: Annotated[float]
subsidy_conversion_rate: Annotated[float]
subsidy_trigger_threshold: Annotated[float]
solidarity_activation_threshold: Annotated[float]
mass_awakening_threshold: Annotated[float]
heat_decay_rate: Annotated[float]
high_profile_heat_gain: Annotated[float]
eviction_heat_threshold: Annotated[float]
rent_spike_multiplier: Annotated[float]
displacement_rate: Annotated[float]
heat_spillover_rate: Annotated[float]
clarity_profile_coefficient: Annotated[float]
initial_rent_pool: Annotated[float]
pool_high_threshold: Annotated[float]
pool_low_threshold: Annotated[float]
pool_critical_threshold: Annotated[float]
min_wage_rate: Annotated[float]
max_wage_rate: Annotated[float]
superwage_ppp_impact: Annotated[float]
concentration_camp_decay_rate: Annotated[float]
displacement_priority_mode: DisplacementPriorityMode
elimination_rent_threshold: Annotated[float]
elimination_tension_threshold: Annotated[float]
containment_rent_threshold: Annotated[float]
containment_tension_threshold: Annotated[float]