oximo-baron
BARON (Branch-And-Reduce Optimization Navigator) backend for oximo.
Writes an oximo Model to a temporary .bar file, invokes the BARON executable via std::process::Command, and parses the solution from BARON's times (tim.lst) and results (res.lst) files. Supports LP, MILP, QP, MIQP, NLP, and MINLP model kinds.
BARON is a global optimizer for nonconvex MINLP.
Requirements
- Install BARON for your platform.
- Obtain and activate a BARON license.
- Verify by running
baronin a terminal.
If baron is not on PATH, pass an explicit path via BaronOptions::baron_path or Baron::with_exec:
use Baron;
let solver = with_exec;
Usage
Enable the baron feature on the umbrella oximo crate:
[]
= { = "0.5.1", = ["baron"] }
To use this crate directly:
[]
= "0.5.1"
= "0.5.1"
= "0.5.1"
Quick example
use *;
use Baron;
let m = new;
variable!;
variable!;
constraint!;
objective!;
let result = new.solve?;
println!;
println!;
println!;
Run the bundled example:
Options
BaronOptions is a plain struct with builder methods. Universal options come from UniversalOptionsExt. Every other knob maps to a BARON keyword written into the OPTIONS{ ... } block of the generated .bar file.
Universal options (via UniversalOptionsExt)
| Method | BARON option | Default |
|---|---|---|
.time_limit(Duration) |
MaxTime: <seconds> |
none |
.threads(u32) |
threads: <n> |
none |
.verbose(bool) |
PrLevel: 1/0 |
none |
BARON-specific options
Each builder method is the snake_case form of a BARON keyword. Highlights:
| Method | BARON option | Description |
|---|---|---|
.eps_r(f64) |
EpsR |
Relative termination tolerance |
.eps_a(f64) |
EpsA |
Absolute termination tolerance |
.max_iter(i64) |
MaxIter |
Node limit (-1 = unlimited) |
.num_sol(i64) |
NumSol |
Number of feasible solutions to find |
.first_feas(bool) |
FirstFeas |
Stop at first feasible solution |
.num_loc(i64) |
NumLoc |
Multistart local searches (-1 = automatic) |
.want_dual(bool) |
WantDual |
Return duals at the best primal point |
.lp_sol(i64) |
LPSol |
LP subsolver selection |
.nlp_sol(i64) |
NLPSol |
NLP subsolver selection |
.pr_level(i64) |
PrLevel |
Print level (0 silent) |
.baron_path(path) |
- | Override path to the baron executable |
See the BARON manual for the full set (branching, range-reduction, and feasibility-tolerance options are all exposed). For any keyword without a dedicated builder, use the escape hatch:
// Note: The following options ARE exposed in the BaronOptions builder
use BaronOptions;
let opts = default.raw.raw;
use Duration;
use BaronOptions;
use UniversalOptionsExt;
let opts = default
.time_limit
.threads
.eps_r
.verbose;
ResName, TimName, results, and times are managed by the backend (it needs those files to parse the solution) and cannot be overridden. Every other documented BARON option has a dedicated builder. MaxTime/threads/PrLevel come from the universal options. When no time_limit is set, the backend emits MaxTime: -1 (no limit) so BARON does not silently fall back to its own default.
Limitations
BARON's .bar format has no trigonometric intrinsics, so a model whose objective or constraints contain sin/cos is rejected with a clear SolverError::Backend. A variable-exponent power x^y is rewritten to the equivalent exp(y*log(x)), and an absolute value |x| to (x^2)^(1/2), both as suggested by the BARON manual. Symbolic parameters and semicontinuous/semi-integer variables are not representable in .bar and are likewise rejected.
Result
SolverResult fields, populated whenever a usable point is available (primal_status is FeasiblePoint or OptimalPoint):
solutions: primal points (Vec<SolutionPoint>), best first. Each point holds itsprimalvalues keyed byVarIdand itsobjective. With.num_sol(n)BARON enumerates up tondistinct solutions into the pool, otherwise the vector holds the single incumbent. Access the best point viaresult.objective()/result.value_of(var)and the rest viaresult.solution(i)dual: constraint marginals at the best point, keyed byConstraintId, access viaresult.dual_of(c)reduced_costs: variable marginals at the best point, keyed byVarIdtermination: why the solve stopped, read from BARON'sres.lsttermination bannerprimal_status: whether a usable point came back (NoSolution/FeasiblePoint/OptimalPoint),result.has_solution()is the shortcutbest_bound: BARON's relaxation/dual bound (the bound opposite the incumbent)gap: relative optimality gap from BARON's lower/upper bounds, when both are finitesolve_time: wall time around the BARON process invocationiterations: branch-and-reduce iteration count fromtim.lstraw_log: BARON stdout/stderr, captured when BARON exits non-zero in quiet mode. Withverbose(true)the output is streamed live to the terminal and not captured (raw_logisNone)
Acknowledgements
We would like to thank The Optimization Firm for providing a BARON license for development and testing of this crate.
License
MIT OR Apache-2.0
Note: BARON itself is commercial software. A valid BARON license is required at runtime. This crate is not affiliated with The Optimization Firm.