use std::{
cmp::{Ordering, Reverse},
collections::{BinaryHeap, VecDeque},
};
use crate::{BoundingOperator, BranchingOperator};
pub trait NodeSequencer<T>: Sized {
fn is_ordered(&self) -> bool;
fn init(item: T) -> Self;
fn push(&mut self, item: T);
fn pop(&mut self) -> Option<T>;
fn len(&self) -> usize;
fn is_empty(&self) -> bool {
self.len() == 0
}
fn to_vec(self) -> Vec<T>;
fn from_vec(items: Vec<T>) -> Self;
fn convert_from<S>(other: S) -> Self
where
S: NodeSequencer<T>,
{
Self::from_vec(other.to_vec())
}
fn pop_until_satisfied<F>(&mut self, f: F) -> Option<T>
where
F: Fn(&T) -> bool,
{
while let Some(item) = self.pop() {
if f(&item) {
return Some(item);
}
}
None
}
}
pub type Stack<T> = Vec<T>;
pub type Queue<T> = VecDeque<T>;
pub type PrioQueue<T> = BinaryHeap<T>;
pub struct RevPrioQueue<T>(BinaryHeap<Reverse<T>>);
impl<T> NodeSequencer<T> for Stack<T> {
fn is_ordered(&self) -> bool {
false
}
fn init(item: T) -> Self {
vec![item]
}
fn push(&mut self, item: T) {
self.push(item)
}
fn pop(&mut self) -> Option<T> {
self.pop()
}
fn len(&self) -> usize {
self.len()
}
fn to_vec(self) -> Vec<T> {
self
}
fn from_vec(items: Vec<T>) -> Self {
items
}
}
impl<T> NodeSequencer<T> for Queue<T> {
fn is_ordered(&self) -> bool {
false
}
fn init(item: T) -> Self {
Self::from(vec![item])
}
fn push(&mut self, item: T) {
self.push_back(item)
}
fn pop(&mut self) -> Option<T> {
self.pop_front()
}
fn len(&self) -> usize {
self.len()
}
fn to_vec(self) -> Vec<T> {
self.into()
}
fn from_vec(items: Vec<T>) -> Self {
Self::from(items)
}
}
impl<T> NodeSequencer<T> for PrioQueue<T>
where
T: Ord,
{
fn is_ordered(&self) -> bool {
true
}
fn init(item: T) -> Self {
Self::from(vec![item])
}
fn push(&mut self, item: T) {
self.push(item)
}
fn pop(&mut self) -> Option<T> {
self.pop()
}
fn len(&self) -> usize {
self.len()
}
fn to_vec(self) -> Vec<T> {
self.into_vec()
}
fn from_vec(items: Vec<T>) -> Self {
Self::from(items)
}
}
impl<T> NodeSequencer<T> for RevPrioQueue<T>
where
T: Ord,
{
fn is_ordered(&self) -> bool {
true
}
fn init(item: T) -> Self {
RevPrioQueue(BinaryHeap::from(vec![Reverse(item)]))
}
fn push(&mut self, item: T) {
self.0.push(Reverse(item))
}
fn pop(&mut self) -> Option<T> {
if let Some(Reverse(item)) = self.0.pop() {
return Some(item);
}
None
}
fn len(&self) -> usize {
self.0.len()
}
fn to_vec(self) -> Vec<T> {
self.0.into_iter().map(|Reverse(item)| item).collect()
}
fn from_vec(items: Vec<T>) -> Self {
RevPrioQueue(BinaryHeap::from(
items
.into_iter()
.map(|item| Reverse(item))
.collect::<Vec<Reverse<T>>>(),
))
}
}
pub struct BoundedSolution<V, B>
where
V: PartialOrd + Clone,
B: BranchingOperator + BoundingOperator<V>,
{
bound: V,
solution: B,
}
impl<V, B> PartialEq for BoundedSolution<V, B>
where
V: PartialOrd + Clone,
B: BranchingOperator + BoundingOperator<V>,
{
fn eq(&self, other: &Self) -> bool {
self.partial_cmp(other) == Some(Ordering::Equal)
}
}
impl<V, B> Eq for BoundedSolution<V, B>
where
V: PartialOrd + Clone,
B: BranchingOperator + BoundingOperator<V>,
{
}
impl<V, B> PartialOrd for BoundedSolution<V, B>
where
V: PartialOrd + Clone,
B: BranchingOperator + BoundingOperator<V>,
{
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.cmp(other))
}
}
impl<V, B> Ord for BoundedSolution<V, B>
where
V: PartialOrd + Clone,
B: BranchingOperator + BoundingOperator<V>,
{
fn cmp(&self, other: &Self) -> Ordering {
match self.bound.partial_cmp(&other.bound) {
Some(ordering) => ordering,
None => Ordering::Equal,
}
}
}
impl<V, B> BoundedSolution<V, B>
where
V: PartialOrd + Clone,
B: BranchingOperator + BoundingOperator<V>,
{
pub fn new(bound: V, node: B) -> Self {
Self {
bound,
solution: node,
}
}
pub fn init(node: B) -> Self {
Self {
bound: node.bound(),
solution: node,
}
}
pub fn split(self) -> (V, B) {
(self.bound, self.solution)
}
pub fn value(&self) -> V {
self.bound.clone()
}
}