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.

Overview

Pick the path that matches your workflow

This page follows the current public README, API headers, parameter template, and the public algorithm description.

Run files

CLI solver

Solve existing .mps or .lp models, use .set files, and script benchmark runs.

Open CLI tutorial
Embed

C++ / Python APIs

Configure Local-MIP from code, run the solver, and query feasibility, objective value, and solution vectors.

Open API tutorial
Build models

Modeling API

Create variables, constraints, objective sense, integrality, and solve a model without reading a file.

Open modeling tutorial
Customize search

Callbacks

Customize starts, restarts, weights, neighbor generation, and feasible or infeasible scoring logic.

Open callback tutorial
Command Line

Solve 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.

Basic Usage

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.

Parameter File

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.

Input files.mps and .lp

The current reader handles MPS RANGES sections; SOS data is rejected with an error.

Inspect flags./Local-MIP --help

Use the binary help output as the final source for flag names in the checked-out version.

Templatedefault.set

The 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
Library Use

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.

C++ static library

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;
}
Python bindings

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())
Modeling API

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.

Python sketch

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])
API surface

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.

Concepts

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.

Feasible mode

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.

Infeasible mode

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.

Parameters Reference

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

ParameterDescriptionFlagTypeRangeDefault
model_filePath to input model file (.mps/.lp). Required for CLI runs.-istring-""
sol_pathPath to output solution file (.sol).-sstring-""
param_set_filePath to parameter configuration file (.set).-cstring-""
time_limitTime limit in seconds.-tdouble[0, 1e8]10
random_seedRandom seed for local search. 0 uses the default behavior.-Sint[0, 2147483647]0

Numerical and search parameters

ParameterDescriptionFlagTypeRangeDefault
feas_toleranceFeasibility tolerance.-Fdouble[0, 1e-2]1e-6
opt_toleranceOptimality tolerance.-Odouble[0, 1]1e-4
zero_toleranceZero value tolerance.-Zdouble[0, 1e-3]1e-9
bound_strengthenBound strengthening level: 0 off, 1 IP, 2 MIP.-bint[0, 2]1
log_objLog objective values during search.-lint[0, 1]1
split_eqSplit equality constraints into two inequalities.-jint[0, 1]1
activity_periodConstraint activity recompute period.-Hint[1, 100000000]100000
break_eq_feasBreak feasibility on equality constraints in the lift process.-zint[0, 1]0
restart_stepNo-improvement steps before restart. 0 disables restarts.-rint[0, 100000000]1000000
smooth_probWeight smoothing probability in units of 1/10000.-0int[0, 10000]1

BMS and tabu parameters

ParameterDescriptionFlagTypeRangeDefault
bms_unsat_conBMS unsatisfied constraint sample size.-uint[0, 100000000]12
bms_unsat_opsBMS MTM unsatisfied operations.-pint[0, 100000000]2250
bms_sat_conBMS satisfied constraint sample size.-vint[0, 100000000]1
bms_sat_opsBMS MTM satisfied operations.-oint[0, 100000000]80
bms_flip_opsBMS flip operations.-xint[0, 100000000]0
bms_easy_opsBMS easy operations.-qint[0, 100000000]5
bms_random_opsBMS random operations.-gint[0, 100000000]250
tabu_baseBase tabu tenure.-aint[0, 100000000]4
tabu_varTabu tenure variation.-eint[1, 100000000]7

Strategy selectors

ParameterDescriptionFlagValuesDefault
startStart method.-mzero, randomzero
restartRestart strategy.-yrandom, best, hybridbest
weightConstraint weight update method.-wsmooth, monotonemonotone
lift_scoringFeasible-phase lift scoring method.-flift_age, lift_randomlift_age
neighbor_scoringInfeasible-phase neighbor scoring method.-nprogress_bonus, progress_ageprogress_bonus
Callback System

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.

InitializationStart::Start_Ctx

Modify initial variable values and use the solver RNG.

RestartRestart::Restart_Ctx

Perturb the current assignment and adjust weights after restart triggers.

WeightWeight::Weight_Ctx

Update constraint and objective weights.

NeighborNeighbor::Neighbor_Ctx

Generate custom move candidates with helper methods.

Neighbor scoringScoring::Neighbor_Ctx

Rank infeasible-phase candidates using progress and tie-breaking state.

Lift scoringScoring::Lift_Ctx

Rank 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.

Model data

m_model_manager, objective coefficients, variable and constraint metadata.

Current state

Current values, best values, activities, constants, equality flags, and weights.

Constraint sets

Unsatisfied and satisfied constraint index lists used by neighbor and scoring logic.

Search status

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/.

Resources

Where to go next