1use std::fmt;
3use std::fmt::Formatter;
4
5use crate::lp_format::{AsVariable, Constraint, LpObjective, LpProblem, WriteToLpFileFormat};
6
7pub struct StrExpression(pub String);
9
10pub struct Variable {
12 pub name: String,
14 pub is_integer: bool,
16 pub lower_bound: f64,
18 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
46pub struct Problem<EXPR = StrExpression, VAR = Variable> {
48 pub name: String,
51 pub sense: LpObjective,
53 pub objective: EXPR,
55 pub variables: Vec<VAR>,
57 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}