-
-
Notifications
You must be signed in to change notification settings - Fork 0
LP Planner
The core planning question — given the inputs I have and the outputs I need, what's the cheapest set of recipes that satisfies them? — is solved as a linear program using Google OR-Tools (GLOP solver).
| Layer | File | Role |
|---|---|---|
| Domain | src/ERP/Domain/ProductionPlan.cs |
Output type: Targets, Available, Steps, RawInputsConsumed, MissingInputs, ExtractorAllocations, Warnings, FluidPipes, Sensitivity, GeneratorAllocations
|
| Application | src/ERP/Application/IRecipePlanner.cs |
Port |
| Application | src/ERP/Application/RecursiveRecipePlanner.cs |
Heuristic fallback (kept for parity tests) |
| Infrastructure | src/ERP/Infrastructure/OrToolsRecipePlanner.cs |
LP implementation (native OR-Tools dep) |
| Infrastructure | src/ERP/Infrastructure/PlannerOptions.cs |
Tuneables: penalties, tie-breakers, planner selection |
Native OR-Tools stays in Infrastructure; Application talks to the port only.
| Variable | Meaning |
|---|---|
recipe[r] |
Production rate (per-minute, fractional) for recipe r
|
item[i] |
Net supply of item i (raw inputs + recipe outputs − recipe inputs) |
raw[i] |
How much of raw input i is drawn from Available
|
short[i] |
Shortfall on item i — non-zero only when supply can't meet demand |
node[n] |
Extractor allocation per resource node (#92) |
generator[g, fuel] |
Buildings count + fuel draw per generator/fuel pair (#137) |
The variables are continuous — the LP relaxation gives fractional building counts which we surface alongside whole-integer rates. That's deliberate; an ILP would block on solver licensing and is overkill for steady-state planning.
- Supply ≥ demand per item — sum of all contributions (recipe outputs + raw inputs + shortfall) is at least the demand (recipe inputs + targets).
- Power supply ≥ recipe draw — only when a power target is set; generators contribute, recipes draw.
-
Node capacity —
node[n]is bounded by the node's max extraction rate derived from purity + extractor tier.
Minimise (in this priority order):
-
Shortfall on produced items (huge penalty,
ShortfallPenaltyForProduced = 1e9) -
Shortfall on raw inputs (smaller penalty,
ShortfallPenaltyForRaw = 1e6) - Power demand (base draw + miner draw + generator building cost)
-
Raw draw (
RawDrawTieBreaker = 1e-3— above GLOP optimality tolerance, below recipe power)
The two-tier shortfall penalty exists so the LP attributes blame correctly — without it, the solver would happily mark a target item short rather than its upstream raw input, hiding the real bottleneck.
-
Steps— every active recipe with rate, building count, machine type. -
RawInputsConsumed— final per-raw draw. -
MissingInputs(InfeasibleItem) — anything still short after the LP found its best objective; surfaces the real deficit. -
ExtractorAllocations— which nodes were used at what rate (#92). -
FluidPipes— per-item pipe throughput requirements + recommended tier (#90). -
Sensitivity(LpSensitivity) — shadow prices on supply constraints and reduced costs on production recipes (#129). Surfaces "what's pinning the plan" without the user having to re-solve manually. -
GeneratorAllocations— per-generator building counts and fuel draw for the chosen power target (#137).
Pass PowerTargetMw on the PlanProductionQuery. The LP chooses freely
between generator kinds (Coal, Fuel, Nuclear, …) and fuels (e.g. coal vs
compacted coal) — there's no preference; the objective picks the lowest-cost
mix.
If the available raw inputs can't sustain the requested power, the LP
returns the closest feasible solution and the shortfall surfaces as a
MissingInput rather than infeasibility.
Sensitivity.SupplyConstraints[i].ShadowPrice tells you how much the
objective would improve per additional unit of item i. Reduced costs on
recipes show how expensive an inactive recipe would have to become before it
gets brought into the plan.
The view layer surfaces these in the planner page under the Sensitivity tab, so users can answer "would adding one more iron ore patch help?" without re-running the LP.
-
test/ERP/Infrastructure.Tests/OrToolsRecipePlannerTests.cs— golden-path- edge cases (no raw, contradictory targets, missing recipes, …).
-
test/ERP/Application.Tests/RecursiveRecipePlannerTests.cs— heuristic baseline; kept so we can spot regressions when changing penalties.
Start here
How it works
Reference
Off-wiki