Expand description
§oximo-core
Core modeling types for oximo: Model, Variable, Set, Constraint, Objective, Parameter, IndexedVar, Domain, and ModelKind.
Re-exports oximo-expr types (Expr, ExprArena, ExprId, ExprNode, ParamId, VarId) so downstream code does not need a separate oximo-expr import.
End users typically depend on the umbrella oximo crate rather than this one directly.
§Usage
[dependencies]
oximo-core = "0.1"Or via the umbrella crate (recommended for end users):
[dependencies]
oximo = "0.1"§Quick example
use oximo_core::prelude::*;
let m = Model::new("transport");
// Scalar variables
let x = m.var("x").lb(0.0).build();
let y = m.var("y").lb(0.0).ub(10.0).build();
// Constraints
m.constraint("c1", (x + 2.0 * y).le(14.0));
m.constraint("c2", (3.0 * x - y).ge(0.0));
// Objective
m.maximize(3.0 * x + 4.0 * y);
println!("kind = {:?}", m.kind()); // LP§Model
Model uses interior mutability (RefCell) so the builder API takes &self. This lets you hold a &Model reference, build variables and constraints, and immediately use the returned Expr handles, no &mut threading required.
let m = Model::new("my_model");
let x = m.var("x").lb(0.0).build(); // returns Expr<'_>
m.constraint("cap", x.le(5.0)); // uses x while holding &mNames are unique per registry. Registering a duplicate variable or constraint name panics.
§Accessors
m.num_variables() // usize
m.num_constraints() // usize
m.variables() // Ref<'_, Vec<Variable>>
m.constraints() // Ref<'_, Vec<Constraint>>
m.arena() // Ref<'_, ExprArena>
m.kind() // ModelKind, cached, invalidated on change
m.try_objective() // Result<Objective, Error>
m.variable_id("x") // Option<VarId>
m.constraint_id("cap") // Option<ConstraintId>§Fixing and unfixing variables
m.fix_var(var_id, 3.0); // lb = ub = 3.0
m.unfix_var(var_id, 0.0, 10.0); // restore bounds§Variables
§Scalar variable builder
let x = m.var("x")
.lb(0.0) // lower bound (default: -inf)
.ub(10.0) // upper bound (default: +inf)
.domain(Domain::Real) // explicit domain (default: Real)
.build(); // returns Expr<'_>
// Shorthand domain setters:
let b = m.var("b").binary().build(); // Domain::Binary, bounds [0, 1]
let n = m.var("n").integer().lb(0.0).build(); // Domain::Integer§Indexed variable builder
Creates one scalar variable per key in a Set, named base[key].
let i = Set::range(0..5);
let x = m.indexed_var("x", &i)
.lb(0.0)
.integer()
.build(); // IndexedVar<'_>
// Access by key (panics on missing key):
let expr = x[2]; // or x["name"], x[(a, b)]
// Per-key bounds:
let x = m.indexed_var("x", &i)
.lb_by(|k: usize| lower_bounds[k])
.ub_by(|k: usize| upper_bounds[k])
.build();§Domain
| Variant | Description |
|---|---|
Domain::Real | Any real number (default) |
Domain::Integer | Any integer |
Domain::Binary | 0 or 1 |
Domain::SemiContinuous { threshold } | 0 or any value >= threshold |
Domain::SemiInteger { threshold } | 0 or any integer >= threshold |
§Sets
Set is an ordered finite index set. Three variants:
let i = Set::range(0..5); // Range: i64 keys 0..5
let j = Set::strings(["a", "b", "c"]); // Strings
let k = Set::product(&i, &j); // Tuples: (0,"a"), (0,"b"), ...
let k = &i * &j; // Same via Mul operator
// From sparse ints:
let s = Set::from_ints([0, 2, 4, 8]);
// Filter:
let evens = i.filter(|k| k.as_i64().unwrap() % 2 == 0);§Constraints
§Single constraint
let c_id = m.constraint("name", expr.le(rhs)); // <=
let c_id = m.constraint("name", expr.ge(rhs)); // >=
let c_id = m.constraint("name", expr.eq(rhs)); // ==§Bulk, rule over a set
m.add_constraints_over("supply", &plants, |p: String| {
supply[&p].le(capacity[&p])
});
// Tuple sets, destructure inline:
m.add_constraints_over("flow", &(&plants * &markets), |(p, m): (String, String)| {
x[(&p, &m)].le(capacity[&p])
});§Objectives
m.minimize(cost_expr);
m.maximize(revenue_expr);§Model kind
Inferred automatically from variables and expressions, cached and invalidated on change:
| Kind | Conditions |
|---|---|
LP | All continuous, all linear |
MILP | Any integer/binary, all linear |
QP | All continuous, Mul with ≥2 non-const children |
MIQP | Any integer/binary + quadratic |
NLP | All continuous, Pow/Sin/Cos/Exp/Log |
MINLP | Any integer/binary + nonlinear |
For now, we only support linear constraints, so QP and NLP are not possible. But the API is designed to allow nonlinear constraints in the future without breaking changes.
§License
MIT OR Apache-2.0
Re-exports§
pub use constraint::Constraint;pub use constraint::ConstraintExpr;pub use constraint::ConstraintId;pub use constraint::IntoRhs;pub use constraint::Relate;pub use constraint::Sense;pub use domain::Domain;pub use error::Error;pub use error::Result;pub use indexed::IndexedVar;pub use model::IndexedVarBuilder;pub use model::Model;pub use model::ModelKind;pub use model::display_index_key;pub use objective::Objective;pub use objective::ObjectiveSense;pub use param::Parameter;pub use set::FromIndexKey;pub use set::IndexKey;pub use set::IndexTuple;pub use set::Set;pub use set::SetIter;pub use var::VarBuilder;pub use var::Variable;
Modules§
Structs§
Enums§
- Expr
Node - Here we use a linear fast-path:
sum(coeff * var) + constant. Built by the operator overloads when all children are linear, so LP/MILP construction never walks anAdd(Mul(Const, Var), ...)tree.