use std::cmp::Ordering;
use compare::Compare;
use crate::core::abstraction::heuristics::{LoadVars, VariableHeuristic, WidthHeuristic};
use crate::core::common::{Layer, Node, Variable, VarSet};
#[derive(Debug, Clone)]
pub struct NbUnassigned;
impl WidthHeuristic for NbUnassigned {
fn max_width(&self, free: &VarSet) -> usize {
free.len()
}
}
#[derive(Debug, Clone)]
pub struct FixedWidth(pub usize);
impl WidthHeuristic for FixedWidth {
fn max_width(&self, _free: &VarSet) -> usize {
self.0
}
}
#[derive(Default, Debug, Clone)]
pub struct NaturalOrder;
impl <T> VariableHeuristic<T> for NaturalOrder {
fn next_var<'a>(&self, free_vars: &'a VarSet, _c: Layer<'a, T>, _n: Layer<'a, T>) -> Option<Variable> {
free_vars.iter().next()
}
}
#[derive(Debug, Default, Clone)]
pub struct MinLP;
impl <T> Compare<Node<T>> for MinLP {
fn compare(&self, a: &Node<T>, b: &Node<T>) -> Ordering {
a.info.lp_len.cmp(&b.info.lp_len)
}
}
#[derive(Debug, Default, Clone)]
pub struct MaxUB;
impl <T> Compare<Node<T>> for MaxUB {
fn compare(&self, a: &Node<T>, b: &Node<T>) -> Ordering {
a.info.ub.cmp(&b.info.ub).then_with(|| a.info.lp_len.cmp(&b.info.lp_len))
}
}
#[derive(Debug, Clone)]
pub struct FromLongestPath {
all_vars: VarSet
}
impl FromLongestPath {
pub fn new(all_vars: VarSet) -> FromLongestPath {
FromLongestPath { all_vars }
}
}
impl <T> LoadVars<T> for FromLongestPath {
fn variables(&self, node: &Node<T>) -> VarSet {
let mut vars = self.all_vars.clone();
for d in node.info.longest_path() {
vars.remove(d.variable);
}
vars
}
}
#[cfg(test)]
mod test_nbunassigned {
use crate::core::common::{Variable, VarSet};
use crate::core::abstraction::heuristics::WidthHeuristic;
use crate::core::implementation::heuristics::NbUnassigned;
#[test]
fn non_empty() {
let mut var_set = VarSet::all(5); var_set.remove(Variable(1)); var_set.remove(Variable(3));
var_set.remove(Variable(4));
assert_eq!(2, NbUnassigned.max_width(&var_set));
}
#[test]
fn all() {
let var_set = VarSet::all(5);
assert_eq!(5, NbUnassigned.max_width(&var_set));
}
#[test]
fn empty() {
let mut var_set = VarSet::all(5);
var_set.remove(Variable(0));
var_set.remove(Variable(1));
var_set.remove(Variable(2));
var_set.remove(Variable(3));
var_set.remove(Variable(4));
assert_eq!(0, NbUnassigned.max_width(&var_set));
}
}
#[cfg(test)]
mod test_fixedwidth {
use crate::core::common::{Variable, VarSet};
use crate::core::abstraction::heuristics::WidthHeuristic;
use crate::core::implementation::heuristics::FixedWidth;
#[test]
fn non_empty() {
let mut var_set = VarSet::all(5); var_set.remove(Variable(1)); var_set.remove(Variable(3));
var_set.remove(Variable(4));
assert_eq!(100, FixedWidth(100).max_width(&var_set));
}
#[test]
fn all() {
let var_set = VarSet::all(5);
assert_eq!(100, FixedWidth(100).max_width(&var_set));
}
#[test]
fn empty() {
let mut var_set = VarSet::all(5);
var_set.remove(Variable(0));
var_set.remove(Variable(1));
var_set.remove(Variable(2));
var_set.remove(Variable(3));
var_set.remove(Variable(4));
assert_eq!(100, FixedWidth(100).max_width(&var_set));
}
}
#[cfg(test)]
mod test_naturalorder {
use crate::core::common::{Variable, VarSet};
use crate::core::abstraction::heuristics::VariableHeuristic;
use crate::core::implementation::heuristics::NaturalOrder;
use crate::core::common::Layer;
#[test]
fn example() {
let dummy = vec![];
let mut variables = VarSet::all(3);
let current_layer = Layer::<u8>::Plain(dummy.iter());
let next_layer = Layer::<u8>::Plain(dummy.iter());
assert_eq!(Some(Variable(0)), NaturalOrder.next_var(&variables, current_layer, next_layer));
variables.remove(Variable(0)); let current_layer = Layer::<u8>::Plain(dummy.iter());
let next_layer = Layer::<u8>::Plain(dummy.iter());
assert_eq!(Some(Variable(1)), NaturalOrder.next_var(&variables, current_layer, next_layer));
variables.remove(Variable(1)); let current_layer = Layer::<u8>::Plain(dummy.iter());
let next_layer = Layer::<u8>::Plain(dummy.iter());
assert_eq!(Some(Variable(2)), NaturalOrder.next_var(&variables, current_layer, next_layer));
variables.remove(Variable(2)); let current_layer = Layer::<u8>::Plain(dummy.iter());
let next_layer = Layer::<u8>::Plain(dummy.iter());
assert_eq!(None, NaturalOrder.next_var(&variables, current_layer, next_layer));
}
}
#[cfg(test)]
mod test_minlp {
use compare::Compare;
use crate::core::common::{Node, NodeInfo};
use crate::core::implementation::heuristics::MinLP;
use std::cmp::Ordering;
#[test]
fn example() {
let a = Node {state: 'a', info: NodeInfo{lp_len: 42, lp_arc: None, ub: 100, is_exact: true, is_relaxed: false}};
let b = Node {state: 'b', info: NodeInfo{lp_len: 2, lp_arc: None, ub: 100, is_exact: true, is_relaxed: false}};
let c = Node {state: 'c', info: NodeInfo{lp_len: 24, lp_arc: None, ub: 100, is_exact: true, is_relaxed: false}};
let d = Node {state: 'd', info: NodeInfo{lp_len: 13, lp_arc: None, ub: 100, is_exact: true, is_relaxed: false}};
let e = Node {state: 'e', info: NodeInfo{lp_len: 65, lp_arc: None, ub: 100, is_exact: true, is_relaxed: false}};
let f = Node {state: 'f', info: NodeInfo{lp_len: 19, lp_arc: None, ub: 100, is_exact: true, is_relaxed: false}};
let mut nodes = vec![&a, &b, &c, &d, &e, &f];
nodes.sort_by(|x, y| MinLP.compare(x, y).reverse());
assert_eq!(vec![&e, &a, &c, &f, &d, &b], nodes);
}
#[test]
fn gt_because_of_lplen() {
let a = Node {state: 'a', info: NodeInfo{lp_len: 42, lp_arc: None, ub: 100, is_exact: true, is_relaxed: false}};
let b = Node {state: 'b', info: NodeInfo{lp_len: 2, lp_arc: None, ub: 100, is_exact: true, is_relaxed: false}};
assert_eq!(Ordering::Greater, MinLP.compare(&a, &b));
}
#[test]
fn lt_because_of_lplen() {
let a = Node {state: 'a', info: NodeInfo{lp_len: 42, lp_arc: None, ub: 100, is_exact: true, is_relaxed: false}};
let b = Node {state: 'b', info: NodeInfo{lp_len: 2, lp_arc: None, ub: 100, is_exact: true, is_relaxed: false}};
assert_eq!(Ordering::Less, MinLP.compare(&b, &a));
}
#[test]
fn eq_if_all_match() {
let a = Node {state: 'a', info: NodeInfo{lp_len: 42, lp_arc: None, ub: 100, is_exact: true, is_relaxed: false}};
let b = Node {state: 'b', info: NodeInfo{lp_len: 42, lp_arc: None, ub: 100, is_exact: true, is_relaxed: false}};
assert_eq!(Ordering::Equal, MinLP.compare(&a, &b));
}
#[test]
fn eq_self() {
let a = Node {state: 'a', info: NodeInfo{lp_len: 42, lp_arc: None, ub: 100, is_exact: true, is_relaxed: false}};
assert_eq!(Ordering::Equal, MinLP.compare(&a, &a));
}
}
#[cfg(test)]
mod test_maxub {
use binary_heap_plus::BinaryHeap;
use compare::Compare;
use crate::core::common::{Node, NodeInfo};
use crate::core::implementation::heuristics::MaxUB;
use std::cmp::Ordering;
#[test]
fn example() {
let a = Node {state: 'a', info: NodeInfo{lp_len: 42, lp_arc: None, ub: 300, is_exact: true, is_relaxed: false}};
let b = Node {state: 'b', info: NodeInfo{lp_len: 2, lp_arc: None, ub: 100, is_exact: true, is_relaxed: false}};
let c = Node {state: 'c', info: NodeInfo{lp_len: 24, lp_arc: None, ub: 150, is_exact: true, is_relaxed: false}};
let d = Node {state: 'd', info: NodeInfo{lp_len: 13, lp_arc: None, ub: 60, is_exact: true, is_relaxed: false}};
let e = Node {state: 'e', info: NodeInfo{lp_len: 65, lp_arc: None, ub: 700, is_exact: true, is_relaxed: false}};
let f = Node {state: 'f', info: NodeInfo{lp_len: 19, lp_arc: None, ub: 100, is_exact: true, is_relaxed: false}};
let nodes = vec![a.clone(), b.clone(), c.clone(), d.clone(), e.clone(), f.clone()];
let mut priority_q = BinaryHeap::from_vec_cmp(nodes, MaxUB);
assert_eq!(e, priority_q.pop().unwrap()); assert_eq!(a, priority_q.pop().unwrap()); assert_eq!(c, priority_q.pop().unwrap()); assert_eq!(f, priority_q.pop().unwrap()); assert_eq!(b, priority_q.pop().unwrap()); assert_eq!(d, priority_q.pop().unwrap()); }
#[test]
fn gt_because_ub() {
let a = Node {state: 'a', info: NodeInfo{lp_len: 42, lp_arc: None, ub: 300, is_exact: true, is_relaxed: false}};
let b = Node {state: 'b', info: NodeInfo{lp_len: 42, lp_arc: None, ub: 100, is_exact: true, is_relaxed: false}};
assert_eq!(Ordering::Greater, MaxUB.compare(&a, &b));
}
#[test]
fn gt_because_lplen() {
let a = Node {state: 'a', info: NodeInfo{lp_len: 42, lp_arc: None, ub: 300, is_exact: true, is_relaxed: false}};
let b = Node {state: 'b', info: NodeInfo{lp_len: 2, lp_arc: None, ub: 300, is_exact: true, is_relaxed: false}};
assert_eq!(Ordering::Greater, MaxUB.compare(&a, &b));
}
#[test]
fn lt_because_ub() {
let a = Node {state: 'a', info: NodeInfo{lp_len: 42, lp_arc: None, ub: 300, is_exact: true, is_relaxed: false}};
let b = Node {state: 'b', info: NodeInfo{lp_len: 42, lp_arc: None, ub: 100, is_exact: true, is_relaxed: false}};
assert_eq!(Ordering::Less, MaxUB.compare(&b, &a));
}
#[test]
fn lt_because_lplen() {
let a = Node {state: 'a', info: NodeInfo{lp_len: 42, lp_arc: None, ub: 300, is_exact: true, is_relaxed: false}};
let b = Node {state: 'b', info: NodeInfo{lp_len: 2, lp_arc: None, ub: 300, is_exact: true, is_relaxed: false}};
assert_eq!(Ordering::Less, MaxUB.compare(&b, &a));
}
#[test]
fn eq_because_all_match() {
let a = Node {state: 'a', info: NodeInfo{lp_len: 42, lp_arc: None, ub: 300, is_exact: true, is_relaxed: false}};
let b = Node {state: 'b', info: NodeInfo{lp_len: 42, lp_arc: None, ub: 300, is_exact: true, is_relaxed: false}};
assert_eq!(Ordering::Equal, MaxUB.compare(&a, &b));
}
#[test]
fn eq_self() {
let a = Node {state: 'a', info: NodeInfo{lp_len: 42, lp_arc: None, ub: 300, is_exact: true, is_relaxed: false}};
assert_eq!(Ordering::Equal, MaxUB.compare(&a, &a));
}
}
#[cfg(test)]
mod test_fromlongestpath {
use crate::core::implementation::heuristics::FromLongestPath;
use crate::core::abstraction::dp::Problem;
use crate::core::common::{Variable, VarSet, Domain, Decision, Node, Edge};
use crate::core::abstraction::heuristics::LoadVars;
use std::sync::Arc;
struct Dummy;
impl Problem<usize> for Dummy {
fn nb_vars(&self) -> usize { 5 }
fn initial_state(&self) -> usize { 0 }
fn initial_value(&self) -> i32 { 0 }
fn domain_of<'a>(&self, _: &'a usize, _: Variable) -> Domain<'a> {
(0..1).into()
}
fn transition(&self, state: &usize, _: &VarSet, _: Decision) -> usize {
*state
}
fn transition_cost(&self, _: &usize, _: &VarSet, _: Decision) -> i32 {
1
}
}
#[test]
fn at_root() {
let pb = Dummy;
let heu = FromLongestPath::new(pb.all_vars());
let root= pb.root_node();
let vars= heu.variables(&root);
assert_eq!(pb.all_vars(), vars);
}
#[test]
fn some_vars_assigned() {
let pb = Dummy;
let heu = FromLongestPath::new(pb.all_vars());
let root= pb.root_node();
let node= Node::new(12, 15, Some(Edge{src: Arc::new(root.info), decision: Decision{variable: Variable(0), value: 1}}), true, false);
let node= Node::new(10, 20, Some(Edge{src: Arc::new(node.info), decision: Decision{variable: Variable(1), value: 0}}), true, false);
let node= Node::new( 7, 30, Some(Edge{src: Arc::new(node.info), decision: Decision{variable: Variable(3), value: 0}}), true, false);
let vars= heu.variables(&node);
let mut expected= pb.all_vars();
expected.remove(Variable(0));
expected.remove(Variable(1));
expected.remove(Variable(3));
assert_eq!(expected, vars);
}
#[test]
fn all_vars_assigned() {
let pb = Dummy;
let heu = FromLongestPath::new(pb.all_vars());
let root= pb.root_node();
let node= Node::new(12, 15, Some(Edge{src: Arc::new(root.info), decision: Decision{variable: Variable(0), value: 1}}), true, false);
let node= Node::new(10, 20, Some(Edge{src: Arc::new(node.info), decision: Decision{variable: Variable(1), value: 0}}), true, false);
let node= Node::new( 7, 30, Some(Edge{src: Arc::new(node.info), decision: Decision{variable: Variable(2), value: 0}}), true, false);
let node= Node::new( 3, 40, Some(Edge{src: Arc::new(node.info), decision: Decision{variable: Variable(3), value: 0}}), true, false);
let node= Node::new( 0, 50, Some(Edge{src: Arc::new(node.info), decision: Decision{variable: Variable(4), value: 0}}), true, false);
let vars= heu.variables(&node);
let mut expected= pb.all_vars();
expected.remove(Variable(0));
expected.remove(Variable(1));
expected.remove(Variable(2));
expected.remove(Variable(3));
expected.remove(Variable(4));
assert_eq!(expected, vars);
}
}