oximo-solver
Solver trait, result types, status codes, and shared option building blocks for oximo.
This crate defines the contract that backend crates implement. End users interact with concrete backends (Highs, Gurobi, Gams) exposed by the umbrella oximo crate, they do not depend on this crate directly unless they are writing a new backend.
Usage
[]
= "0.1"
= "0.1"
Solver trait
Each backend defines its own Options type. Users get compile-time validation and LSP autocomplete on the options that actually apply to that backend.
SolverResult
Populated by the backend on Optimal or Feasible. Sparse maps (FxHashMap) mean backends that don't return duals or reduced costs simply leave those fields empty.
| Field | Type | Description |
|---|---|---|
status |
SolverStatus |
Outcome of the solve |
objective |
Option<f64> |
Objective value |
primal |
FxHashMap<VarId, f64> |
Variable values |
dual |
FxHashMap<ConstraintId, f64> |
Constraint duals (LP only) |
reduced_costs |
FxHashMap<VarId, f64> |
Variable reduced costs (LP only) |
solve_time |
Duration |
Wall time around the solve call |
iterations |
u64 |
Simplex iteration count (if reported) |
raw_log |
Option<String> |
Solver stdout/stderr |
Accessors
result.value_of // Option<f64>, primal value for a Var expr
result.value // Option<f64>, primal value by VarId
result.dual_of // Option<f64>, dual for a constraint
result.status.has_solution // true if Optimal or Feasible
// Indexed variables
result.value_of_idx // Option<f64>, value at a specific index
result.values_of // Iterator<(&IndexKey, f64)>, all entries with a primal value
result.values_of.filter // nonzero only (sparse solutions)
SolverStatus
| Variant | Meaning |
|---|---|
Optimal |
Proven optimal |
Feasible |
Feasible but not proven optimal (e.g. time limit with incumbent) |
Infeasible |
No feasible solution exists |
Unbounded |
Objective is unbounded |
TimeLimit |
Time limit reached with no feasible solution |
NumericError |
Solver reported numerical difficulties |
NotSolved |
Default, solve not yet called |
Other(String) |
Backend-specific status not covered above |
SolverError
| Variant | Cause |
|---|---|
UnsupportedKind(ModelKind) |
Backend does not support this model kind |
NoObjective |
Model has no objective set |
Nonlinear |
Backend cannot handle nonlinear expressions |
Backend(String) |
Backend-reported error (e.g. license failure, bad option) |
Core(Error) |
Error from oximo-core |
Universal options
All backend options structs embed UniversalOptions and implement HasUniversal, which enables the UniversalOptionsExt blanket impl:
use UniversalOptionsExt;
use Duration;
let opts = default
.time_limit
.threads
.verbose;
| Method | Field | Type |
|---|---|---|
.time_limit(Duration) |
time_limit |
Option<Duration> |
.threads(u32) |
threads |
Option<u32> |
.verbose(bool) |
verbose |
Option<bool> |
Implementing HasUniversal for a new backend
use ;
Writing a new backend
Mirror the layout of an existing backend crate (oximo-highs, oximo-gurobi, oximo-gams):
lib.rs: public struct +impl Solver.supports()declares whichModelKinds are handled.solve()delegates totranslate::solve.options.rs: convertsMyOptionsinto the backend's native option calls.translate.rs:Model-> backend conversion and result extraction.
Add an optional dep + feature in oximo/Cargo.toml and re-export the type under oximo::solvers.
License
MIT OR Apache-2.0