Results

Inspect solver status, solutions, duals, and solution pools.

Every oximo backend returns the same SolverResult. Read it the same way independently of the solver. It is recommended to first check what stopped the solve and whether a usable point is available, then inspect the values relevant to your application.

🔗Reading results

The quickest option is the built-in report, which renders a model-aware summary:

print!("{}", result.report(&m));

For programmatic access, SolverResult separates why the solver stopped from whether a usable point came back. That split matters because, for example, a run that hits a time limit can still carry a good incumbent.

let result = Highs.solve(&m, &HighsOptions::default())?;

match result.termination {
    TerminationStatus::Optimal => {
        // `objective()` is Option, since a model may have no objective.
        if let Some(obj) = result.objective() {
            println!("optimal: {obj}");
        }
    }
    TerminationStatus::Infeasible => println!("infeasible"),
    TerminationStatus::TimeLimit if result.has_solution() => {
        println!("time limit, best = {:?}", result.objective());
    }
    _ => {}
}

let x_val = result.value_of(x);            // Option<f64>
let dual  = result.dual_of(constraint_id); // Option<f64>

🔗Status

TerminationStatus says why the solver stopped: Optimal, LocallyOptimal, Feasible, Infeasible, Unbounded, InfeasibleOrUnbounded, IterationLimit, TimeLimit, NodeLimit, Interrupted, NumericError, NotSolved, or Other(String) for an unmapped backend status.

PrimalStatus says what you actually got: NoSolution, FeasiblePoint, or OptimalPoint. result.has_solution() is the shorthand. Always check it before trusting a value.

🔗Fields and accessors

ItemTypeWhat information is available
terminationTerminationStatusWhy the solver stopped
primal_statusPrimalStatusWhether a usable point is present
objective()Option<f64>Objective of the best solution
value_of(expr)Option<f64>Primal value for a variable or indexed element
values_of(&var)iterator of (&IndexKey, f64)Every element of an indexed variable
dual_of(id)Option<f64>Shadow price (continuous models)
reduced_costsmap keyed by VarIdReduced costs (continuous models)
best_bound, gapOption<f64>Populated by branch-and-bound backends
solve_timeDurationWall-clock time in the backend
iterationsu64Iteration count when the backend reports one
raw_logOption<String>Backend log, when captured

🔗Indexed variables

values_of walks an indexed family without a manual key loop:

for (key, value) in result.values_of(&x) {
    println!("x[{}] = {value:.2}", display_index_key(key));
}

🔗Solution pools

Backends that can return multiple points expose them, best-first:

for i in 0..result.result_count() {
    let point = result.solution(i).unwrap();
    println!("objective {:?}", point.objective);
}

🔗Next steps

  • Solvers: choose a backend and set its options
  • Printing & Debugging: inspect the model that produced a result
  • I/O: export a model for inspection in another tool