babylon.engine.systems.vol2_circulation

Vol II Circulation sub-stage (Spec 063 T055 / T018).

Per-tick transformation that consumes the year-scoped LODESYearMatrix plus the current in-memory hex v vector and produces (a) the next-tick hex v vector for in-study-area hexes and (b) boundary register rows for every flow that exits the study area, each paired with a wage-repatriation TRADE_EDGE row per FR-030a.

This is a sub-stage of ImperialRentSystem (pipeline slot 5c per spec 062 FR-053), not a top-level System. The sub-stage signature differs from babylon.kernel.system_protocol.System because the caller is ImperialRentSystem.step() and supplies the boundary register and session metadata directly.

Constitution constraints:

  • II.6 + GATE-2: no DB I/O during the step body; the OD matrix is loaded once at session init and passed in via constructor.

  • II.12 GATE-4: the matrix is scipy.sparse.csr_matrix; the formula is expressed as a single matrix-vector multiplication for the in-area portion (FR-009 / FR-016).

  • II.13 GATE-5: this is the deterministic min-cost flow component only. Slime-mold conductivity (the emergent component of II.13) is out of scope.

  • III.7: identical pre-state + identical OD matrix → bit-identical post-state and boundary rows (FR-014).

See also

specs/063-vol-ii-circulation/spec.md FR-008 .. FR-016, FR-030a/b/c. specs/063-vol-ii-circulation/data-model.md §1.3. babylon.domain.economics.lodes_commute_matrix:

LODESCommuteMatrixLoader, LODESYearMatrix.

Classes

CirculationStepResult(tick, pre_total_v, ...)

Outcome record for one Vol II Circulation sub-stage execution.

Vol2CirculationStep(*, od_loader[, classifier])

Sub-stage 5c: variable-capital redistribution across hexes per LODES OD.

Exceptions

CirculationConservationViolation

Raised when FR-010 conservation invariant is violated mid-tick.

exception babylon.engine.systems.vol2_circulation.CirculationConservationViolation[source]

Bases: RuntimeError

Raised when FR-010 conservation invariant is violated mid-tick.

Aborts the per-tick transaction (spec 062 FR-008a) so the engine state rolls back cleanly. Audit log entry is recorded by the auditor.

class babylon.engine.systems.vol2_circulation.CirculationStepResult(tick, pre_total_v, post_total_v_in_area, boundary_out_total_v, rows_emitted, od_year_used, conservation_residual, wall_time_ms=0.0)[source]

Bases: object

Outcome record for one Vol II Circulation sub-stage execution.

Returned from Vol2CirculationStep.step() so callers (tests, instrumentation, the conservation auditor) can verify FR-010 invariants without re-walking the graph.

Parameters:
  • tick (int)

  • pre_total_v (float)

  • post_total_v_in_area (float)

  • boundary_out_total_v (float)

  • rows_emitted (int)

  • od_year_used (int)

  • conservation_residual (float)

  • wall_time_ms (float)

tick: int
pre_total_v: float
post_total_v_in_area: float
boundary_out_total_v: float
rows_emitted: int
od_year_used: int
conservation_residual: float
wall_time_ms: float = 0.0
__init__(tick, pre_total_v, post_total_v_in_area, boundary_out_total_v, rows_emitted, od_year_used, conservation_residual, wall_time_ms=0.0)
Parameters:
  • tick (int)

  • pre_total_v (float)

  • post_total_v_in_area (float)

  • boundary_out_total_v (float)

  • rows_emitted (int)

  • od_year_used (int)

  • conservation_residual (float)

  • wall_time_ms (float)

Return type:

None

class babylon.engine.systems.vol2_circulation.Vol2CirculationStep(*, od_loader, classifier=None)[source]

Bases: object

Sub-stage 5c: variable-capital redistribution across hexes per LODES OD.

The sub-stage executes the formula:

v[A, t+1] = sum_j(OD[j, A] × v[j, t] / row_sum[j])  for in-area A

For origins j with row_sum[j] == 0 (uninhabited cells), v[j] carries forward unchanged and no boundary rows are emitted from j (FR-011). For destinations outside the study area, the share is recorded as a COMMUTE_OUT row in the boundary register plus a paired observational TRADE_EDGE row representing wage repatriation (FR-030a — the paired row does NOT modify the in-area v vector).

Construction takes the loader so the year-scoped matrix is fetched lazily at each step() call (the loader caches the current year, so repeated step calls in a year share the same CSR matrix).

Parameters:
__init__(*, od_loader, classifier=None)[source]
Parameters:
Return type:

None

step(*, graph, register, session_id, tick, simulated_year)[source]

Execute one tick of Vol II Circulation.

Parameters:
  • graph (GraphProtocol) – In-memory hex graph; hex nodes carry the v attribute. Modified in-place: post-step v values are written back to graph.nodes[hex_id]["v"].

  • register (BoundaryFlowRegister) – Per-tick boundary register buffer; receives the COMMUTE_OUT + paired TRADE_EDGE rows.

  • session_id (UUID) – UUID of the active session (for register rows).

  • tick (int) – Current tick number (for register rows).

  • simulated_year (int) – The calendar year mapped to this tick. The loader applies FR-004 nearest-year clamp internally if needed; the actually-consumed year is returned in CirculationStepResult.od_year_used.

Return type:

CirculationStepResult

Returns:

CirculationStepResult summarizing the operation.

Raises:

CirculationConservationViolation – if the FR-010 conservation invariant fails for any reason (precision drift, matrix corruption, etc.). The per-tick transaction MUST be rolled back by the caller.