babylon.formulas.balkanization

Spec-070 Balkanization formulas (FR-003, FR-004, FR-007, FR-021, FR-029b, FR-034).

This module exposes pure deterministic functions consumed by the three new Systems (FactionInfluenceSystem, SovereigntySystem, CollapseTransitionSystem). All multipliers and thresholds funnel through babylon.config.defines.balkanization.BalkanizationDefines so no magic numbers appear at the system layer (Constitution III.1).

Functions

calculate_metabolic_impact(policy[, defines])

Return the per-tick habitability change for a given ExtractionPolicy (spec-070 FR-004).

contiguous_influence_majority_subregion(...)

Compute the largest contiguous H3-res-7 sub-region of a Sovereign's territory where faction_id's INFLUENCES.influence_level exceeds BalkanizationDefines.secession_influence_threshold (spec-070 FR-029b).

derive_default_multipliers_from_stance(stance)

Return the canonical 4-tuple of Faction mechanical multipliers (FR-007 + data-model.md §3.1) for a given ColonialStance.

derive_extraction_policy_from_stance(stance)

Derive the Sovereign's ExtractionPolicy from a Faction's ColonialStance (spec-070 FR-003).

detect_red_settler_trap(...[, defines])

Detect the Red Settler Trap diagnostic condition (spec-070 FR-034).

extrapolate_habitability(...)

Linearly extrapolate a Territory's habitability over a horizon (spec-070 FR-051, used by SovereignProjection).

winning_faction_for_territory(graph, ...)

Determine the winning BalkanizationFaction for a Territory (spec-070 FR-021).

babylon.formulas.balkanization.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.02

  • CONTINUE → -0.005

  • CEASE → +0.01

Override any of the three via BalkanizationDefines (no magic numbers at the system layer, Constitution III.1).

Parameters:
Return type:

float

Returns:

Per-tick habitability change to apply along each CLAIMS edge.

Raises:

ValueError – If policy is not a recognized ExtractionPolicy member.

Example

>>> from babylon.models.enums import ExtractionPolicy
>>> calculate_metabolic_impact(ExtractionPolicy.INTENSIFY)
-0.02
babylon.formulas.balkanization.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 exceeds BalkanizationDefines.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_id and satisfying the influence predicate.

Parameters:
  • graph (GraphProtocol) – GraphProtocol exposing query_sovereign_claims(), query_adjacent_territories(), and query_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:

frozenset[str]

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 graph does not implement the required query methods.

babylon.formulas.balkanization.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:
Return type:

tuple[float, float, float, float]

Returns:

4-tuple of multipliers in the canonical order above.

Raises:

KeyError – If stance is 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.balkanization.derive_extraction_policy_from_stance(stance)[source]

Derive the Sovereign’s ExtractionPolicy from a Faction’s ColonialStance (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:

ExtractionPolicy

Returns:

Derived ExtractionPolicy.

Raises:

KeyError – If stance is not a recognized ColonialStance member.

Example

>>> from babylon.models.enums import ColonialStance
>>> derive_extraction_policy_from_stance(ColonialStance.UPHOLD)
<ExtractionPolicy.INTENSIFY: 'intensify'>
babylon.formulas.balkanization.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), AND

  • colonial_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:

bool

Returns:

True iff 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.balkanization.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:
  • current_habitability (float) – Current habitability ∈ [0, 1].

  • metabolic_impact (float) – Per-tick habitability change.

  • horizon_ticks (int) – Number of ticks to project forward.

Return type:

float

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.balkanization.winning_faction_for_territory(graph, territory_id, incumbent_faction_id, rng)[source]

Determine the winning BalkanizationFaction for a Territory (spec-070 FR-021).

Computes argmax_f Σ INFLUENCES(f territory).influence_level with a two-stage tiebreaker:

  1. If the incumbent ruling_faction is among the tied factions, the incumbent wins (stability preserved).

  2. Otherwise, draw deterministically from rng over the sorted-ID tied set.

Parameters:
  • graph (GraphProtocol) – GraphProtocol exposing query_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 be None for unclaimed territory.

  • rng (Random) – Seeded random.Random used for deterministic tiebreaking when no incumbent participates.

Return type:

str | None

Returns:

The winning Faction ID, or None if the Territory has zero incoming INFLUENCES.

Raises:

AttributeError – If graph does not implement query_faction_influence_by_territory().