mixle.pipeline_twin module¶
Digital-twin simulation of a min-cost-flow network under stochastic arrivals (H8).
A PipelineTwin is a period-stepped re-solve of a production network’s flow: each period
it re-runs mixle.relations.min_cost_flow() (IC-9) under the current arc capacities/costs and a
draw of stochastic arrivals, then accumulates queue/bottleneck diagnostics as state. It is wrapped
as a mixle.inference.simulate.Simulator so the per-period stochastic draws come from the
same .sampler(seed=...) surface every other simulated model in the codebase uses, and named
interventions are registered through the same Scenario bookkeeping
the simulate module already exposes – though, unlike a learned Bayesian network, a deterministic
flow network has no do-operator to route through, so interventions here are applied directly as
arc/capacity/supply overrides (see PipelineTwin._apply_interventions()).
Nothing about the twin itself is domain-specific: it is a general period-stepped supply/demand network simulator with pluggable scenario interventions (new/changed arcs, node outages, supply-rate shifts, demand shifts). This module’s worked instantiation is a mine -> plant -> distribution pipeline (source nodes are mines, sinks are customers, “plant-down” and “supply-rate shift” are the named interventions below), but the network topology, capacities, and interventions are all caller-supplied.
Network capacities can be tightened by H5 (mixle_pde.material_transport) transport-physics
numbers – those arrive as a plain {(u, v): capacity} mapping (no cross-plugin import) and are
combined with the network’s nameplate capacities in build_twin().
- build_twin(network, transport, *, seed=0)[source]
Build a
PipelineTwinfrom a network spec and (optionally empty) H5 transport caps.networkkeys:cap/cost((n, n)arc matrices),supply(lengthn, positive = source (a mine, in this module’s worked instantiation), negative = demand (a customer)),supply_nodes/demand_nodes(node-index lists; inferred from the sign ofsupplyif omitted), and an optionalarrival_noisestd-dev for the per-period stochastic-arrivals draw (default 0, deterministic).transportis a plain{(u, v): capacity}mapping of H5 (mixle_pde.material_transport) derived real-world throughput ceilings (slurry line / conveyor limits, etc.) – these are combined withnetwork’s nameplate arc capacities viamin(no cross-plugin import: the twin only ever sees the resulting plain numbers).
- class PipelineTwin(cap, cost, supply, *, supply_nodes, demand_nodes, seed=0, arrival_noise=0.0, interventions=None)[source]
Bases:
objectA period-stepped digital twin of the production network’s flow.
Each
run()re-solvesmin_cost_flowper period under the twin’s (possibly scenario-modified) capacities/costs and a draw of stochastic arrivals on the supply nodes, tracking per-period throughput/queue/bottleneck-arc diagnostics.- Parameters:
- scenario(name, interventions)[source]
Register a named intervention (node outage / supply-rate shift / demand-spike / new arc / …).
Returns a new twin sharing this one’s network and seed but with
nameavailable torun()via itsscenario=argument – the base twin (and any other scenario already registered on it) is left untouched.
- run(n_periods, *, scenario=None)[source]
Step the twin
n_periodsperiods, re-solving the flow each period.Returns a dict of per-period diagnostics:
throughput(delivered per period),lost_sales(demand unmet in that period),lost_sales_cumulative(the running total),demand(the effective per-demand-node demand actually solved against, after any scenario interventions),utilization(per-period(n, n)arc flow/capacity ratios),bottleneck_arc(the(u, v)with highest utilization in the final period), andbottleneck_utilization(that arc’s utilization series).lost_salesis LOST demand, not a backlog. Every period solves against the same nominal demand; unmet demand is counted and dropped, never added to a later period’s demand or carried as state, so it can never be served late. This series used to be reported asqueue, which read as a backlog that would eventually clear: a capacity-five network facing demand ten reported a growing “queue” of 5 then 10 while the second solve still requested only ten rather than the outstanding fifteen. Modelling an actual backlog needs per-node carried state in the conservation constraints, with aging, service and terminal treatment defined; until that exists, the honest name for this number is lost sales.Raises
ValueErrorforn_periods < 1– matching this class’s other invalid-input conventions (an unregisteredscenarioname or interventionkindraises rather than returning a degraded result), a zero/negative period count has no meaningful per-period diagnostics to report, and silently returning empty series would only move today’s crash (an unconditionalbottleneck_arcs[-1]index) to whatever code reads the result instead of surfacing it here at the call that actually got the invalid count.