lp_solvers/
problem.rs

1//! Concrete implementations for the traits in [crate::lp_format]
2use std::fmt;
3use std::fmt::Formatter;
4
5use crate::lp_format::{AsVariable, Constraint, LpObjective, LpProblem, WriteToLpFileFormat};
6
7/// A string that is a valid expression in the .lp format for the solver you are using
8pub struct StrExpression(pub String);
9
10/// A variable to optimize
11pub struct Variable {
12    /// The variable name should be unique in the problem and have a name accepted by the solver
13    pub name: String,
14    /// Whether the variable is restricted to only integer values
15    pub is_integer: bool,
16    /// -INFINITY if there is no lower bound
17    pub lower_bound: f64,
18    /// INFINITY if there is no upper bound
19    pub upper_bound: f64,
20}
21
22impl WriteToLpFileFormat for StrExpression {
23    fn to_lp_file_format(&self, f: &mut Formatter) -> fmt::Result {
24        f.write_str(&self.0)
25    }
26}
27
28impl AsVariable for Variable {
29    fn name(&self) -> &str {
30        &self.name
31    }
32
33    fn is_integer(&self) -> bool {
34        self.is_integer
35    }
36
37    fn lower_bound(&self) -> f64 {
38        self.lower_bound
39    }
40
41    fn upper_bound(&self) -> f64 {
42        self.upper_bound
43    }
44}
45
46/// A concrete linear problem
47pub struct Problem<EXPR = StrExpression, VAR = Variable> {
48    /// problem name. "lp_solvers_problem" by default
49    /// Write the problem in the lp file format to the given formatter
50    pub name: String,
51    /// Whether to maximize or minimize the objective
52    pub sense: LpObjective,
53    /// Target objective function
54    pub objective: EXPR,
55    /// Variables of the problem
56    pub variables: Vec<VAR>,
57    /// List of constraints to apply
58    pub constraints: Vec<Constraint<EXPR>>,
59}
60
61impl<'a, EXPR: 'a, VAR: 'a> LpProblem<'a> for Problem<EXPR, VAR>
62where
63    &'a VAR: AsVariable,
64    &'a EXPR: WriteToLpFileFormat,
65{
66    type Variable = &'a VAR;
67    type Expression = &'a EXPR;
68    type ConstraintIterator = Box<dyn Iterator<Item = Constraint<&'a EXPR>> + 'a>;
69    type VariableIterator = std::slice::Iter<'a, VAR>;
70
71    fn name(&self) -> &str {
72        &self.name
73    }
74
75    fn variables(&'a self) -> Self::VariableIterator {
76        self.variables.iter()
77    }
78
79    fn objective(&'a self) -> Self::Expression {
80        &self.objective
81    }
82
83    fn sense(&self) -> LpObjective {
84        self.sense
85    }
86
87    fn constraints(&'a self) -> Self::ConstraintIterator {
88        Box::new(
89            self.constraints
90                .iter()
91                .map(|Constraint { lhs, operator, rhs }| Constraint {
92                    lhs,
93                    operator: *operator,
94                    rhs: *rhs,
95                }),
96        )
97    }
98}