Documentation
¶
Overview ¶
Package milp is a pure-Go mixed-integer linear programming solver.
It defines and solves linear programs (LP) and mixed-integer linear programs (MILP): decision variables with lower/upper bounds and a kind (continuous, integer, or binary), a single linear objective to minimize or maximize, and linear constraints (<=, >=, =). Solve returns the optimal objective value, the variable values, and a status.
The LP relaxation is solved with a native, pure-Go sparse revised simplex (bounded-variable, with a Gilbert–Peierls sparse-LU basis factorization and product-form updates); integrality is enforced by a branch-and-bound search with warm-started re-solves and pseudocost branching over the integer and binary variables. The default build is pure Go and links zero C and zero third-party runtime dependencies: CGO_ENABLED=0 go build ./... succeeds.
GLPK (via cgo) is used only as a parity oracle in the build-tagged parity tests under internal/parity_tests; it is never a runtime backend. gonum is a test-only differential cross-check and is not imported by any runtime code.
Concurrency ¶
A Model is not safe for concurrent modification. Solve does not mutate the Model and may be called concurrently on the same Model from multiple goroutines; each call allocates its own working state.
Model building ¶
Construct a Model, add variables, set the objective, add constraints, and Solve:
m := milp.NewModel()
x := m.AddInteger(0, 10)
y := m.AddContinuous(0, milp.Inf)
m.SetObjective(milp.Maximize, []milp.Term{{x, 3}, {y, 2}})
m.AddConstraint([]milp.Term{{x, 1}, {y, 1}}, milp.LessEq, 4)
sol, err := m.Solve()
Index ¶
- Variables
- type Constraint
- type Model
- func (m *Model) AddBinary() Var
- func (m *Model) AddConstraint(terms []Term, rel Relation, rhs float64) Constraint
- func (m *Model) AddContinuous(lower, upper float64) Var
- func (m *Model) AddInteger(lower, upper float64) Var
- func (m *Model) AddVar(lower, upper float64, kind VarKind) Var
- func (m *Model) NumConstraints() int
- func (m *Model) NumVars() int
- func (m *Model) SetObjective(sense Sense, terms []Term)
- func (m *Model) Solve() (*Solution, error)
- func (m *Model) SolveWith(opts Options) (*Solution, error)
- func (m *Model) SolveWithStats(opts Options) (*Solution, SolveStats, error)
- type Options
- type Relation
- type Sense
- type Solution
- type SolveStats
- type Solver
- type Status
- type Term
- type Var
- type VarKind
Constants ¶
This section is empty.
Variables ¶
var ( // ErrNoObjective is returned by Solve when no objective has been set. ErrNoObjective = errors.New("milp: no objective set") // ErrNoVariables is returned by Solve when the model has no variables. ErrNoVariables = errors.New("milp: model has no variables") // ErrInvalidBounds is returned by an AddVar call whose lower bound exceeds // its upper bound, or whose bound is NaN. ErrInvalidBounds = errors.New("milp: variable lower bound exceeds upper bound") // ErrUnknownVar is returned when a Term references a variable that does not // belong to the model being solved. ErrUnknownVar = errors.New("milp: term references a variable from another model") // ErrInvalidCoef is returned when a coefficient or right-hand side is NaN or // infinite. ErrInvalidCoef = errors.New("milp: coefficient or right-hand side is not finite") // ErrNodeLimit is returned by Solve when the branch-and-bound node limit was // reached before the search completed. Any incumbent found is still returned // in the Solution. ErrNodeLimit = errors.New("milp: branch-and-bound node limit reached") // ErrTimeLimit is returned by Solve when Options.TimeLimit elapsed before the // search completed. Any incumbent found is still returned in the Solution, // with BestBound and Gap reporting the proven optimality gap. ErrTimeLimit = errors.New("milp: branch-and-bound time limit reached") // ErrNumeric is returned when the underlying LP solver fails for numeric or // structural reasons (singular basis, cycling, ill-conditioning) that are // neither infeasibility nor unboundedness. ErrNumeric = errors.New("milp: linear relaxation failed numerically") )
Sentinel errors returned by the milp package. Every message is prefixed with "milp:".
var ( Inf = math.Inf(1) NegInf = math.Inf(-1) )
Inf and NegInf are the positive and negative infinities used to express an absent upper or lower bound on a variable.
Functions ¶
This section is empty.
Types ¶
type Constraint ¶
type Constraint struct {
// contains filtered or unexported fields
}
Constraint is an opaque handle to a linear constraint within one Model.
func (Constraint) ID ¶
func (c Constraint) ID() int
ID returns the constraint's zero-based index within its Model.
type Model ¶
type Model struct {
// contains filtered or unexported fields
}
Model builds a linear or mixed-integer linear program. Construct one with NewModel, add variables and constraints, set an objective, then Solve.
A Model is not safe for concurrent modification. Solve is read-only and may be called concurrently on the same Model.
func (*Model) AddConstraint ¶
func (m *Model) AddConstraint(terms []Term, rel Relation, rhs float64) Constraint
AddConstraint adds the linear constraint (sum of terms) rel rhs and returns a handle to it. Terms referencing the same variable are summed.
func (*Model) AddContinuous ¶
AddContinuous adds a continuous variable in [lower, upper].
func (*Model) AddInteger ¶
AddInteger adds an integer variable in [lower, upper].
func (*Model) AddVar ¶
AddVar adds a variable with the given lower and upper bounds and kind, and returns a handle to it. Use Inf / NegInf for an absent upper / lower bound. For a Binary variable the bounds are ignored and set to [0, 1].
If the bounds are invalid (lower > upper, or NaN) the returned handle is still usable but Solve will fail with ErrInvalidBounds.
func (*Model) NumConstraints ¶
NumConstraints reports the number of constraints added to the model.
func (*Model) SetObjective ¶
SetObjective sets the optimization sense and the linear objective. Terms with the same variable are summed; variables absent from terms have coefficient zero. Calling SetObjective again replaces the objective.
func (*Model) Solve ¶
Solve solves the model with DefaultOptions using the built-in branch-and-bound solver and returns the Solution.
Solve does not mutate the Model and is safe for concurrent use on the same Model. It returns a build error (ErrInvalidBounds, ErrUnknownVar, ErrInvalidCoef), ErrNoVariables, or ErrNoObjective when the model is malformed; ErrNumeric when the LP relaxation fails numerically; and ErrNodeLimit when branch-and-bound is truncated by Options.NodeLimit (the best incumbent, if any, is still returned in the Solution).
func (*Model) SolveWithStats ¶
func (m *Model) SolveWithStats(opts Options) (*Solution, SolveStats, error)
SolveWithStats solves the model with the given Options and additionally returns SolveStats: branch-and-bound node count, LP relaxations solved, total simplex pivots, basis factorizations, and warm-started re-solves. The stats are diagnostic only; the Solution and error are exactly as SolveWith returns.
type Options ¶
type Options struct {
// IntegralityTol is the tolerance for treating an LP value as integral: a
// value within IntegralityTol of the nearest integer is considered integer.
IntegralityTol float64
// LPTolerance is the optimality tolerance on the reduced costs used by the LP
// relaxation.
LPTolerance float64
// NodeLimit caps the number of LP relaxations solved during
// branch-and-bound. Zero means no limit. When the limit is reached the best
// incumbent found so far is returned together with ErrNodeLimit.
NodeLimit int
// MaxDepth caps the branch-and-bound tree depth. Zero means no limit.
MaxDepth int
// TimeLimit caps the wall-clock time of the search. Zero means no limit. When
// the limit is reached the best incumbent found so far is returned together
// with ErrTimeLimit, and the Solution's BestBound and Gap report the proven
// optimality gap at that point (an anytime answer).
TimeLimit time.Duration
// RelativeGap stops the search once the proven relative optimality gap
// (Objective − BestBound) / (|Objective| + 1e-10) drops to or below this
// value. Zero means solve to proven optimality (gap 0).
RelativeGap float64
// AbsoluteGap stops the search once the proven absolute gap
// |Objective − BestBound| drops to or below this value. Zero means solve to
// proven optimality.
AbsoluteGap float64
// IncumbentCallback, when non-nil, is invoked each time branch-and-bound
// finds a new best integer-feasible solution, with the objective (in the
// model's own sense) and a copy of the variable values. It must not retain or
// mutate the slice beyond the call and must not call back into the solver.
IncumbentCallback func(objective float64, values []float64)
// DisableCuts turns off root Gomory cut generation. Cuts are on by default;
// they tighten the relaxation of integer-heavy problems (a no-op on already
// tight models like the energy shape).
DisableCuts bool
// DisablePresolve turns off the root presolve pass (activity-based bound
// propagation, singleton/duplicate/redundant rows, binary coefficient
// tightening). Presolve is on by default and never eliminates a variable, so
// it is transparent to the returned solution.
DisablePresolve bool
}
Options tunes the branch-and-bound search and the LP relaxation.
func DefaultOptions ¶
func DefaultOptions() Options
DefaultOptions returns the options used by Model.Solve.
type Relation ¶
type Relation uint8
Relation is the comparison operator of a linear constraint.
type Sense ¶
type Sense uint8
Sense is the optimization direction of the objective.
type Solution ¶
type Solution struct {
// Status is the solve outcome.
Status Status
// Objective is the objective value in the Model's own sense (already negated
// back for Maximize problems). It is meaningful only when Status is Optimal.
Objective float64
// Values holds the optimal value of every variable, indexed by Var.ID.
// It is nil when no feasible solution was found.
Values []float64
// BestBound is the best proven dual bound on the objective in the Model's own
// sense: a lower bound for Minimize, an upper bound for Maximize. When the
// search completes it equals Objective (proven optimal); when the search is
// truncated (time/node limit or a requested gap) it bounds how far the
// incumbent could still be from optimal.
BestBound float64
// Gap is the relative optimality gap |Objective − BestBound| / (|Objective| +
// 1e-10). It is 0 (within rounding) when the solution is proven optimal.
Gap float64
}
Solution is the result of solving a Model.
type SolveStats ¶
type SolveStats struct {
// Nodes is the number of branch-and-bound nodes explored.
Nodes int
// LPSolves is the number of LP relaxations solved (root + nodes).
LPSolves int
// SimplexPivots is the total number of simplex pivots across all relaxations.
SimplexPivots int
// Refactorizations is the total number of basis factorizations.
Refactorizations int
// WarmStarts is the number of relaxations started from a parent basis.
WarmStarts int
// Cuts is the number of Gomory cutting planes added at the root.
Cuts int
// CutRounds is the number of root cut-generation rounds performed.
CutRounds int
}
SolveStats reports diagnostics from the native LP/branch-and-bound core.
type Solver ¶
Solver solves a Model and returns its Solution. NewSolver returns the built-in branch-and-bound solver; the interface allows callers to substitute their own.
type Status ¶
type Status uint8
Status is the outcome of a solve.
type Var ¶
type Var struct {
// contains filtered or unexported fields
}
Var is an opaque handle to a decision variable within one Model. The zero Var is not valid; obtain one from a Model's AddVar family.
type VarKind ¶
type VarKind uint8
VarKind is the integrality class of a decision variable.
Source Files
¶
Directories
¶
| Path | Synopsis |
|---|---|
|
examples
|
|
|
knapsack
command
Command knapsack demonstrates solving a 0/1 knapsack problem with go-milp.
|
Command knapsack demonstrates solving a 0/1 knapsack problem with go-milp. |
|
internal
|
|
|
testproblems
Package testproblems defines a solver-neutral description of LP/MILP problems and generators for them, shared by the pure-Go unit tests and the build-tagged GLPK parity oracle.
|
Package testproblems defines a solver-neutral description of LP/MILP problems and generators for them, shared by the pure-Go unit tests and the build-tagged GLPK parity oracle. |
|
tools
|
|
|
llmsgen
command
Command llmsgen regenerates llms.txt and llms-full.txt at the repository root from the README and the Go API reference, following the llms.txt convention (https://llmstxt.org).
|
Command llmsgen regenerates llms.txt and llms-full.txt at the repository root from the README and the Go API reference, following the llms.txt convention (https://llmstxt.org). |