oximo is a Rust algebraic modeling library for mathematical optimization. Build LP, MILP, QP/MIQP, NLP, and MINLP models with a clean builder API, then solve them with bundled or commercial solvers.
use *;
use Highs;
let m = new;
let x = m.var.lb.build;
let y = m.var.lb.ub.build;
m.constraint;
m.constraint;
m.constraint;
m.maximize;
let result = Highs.solve?;
println!; // 34.0
println!; // 6.0
println!; // 4.0
# Ok::
Building models
Variables
let m = new;
let x = m.var.lb.build; // continuous, x >= 0
let y = m.var.lb.ub.build; // continuous, 0 <= y <= 10
let z = m.var.build; // free (unbounded by default)
let b = m.var.binary.build; // binary {0, 1}
let n = m.var.lb.integer.build; // general integer
Constraints and objectives
Expressions are built with standard Rust operators. Scalar multiplication, addition, subtraction, and nonlinear operations (see Nonlinear Expressions) all work out of the box:
m.constraint;
m.constraint;
m.constraint;
m.minimize;
// or
m.maximize;
Index sets
Set is the modeling-layer container for an ordered, finite index set. Build
one over integers, strings, or arbitrary tuples. You can combine sets with the
Cartesian product operator &a * &b, and filter sparsely.
use *;
let items = range;
let n_items = range;
let plants = strings;
// Cartesian product -> tuple keys, flattens automatically across nesting.
let routes = &plants * &strings;
assert_eq!;
// Sparse subsets via filter without self-loops
let arcs = .filter;
Indexed variables
Model::indexed_var(name, &set) registers one scalar per key with auto-named
entries like x[seattle,nyc]. Bounds apply uniformly by default, you can use
lb_by / ub_by for per-key bounds.
let m = new;
let x = m.indexed_var.lb.build;
// Scalar lookup: any type that converts to IndexKey works.
let e1 = x;
let e2 = x;
// Per-key upper bound (e.g. capacity per arc).
let _y = m.indexed_var
.lb
.ub_by
.build;
Summing over sets
sum_over(&set, |k| expr) reads as sum_{k in set} expr(k). The closure
receives the index as a typed value via FromIndexKey. Built-in impls cover
i64, i32, usize, String, raw IndexKey, and tuples up to arity 4.
State the shape in the closure-arg annotation.
// Single sum: sum_{i in items} weights[i] * x[i]
let total_weight = sum_over;
m.constraint;
// Double sum, flat: sum_{(p,q) in P*M} c[p,q] * x[p,q]
let total_cost = sum_over;
// Coefficient-weighted sum on paired Vecs: sum_{i} w_i * x_i
let weight_sum = dot;
// Freeform iterator -> use Iterator::sum.
let active = .filter.map.;
Rule-style constraints
Model::add_constraints_over is the constraint equivalent of sum_over, a
closure receives the index as a typed value and returns one constraint per
set element.
// Scalar set: one constraint per period.
let periods = range;
m.add_constraints_over;
// Tuple set: destructure inline. Inner `sum_over` builds the LHS expression.
m.add_constraints_over;
// Want the raw key? Annotate as IndexKey (clones once per iteration).
m.add_constraints_over;
Nonlinear expressions
Pow, Sin, Cos, Exp, Log, Abs, and bilinear products are first-class. The
model's kind (LP/MILP/QP/MIQP/NLP/MINLP) is inferred from the
expressions.
// Rosenbrock NLP
m.minimize;
// Quadratic constraint
m.constraint;
// Transcendental utility (MINLP when any variable is integer/binary)
m.maximize;
Solving
All backends implement the Solver trait:
Features
| Feature | What it adds | Default |
|---|---|---|
highs |
HiGHS - LP/MILP/QP solver (bundled, no install) | yes |
io |
MPS and LP file writers | yes |
gurobi |
Gurobi - LP/MILP/QP/MIQP/NLP/MINLP solver (requires licensed install) | no |
gams |
GAMS bridge - LP/MILP/QP/MIQP/NLP/MINLP depending on solver | no |
baron |
BARON - LP/MILP/QP/MIQP/NLP/MINLP solver (requires licensed install) | no |
HiGHS (default)
No install required, HiGHS is compiled from source via the highs crate.
use *;
use Highs;
let result = Highs.solve?;
Gurobi
Requires a licensed Gurobi install and GUROBI_HOME set. See crates/oximo-gurobi/README.md.
use *;
use Gurobi;
let result = Gurobi.solve?;
GAMS
Requires GAMS on PATH. Supports solving models via GAMS solvers (CPLEX, BARON, etc.). See crates/oximo-gams/README.md.
use *;
use Gams;
let result = Gams.solve?;
BARON
Requires a licensed BARON install on PATH. Global solver for nonconvex LP/MILP/QP/MIQP/NLP/MINLP. See crates/oximo-baron/README.md.
use *;
use Baron;
let result = new.solve?;
Reading results
let result = Highs.solve?;
match result.status
// Variable values
let x_val = result.value_of; // Option<f64>
// Constraint duals (LP only)
let dual = result.dual.get;
// Reduced costs
let rc = result.reduced_costs.get;
Model export
With the io feature (default), you can export models to MPS, LP and NL format for inspection or use with external solvers.
Requirements
- Gurobi feature: Gurobi,
GUROBI_HOMEset, valid license - GAMS feature: GAMS on
PATH, valid license - BARON feature: BARON on
PATH, valid license
License
MIT OR Apache-2.0