1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
use std::convert::TryFrom;
use std::fmt::{Debug, Formatter};
use std::os::raw::c_int;

/// The kinds of results of an optimization
#[derive(Clone, Copy, Debug, PartialOrd, PartialEq, Ord, Eq)]
pub enum HighsModelStatus {
    /// not initialized
    NotSet = 0,
    /// Unable to load model
    LoadError = 1,
    /// invalid model
    ModelError = 2,
    /// Unable to run the pre-solve phase
    PresolveError = 3,
    /// Unable to solve
    SolveError = 4,
    /// Unable to clean after solve
    PostsolveError = 5,
    /// No variables in the model: nothing to optimize
    /// ```
    /// use highs::*;
    /// let mut model = Model::default();
    /// model.set_problem(Problem::default());
    /// let solved = model.solve();
    /// assert_eq!(solved.status(), HighsModelStatus::ModelEmpty);
    /// ```
    ModelEmpty = 6,
    /// There is no solution to the problem
    PrimalInfeasible = 7,
    /// The problem is unbounded: there is no single optimal value
    PrimalUnbounded = 8,
    /// An optimal solution was found
    Optimal = 9,
    /// reached limit
    ReachedDualObjectiveValueUpperBound = 10,
    /// reached limit
    ReachedTimeLimit = 11,
    /// reached limit
    ReachedIterationLimit = 12,
    /// cannot solve dual
    PrimalDualInfeasible = 13,
    /// cannot solve dual
    DualInfeasible = 14,
}

/// This error should never happen: an unexpected status was returned
#[derive(PartialEq, Clone, Copy)]
pub struct InvalidStatus(pub c_int);

impl Debug for InvalidStatus {
    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
        write!(
            f,
            "{} is not a valid HiGHS model status. \
        This error comes from a bug in highs rust bindings. \
        Please report it.",
            self.0
        )
    }
}

impl TryFrom<c_int> for HighsModelStatus {
    type Error = InvalidStatus;

    fn try_from(value: c_int) -> Result<Self, Self::Error> {
        use highs_sys::*;
        match value {
            MODEL_STATUS_NOTSET => Ok(Self::NotSet),
            MODEL_STATUS_LOAD_ERROR => Ok(Self::LoadError),
            MODEL_STATUS_MODEL_ERROR => Ok(Self::ModelError),
            MODEL_STATUS_PRESOLVE_ERROR => Ok(Self::PresolveError),
            MODEL_STATUS_SOLVE_ERROR => Ok(Self::SolveError),
            MODEL_STATUS_POSTSOLVE_ERROR => Ok(Self::PostsolveError),
            MODEL_STATUS_MODEL_EMPTY => Ok(Self::ModelEmpty),
            MODEL_STATUS_PRIMAL_INFEASIBLE => Ok(Self::PrimalInfeasible),
            MODEL_STATUS_PRIMAL_UNBOUNDED => Ok(Self::PrimalUnbounded),
            MODEL_STATUS_OPTIMAL => Ok(Self::Optimal),
            MODEL_STATUS_REACHED_DUAL_OBJECTIVE_VALUE_UPPER_BOUND => {
                Ok(Self::ReachedDualObjectiveValueUpperBound)
            }
            MODEL_STATUS_REACHED_TIME_LIMIT => Ok(Self::ReachedTimeLimit),
            MODEL_STATUS_REACHED_ITERATION_LIMIT => Ok(Self::ReachedIterationLimit),
            MODEL_STATUS_PRIMAL_DUAL_INFEASIBLE => Ok(Self::PrimalDualInfeasible),
            MODEL_STATUS_DUAL_INFEASIBLE => Ok(Self::DualInfeasible),
            n => Err(InvalidStatus(n)),
        }
    }
}

/// The status of a highs operation
#[derive(Clone, Copy, Debug, PartialOrd, PartialEq, Ord, Eq)]
pub enum HighsStatus {
    /// Success
    OK = 0,
    /// Done, with warning
    Warning = 1,
    /// An error occurred
    Error = 2,
}

impl TryFrom<c_int> for HighsStatus {
    type Error = InvalidStatus;

    fn try_from(value: c_int) -> Result<Self, InvalidStatus> {
        use highs_sys::*;
        match value {
            STATUS_OK => Ok(Self::OK),
            STATUS_WARNING => Ok(Self::Warning),
            STATUS_ERROR => Ok(Self::Error),
            n => Err(InvalidStatus(n)),
        }
    }
}