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
use crate::lp_format::{LpObjective, LpProblem};
use crate::problem::{Problem, StrExpression, Variable};
#[cfg(feature = "cplex")]
use crate::solvers::cplex::Cplex;
use crate::solvers::{CbcSolver, GlpkSolver, GurobiSolver, Solution};
use super::SolverTrait;
#[derive(Debug, Clone)]
pub struct AutoSolver<SOLVER, NEXT>(SOLVER, NEXT);
#[derive(Debug, Clone, Default)]
pub struct NoSolver;
#[cfg(not(feature = "cplex"))]
type Cplex = NoSolver;
pub type AllSolvers = AutoSolver<
GurobiSolver,
AutoSolver<Cplex, AutoSolver<CbcSolver, AutoSolver<GlpkSolver, NoSolver>>>,
>;
impl SolverTrait for NoSolver {
fn run<'a, P: LpProblem<'a>>(&self, _problem: &'a P) -> Result<Solution, String> {
Err("No solver available".to_string())
}
}
impl<A: Default, B: Default> Default for AutoSolver<A, B> {
fn default() -> Self {
AutoSolver(A::default(), B::default())
}
}
impl<SOLVER: Default, NEXT: Default> AutoSolver<SOLVER, NEXT> {
pub fn new() -> Self {
Self::default()
}
pub fn with_solver<NewSolver>(self, solver: NewSolver) -> AutoSolver<NewSolver, Self> {
AutoSolver(solver, self)
}
}
impl<S: SolverTrait, T: SolverTrait> SolverTrait for AutoSolver<S, T> {
fn run<'a, P: LpProblem<'a>>(&self, problem: &'a P) -> Result<Solution, String> {
let works = self
.0
.run(&Problem {
name: "dummy".to_string(),
sense: LpObjective::Minimize,
objective: StrExpression("x".to_string()),
variables: vec![Variable {
name: "x".to_string(),
is_integer: false,
lower_bound: 0.0,
upper_bound: 1.0,
}],
constraints: vec![],
})
.is_ok();
if works {
self.0.run(problem)
} else {
self.1.run(problem)
}
}
}