use binary_heap_plus::BinaryHeap;
use crate::*;
pub struct SimpleFrontier<O: SubProblemRanking> {
heap: BinaryHeap<SubProblem<O::State>, CompareSubProblem<O>>
}
impl <O> SimpleFrontier<O> where O: SubProblemRanking {
pub fn new(o: O) -> Self {
Self{ heap: BinaryHeap::from_vec_cmp(vec![], CompareSubProblem::new(o)) }
}
}
impl <O> Frontier for SimpleFrontier<O> where O: SubProblemRanking {
type State = O::State;
fn push(&mut self, node: SubProblem<Self::State>) {
self.heap.push(node)
}
fn pop(&mut self) -> Option<SubProblem<Self::State>> {
self.heap.pop()
}
fn clear(&mut self) {
self.heap.clear()
}
fn len(&self) -> usize {
self.heap.len()
}
}
#[cfg(test)]
#[allow(clippy::many_single_char_names)]
mod test_simple_frontier {
use crate::*;
use std::{sync::Arc, cmp::Ordering, ops::Deref};
struct CharRanking;
impl StateRanking for CharRanking {
type State = char;
fn compare(&self, a: &Self::State, b: &Self::State) -> Ordering {
a.cmp(b)
}
}
#[test]
fn by_default_it_is_empty() {
let order = MaxUB::new(&CharRanking);
let front = SimpleFrontier::new(order);
assert!(front.is_empty())
}
#[test]
fn when_the_size_is_zero_then_it_is_empty() {
let order = MaxUB::new(&CharRanking);
let frontier = SimpleFrontier::new(order);
assert_eq!(frontier.len(), 0);
assert!(frontier.is_empty());
}
#[test]
fn when_the_size_is_greater_than_zero_it_is_not_empty() {
let order = MaxUB::new(&CharRanking);
let mut frontier = SimpleFrontier::new(order);
frontier.push(SubProblem {
state: Arc::new('a'),
value: 10,
ub : 10,
path : vec![]
});
assert_eq!(frontier.len(), 1);
assert!(!frontier.is_empty());
}
#[test]
fn when_i_push_a_node_onto_the_frontier_then_the_length_increases() {
let order = MaxUB::new(&CharRanking);
let mut frontier = SimpleFrontier::new(order);
frontier.push(SubProblem {
state: Arc::new('a'),
value: 10,
ub : 10,
path : vec![]
});
frontier.push(SubProblem {
state: Arc::new('b'),
value: 20,
ub : 20,
path : vec![]
});
assert_eq!(frontier.len(), 2);
}
#[test]
fn when_i_pop_a_node_off_the_frontier_then_the_length_decreases() {
let order = MaxUB::new(&CharRanking);
let mut frontier = SimpleFrontier::new(order);
frontier.push(SubProblem {
state: Arc::new('a'),
value: 10,
ub : 10,
path : vec![]
});
frontier.push(SubProblem {
state: Arc::new('b'),
value: 20,
ub : 20,
path : vec![]
});
assert_eq!(frontier.len(), 2);
frontier.pop();
assert_eq!(frontier.len(), 1);
frontier.pop();
assert_eq!(frontier.len(), 0);
}
#[test]
fn when_i_try_to_pop_a_node_off_an_empty_frontier_i_get_none() {
let order = MaxUB::new(&CharRanking);
let mut frontier = SimpleFrontier::new(order);
assert!(frontier.pop().is_none());
}
#[test]
fn when_i_pop_a_node_it_is_always_the_one_with_the_largest_ub_then_lp() {
let order = MaxUB::new(&CharRanking);
let mut frontier = SimpleFrontier::new(order);
frontier.push(SubProblem {
state: Arc::new('a'),
value: 1,
ub : 1,
path : vec![]
});
frontier.push(SubProblem {
state: Arc::new('b'),
value: 2,
ub : 2,
path : vec![]
});
frontier.push(SubProblem {
state: Arc::new('c'),
value: 3,
ub : 3,
path : vec![]
});
frontier.push(SubProblem {
state: Arc::new('d'),
value: 4,
ub : 4,
path : vec![]
});
frontier.push(SubProblem {
state: Arc::new('e'),
value: 4,
ub : 5,
path : vec![]
});
frontier.push(SubProblem {
state: Arc::new('f'),
value: 5,
ub : 5,
path : vec![]
});
assert_eq!(frontier.pop().unwrap().state.deref(), &'f');
assert_eq!(frontier.pop().unwrap().state.deref(), &'e');
assert_eq!(frontier.pop().unwrap().state.deref(), &'d');
assert_eq!(frontier.pop().unwrap().state.deref(), &'c');
assert_eq!(frontier.pop().unwrap().state.deref(), &'b');
assert_eq!(frontier.pop().unwrap().state.deref(), &'a');
}
#[test]
fn when_i_clear_an_empty_frontier_it_remains_empty() {
let order = MaxUB::new(&CharRanking);
let mut frontier = SimpleFrontier::new(order);
assert!(frontier.is_empty());
frontier.clear();
assert!(frontier.is_empty());
}
#[test]
fn when_i_clear_a_non_empty_frontier_it_becomes_empty() {
let order = MaxUB::new(&CharRanking);
let mut frontier = SimpleFrontier::new(order);
frontier.push(SubProblem {
state: Arc::new('f'),
value: 5,
ub : 5,
path : vec![]
});
assert!(!frontier.is_empty());
frontier.clear();
assert!(frontier.is_empty());
}
}