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
use std::fmt;
use std::fmt::Formatter;
use crate::lp_format::{AsVariable, Constraint, LpObjective, LpProblem, WriteToLpFileFormat};
pub struct StrExpression(pub String);
pub struct Variable {
pub name: String,
pub is_integer: bool,
pub lower_bound: f64,
pub upper_bound: f64,
}
impl WriteToLpFileFormat for StrExpression {
fn to_lp_file_format(&self, f: &mut Formatter) -> fmt::Result {
f.write_str(&self.0)
}
}
impl AsVariable for Variable {
fn name(&self) -> &str {
&self.name
}
fn is_integer(&self) -> bool {
self.is_integer
}
fn lower_bound(&self) -> f64 {
self.lower_bound
}
fn upper_bound(&self) -> f64 {
self.upper_bound
}
}
pub struct Problem<EXPR = StrExpression, VAR = Variable> {
pub name: String,
pub sense: LpObjective,
pub objective: EXPR,
pub variables: Vec<VAR>,
pub constraints: Vec<Constraint<EXPR>>,
}
impl<'a, EXPR: 'a, VAR: 'a> LpProblem<'a> for Problem<EXPR, VAR>
where
&'a VAR: AsVariable,
&'a EXPR: WriteToLpFileFormat,
{
type Variable = &'a VAR;
type Expression = &'a EXPR;
type ConstraintIterator = Box<dyn Iterator<Item = Constraint<&'a EXPR>> + 'a>;
type VariableIterator = std::slice::Iter<'a, VAR>;
fn name(&self) -> &str {
&self.name
}
fn variables(&'a self) -> Self::VariableIterator {
self.variables.iter()
}
fn objective(&'a self) -> Self::Expression {
&self.objective
}
fn sense(&self) -> LpObjective {
self.sense
}
fn constraints(&'a self) -> Self::ConstraintIterator {
Box::new(
self.constraints
.iter()
.map(|Constraint { lhs, operator, rhs }| Constraint {
lhs,
operator: *operator,
rhs: *rhs,
}),
)
}
}