Skip to main content

Crate oximo_core

Crate oximo_core 

Source
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 &m

Names 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

VariantDescription
Domain::RealAny real number (default)
Domain::IntegerAny integer
Domain::Binary0 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:

KindConditions
LPAll continuous, all linear
MILPAny integer/binary, all linear
QPAll continuous, Mul with ≥2 non-const children
MIQPAny integer/binary + quadratic
NLPAll continuous, Pow/Sin/Cos/Exp/Log
MINLPAny 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§

constraint
domain
error
indexed
model
objective
param
prelude
set
var

Structs§

Expr
Lightweight handle to a node in an ExprArena.
ExprArena
ExprId
ParamId
VarId

Enums§

ExprNode
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 an Add(Mul(Const, Var), ...) tree.