SKILL.md
MILP Solver Workflow
Use this skill for binary/integer decisions, linear constraints, and linear or piecewise-linear objectives. It is useful for time-expanded scheduling models with many repeated resource-period constraints.
This is a workflow and implementation guide, not a complete formulation for any one task.
Workflow
- Parse and normalize data into ordered arrays.
- Define decision states before coding: status, transitions, continuous quantities, slacks, segments, tiers.
- Build a deterministic variable map.
- Add constraints family by family: bounds, linking, balance, time coupling, capacity/ramp limits, cost logic.
- Solve with an available open-source MILP solver.
- Extract a candidate solution, rounding binaries only if near integral.
- Convert internal variables into the report convention.
- Independently validate extracted arrays.
- Recompute objective and summaries from extracted arrays.
- Write final output only after validation passes.
Variable Map Pattern
Use helper functions or dictionaries, not scattered index arithmetic.
offset = {}
n = 0
def alloc(name, shape, lb=0.0, ub=float("inf"), integer=False):
global n
size = int(np.prod(shape))
idx = np.arange(n, n + size).reshape(shape)
offset[name] = idx
n += size
return idx
u = alloc("commitment", (G, T), lb=0, ub=1, integer=True)
start = alloc("startup", (G, T), lb=0, ub=1, integer=True)
dispatch = alloc("dispatch", (G, T), lb=0)
reserve = alloc("reserve", (G, T), lb=0)
Keep variable ownership obvious: type, resource, period, and optional segment/tier.
Sparse Constraint Pattern
Use sparse rows for large time-expanded models:
rows, cols, vals = [], [], []
lb, ub = [], []
row = 0
def add_row(terms, lo, hi):
global row
for j, a in terms:
if abs(a) > 0:
rows.append(row)
cols.append(j)
vals.append(float(a))
lb.append(float(lo))
ub.append(float(hi))
row += 1
