Operational MILP Warm Starts
The operational MILP now accepts heuristic schedules as warm starts via fhops solve-mip-operational --incumbent seed.csv. This page documents how to generate those CSVs, what the CLI/API derive from them, and—critically—why the feature is still experimental for medium/large ladders.
Workflow
Generate a candidate schedule. Use any heuristic command that emits assignments with the canonical column schema:
fhops solve-heur examples/med42/scenario.yaml \ --iters 0 \ --out tmp/med42_greedy_incumbent.csv
The CSV must include
machine_id,block_id,day, andshift_id. If you pass the optionalassignedorproductioncolumns they are honoured when seeding Pyomo variables.Feed the incumbent to the MILP. Any
solve-mip-operationalinvocation can reuse the schedule:fhops solve-mip-operational examples/med42/scenario.yaml \ --solver gurobi \ --solver-option Threads=36 \ --solver-option TimeLimit=120 \ --incumbent tmp/med42_greedy_incumbent.csv \ --out tmp/med42_mip_seeded.csv
The CLI rebuilds the
fhops.optimization.operational_problem.OperationalProblemcontext, derives the implied transitions, activation binaries, per-role inventories, landing surplus, and leftovers, and then sets Pyomo’swarmstart=Trueflag before launching the solver.Inspect the solver log. Successful warm starts show the candidate objective up-front. When the log contains
User MIP start did not produce a new incumbent solutionthe solver ignored the seed (usually because it can find a better incumbent through its own heuristics).
Current limitations
The plumbing works end-to-end—tiny7/small21 reuse the incumbent immediately—but med42 and large84 still reject greedy or short SA seeds. Those incumbents complete all blocks in ≈23–47 days, while the MILP needs high-quality assignments that respect every loader/landing constraint; the solver therefore finds its own incumbent faster than it can repair the provided schedule.
Gurobi and HiGHS require every binary implied by the incumbent (assignment, transition, mobilisation activation, loader buffer) to be populated. The CLI handles this automatically, but if you call
fhops.model.milp.driver.solve_operational_milp()directly you must pass theOperationalProblemcontext so the helper can rebuild sequencing state.Warm starts are best-effort. Providing an incumbent is always safe, yet you should not expect runtime improvements unless the seed is near-feasible for the operational MILP. Until we develop stronger heuristics (e.g., 60 s SA runs with repairs or rolling-horizon MILPs), treat
--incumbentas a diagnostic tool rather than a guaranteed accelerator.
Practical guidance
Capture solver logs with
--solver-option LogFile=med42.logwhen experimenting so you can confirm whether the incumbent was accepted.Budget heuristics so they can produce a schedule that finishes close to the horizon (e.g., SA with
--iters 2000and--watchset to 60 seconds). Seeds that leave large staged volume or violate sequencing will be discarded.Fall back to solver-based heuristics (pure Gurobi/HiGHS) if the warm start keeps getting rejected—the solver is often faster at generating its own incumbent once it hits the strong root relaxation.
Future work
Warm starts become truly useful once we can:
Generate med42-quality incumbents that satisfy loader/landing balance (potentially by repairing SA outputs with the SequencingTracker).
Lock in early-week decisions via rolling-horizon MILPs so the incumbent only needs to cover a subset of shifts at a time.
Expose benchmark automation that measures “seeded vs unseeded” runtime/gap curves in CI.
Until then, the published CLI/API docs intentionally describe the feature as operational-but-not-yet-practically-useful so users know what to expect.