Formulas
Mathematical formulas implementing MLM-TW theory.
Mathematical formulas for the Babylon simulation.
This module contains the pure mathematical functions that drive the dialectical mechanics of the simulation. These are deterministic functions with no side effects - the same inputs always produce the same outputs.
Key Formulas: 1. Fundamental Theorem of MLM-TW:
Imperial Rent: Phi(Wp, Psip) = alpha * Wp * (1 - Psip)
Labor Aristocracy: Wc/Vc > 1
Consciousness Drift: dPsic/dt = k(1 - Wc/Vc) - lambda*Psic
Survival Calculus: - Acquiescence: P(S|A) = 1 / (1 + e^(-k(x - x_critical))) - Revolution: P(S|R) = Cohesion / (Repression + epsilon) - Loss Aversion: lambda = 2.25
Unequal Exchange: - Exchange Ratio: epsilon = (Lp/Lc) * (Wc/Wp) - Prebisch-Singer Effect
- babylon.formulas.calculate_labor_aristocracy_ratio(core_wages, value_produced)[source]
Wc/Vc ratio. When > 1, worker receives more than produced.
- Parameters:
- Return type:
- Returns:
Labor aristocracy ratio.
- Raises:
ValueError – If value_produced <= 0.
Examples
>>> calculate_labor_aristocracy_ratio(120.0, 100.0) 1.2
- babylon.formulas.is_labor_aristocracy(core_wages, value_produced)[source]
True if Wc/Vc > 1 (receives more than produces).
- Parameters:
- Return type:
- Returns:
True if labor aristocracy.
- Raises:
ValueError – If value_produced <= 0.
Examples
>>> is_labor_aristocracy(120.0, 100.0) True >>> is_labor_aristocracy(80.0, 100.0) False
- babylon.formulas.calculate_consciousness_drift(core_wages, value_produced, current_consciousness, sensitivity_k, decay_lambda, solidarity_pressure=0.0, wage_change=0.0)[source]
dPsi/dt = k(1 - Wc/Vc) - lambda*Psi + bifurcation.
- Parameters:
core_wages (
float) – Wages received.value_produced (
float) – Value produced.current_consciousness (
float) – Current level [0, 1].sensitivity_k (
float) – Material conditions sensitivity.decay_lambda (
float) – Consciousness decay rate.solidarity_pressure (
float) – Incoming SOLIDARITY strength.wage_change (
float) – Wage delta (negative = crisis).
- Return type:
- Returns:
Consciousness drift rate (positive = revolutionary).
- Raises:
ValueError – If value_produced <= 0.
- babylon.formulas.calculate_acquiescence_probability(wealth, subsistence_threshold, steepness_k)[source]
P(S|A) sigmoid. At threshold, probability = 0.5.
- Parameters:
- Return type:
- Returns:
Survival probability via acquiescence, in [0, 1]. The sigmoid is mathematically bounded by construction.
Examples
>>> calculate_acquiescence_probability(100.0, 100.0, 0.1) 0.5
- babylon.formulas.calculate_revolution_probability(cohesion, repression)[source]
P(S|R) = Cohesion / (Repression + eps). Capped at 1.0.
- Parameters:
- Return type:
- Returns:
Survival probability via revolution, in [0, 1]. Bounded below by the early-return for non-positive cohesion and above by
min(1.0, ...).
Examples
>>> calculate_revolution_probability(0.8, 0.2) 1.0 >>> calculate_revolution_probability(0.0, 0.5) 0.0
- babylon.formulas.calculate_crossover_threshold(cohesion, repression, subsistence_threshold, steepness_k)[source]
Wealth level where P(S|R) = P(S|A) (revolution becomes rational).
- babylon.formulas.apply_loss_aversion(value)[source]
Amplify losses by 2.25x (Kahneman-Tversky).
- Parameters:
value (
float) – Raw value change (negative = loss).- Return type:
- Returns:
Perceived value (losses amplified).
Examples
>>> apply_loss_aversion(100.0) 100.0 >>> apply_loss_aversion(-100.0) -225.0
- babylon.formulas.calculate_exchange_ratio(periphery_labor_hours, core_labor_hours, core_wage, periphery_wage)[source]
Calculate exchange ratio: epsilon = (Lp/Lc) * (Wc/Wp).
The exchange ratio quantifies unequal exchange. When epsilon > 1, the periphery gives more value than it receives.
- Parameters:
- Return type:
- Returns:
Exchange ratio
- Raises:
ValueError – If any denominator value is zero or negative
Examples
>>> calculate_exchange_ratio(100.0, 100.0, 20.0, 5.0) # Equal labor, 4x wage gap 4.0 >>> calculate_exchange_ratio(200.0, 100.0, 20.0, 10.0) # 2x labor, 2x wage 4.0 >>> calculate_exchange_ratio(100.0, 100.0, 10.0, 10.0) # Fair exchange 1.0
- babylon.formulas.calculate_unequal_exchange_rate(exchange_ratio)[source]
Convert exchange ratio to exploitation rate percentage.
epsilon = 2 means 100% exploitation (double value extracted). epsilon = 1 means 0% exploitation (fair exchange).
- babylon.formulas.calculate_value_transfer(production_value, exchange_ratio)[source]
Calculate value transferred from periphery to core.
Value transfer = production * (1 - 1/epsilon)
- babylon.formulas.prebisch_singer_effect(initial_price, production_increase, elasticity)[source]
Calculate Prebisch-Singer effect on commodity prices.
Terms of trade decline for commodity exporters: More production -> lower prices -> same poverty.
- babylon.formulas.calculate_solidarity_transmission(source_consciousness, target_consciousness, solidarity_strength, activation_threshold=0.3)[source]
Calculate consciousness delta via solidarity edge.
- Parameters:
- Return type:
- Returns:
Change in target consciousness. Negative if target > source.
Examples
>>> round(calculate_solidarity_transmission(0.8, 0.2, 0.5), 2) 0.3 >>> calculate_solidarity_transmission(0.2, 0.5, 0.5) # Below threshold 0.0
- babylon.formulas.compute_agitation_delta(exploitation_rate_delta, imperial_rent_delta, visibility_delta, defines=None)[source]
Convert value tensor changes into agitation increment.
Agitation is generated by three sources of material crisis:
Rising exploitation rate (Δ(s/v) > 0): Workers produce more surplus relative to wages.
Declining imperial rent (ΔΦ < 0): Core workers losing their bribe from unequal exchange.
Increasing reproductive visibility (Δg₃₃ > 0): Previously invisible care work becoming monetized/contested.
Formula:
Δagitation = max(0, Δ(s/v)) × α_e + max(0, -ΔΦ) × α_r + max(0, Δg₃₃) × α_v- Parameters:
exploitation_rate_delta (
float) – Change in s/v since last tick.imperial_rent_delta (
float) – Change in Φ since last tick (negative = crisis).visibility_delta (
float) – Change in g₃₃ since last tick.defines (
ConsciousnessDefines|None) – Optional custom coefficients.
- Return type:
- Returns:
Non-negative agitation increment.
- babylon.formulas.compute_exploitation_visibility(exploitation_rate, imperial_rent, defines=None)[source]
Determine how visible exploitation is to a population.
Imperial rent acts as an opacity filter on exploitation: when workers receive a “bribe” via unequal exchange with the periphery, the exploitation that does exist becomes obscured by material comfort.
Formula:
visibility = s/v / (s/v + Φ × opacity + ε)
When Φ = 0 (periphery), visibility approaches 1.0 for high s/v. When Φ > 0 (core), visibility is dampened.
- Parameters:
exploitation_rate (
float) – Current s/v ratio for this population.imperial_rent (
float) – Current Φ (positive = core, negative = periphery).defines (
ConsciousnessDefines|None) – Optional custom coefficients.
- Return type:
- Returns:
Exploitation visibility in [0, 1].
- babylon.formulas.compute_reification_buffer(imperial_rent, total_v)[source]
Measure commodity fetishism from imperial rent.
The reification buffer represents how much the commodity form obscures underlying class relations. Higher imperial rent means core workers experience class relations as “natural” rather than exploitative — the bribe makes the system appear to work.
Formula:
reification = |Φ| / (|Φ| + v + ε)
- babylon.formulas.route_agitation_to_ternary(agitation, solidarity_factor, education_pressure, defines=None)[source]
Route accumulated agitation into ternary consciousness shifts.
Agitation is consumed and routed to (Δr, Δl, Δf) based on:
Solidarity determines the revolutionary vs fascist split. With solidarity, agitation routes to r (class consciousness). Without solidarity, agitation routes to f (fascism).
Education pressure biases the split toward revolutionary. This is the mechanized effect of the EDUCATE verb.
Liberal drain absorbs a fraction as liberal drift.
Formula:
consumed = agitation × consumption_rate effective_solidarity = min(1.0, solidarity + education_pressure) Δr = consumed × effective_solidarity × routing_scale Δf = consumed × (1 - effective_solidarity) × routing_scale Δl = -(Δr + Δf) × liberal_backpressure
- Parameters:
agitation (
float) – Accumulated agitation on this node [0, ∞).solidarity_factor (
float) – Incoming SOLIDARITY edge strength [0, 1].education_pressure (
float) – Education pressure on community [0, 1].defines (
ConsciousnessDefines|None) – Optional custom coefficients.
- Return type:
- Returns:
Tuple of (Δr, Δl, Δf) — directional shifts in ternary space. Δl is typically negative (agitation drains liberal tendency).
- babylon.formulas.normalize_to_simplex(r, lib, f)[source]
Project (r, l, f) onto the probability simplex (r + l + f = 1).
The simplex constraint ensures consciousness is a valid probability distribution. Values below zero are clamped. If the sum is below 1, the remainder is assigned to liberal (hegemonic default). If above 1, values are scaled proportionally.
- class babylon.formulas.BourgeoisieDecision[source]
Bases:
objectEnumeration of bourgeoisie decision types.
Sprint 3.4.4: Dynamic Balance - The “Driver” decisions based on imperial rent pool level and aggregate class tension.
- NO_CHANGE = 'no_change'
- BRIBERY = 'bribery'
- AUSTERITY = 'austerity'
- IRON_FIST = 'iron_fist'
- CRISIS = 'crisis'
- babylon.formulas.calculate_bourgeoisie_decision(pool_ratio, aggregate_tension, high_threshold=0.7, low_threshold=0.3, critical_threshold=0.1, bribery_wage_delta=0.05, austerity_wage_delta=-0.05, iron_fist_repression_delta=0.10, crisis_wage_delta=-0.15, crisis_repression_delta=0.20, bribery_tension_threshold=0.3, iron_fist_tension_threshold=0.5)[source]
Calculate bourgeoisie policy decision based on pool level and tension.
Sprint 3.4.4: Dynamic Balance - The bourgeoisie as a rational actor responding to material conditions.
- Decision Matrix:
pool_ratio >= high AND tension < bribery_tension -> BRIBERY pool_ratio < critical -> CRISIS (emergency measures) pool_ratio < low AND tension > iron_fist_tension -> IRON_FIST pool_ratio < low AND tension <= iron_fist_tension -> AUSTERITY else -> NO_CHANGE (maintain status quo)
- Parameters:
pool_ratio (
float) – Current pool / initial pool (0.0 to 1.0+)aggregate_tension (
float) – Average tension across class relationships (0.0 to 1.0)high_threshold (
float) – Pool ratio above which prosperity is declared (default 0.7)low_threshold (
float) – Pool ratio below which austerity begins (default 0.3)critical_threshold (
float) – Pool ratio below which crisis fires (default 0.1)bribery_wage_delta (
float) – Wage increase during prosperity (default 0.05)austerity_wage_delta (
float) – Wage cut during austerity (default -0.05)iron_fist_repression_delta (
float) – Repression increase during iron fist (default 0.10)crisis_wage_delta (
float) – Emergency wage cut during crisis (default -0.15)crisis_repression_delta (
float) – Emergency repression spike (default 0.20)bribery_tension_threshold (
float) – Max tension for bribery policy (default 0.3)iron_fist_tension_threshold (
float) – Min tension for iron fist policy (default 0.5)
- Returns:
str, wage_delta: float, repression_delta: float) - decision: One of BourgeoisieDecision values - wage_delta: Change to wage rate (positive = increase) - repression_delta: Change to repression level (positive = increase)
- Return type:
Example
# Prosperity: high pool, low tension -> increase wages decision, wage_d, repr_d = calculate_bourgeoisie_decision(0.8, 0.2) # Returns (“bribery”, 0.05, 0.0)
# Crisis: pool below critical -> emergency measures decision, wage_d, repr_d = calculate_bourgeoisie_decision(0.05, 0.5) # Returns (“crisis”, -0.15, 0.20)
- babylon.formulas.calculate_biocapacity_delta(regeneration_rate, max_biocapacity, extraction_intensity, current_biocapacity, entropy_factor=1.2)[source]
Calculate change in biocapacity stock: dB = R - (E * eta).
The core metabolic formula. Extraction always costs more than the raw value obtained due to entropy/waste (eta > 1.0).
- Parameters:
regeneration_rate (
float) – Fraction of max_biocapacity restored per tick [0, 1]max_biocapacity (
float) – Maximum biocapacity ceilingextraction_intensity (
float) – Current extraction pressure [0, 1]current_biocapacity (
float) – Current biocapacity stockentropy_factor (
float) – Waste multiplier for extraction (default 1.2)
- Return type:
- Returns:
Change in biocapacity (positive = regeneration, negative = depletion)
Examples
>>> calculate_biocapacity_delta(0.02, 100.0, 0.0, 50.0) # No extraction 2.0 >>> calculate_biocapacity_delta(0.02, 100.0, 0.05, 50.0) # Light extraction -1.0 >>> calculate_biocapacity_delta(0.02, 100.0, 0.0, 100.0) # At max, no regen 0.0
- babylon.formulas.calculate_overshoot_ratio(total_consumption, total_biocapacity, max_ratio=999.0)[source]
Calculate ecological overshoot ratio: O = C / B.
When O > 1.0, consumption exceeds biocapacity (overshoot). When O <= 1.0, the system is within ecological limits.
- Parameters:
- Return type:
- Returns:
Overshoot ratio (>1.0 = ecological overshoot)
Examples
>>> calculate_overshoot_ratio(100.0, 200.0) # Sustainable 0.5 >>> calculate_overshoot_ratio(200.0, 100.0) # Overshoot 2.0 >>> calculate_overshoot_ratio(100.0, 0.0) # Depleted biocapacity 999.0
- babylon.formulas.calculate_rent_pool_decay(current_pool, decay_rate)[source]
Apply TRPF rent pool decay (background evaporation).
Models the tendency of accumulated surplus to erode over time, representing the contradiction between the tendency to accumulate and the tendency of profit rates to fall.
- Parameters:
- Return type:
- Returns:
Decayed pool value (always >= 0)
Example
>>> calculate_rent_pool_decay(100.0, 0.002) 99.8 >>> calculate_rent_pool_decay(100.0, 0.0) 100.0
Note
At default decay 0.002: - After 52 ticks (1 year): ~90% remaining - After 520 ticks (10 years): ~35% remaining - After 1040 ticks (20 years): ~12% remaining
- babylon.formulas.calculate_trpf_multiplier(tick, trpf_coefficient, floor=0.1)[source]
Calculate TRPF efficiency multiplier (Epoch 1 Surrogate).
Models Marx’s Tendency of the Rate of Profit to Fall as a time-dependent decay of extraction efficiency. This is a surrogate for proper organic composition tracking.
The multiplier declines linearly from 1.0 at tick 0, representing how rising organic composition of capital reduces profit rates over time under capitalist accumulation.
- Parameters:
- Return type:
- Returns:
Multiplier in range [floor, 1.0]
Example
>>> calculate_trpf_multiplier(0, 0.0005) 1.0 >>> calculate_trpf_multiplier(1000, 0.0005) 0.5 >>> calculate_trpf_multiplier(2000, 0.0005) 0.1
Note
At default coefficient 0.0005: - tick 0: 100% efficiency - tick 520 (10 years): 74% efficiency - tick 1040 (20 years): 48% efficiency - tick 1800+: floors at 10% efficiency
Full OCC-based TRPF calculation planned for Epoch 2. See ai/epoch2-trpf.yaml for specification.
- Theoretical Basis:
Marx, Capital Vol. 3, Chapters 13-15: Rate of Profit p’ = s / (c + v) As OCC (c/v) rises, p’ falls even with constant exploitation rate (s/v).
- babylon.formulas.calculate_mortality_rate(wealth_per_capita, subsistence_needs, inequality, attrition_base_factor=_DEFINES.vitality.attrition_base_factor)[source]
Calculate mortality rate using coverage_ratio threshold.
The formula ensures that with high inequality (e.g., 0.8), you need almost 2x subsistence (1.8 coverage) to prevent deaths.
- Parameters:
- Return type:
- Returns:
Attrition rate [0, 1] representing fraction of population that dies.
- class babylon.formulas.ClassDynamicsParams(alpha_41=0.0, alpha_31=0.0, alpha_21=0.0006, alpha_32=0.0, alpha_42=0.0, alpha_43=0.0, delta_1=0.001, delta_2=0.002, delta_3=0.001, gamma_3=0.0057)[source]
Bases:
objectParameters for class wealth dynamics ODE system.
All rates are per-tick (convert from quarterly by dividing by ticks_per_quarter).
- Parameters:
- alpha_41
Extraction rate from proletariat to bourgeoisie.
- alpha_31
Extraction rate from labor aristocracy to bourgeoisie.
- alpha_21
Extraction rate from petty bourgeoisie to bourgeoisie.
- alpha_32
Rent-seeking from labor aristocracy to petty bourgeoisie.
- alpha_42
Extraction from proletariat to petty bourgeoisie.
- alpha_43
Extraction from proletariat to labor aristocracy.
- delta_1
Redistribution rate from bourgeoisie (taxation).
- delta_2
Redistribution rate from petty bourgeoisie.
- delta_3
Redistribution rate from labor aristocracy.
- gamma_3
Imperial rent formation rate (superwages).
Examples
>>> params = ClassDynamicsParams() >>> params.gamma_3 0.0057
- alpha_41: float = 0.0
- alpha_31: float = 0.0
- alpha_21: float = 0.0006
- alpha_32: float = 0.0
- alpha_42: float = 0.0
- alpha_43: float = 0.0
- delta_1: float = 0.001
- delta_2: float = 0.002
- delta_3: float = 0.001
- gamma_3: float = 0.0057
- __init__(alpha_41=0.0, alpha_31=0.0, alpha_21=0.0006, alpha_32=0.0, alpha_42=0.0, alpha_43=0.0, delta_1=0.001, delta_2=0.002, delta_3=0.001, gamma_3=0.0057)
- class babylon.formulas.SecondOrderParams(beta=(-0.1, -0.15, -0.1, -0.05), omega=(0.05, 0.08, 0.05, 0.03), equilibrium=(0.305, 0.382, 0.294, 0.02))[source]
Bases:
objectSecond-order dynamics parameters for momentum effects.
- Parameters:
- beta
Damping coefficients (negative = mean-reverting).
- omega
Natural frequencies of oscillation.
- equilibrium
Attractor wealth shares (W*).
Examples
>>> params = SecondOrderParams() >>> params.equilibrium (0.305, 0.382, 0.294, 0.02)
- babylon.formulas.calculate_class_dynamics_derivative(wealth_shares, params=None, resistances=(0.0, 0.0, 0.0, 0.0))[source]
Compute dW/dt for all four classes (first-order system).
- Implements:
dW₁/dt = α₄₁W₄ + α₃₁W₃ + α₂₁W₂ - δ₁W₁ dW₂/dt = α₃₂W₃ + α₄₂W₄ - α₂₁W₂ - δ₂W₂ dW₃/dt = α₄₃W₄ + γ₃ - α₃₁W₃ - α₃₂W₃ - δ₃W₃ dW₄/dt = -(dW₁ + dW₂ + dW₃)
- Parameters:
- Return type:
- Returns:
(dW₁/dt, dW₂/dt, dW₃/dt, dW₄/dt) derivatives.
Examples
>>> shares = (0.30, 0.36, 0.30, 0.04) >>> dW = calculate_class_dynamics_derivative(shares) >>> abs(sum(dW)) < 1e-10 # Sum constraint True
- babylon.formulas.calculate_equilibrium_deviation(wealth_shares, equilibrium=None)[source]
Calculate total deviation from equilibrium wealth distribution.
Useful for detecting when the system is far from steady state.
- Parameters:
- Return type:
- Returns:
Sum of squared deviations from equilibrium.
Examples
>>> result = calculate_equilibrium_deviation((0.30, 0.38, 0.29, 0.03)) >>> 0.0001 < result < 0.0003 True
- babylon.formulas.calculate_full_dynamics(wealth_shares, velocities, params=None, second_order=None, resistances=(0.0, 0.0, 0.0, 0.0))[source]
Compute both first and second order derivatives.
Combines first-order wealth flows with second-order momentum dynamics.
- Parameters:
wealth_shares (
tuple[float,float,float,float]) – (W₁, W₂, W₃, W₄) current wealth shares.velocities (
tuple[float,float,float,float]) – (dW₁/dt, dW₂/dt, dW₃/dt, dW₄/dt) current velocities.params (
ClassDynamicsParams|None) – First-order ODE parameters.second_order (
SecondOrderParams|None) – Second-order parameters.resistances (
tuple[float,float,float,float]) – Class consciousness levels.
- Return type:
tuple[tuple[float,float,float,float],tuple[float,float,float,float]]- Returns:
Tuple of (first_derivatives, second_derivatives).
Examples
>>> shares = (0.305, 0.382, 0.294, 0.020) >>> vels = (0.0, -0.001, 0.0006, 0.0004) >>> dW, d2W = calculate_full_dynamics(shares, vels)
- babylon.formulas.calculate_wealth_acceleration(wealth_share, velocity, equilibrium, damping=-0.1, frequency=0.05)[source]
Compute d²W/dt² for second-order dynamics.
- Models momentum effects and oscillation around equilibrium:
d²W/dt² = β(dW/dt) - ω²(W - W*)
- Parameters:
- Return type:
- Returns:
Second derivative d²W/dt².
Examples
>>> result = calculate_wealth_acceleration(0.32, 0.001, 0.30, -0.1, 0.05) >>> round(result, 10) -0.00015
- babylon.formulas.calculate_wealth_flow(source_share, extraction_rate, resistance=0.0)[source]
Calculate per-tick wealth flow from source class.
- Parameters:
- Return type:
- Returns:
Wealth delta flowing out of source class.
Examples
>>> calculate_wealth_flow(0.5, 0.01, 0.0) 0.005 >>> calculate_wealth_flow(0.5, 0.01, 0.5) # 50% resistance 0.0025
- babylon.formulas.invert_wealth_to_population(wealth_shares, target_wealth_pct=33.333)[source]
Find population percentile owning target wealth percentage.
Inverts the wealth distribution to find what fraction of the population owns a given fraction of total wealth. Uses linear interpolation.
- Parameters:
- Return type:
- Returns:
Population percentile owning up to target_wealth_pct of wealth.
Examples
>>> shares = (30.7, 36.4, 30.3, 2.5) >>> result = invert_wealth_to_population(shares, 33.333) >>> 90.0 < result < 91.0 True
- babylon.formulas.compute_ollivier_ricci(graph, u, v, alpha=0.5, weight_attr=None)[source]
Compute Ollivier-Ricci curvature for a single edge (u, v).
- Parameters:
graph (
BabylonUGraph) – Undirected or directed NetworkX graph.u (
str) – Source node.v (
str) – Target node.alpha (
float) – Self-loop probability weight in [0, 1]. Higher alpha = more weight on the node itself.weight_attr (
str|None) – Optional edge attribute name for weights. When set, probability measures distribute (1-alpha) proportional to edge weights instead of uniformly, and shortest path uses weighted distances. None = unweighted (backward compatible).
- Return type:
- Returns:
Curvature kappa(u,v) = 1 - W1(mu_u, mu_v) / d(u,v). Positive = well-connected, negative = bottleneck.
- Raises:
ValueError – If u or v is not in the graph or they are not connected.
- babylon.formulas.calculate_contradiction_intensity(divergence, centrality_a, centrality_b, sensitivity=1.0)[source]
Calculate the emergent intensity of a contradiction edge.
Deprecated since version spec-lawverian-C1: Superseded by
calculate_wealth_asymmetry_gap(). This function fed a raw dollar-scaledivergenceinto a[0, 1]clamp, which saturated to1.0on any real wealth gap and carried no information (the four-inertness-bugs “Formula” defect). Retained for the deprecation window; no production caller remains after Phase C.Combines raw dialectical divergence (e.g. wealth gap, ideological distance) with the topological importance of the entities involved, scaling the divergence magnitude by their hypergraph centrality or degree.
- Formula:
intensity = divergence * (1 + sqrt(Centrality_a * Centrality_b)) * sensitivity Bound to [0.0, 1.0]
- Parameters:
divergence (
float) – Raw difference between node states (typically [0, 1]).centrality_a (
float) – Network/Hypergraph centrality of node A (typically [0, 1]).centrality_b (
float) – Network/Hypergraph centrality of node B (typically [0, 1]).sensitivity (
float) – System or definition-level scaling factor.
- Return type:
- Returns:
Intensity scalar bounded [0.0, 1.0].
Example
>>> calculate_contradiction_intensity(0.5, 0.8, 0.2, 1.0) 0.7...
- babylon.formulas.calculate_wealth_asymmetry_balance(wealth_a, wealth_b, epsilon=1e-9)[source]
Signed dominance of pole B over pole A, in
[-1, 1].The signed counterpart of
calculate_wealth_asymmetry_gap(): \((W_b - W_a) / (W_a + W_b)\), clamped to[-1, 1]. Positive means pole B (by convention the richer/target side) dominates; negative means pole A dominates;0is parity. Its magnitude equals the gap. Like the gap it is exactly numeraire-invariant.- Parameters:
- Return type:
- Returns:
The signed balance in
[-1, 1];0.0when both poles are empty.
Example
>>> calculate_wealth_asymmetry_balance(10.0, 30.0) 0.5 >>> calculate_wealth_asymmetry_balance(30.0, 10.0) -0.5
See also
calculate_wealth_asymmetry_gap(): the unsigned magnitude.
- babylon.formulas.calculate_wealth_asymmetry_gap(wealth_a, wealth_b, epsilon=1e-9)[source]
Scale-free distance of a two-pole wealth relation from closure.
The gap is the normalized absolute difference of the two poles’ wealth, \(|W_b - W_a| / (W_a + W_b)\), clamped to
[0, 1]:0when the poles are at parity (the contradiction is resolved), approaching1as one pole holds all the wealth. Dividing by the pole sum makes it a pure number — multiplying both wealths by anyk > 0(a change of monetary numeraire) leaves it unchanged.epsilonguards ONLY the degenerate all-zero case (both poles empty); it is deliberately NOT added into the ratio, so the measure stays exactly numeraire-invariant rather than invariant-up-to-epsilon (this is the difference that lets the property test hold to 1e-12).- Parameters:
- Return type:
- Returns:
The asymmetry gap in
[0, 1];0.0when both poles are empty.
Example
>>> calculate_wealth_asymmetry_gap(10.0, 30.0) 0.5 >>> calculate_wealth_asymmetry_gap(0.0, 0.0) 0.0 >>> round(calculate_wealth_asymmetry_gap(1.0, 3.0), 6) == round( ... calculate_wealth_asymmetry_gap(1000.0, 3000.0), 6) True
See also
calculate_wealth_asymmetry_balance(): the signed counterpart.
- babylon.formulas.compute_ternary_consciousness(community_type, org_landscape, substrate_floor=0.0)[source]
Compute ternary consciousness from organizational landscape.
Algorithm: 1. Sum weighted contributions per tendency.
Weight w_i = membership_density * cadre_level * cohesion.
Unorganized fraction = max(0, 1 - sum(membership_densities)). Defaults to liberal (Jackson: passive acceptance is liberal hegemony).
Normalize to simplex (r + l + f = 1.0).
Apply substrate floor post-normalization: if r < floor, set r = floor and redistribute remaining (1-floor) to l and f proportionally.
- Parameters:
community_type (
CommunityType) – Which community this is for (used for logging).org_landscape (
list[OrgContribution]) – Organizations operating in the community.substrate_floor (
float) – Minimum r regardless of org landscape [0, 1].
- Return type:
- Returns:
TernaryConsciousness with r, l, f derived from org landscape. contestation_stored is None (uses Shannon entropy).
- babylon.formulas.calculate_solidarity_potential(base_solidarity, shared_count, rent_a, rent_b, overlap_bonus=0.1, rent_penalty=0.05)[source]
Compute solidarity potential between two agents from community overlap.
Shared community membership creates conditions for solidarity formation, penalized by imperial rent differential (material divergence impedes solidarity even with shared identity).
- Parameters:
base_solidarity (
float) – Base class solidarity between the two agents.shared_count (
int) – Number of communities both agents share.rent_a (
float) – Imperial rent received by agent A.rent_b (
float) – Imperial rent received by agent B.overlap_bonus (
float) – Bonus per shared community membership.rent_penalty (
float) – Penalty per unit of rent differential.
- Return type:
- Returns:
Solidarity potential score (may be negative if rent gap dominates).
Examples
>>> calculate_solidarity_potential(0.3, 2, 0.0, 0.0) 0.5 >>> calculate_solidarity_potential(0.3, 0, 0.0, 0.0) 0.3
- babylon.formulas.calculate_threat_score(memberships)[source]
Compute per-agent threat score from community memberships.
Each membership contributes: heat * effective_visibility * role_weight * legal_status_multiplier. The total is the sum across all memberships.
- Parameters:
memberships (
list[tuple[float,float,float,float]]) – List of (heat, effective_visibility, role_weight, legal_status_multiplier) tuples, one per community membership.- Return type:
- Returns:
Cumulative threat score for the agent.
Examples
>>> round(calculate_threat_score([(0.4, 0.8, 1.0, 1.0)]), 6) 0.32
- babylon.formulas.calculate_infrastructure_decay(current, decay_alpha, core_organizer_count, maintenance_factor=0.1)[source]
Compute new infrastructure after one tick of decay.
Infrastructure decays toward zero without maintenance. CORE_ORGANIZER members counteract decay proportionally.
Formula: new = current * (1 - alpha) + maintenance * alpha where maintenance = min(core_organizer_count * maintenance_factor, 1.0)
- Parameters:
- Return type:
- Returns:
New infrastructure level after decay and maintenance, clamped to [0, 1].
Examples
>>> round(calculate_infrastructure_decay(0.5, 0.04, 0), 4) 0.48 >>> round(calculate_infrastructure_decay(0.5, 0.04, 2, 0.1), 4) 0.488
- babylon.formulas.calculate_solidarity_amplification(base_strength, shared_communities)[source]
Amplify solidarity_strength based on shared community infrastructure.
For each shared community, the amplification is scaled by the community’s infrastructure, cohesion, and both agents’ membership strengths.
Formula: amplified = base * (1 + sum(infra * cohesion * str_a * str_b))
- Parameters:
- Return type:
- Returns:
Amplified solidarity strength.
Examples
>>> calculate_solidarity_amplification(0.5, []) 0.5 >>> round(calculate_solidarity_amplification(0.5, [(0.8, 0.6, 0.7, 0.4)]), 6) 0.5672
- babylon.formulas.compute_community_cost_modifier(memberships, community_states)[source]
Compute compound reproduction cost modifier from community memberships.
The modifier is the product of reproduction_cost_modifier across all communities the agent belongs to. No memberships → 1.0 (no effect).
- Parameters:
- Return type:
- Returns:
Multiplicative compound modifier (product of all community modifiers).
Examples
>>> compute_community_cost_modifier([], {}) 1.0
- babylon.formulas.compute_population_flow(*, pop_d, pop_p, pop_d_prime, birth_rate, rate_d_to_p, rate_p_to_d_prime, rate_d_prime_to_death)[source]
Compute one-tick population transitions across D/P/D’ phases.
Applies birth, transition, and death rates to compute new population in each phase. All outputs are clamped to non-negative.
- Parameters:
pop_d (
float) – Current D phase population.pop_p (
float) – Current P phase population.pop_d_prime (
float) – Current D’ phase population.birth_rate (
float) – Births per P-phase person per tick.rate_d_to_p (
float) – D → P transition rate per tick.rate_p_to_d_prime (
float) – P → D’ transition rate per tick.rate_d_prime_to_death (
float) – D’ mortality rate per tick.
- Return type:
- Returns:
Tuple of (new_pop_d, new_pop_p, new_pop_d_prime, births, deaths).
Examples
>>> result = compute_population_flow( ... pop_d=2150, pop_p=6050, pop_d_prime=1800, ... birth_rate=0.0107, rate_d_to_p=0.0556, ... rate_p_to_d_prime=0.0213, rate_d_prime_to_death=0.039, ... ) >>> abs(result[3] - 64.735) < 1 # births ≈ 64.7 True
- babylon.formulas.compute_dependency_ratio(*, pop_d, pop_p, pop_d_prime)[source]
Compute dependency ratio: non-productive to productive population.
- Parameters:
- Return type:
- Returns:
(pop_d + pop_d_prime) / pop_p, or inf if pop_p is zero.
Examples
>>> compute_dependency_ratio(pop_d=2150, pop_p=6050, pop_d_prime=1800) 0.6528...
- babylon.formulas.compute_legitimation_index(*, pension_coverage, ss_replacement_rate, healthcare_security, home_ownership_rate, retirement_confidence, w_home, w_health, w_retire, w_pension, w_ss)[source]
Compute weighted legitimation index from five material components.
The index measures how credibly the D’ promise is underwritten. Weight ordering reflects political judgment about which conditions most credibly back the promise.
- Parameters:
pension_coverage (
float) – Fraction with pension access [0, 1].ss_replacement_rate (
float) – Social Security replacement ratio [0, 1].healthcare_security (
float) – Fraction with secure healthcare [0, 1].home_ownership_rate (
float) – Home ownership rate [0, 1].retirement_confidence (
float) – Subjective security assessment [0, 1].w_home (
float) – Weight for home ownership.w_health (
float) – Weight for healthcare security.w_retire (
float) – Weight for retirement confidence.w_pension (
float) – Weight for pension coverage.w_ss (
float) – Weight for SS replacement.
- Return type:
- Returns:
Legitimation index [0, 1].
Examples
>>> round(compute_legitimation_index( ... pension_coverage=0.73, ss_replacement_rate=0.43, ... healthcare_security=0.60, home_ownership_rate=0.66, ... retirement_confidence=0.50, ... w_home=0.35, w_health=0.30, w_retire=0.20, ... w_pension=0.10, w_ss=0.05, ... ), 6) 0.6055
- babylon.formulas.compute_pareto_gini(*, alpha)[source]
Compute Gini coefficient from Pareto shape parameter.
- For a Pareto distribution with shape α > 0.5:
Gini = 1 / (2α - 1)
- Parameters:
alpha (
float) – Pareto shape parameter (must be > 0.5).- Return type:
- Returns:
Gini coefficient [0, 1].
- Raises:
ValueError – If alpha <= 0.5 (Gini would be >= 1.0 or undefined).
Examples
>>> compute_pareto_gini(alpha=1.5) 0.5
- babylon.formulas.compute_ideology_transmission(*, caregiver_ideology, institutional_hegemony, caregiver_weight, institutional_weight)[source]
Compute ideology transmitted during D→P phase transition.
Blends caregiver (family) influence with institutional hegemony (schools, media, state) to determine P-phase entry ideology.
- Parameters:
- Return type:
- Returns:
Transmitted ideology value.
Examples
>>> round(compute_ideology_transmission( ... caregiver_ideology=0.3, institutional_hegemony=0.8, ... caregiver_weight=0.7, institutional_weight=0.3, ... ), 6) 0.45
- babylon.formulas.compute_shadow_subsidy(*, p_g2_labor_value, wage_paid_for_d_g2)[source]
Compute shadow subsidy from intergenerational labor reproduction.
The shadow subsidy is the difference between the value of labor-power produced (P_g2) and the wages paid to P_g1 for raising D_g2. This measures the unpaid reproductive labor externalized to households.
- Parameters:
- Return type:
- Returns:
Shadow subsidy (always >= 0).
Examples
>>> compute_shadow_subsidy(p_g2_labor_value=60000.0, wage_paid_for_d_g2=12000.0) 48000.0
- babylon.formulas.calculate_defection_probability(chauvinism, discipline)[source]
Probability an entitled org member defects under crisis.
P_defection = sigmoid(chauvinism − discipline). Chauvinism is the accumulated reactionary sentiment of a labor-aristocratic recruit; discipline is the organization’s counter-pressure. At parity the probability is 0.5.- Parameters:
- Return type:
- Returns:
Defection probability in [0, 1] (bounded by the sigmoid).
Example
>>> calculate_defection_probability(chauvinism=0.5, discipline=0.5) 0.5
- babylon.formulas.calculate_entitlement_effective(base_entitlement, threat, threat_gain=_REACT.entitlement_threat_gain)[source]
Effective entitlement under threat (a threatened stake reacts harder).
effective = clamp(base + threat_gain × threat × (1 − base), 0, 1). A stake under threat (loss of privilege) amplifies toward the ceiling; with no threat the effective value passes the base through unchanged.- Parameters:
- Return type:
- Returns:
Effective entitlement in [0, 1].
Example
>>> calculate_entitlement_effective(base_entitlement=0.8, threat=0.0) 0.8
- babylon.formulas.calculate_fascist_pull(agitation, entitlement, solidarity, epsilon=_REACT.solidarity_pull_epsilon)[source]
Fascist pull on an entitled stratum under crisis.
Fascist_Pull = Agitation × (Entitlement / (Solidarity + ε)).Crisis-gated: with zero agitation the pull is zero (hegemony holds — the Fundamental Theorem). Solidarity in the denominator suppresses the pull (I.4: solidarity across the colonial divide reroutes agitation to revolution). The
εguard both prevents division by zero and sets the maximal unsuppressed pull.- Parameters:
agitation (
float) – Raw crisis energy [0, ∞) from falling wages / rising exploitation (babylon.formulas.consciousness_routing).entitlement (
float) – The stratum’s stake in the imperial order [0, 1].solidarity (
float) – Incident solidarity strength [0, 1] — the cross-colonial bridge that dampens reaction.epsilon (
float) – Denominator guard (default from ReactionaryDefines).
- Return type:
- Returns:
The fascist pull (≥ 0). Compared against
ReactionaryDefines.fascist_pull_thresholdby the system.
Example
>>> calculate_fascist_pull(agitation=2.0, entitlement=0.8, solidarity=0.0, epsilon=0.1) 16.0 >>> calculate_fascist_pull(agitation=0.0, entitlement=0.8, solidarity=0.0) 0.0
- babylon.formulas.calculate_spontaneous_riot_risk(volatility, discipline)[source]
Undirected-disorder risk for the declassed lumpenproletariat.
riot_risk = volatility × (1 − discipline), clamped to [0, 1]. High volatility with low organizational discipline produces spontaneous, non-revolutionary disorder — the reactionary inverse of the organized, solidarity-building UPRISING (it destroys wealth but builds no solidarity).- Parameters:
- Return type:
- Returns:
Riot risk in [0, 1]. Compared against
ReactionaryDefines.spontaneous_riot_threshold.
Example
>>> calculate_spontaneous_riot_risk(volatility=0.8, discipline=0.0) 0.8 >>> calculate_spontaneous_riot_risk(volatility=0.8, discipline=1.0) 0.0
- babylon.formulas.calculate_metabolic_impact(policy, defines=None)[source]
Return the per-tick habitability change for a given
ExtractionPolicy(spec-070 FR-004).The default mapping is:
INTENSIFY →
-0.02CONTINUE →
-0.005CEASE →
+0.01
Override any of the three via
BalkanizationDefines(no magic numbers at the system layer, Constitution III.1).- Parameters:
policy (
ExtractionPolicy) – The Sovereign’s current extraction policy.defines (
BalkanizationDefines|None) – Optional override defines; uses canonical defaults when omitted.
- Return type:
- Returns:
Per-tick habitability change to apply along each CLAIMS edge.
- Raises:
ValueError – If
policyis not a recognizedExtractionPolicymember.
Example
>>> from babylon.models.enums import ExtractionPolicy >>> calculate_metabolic_impact(ExtractionPolicy.INTENSIFY) -0.02
- babylon.formulas.contiguous_influence_majority_subregion(graph, faction_id, sovereign_id, defines=None)[source]
Compute the largest contiguous H3-res-7 sub-region of a Sovereign’s territory where
faction_id’s INFLUENCES.influence_level exceedsBalkanizationDefines.secession_influence_threshold(spec-070 FR-029b).The result is a deterministic, lex-sorted frontier BFS over ADJACENCY-linked H3 res-7 hexes, restricted to hexes claimed by
sovereign_idand satisfying the influence predicate.- Parameters:
graph (
GraphProtocol) – GraphProtocol exposingquery_sovereign_claims(),query_adjacent_territories(), andquery_faction_influence_by_territory().faction_id (
str) – Candidate secessionist Faction ID.sovereign_id (
str) – Parent Sovereign whose territory is being analyzed.defines (
BalkanizationDefines|None) – Optional override defines.
- Return type:
- Returns:
Frozen set of Territory IDs comprising the largest contiguous sub-region. Returns the empty set if no eligible component is ≥
BalkanizationDefines.min_contiguous_hex_count.- Raises:
AttributeError – If
graphdoes not implement the required query methods.
- babylon.formulas.derive_default_multipliers_from_stance(stance, defines=None)[source]
Return the canonical 4-tuple of Faction mechanical multipliers (FR-007 + data-model.md §3.1) for a given
ColonialStance.Tuple order is:
(extraction_modifier, violence_modifier, class_reduction, metabolic_reduction)
The default mapping (overridable via
BalkanizationDefines):Stance
extraction
violence
class_red.
metab_red.
UPHOLD IGNORE ABOLISH
1.5 0.8 0.0
2.0 0.5 0.3
0.0 0.7 0.5
- -0.5
0.0
+0.8
- Parameters:
stance (
ColonialStance) – The Faction’s colonial stance.defines (
BalkanizationDefines|None) – Optional override defines; uses canonical defaults when omitted.
- Return type:
- Returns:
4-tuple of multipliers in the canonical order above.
- Raises:
KeyError – If
stanceis not a recognized ColonialStance member.
Example
>>> from babylon.models.enums import ColonialStance >>> derive_default_multipliers_from_stance(ColonialStance.UPHOLD) (1.5, 2.0, 0.0, -0.5)
- babylon.formulas.derive_extraction_policy_from_stance(stance)[source]
Derive the Sovereign’s
ExtractionPolicyfrom a Faction’sColonialStance(spec-070 FR-003).Mapping (data-model.md §3.2; deterministic):
UPHOLD → INTENSIFY
IGNORE → CONTINUE
ABOLISH → CEASE
- Parameters:
stance (
ColonialStance) – The ruling Faction’s colonial stance.- Return type:
- Returns:
Derived ExtractionPolicy.
- Raises:
KeyError – If
stanceis not a recognized ColonialStance member.
Example
>>> from babylon.models.enums import ColonialStance >>> derive_extraction_policy_from_stance(ColonialStance.UPHOLD) <ExtractionPolicy.INTENSIFY: 'intensify'>
- babylon.formulas.detect_red_settler_trap(faction_class_reduction, faction_colonial_stance, defines=None)[source]
Detect the Red Settler Trap diagnostic condition (spec-070 FR-034).
Fires when a Faction has both:
class_reduction >= red_settler_trap_class_reduction_threshold(default 0.6), ANDcolonial_stance ∈ {UPHOLD, IGNORE}
The combination represents a Faction successfully reducing class contradiction while leaving settler-colonial relations intact — the canonical RED_OGV (Occupied Garrison of the Volksgemeinschaft) trap.
- Parameters:
faction_class_reduction (
float) – Faction’s class_reduction multiplier.faction_colonial_stance (
ColonialStance) – Faction’s colonial_stance.defines (
BalkanizationDefines|None) – Optional override defines.
- Return type:
- Returns:
Trueiff the trap condition is satisfied.
Example
>>> from babylon.models.enums import ColonialStance >>> detect_red_settler_trap(0.7, ColonialStance.IGNORE) True >>> detect_red_settler_trap(0.7, ColonialStance.ABOLISH) False
- babylon.formulas.extrapolate_habitability(current_habitability, metabolic_impact, horizon_ticks)[source]
Linearly extrapolate a Territory’s habitability over a horizon (spec-070 FR-051, used by
SovereignProjection).Assumes constant policy (no Faction transitions during the horizon). Clamps to [0.0, 1.0].
- Parameters:
- Return type:
- Returns:
Projected habitability, clamped to
[0.0, 1.0].
Example
>>> round(extrapolate_habitability(0.8, -0.02, 10), 6) 0.6 >>> extrapolate_habitability(0.5, 0.01, 100) # would overshoot 1.0
- babylon.formulas.winning_faction_for_territory(graph, territory_id, incumbent_faction_id, rng)[source]
Determine the winning
BalkanizationFactionfor a Territory (spec-070 FR-021).Computes
argmax_f Σ INFLUENCES(f → territory).influence_levelwith a two-stage tiebreaker:If the incumbent ruling_faction is among the tied factions, the incumbent wins (stability preserved).
Otherwise, draw deterministically from
rngover the sorted-ID tied set.
- Parameters:
graph (
GraphProtocol) – GraphProtocol exposingquery_faction_influence_by_territory().territory_id (
str) – Target Territory node ID.incumbent_faction_id (
str|None) – ID of the Territory’s current ruling Faction, if any. May beNonefor unclaimed territory.rng (
Random) – Seededrandom.Randomused for deterministic tiebreaking when no incumbent participates.
- Return type:
- Returns:
The winning Faction ID, or
Noneif the Territory has zero incoming INFLUENCES.- Raises:
AttributeError – If
graphdoes not implementquery_faction_influence_by_territory().
Economic System
Economic systems: 5-phase Imperial Circuit with pool tracking.
See Simulation Systems Reference for full theory (PPP Model, Iron Lung, Decision Matrix).
- class babylon.engine.systems.economic.ImperialRentSystem[source]
Bases:
SystemBase5-phase Imperial Circuit: Extraction → Tribute → Wages → Subsidy → Decision.
ADR032: Subsistence burn moved to VitalitySystem (Phase 1: The Drain). This system now handles only economic extraction phases.
Pool tracks finite resources (inflow from tribute, outflow to wages/subsidy). See Simulation Systems Reference for full theory.
- step(graph, services, context)[source]
Execute 5-phase circuit. Economy state in graph.graph[‘economy’].
- Return type:
None
- Parameters:
graph (GraphProtocol)
services (ServicesProtocol)
context (ContextType)
Solidarity System
Solidarity system for the Babylon simulation - Proletarian Internationalism.
Sprint 3.4.2: The Counterforce to Imperial Rent Bribery. Sprint 3.4.3: Updated for IdeologicalProfile (multi-dimensional consciousness).
When periphery workers are in revolutionary struggle (consciousness >= threshold), their consciousness transmits through SOLIDARITY edges to core workers, awakening class consciousness that counters the super-wage bribery.
Key Design Decision: solidarity_strength is a PERSISTENT ATTRIBUTE ON THE EDGE, NOT auto-calculated from source organization. This enables the Fascist Bifurcation scenario where periphery revolts but core workers remain passive due to lack of built solidarity infrastructure.
Categorical reading (Phase B, project/06-lawverian-dialectics.md §4):
every SOLIDARITY edge this system strengthens moves the solidarity graph
toward the sheaf/unity pole \(\bigcirc\) of the connectivity
cylinder — it shrinks
atomization_index
and raises the cylinder’s
balance.
Repression and atomization pull the opposite direction, toward the
skeleton/atomized pole \(\Box\) (the edgeless graph). See
babylon.domain.dialectics.instances.connectivity for the instance; this
system does not call it directly (no behavior change in Phase B).
- class babylon.engine.systems.solidarity.SolidaritySystem[source]
Bases:
SystemBaseProletarian Internationalism - Consciousness Transmission System.
Implements consciousness transmission via SOLIDARITY edges: - Unidirectional flow (Periphery -> Core) - solidarity_strength stored on edge (key for Fascist Bifurcation) - Emits CONSCIOUSNESS_TRANSMISSION and MASS_AWAKENING events
Sprint 3.4.3: Updated to work with IdeologicalProfile, affecting only the class_consciousness dimension.
- step(graph, services, context)[source]
Apply solidarity transmission to all SOLIDARITY edges.
For each SOLIDARITY edge: 1. Check if source consciousness > activation_threshold 2. Check if solidarity_strength > 0 3. Calculate transmission delta 4. Apply delta to target class_consciousness 5. Emit events for narrative layer
- Return type:
None
- Parameters:
graph (GraphProtocol)
services (ServicesProtocol)
context (ContextType)
Ideology System
Ideology systems for the Babylon simulation - The Superstructure.
Sprint 3.4.2b: Extended with Fascist Bifurcation mechanic. Sprint 3.4.3: George Jackson Refactor - Multi-dimensional consciousness model.
When wages FALL, crisis creates “agitation energy” that channels into: - Class Consciousness (if solidarity_pressure > 0) - Revolutionary Path - National Identity (if solidarity_pressure = 0) - Fascist Path via loss aversion
- class babylon.engine.systems.ideology.ConsciousnessSystem[source]
Bases:
SystemBasePhase 2: Consciousness Drift based on material conditions.
Sprint 3.4.3 (George Jackson Refactor): Uses multi-dimensional IdeologicalProfile. - class_consciousness: Relationship to Capital [0=False, 1=Revolutionary] - national_identity: Relationship to State/Tribe [0=Internationalist, 1=Fascist] - agitation: Raw political energy from crisis (falling wages)
Extended with Fascist Bifurcation mechanic: - Reads incoming SOLIDARITY edges to calculate solidarity_pressure - Tracks wage changes between ticks to detect crisis conditions - Routes agitation to either class_consciousness or national_identity
- step(graph, services, context)[source]
Apply consciousness drift to all entities with bifurcation routing.
- Return type:
None
- Parameters:
graph (GraphProtocol)
services (ServicesProtocol)
context (ContextType)
Survival System
Survival systems for the Babylon simulation - The Calculus of Living.
Sprint 3.4.2: Fixed Bug 1 - Organization is now dynamic based on SOLIDARITY edges. P(S|R) = (base_organization + solidarity_bonus) / repression
Mass Line Phase 4: P(S|A) now uses per-capita wealth, not aggregate. A block of 50,000 workers with $1000 total sees wealth_per_capita=$0.02 (impoverished).
The solidarity_bonus is the sum of incoming SOLIDARITY edge weights (solidarity_strength). This makes organization a function of class solidarity infrastructure, not just a static value.
- class babylon.engine.systems.survival.SurvivalSystem[source]
Bases:
SystemBasePhase 3: Survival Calculus (P(S|A) vs P(S|R)).
Bug Fix (Sprint 3.4.2): Organization is now DYNAMIC. organization = base_organization + solidarity_bonus
Mass Line Phase 4: P(S|A) uses per-capita wealth. wealth_per_capita = wealth / population
Where solidarity_bonus = sum of incoming SOLIDARITY edge weights. This ensures that High Solidarity scenarios produce higher P(S|R).
- step(graph, services, _context)[source]
Update P(S|A) and P(S|R) for all entities.
Mass Line Phase 4: P(S|A) uses wealth_per_capita, not aggregate wealth. This ensures demographic blocks are evaluated per-person, not as monolith.
- Return type:
None
- Parameters:
graph (GraphProtocol)
services (ServicesProtocol)
_context (ContextType)
- Organization is calculated as:
effective_org = base_org * solidarity_multiplier
Where solidarity_multiplier = 1.0 + sum(solidarity_strength for incoming SOLIDARITY edges)
Contradiction System
Contradiction system — Lawverian opposition registry (Phase C1.3).
Position 18 in the pipeline. This is the rewrite that retires the saturating,
add-only edge-tension accumulator (the “Formula” + “Consumption” inertness
bugs of project/06-lawverian-dialectics.md §2). Each tick the system:
writes per-edge
tensionas the fresh wealth-asymmetry gap of that edge (EXPLOITATION / WAGES / TENANCY) — scale-free, recomputed from current wealth, never accumulated;steps the
OppositionRegistry(wired byServicesProtocol.create()) over aGraphInputssnapshot built from the live graph, deriving each opposition’s gap, rate, and the Maoist principal contradiction;derives
contradiction_framesfrom the registry states (intensity ← gap, aspect_balance ← rate, principal_aspect ← leading_pole; frame principal/secondary = registry principal + runner-up);fires RUPTURE on the principal opposition’s gap exceeding the defines threshold AND rising (rate > 0) — Mao’s “condition AND level”, never on hitting a ceiling.
- Cross-tick + handoff channel.
The registry snapshot is stashed on the graph attribute
opposition_states(notcontext.persistent_data). The bridged headless runner recreates a freshTickContextevery tick (engine/headless_runner/runner.py_advance_tick), sopersistent_datais not a cross-tick channel there; the graph, by contrast, persists in-place across ticks in both the bridged runner and the in-memorySimulationfacade. The graph attribute is therefore the reliable place to (a) recover the previous tick’s gaps for rate/inertia, (b) hand the capital_labor gap to the pre-position-18 consumers (ImperialRent @9, Struggle @16, Consciousness @17 read last tick’s snapshot), and (c) let the bridge’spersist_tickread the snapshot. This is the same channelcontradiction_framesalready uses.
- babylon.engine.systems.contradiction.OPPOSITION_STATES_ATTR = 'opposition_states'
Graph attribute holding
{key: OppositionState.model_dump()}for the tick.
- babylon.engine.systems.contradiction.DIALECTICAL_REGIME_ATTR = 'dialectical_regime'
Graph attribute holding this tick’s fixed-point regime (Phase E2):
{"regime": <reproduction|crisis|sublation>, "principal": key, "rate": float}.
- babylon.engine.systems.contradiction.OPPOSITION_INTERVENTIONS_ATTR = 'opposition_interventions'
Graph attribute holding a list of
StanceInterventiondumps to apply this tick. Written by verb/OODA systems (spec-071), read + CLEARED here (consumed-once). No producer writes it yet; unit tests set it directly.
- class babylon.engine.systems.contradiction.ContradictionSystem[source]
Bases:
SystemBasePhase 18: fresh-gap tension + opposition-registry contradiction frames.
- step(graph, services, context)[source]
Write fresh per-edge tension, then step the opposition registry.
- Return type:
None
- Parameters:
graph (GraphProtocol)
services (ServicesProtocol)
context (ContextType)
Territory System
Territory systems for the Babylon simulation - Layer 0.
Sprint 3.5.4: The Territorial Substrate. Sprint 3.7: The Carceral Geography - Necropolitical Triad. Sprint 3.7.1: Dynamic Displacement Priority Modes.
TerritorySystem manages: 1. Heat dynamics: HIGH_PROFILE gains heat, LOW_PROFILE decays heat 2. Eviction pipeline: triggered when heat >= threshold, routes to sink nodes 3. Heat spillover: via ADJACENCY edges 4. Necropolitics: CONCENTRATION_CAMP elimination, PENAL_COLONY suppression
Displacement Priority Modes (Sprint 3.7.1): - EXTRACTION: Prison > Reservation > Camp (labor valuable, default) - CONTAINMENT: Reservation > Prison > Camp (crisis/transition) - ELIMINATION: Camp > Prison > Reservation (late fascism)
- class babylon.engine.systems.territory.TerritorySystem[source]
Bases:
SystemBaseTerritory Dynamic System - Layer 0 spatial dynamics.
Implements the territorial substrate mechanics: - Heat dynamics based on operational profile - Eviction pipeline when heat exceeds threshold - Heat spillover between adjacent territories - Necropolitics for sink nodes (Sprint 3.7)
“Legibility over Stealth” - The State knows where you are. The game is about staying below the repression threshold.
Sprint 3.7 additions: - Population transfers to sink nodes during eviction - CONCENTRATION_CAMP population decay (elimination) - PENAL_COLONY organization suppression (atomization)
- step(graph, services, context)[source]
Apply territorial dynamics to the graph.
Phases execute in sequence: 1. Heat dynamics (profile-based accumulation/decay) 2. Eviction pipeline (triggered at threshold, routes to sinks) 3. Heat spillover (via adjacency edges) 4. Necropolitics (sink node effects)
Sprint 3.7.1: Context can contain ‘displacement_mode’ to override the default EXTRACTION mode for sink node routing.
- Return type:
None
- Parameters:
graph (GraphProtocol)
services (ServicesProtocol)
context (ContextType)