Tutorials
Learning Path
Learn Local-MIP
Start with file-based solving, then move to the C++ or Python APIs, in-memory modeling, and callback hooks for custom local-search behavior.
Pick the path that matches your workflow
This page follows the current public README, API headers, parameter template, and the public algorithm description.
CLI solver
Solve existing .mps or .lp models, use .set files, and script benchmark runs.
C++ / Python APIs
Configure Local-MIP from code, run the solver, and query feasibility, objective value, and solution vectors.
Open API tutorialModeling API
Create variables, constraints, objective sense, integrality, and solve a model without reading a file.
Open modeling tutorialCallbacks
Customize starts, restarts, weights, neighbor generation, and feasible or infeasible scoring logic.
Open callback tutorialSolve MPS or LP files directly
Use the CLI when your model already exists as a file. Build from the repository root, then run from build/ so the bundled test-set paths resolve.
Build and run a 10 second solve
./build.sh release
cd build
./Local-MIP -i ../test-set/2club200v15p5scn.mps -t 10
Short and long flags are both supported. For example, -i and --model_file refer to the same required input model parameter.
Keep solver settings in a .set file
cd build
./Local-MIP --param_set_file ../default.set --model_file ../test-set/2club200v15p5scn.mps
A parameter file uses one parameter_name = value assignment per line. Lines beginning with # or ; are comments. Command-line arguments override values loaded from the file.
.mps and .lpThe current reader handles MPS RANGES sections; SOS data is rejected with an error.
./Local-MIP --helpUse the binary help output as the final source for flag names in the checked-out version.
default.setThe repository template lists every parameter with the current default and valid range.
Small configuration example
# General control
time_limit = 10
random_seed = 42
log_obj = 1
# Built-in strategy choices
start = zero
restart = best
weight = monotone
lift_scoring = lift_age
neighbor_scoring = progress_bonus
Embed Local-MIP from C++ or Python
The public APIs expose the same core configuration used in normal runs, plus result queries, parameter-file loading, in-memory modeling, and callback registration.
Minimal file-backed solve
The source build produces build/libLocalMIP.a; headers live under src/. The example projects under example/ show standalone build commands.
#include "local_mip/Local_MIP.h"
int main() {
Local_MIP solver;
solver.set_model_file("test-set/2club200v15p5scn.mps");
solver.set_sol_path("example_simple.sol");
solver.set_time_limit(10.0);
solver.set_log_obj(true);
solver.run();
if (solver.is_feasible()) {
printf("Objective value: %.10f\n", solver.get_obj_value());
}
return 0;
}
Install in a local venv
For Linux x86_64, the published Python bindings are the shortest path. The venv command avoids system Python package restrictions.
python3 -m venv .venv && .venv/bin/python -m pip install localmip
.venv/bin/python -c "import localmip_py as lm; print(lm.LocalMIP)"
import localmip_py as lm
solver = lm.LocalMIP()
solver.set_model_file("test-set/2club200v15p5scn.mps")
solver.set_time_limit(10.0)
solver.set_log_obj(True)
solver.run()
if solver.is_feasible():
print("Objective:", solver.get_obj_value())
Build a model in memory
Use the Model API when you want to add variables and constraints from code instead of reading a model file. Build the model once, call run() once, and create a fresh solver instance for another solve.
Variables, bounds, objective, constraints
import math
import localmip_py as lm
solver = lm.LocalMIP()
solver.enable_model_api()
solver.set_sense(lm.Sense.minimize)
solver.set_time_limit(1.0)
x1 = solver.add_var("x1", 0.0, 1.0, 1.0, lm.VarType.real)
x2 = solver.add_var("x2", 0.0, 10.0, -0.5, lm.VarType.general_integer)
# x1 + 2*x2 <= 20
solver.add_con(-math.inf, 20.0, [x1, x2], [1.0, 2.0])
solver.run()
if solver.is_feasible():
sol = solver.get_solution()
print("Objective:", solver.get_obj_value())
print("x1:", sol[x1], "x2:", sol[x2])
Selected methods
enable_model_api()Enable programmatic modeling first.
set_sense(Sense)Choose minimize or maximize.
add_var(name, lb, ub, cost, type)Add a variable and objective coefficient.
add_con(lb, ub, cols, coefs)Add a bounded linear constraint.
set_integrality(col/name, type)Change variable type when needed.
get_solution()Read the incumbent vector after a run.
Constraint bounds use lb <= expression <= ub. Use infinity for one-sided constraints and equal bounds for equality constraints.
The search model in one page
Mixed Integer Programming (MIP)
In the canonical minimization form used by the algorithmic description, a MIP is:
$$ \min_x \ c^\top x \quad \text{s.t.} \quad Ax \le b, \quad \ell \le x \le u, \quad x_j \in \mathbb{Z} \ \forall j \in I. $$A solution assigns values to all variables. It is feasible when it satisfies the linear constraints, variable bounds, and integrality restrictions. Among feasible solutions, the objective value determines solution quality.
Improve while preserving feasibility
When the current solution is feasible, Local-MIP maintains local feasible domains and uses lift moves to improve the objective without violating constraints.
Balance feasibility and objective progress
When constraints are violated, the search uses mixed tight and breakthrough move candidates, weighted progress scoring, and tie-breaking bonuses.
Six strategy modules
The current implementation exposes these modules through parameters and callbacks. Each module links to its runnable example.
zero, randomStart Callback example
Restartrandom, best, hybridRestart Callback example
Lift scoringlift_age, lift_randomLift Scoring example
Neighbor generationbuilt-in and custom neighborsNeighbor Config example
Neighbor scoringprogress_bonus, progress_ageNeighbor Scoring example
Weightingmonotone, smoothWeight Callback example
CLI flags and .set keys
The table below mirrors the current default.set, src/utils/paras.h, and ./Local-MIP --help output. The input model is required for CLI runs.
General parameters
| Parameter | Description | Flag | Type | Range | Default |
|---|---|---|---|---|---|
model_file | Path to input model file (.mps/.lp). Required for CLI runs. | -i | string | - | "" |
sol_path | Path to output solution file (.sol). | -s | string | - | "" |
param_set_file | Path to parameter configuration file (.set). | -c | string | - | "" |
time_limit | Time limit in seconds. | -t | double | [0, 1e8] | 10 |
random_seed | Random seed for local search. 0 uses the default behavior. | -S | int | [0, 2147483647] | 0 |
Numerical and search parameters
| Parameter | Description | Flag | Type | Range | Default |
|---|---|---|---|---|---|
feas_tolerance | Feasibility tolerance. | -F | double | [0, 1e-2] | 1e-6 |
opt_tolerance | Optimality tolerance. | -O | double | [0, 1] | 1e-4 |
zero_tolerance | Zero value tolerance. | -Z | double | [0, 1e-3] | 1e-9 |
bound_strengthen | Bound strengthening level: 0 off, 1 IP, 2 MIP. | -b | int | [0, 2] | 1 |
log_obj | Log objective values during search. | -l | int | [0, 1] | 1 |
split_eq | Split equality constraints into two inequalities. | -j | int | [0, 1] | 1 |
activity_period | Constraint activity recompute period. | -H | int | [1, 100000000] | 100000 |
break_eq_feas | Break feasibility on equality constraints in the lift process. | -z | int | [0, 1] | 0 |
restart_step | No-improvement steps before restart. 0 disables restarts. | -r | int | [0, 100000000] | 1000000 |
smooth_prob | Weight smoothing probability in units of 1/10000. | -0 | int | [0, 10000] | 1 |
BMS and tabu parameters
| Parameter | Description | Flag | Type | Range | Default |
|---|---|---|---|---|---|
bms_unsat_con | BMS unsatisfied constraint sample size. | -u | int | [0, 100000000] | 12 |
bms_unsat_ops | BMS MTM unsatisfied operations. | -p | int | [0, 100000000] | 2250 |
bms_sat_con | BMS satisfied constraint sample size. | -v | int | [0, 100000000] | 1 |
bms_sat_ops | BMS MTM satisfied operations. | -o | int | [0, 100000000] | 80 |
bms_flip_ops | BMS flip operations. | -x | int | [0, 100000000] | 0 |
bms_easy_ops | BMS easy operations. | -q | int | [0, 100000000] | 5 |
bms_random_ops | BMS random operations. | -g | int | [0, 100000000] | 250 |
tabu_base | Base tabu tenure. | -a | int | [0, 100000000] | 4 |
tabu_var | Tabu tenure variation. | -e | int | [1, 100000000] | 7 |
Strategy selectors
| Parameter | Description | Flag | Values | Default |
|---|---|---|---|---|
start | Start method. | -m | zero, random | zero |
restart | Restart strategy. | -y | random, best, hybrid | best |
weight | Constraint weight update method. | -w | smooth, monotone | monotone |
lift_scoring | Feasible-phase lift scoring method. | -f | lift_age, lift_random | lift_age |
neighbor_scoring | Infeasible-phase neighbor scoring method. | -n | progress_bonus, progress_age | progress_bonus |
Customize search without changing the solver kernel
Callbacks replace selected strategy behavior while the solver owns the main control flow. The C++ API uses typed contexts and optional void* user_data. Python callbacks use structured context objects and can also receive optional user data.
Start::Start_CtxModify initial variable values and use the solver RNG.
Restart::Restart_CtxPerturb the current assignment and adjust weights after restart triggers.
Weight::Weight_CtxUpdate constraint and objective weights.
Neighbor::Neighbor_CtxGenerate custom move candidates with helper methods.
Scoring::Neighbor_CtxRank infeasible-phase candidates using progress and tie-breaking state.
Scoring::Lift_CtxRank feasible-phase lift moves.
Common read-only context
Every callback receives access to a shared snapshot through ctx.m_shared in C++ or the corresponding structured object in Python.
m_model_manager, objective coefficients, variable and constraint metadata.
Current values, best values, activities, constants, equality flags, and weights.
Unsatisfied and satisfied constraint index lists used by neighbor and scoring logic.
Current step, last improvement step, incumbent objective, feasibility status, and breakthrough status.
Neighbor configuration
Neighbor generation can be reset, reordered, mixed with built-in operators, or extended with user-defined generators. Custom generators should emit moves through the context helpers.
Local_MIP solver;
solver.clear_neighbor_list();
solver.add_custom_neighbor("my_random_flip", my_neighbor_cbk);
solver.add_neighbor("unsat_mtm_bm", 12, 8);
solver.add_neighbor("flip", 0, 12);
solver.set_model_file("test-set/2club200v15p5scn.mps");
solver.run();
Registration methods
set_start_cbk(callback, user_data)Custom initialization.
set_restart_cbk(callback, user_data)Custom restart action.
set_weight_cbk(callback, user_data)Custom weight update.
add_custom_neighbor(name, callback, user_data)User-defined neighbor generator.
set_neighbor_scoring_cbk(callback, user_data)Infeasible-phase scoring.
set_lift_scoring_cbk(callback, user_data)Feasible-phase scoring.
Use repository examples as the runnable source of truth: start-callback/, restart-callback/, weight-callback/, neighbor-config/, neighbor-userdata/, scoring-neighbor/, and scoring-lift/.