1use std::time::Duration;
2
3use oximo_core::{ConstraintId, Expr, ExprNode, IndexKey, IndexedVar, VarId};
4use rustc_hash::FxHashMap;
5
6use crate::status::SolverStatus;
7
8#[derive(Clone, Debug)]
11pub struct SolverResult {
12 pub status: SolverStatus,
13 pub objective: Option<f64>,
14 pub primal: FxHashMap<VarId, f64>,
15 pub dual: FxHashMap<ConstraintId, f64>,
16 pub reduced_costs: FxHashMap<VarId, f64>,
17 pub solve_time: Duration,
18 pub iterations: u64,
19 pub raw_log: Option<String>,
20}
21
22impl Default for SolverResult {
23 fn default() -> Self {
24 Self {
25 status: SolverStatus::NotSolved,
26 objective: None,
27 primal: FxHashMap::default(),
28 dual: FxHashMap::default(),
29 reduced_costs: FxHashMap::default(),
30 solve_time: Duration::ZERO,
31 iterations: 0,
32 raw_log: None,
33 }
34 }
35}
36
37impl SolverResult {
38 pub fn value(&self, id: VarId) -> Option<f64> {
40 self.primal.get(&id).copied()
41 }
42
43 pub fn value_of(&self, expr: Expr<'_>) -> Option<f64> {
48 let arena = expr.arena.borrow();
49 match arena.get(expr.id) {
50 ExprNode::Var(v) => self.primal.get(v).copied(),
51 _ => None,
52 }
53 }
54
55 pub fn dual_of(&self, c: ConstraintId) -> Option<f64> {
56 self.dual.get(&c).copied()
57 }
58
59 pub fn value_of_idx<K: Into<IndexKey>>(&self, var: &IndexedVar<'_>, key: K) -> Option<f64> {
64 var.get(key).and_then(|e| self.value_of(e))
65 }
66
67 pub fn values_of<'iv, 'a>(
73 &'iv self,
74 var: &'iv IndexedVar<'a>,
75 ) -> impl Iterator<Item = (&'iv IndexKey, f64)> + 'iv {
76 var.iter().filter_map(|(k, e)| self.value_of(*e).map(|v| (k, v)))
77 }
78}