2 unstable releases
Uses new Rust 2024
| 0.2.0 | Jun 7, 2026 |
|---|---|
| 0.1.0 | May 22, 2026 |
#2637 in Algorithms
Used in oximo
225KB
4.5K
SLoC
oximo-gams
GAMS backend for oximo.
Writes an oximo Model to a temporary .gms file, invokes the GAMS executable via std::process::Command, and parses the solution from a PUT-generated text file. Supports LP, MILP, QP, MIQP, NLP, and MINLP model kinds.
The sub-solver is determined by the GAMS installation (default) or set explicitly via GamsOptions::solver. Any solver available in your GAMS distribution can be targeted, see Sub-solver selection below.
Requirements
A licensed GAMS installation must be on PATH.
- Download and install GAMS for your platform.
- Obtain and activate a GAMS license.
- Verify by running
gamsin a terminal.
If gams is not on PATH, pass an explicit path via GamsOptions::gams_path or Gams::with_exec:
use oximo_gams::Gams;
let solver = Gams::with_exec("/opt/gams53/gams");
Usage
Enable the gams feature on the umbrella oximo crate:
[dependencies]
oximo = { version = "0.1", features = ["gams"] }
To use this crate directly:
[dependencies]
oximo-gams = "0.1"
oximo-core = "0.1"
oximo-solver = "0.1"
Quick example
use oximo::prelude::*;
use oximo::solvers::Gams;
let m = Model::new("transport");
let x = m.var("x").lb(0.0).build();
let y = m.var("y").lb(0.0).ub(4.0).build();
m.constraint("c1", (x + 2.0 * y).le(14.0));
m.constraint("c2", (3.0 * x - y).ge(0.0));
m.constraint("c3", (x - y).le(2.0));
m.maximize(3.0 * x + 4.0 * y);
let result = Gams::new().solve(&m, &GamsOptions::default())?;
println!("status = {:?}", result.status);
println!("obj = {:?}", result.objective);
Run the bundled example:
cargo run -p oximo --example reaction_path --features gams
Options
GamsOptions is a plain struct with builder methods. Universal options come from UniversalOptionsExt.
Universal options (via UniversalOptionsExt)
| Method | GAMS statement | Default |
|---|---|---|
.time_limit(Duration) |
option ResLim = <seconds>; |
none |
.threads(usize) |
option threads = <n>; |
none |
.verbose(bool) |
Forwards GAMS stdout/stderr to raw_log (suppresses lo=0) |
none |
GAMS-specific options
| Method | Description | Default |
|---|---|---|
.mip_gap(f64) |
option OptCR = <gap>; relative MIP optimality gap |
none |
.solver(config) |
Sub-solver selection, see below | none |
.gams_path(path) |
Override path to the gams executable |
"gams" from PATH |
use std::time::Duration;
use oximo_gams::GamsOptions;
use oximo_solver::UniversalOptionsExt;
let opts = GamsOptions::default()
.time_limit(Duration::from_secs(300))
.threads(4)
.mip_gap(0.005)
.verbose(true);
Sub-solver selection
Pass a GamsSolverConfig to .solver(...) to select a GAMS sub-solver. This emits
option {LP|MIP|NLP|MINLP|QCP|MIQCP} = <NAME>; in the generated .gms file, scoped to
the solve type resolved from Model::kind() (QP -> QCP, MIQP -> MIQCP).
use oximo_gams::{GamsOptions, GamsSolver, GamsSolverConfig};
// Named selection, no typed option file
let opts = GamsOptions::default().solver(GamsSolver::Cplex);
// Or via Custom for any solver name not in the enum
let opts = GamsOptions::default().solver(GamsSolver::Custom("MOSEK".into()));
Per-solver typed options
Wrap the sub-solver's options struct in GamsSolverConfig to have oximo write a
<solver>.opt file. GAMS picks it up via model.optfile = 1.
use oximo_gams::{GamsBaronOptions, GamsSolverConfig, GamsOptions};
use std::time::Duration;
use oximo_solver::UniversalOptionsExt;
let opts = GamsOptions::default()
.time_limit(Duration::from_secs(120))
.solver(GamsSolverConfig::Baron(GamsBaronOptions {
eps_r: Some(1e-4),
threads: Some(4),
..Default::default()
}));
Supported typed-option structs:
| Struct | Sub-solver | Reference |
|---|---|---|
GamsBaronOptions |
BARON | https://www.gams.com/latest/docs/S_BARON.html |
GamsCbcOptions |
CBC | https://www.gams.com/latest/docs/S_CBC.html |
GamsCplexOptions |
CPLEX | https://www.gams.com/latest/docs/S_CPLEX.html |
GamsGurobiOptions |
GUROBI | https://www.gams.com/latest/docs/S_GUROBI.html |
GamsHighsOptions |
HIGHS | https://www.gams.com/latest/docs/S_HIGHS.html |
GamsIpoptOptions |
IPOPT | https://www.gams.com/latest/docs/S_IPOPT.html |
GamsKnitroOptions |
KNITRO | https://www.gams.com/latest/docs/S_KNITRO.html |
GamsMosekOptions |
MOSEK | https://www.gams.com/latest/docs/S_MOSEK.html |
GamsScipOptions |
SCIP | https://www.gams.com/latest/docs/S_SCIP.html |
GamsXpressOptions |
XPRESS | https://www.gams.com/latest/docs/S_XPRESS.html |
For any other solver, use GamsSolverConfig::Named(GamsSolver::Custom("NAME".into())).
Result
SolverResult fields populated on Optimal or Feasible:
objective- objective valueprimal- variable values keyed byVarId, access viaresult.value_of(var)status- mapped from GAMS model-status codes (1=Optimal,4=Infeasible,3=Unbounded, ...)solve_time- wall time around the GAMS process invocationraw_log- GAMS stdout/stderr, populated whenverbose(true)or when GAMS exits non-zero
dual, reduced_costs, and iterations are not populated by this backend.
License
MIT OR Apache-2.0
Note: GAMS itself is commercial software. A valid GAMS license is required at runtime. This crate is not affiliated with GAMS Development Corporation.
Dependencies
~2.6–3.5MB
~68K SLoC