Iterated Local Search How-to

The Iterated Local Search (ILS) solver reuses the operator registry to alternate between local improvement phases and diversification perturbations. It sits between simulated annealing and the Tabu prototype: deterministic local search with optional hybrid MIP restarts.

Basic Usage

fhops solve-ils examples/tiny7/scenario.yaml \
    --out tmp/tiny7_ils.csv \
    --iters 250 --perturbation-strength 3 --stall-limit 10 \
    --batch-neighbours 4 --parallel-workers 4 \
    --telemetry-log tmp/ils_runs.jsonl

Key options:

--perturbation-strength

Number of perturbation steps executed after each local search cycle (default: 3).

--stall-limit

Non-improving iterations before perturbation/restart logic triggers (default: 10).

--hybrid-use-mip / --hybrid-mip-time-limit

Opt-in hybrid path: each time stalls reach the limit, the operational MILP (fhops.model.milp.driver.solve_operational_milp(), HiGHS, time-boxed by --hybrid-mip-time-limit seconds, same objective weights as the ILS run) is solved with the best ILS schedule as its incumbent — a genuine MIP start through Pyomo’s appsi_highs interface (see Operational MILP Warm Starts). The MILP schedule replaces the ILS best only when it scores higher under the heuristic objective, scored as planned (its production column and idle locked slots, as playback does, via fhops.optimization.heuristics.common.evaluate_assignments(); before #140 it was repaired and scored at full rates, which charged spurious missing_prereq penalties); a MILP solve without a solution keeps the ILS schedule. When an adopted MILP plan is still the best at the end it is returned as planned (assignments include production). (Before FHOPS 1.0.1 this step solved the legacy day-level MIP without an incumbent, which is infeasible for scenarios with loader roles; #104, #127.)

--batch-neighbours / --parallel-workers

Reuse the batched neighbour generation/evaluation infrastructure from SA. Defaults keep the sequential single-thread behaviour.

Telemetry

ILS telemetry mirrors SA metadata (initial/best score, operator weights/stats) and adds:

  • perturbations – diversification steps executed.

  • restarts – restarts triggered via hybrid or perturbation.

  • improvement_steps – count of local search improvements.

  • hybrid_use_mip / hybrid_mip_time_limit – hybrid configuration echoed for diagnostics.

  • hybrid_mip (result meta only, when the hybrid step is enabled) – one record per hybrid MILP solve: iteration, seed_score, outcome, objective, solver_error, warm_start_accepted, warm_start_seeded_slots, hybrid_score (planned-production score of the MILP plan, used for adoption), hybrid_rate_score (repaired plan at full rates, the pre-#140 score; diagnostic) and adopted; hybrid_mip_adopted_final tells whether the returned plan is an adopted MILP plan.

Benchmarks

fhops bench suite --include-ils emits additional ils rows alongside SA/Tabu/MIP results. Current runs (tiny7/med42/large84, 250 iterations) show ILS closing small gaps faster than Tabu while remaining slightly behind SA. The solver stays opt-in until we complete the hybrid warm-start investigation documented in notes/metaheuristic_roadmap.md.