use crate::core::abstraction::dp::Problem;
use crate::core::common::{Variable, VarSet, Domain, Decision};
#[derive(Debug, Clone)]
pub struct Minimize<P>(pub P);
impl <T, P: Problem<T>> Problem<T> for Minimize<P> {
fn nb_vars(&self) -> usize {
self.0.nb_vars()
}
fn initial_state(&self) -> T {
self.0.initial_state()
}
fn initial_value(&self) -> i32 {
-self.0.initial_value()
}
fn domain_of<'a>(&self, state: &'a T, var: Variable) -> Domain<'a> {
self.0.domain_of(state, var)
}
fn transition(&self, state: &T, vars: &VarSet, d: Decision) -> T {
self.0.transition(state, vars, d)
}
fn transition_cost(&self, state: &T, vars: &VarSet, d: Decision) -> i32 {
-self.0.transition_cost(state, vars, d)
}
fn impacted_by(&self, state: &T, variable: Variable) -> bool {
self.0.impacted_by(state, variable)
}
}
#[cfg(test)]
mod test_minimize {
use crate::core::abstraction::dp::Problem;
use crate::core::abstraction::solver::Solver;
use crate::core::common::{Variable, VarSet, Domain, Decision};
use crate::core::implementation::dp::Minimize;
use crate::core::implementation::mdd::builder::mdd_builder;
use crate::test_utils::MockRelax;
use crate::core::implementation::solver::parallel::ParallelSolver;
#[derive(Debug, Clone)]
struct DummyPb;
impl Problem<usize> for DummyPb {
fn nb_vars(&self) -> usize { 2 }
fn initial_state(&self) -> usize { 0 }
fn initial_value(&self) -> i32 { 1 }
fn domain_of<'a>(&self, _: &'a usize, _: Variable) -> Domain<'a> {
vec![1, 2, 3].into()
}
fn transition(&self, s: &usize, _: &VarSet, d: Decision) -> usize {
s + d.value as usize
}
fn transition_cost(&self, _: &usize, _: &VarSet, d: Decision) -> i32 {
d.value
}
}
#[test]
fn the_minimize_adapter_has_no_impact_except_for_the_costs() {
let original = DummyPb;
let tested = Minimize(original.clone());
assert_eq!(original.nb_vars(), tested.nb_vars());
assert_eq!(original.initial_state(), tested.initial_state());
let state = 0;
let vars = VarSet::all(3);
let decision = Decision{variable: Variable(2), value: 2};
assert_eq!(
original.transition(&state, &vars, decision),
tested .transition(&state, &vars, decision));
assert_eq!(-original.initial_value(), tested.initial_value());
assert_eq!(
-original.transition_cost(&state, &vars, decision),
tested .transition_cost(&state, &vars, decision))
}
#[test]
fn solver_effectively_minimizes_the_function() {
let pb = DummyPb;
let mdd= mdd_builder(pb, MockRelax::default()).build();
let mut slv= ParallelSolver::new(mdd);
let (opt, sln) = slv.maximize();
assert_eq!(7, opt);
assert_eq!(sln.as_ref().unwrap().clone(), vec![
Decision{variable: Variable(1), value: 3},
Decision{variable: Variable(0), value: 3},
]);
let pb = Minimize(DummyPb);
let mdd= mdd_builder(pb, MockRelax::default()).build();
let mut slv= ParallelSolver::new(mdd);
let (opt, sln) = slv.maximize();
assert_eq!(3, -opt);
assert_eq!(sln.as_ref().unwrap().clone(), vec![
Decision{variable: Variable(1), value: 1},
Decision{variable: Variable(0), value: 1},
]);
}
}