ellp 0.2.0

Linear programming library that provides primal and dual simplex solvers.
Documentation
use crate::error::EllPError;
use crate::standard_form::{BasicPoint, Point, StandardForm};

pub type EllPResult = Result<SolverResult, EllPError>;

#[derive(Debug)]
pub enum SolverResult {
    Optimal(Solution),
    Infeasible,
    Unbounded,
    MaxIter { obj: f64 },
}

impl std::fmt::Display for SolverResult {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        match self {
            Self::Optimal(sol) => write!(f, "found optimal point with objective {}", sol.obj()),
            Self::Infeasible => write!(f, "problem is infeasible"),
            Self::Unbounded => write!(f, "problem is unbounded"),
            Self::MaxIter { obj } => {
                write!(f, "reached max iterations, current objective = {}", obj)
            }
        }
    }
}

#[derive(Debug)]
pub enum SolutionStatus {
    Optimal,
    Infeasible,
    Unbounded,
    MaxIter,
}

#[derive(Debug)]
pub struct Solution {
    std_form: StandardForm,
    point: OptimalPoint,
}

impl Solution {
    pub fn new(std_form: StandardForm, point: OptimalPoint) -> Self {
        Self { std_form, point }
    }

    #[inline]
    pub fn obj(&self) -> f64 {
        self.std_form.obj(&self.point.x)
    }

    pub fn x(&self) -> nalgebra::DVectorSlice<f64> {
        self.std_form.extract_solution(&self.point)
    }
}

#[derive(Debug)]
pub struct OptimalPoint(Point);

impl OptimalPoint {
    pub fn new(point: Point) -> Self {
        Self(point)
    }
}

impl BasicPoint for OptimalPoint {
    #[inline]
    fn into_pt(self) -> Point {
        self.0
    }
}

impl std::ops::Deref for OptimalPoint {
    type Target = Point;

    #[inline]
    fn deref(&self) -> &Self::Target {
        &self.0
    }
}

impl std::ops::DerefMut for OptimalPoint {
    #[inline]
    fn deref_mut(&mut self) -> &mut Self::Target {
        &mut self.0
    }
}