A mathematical optimization tool for the factory-building game Satisfactory, using Mixed-Integer Linear Programming (MILP) to maximize AWESOME Sink points per minute across the entire resource and production network.
- Point Maximization: Finds the globally optimal allocation of recipes, miners, extractors, and generators to maximize sink points per minute.
- Full Resource Modeling: Accounts for all resource nodes and resource wells by purity tier (Impure / Normal / Pure), with per-resource extractor assignment.
- Power Shards: Linearizes the nonlinear
machines × shardsproduct via McCormick envelopes, enabling exact shard allocation within the MILP. - Somersloop / Production Amplifier: Splits machines into sloop groups (0 … max_sloops) to model the output boost and quadratic power penalty introduced by Somersloops, subject to a global Somersloop budget.
- Alien Power Augmenter: Models fueled and unfueled augmenters with a bilinear power multiplier, also linearized via McCormick envelopes.
- Generator & Fuel Selection: Chooses generator buildings, fuel types, and water consumption to satisfy the power balance constraint.
- Nuclear Waste Handling: Automatically accounts for Uranium and Plutonium waste as a production side-effect.
- Belt & Pipe Capacity: Enforces per-machine throughput limits for both conveyor belts and pipelines.
- Hardcoded Solution Pinning: Optional constraints to fix parts of the solution (recipes, extractors, generators, sinks) for debugging or scenario analysis.
- Integer Scaling: Optional
enforce_decimal_digitsparameter converts continuous variables to scaled integers for solutions with a defined decimal precision. - Linear Power Scaling: Assumes the Linear Overclock mod, which replaces the vanilla exponential clock-speed power curve with a linear one, making the MILP formulation exact.
- Prerequisites (in-game): Satisfactory 1.1 with the Linear Overclock mod installed — required for results to be valid, not for running the optimizer itself.
- Language: Python 3.14.3
- Solver: Gurobi via
gurobipy(requires a valid Gurobi license) - Libraries:
numpy
The optimizer formulates a MILP over the full Satisfactory production graph.
Objective:
where
Subject to:
- Item balance — for every item: produced + extracted + waste = consumed + sinked + used as fuel
- Power balance — total consumption ≤ augmented generation (geothermal + generators + augmenters)
- Resource limits — miners / extractors bounded by available map nodes per purity
- Somersloop budget — sum of sloops used across all buildings + augmenter costs ≤ total collected Somersloops
- Belt / pipe capacity — output rate per machine ≤ MAX_BELT (1.200 items/min) or MAX_PIPE (600 m³/min)
- Sink capacity — total sinked flow ≤ number of AWESOME Sinks × belt limit
The bilinear terms machines × shards and total_augmenters × fueled_augmenters are linearized using McCormick envelopes, keeping the model linear throughout.
Without the assumption of linear clock-speed power curve, the power constraint would be cubic, making the problem non-convex and intractable for standard MILP solvers.
The optimizer achieves 483,490,254 sink points/min, surpassing the current best known result of 480,345,879 documented on the Satisfactory Wiki — an improvement of ~3,144,375 points/min (+0.65%).
satisfactory_solver/
├── data_loader.py # JSON → typed model objects
├── models.py # Frozen dataclasses (Recipe, ResourceNode, …)
├── optimizer.py # MILP formulation & solution extraction
data/ # JSON data files (recipes, nodes, buildings, …)
main.py # Entry point
- Game version: Satisfactory 1.1
- All game data (recipes, buildings, resource nodes, sink points, etc.) sourced from the Satisfactory Wiki.
-
Clone the repository:
git clone https://github.com/GaiusJ/Satisfactory.git cd Satisfactory -
Install dependencies:
pip install -r requirements.txt
-
Ensure a valid Gurobi license is active (academic licenses are available free of charge at gurobi.com).
-
Run the optimizer:
python main.py
Output is written to model_summary.txt and solution_output.txt in the working directory.
All tunable parameters are at the top of main.py:
| Parameter | Default | Description |
|---|---|---|
MINER_TIER |
"Miner Mk.3" |
Default extractor for solid resources |
EXTRACTOR_MAP |
see file | Per-resource extractor overrides |
time_limit |
90 |
Gurobi wall-clock limit in seconds |
use_hardcoded_solutions |
False |
Pin parts of the solution for debugging |
hardcoded_solution_name |
"best_possible" |
Which hardcoded scenario to apply |
enforce_decimal_digits |
None |
Integer scaling precision (None = continuous) |
This is an academic side project.
- Personal & Educational Use: Feel free to explore, learn from, and use this tool for private purposes.
- Commercial Use: Prohibited. If you intend to use this code, the optimization logic, or any derivatives for commercial purposes or financial gain, please contact me directly for written permission.