lp_solvers/solvers/
auto.rs1use crate::lp_format::{LpObjective, LpProblem};
5use crate::problem::{Problem, StrExpression, Variable};
6#[cfg(feature = "cplex")]
7use crate::solvers::cplex::Cplex;
8use crate::solvers::{CbcSolver, GlpkSolver, GurobiSolver, Solution};
9
10use super::SolverTrait;
11
12#[derive(Debug, Clone)]
14pub struct AutoSolver<SOLVER, NEXT>(SOLVER, NEXT);
15
16#[derive(Debug, Clone, Default)]
18pub struct NoSolver;
19
20#[cfg(not(feature = "cplex"))]
21type Cplex = NoSolver;
22
23pub type AllSolvers = AutoSolver<
25 GurobiSolver,
26 AutoSolver<Cplex, AutoSolver<CbcSolver, AutoSolver<GlpkSolver, NoSolver>>>,
27>;
28
29impl SolverTrait for NoSolver {
30 fn run<'a, P: LpProblem<'a>>(&self, _problem: &'a P) -> Result<Solution, String> {
31 Err("No solver available".to_string())
32 }
33}
34
35impl<A: Default, B: Default> Default for AutoSolver<A, B> {
37 fn default() -> Self {
38 AutoSolver(A::default(), B::default())
39 }
40}
41
42impl<SOLVER: Default, NEXT: Default> AutoSolver<SOLVER, NEXT> {
43 pub fn new() -> Self {
45 Self::default()
46 }
47
48 pub fn with_solver<NewSolver>(self, solver: NewSolver) -> AutoSolver<NewSolver, Self> {
50 AutoSolver(solver, self)
51 }
52}
53
54impl<S: SolverTrait, T: SolverTrait> SolverTrait for AutoSolver<S, T> {
55 fn run<'a, P: LpProblem<'a>>(&self, problem: &'a P) -> Result<Solution, String> {
56 let works = self
58 .0
59 .run(&Problem {
60 name: "dummy".to_string(),
61 sense: LpObjective::Minimize,
62 objective: StrExpression("x".to_string()),
63 variables: vec![Variable {
64 name: "x".to_string(),
65 is_integer: false,
66 lower_bound: 0.0,
67 upper_bound: 1.0,
68 }],
69 constraints: vec![],
70 })
71 .is_ok();
72 if works {
73 self.0.run(problem)
74 } else {
75 self.1.run(problem)
76 }
77 }
78}