use std::cmp::Reverse;
use crate::search_space::{GuidedSpace, TotalNeighborGeneration};
#[derive(Debug,Clone)]
pub struct DiscrepancyNode<N> {
pub node: N,
pub discrepancies: f64
}
pub trait DiscrepancyType {
fn compute_discrepancies<S,N,G>(&mut self, s:&mut S, n:&mut DiscrepancyNode<N>) -> Vec<DiscrepancyNode<N>>
where S:TotalNeighborGeneration<N>+GuidedSpace<N,G>, G:Ord+Into<f64>+From<f64>;
}
#[derive(Debug, Default)]
pub struct LinearDiscrepancy {}
impl DiscrepancyType for LinearDiscrepancy {
fn compute_discrepancies<S,N,G>(&mut self, s:&mut S, n:&mut DiscrepancyNode<N>) -> Vec<DiscrepancyNode<N>>
where S:TotalNeighborGeneration<N>+GuidedSpace<N,G>, G:Ord {
let d:f64 = n.discrepancies;
let mut neighbors:Vec<N> = s.neighbors(&mut n.node);
neighbors.sort_by_key(|e| Reverse(s.guide(e)));
let mut res:Vec<DiscrepancyNode<N>> = Vec::new();
let mut i = 0;
while !neighbors.is_empty() {
let tmp = neighbors.pop().unwrap();
res.push(DiscrepancyNode {node:tmp, discrepancies:d+(i as f64)});
i += 1;
}
res
}
}
#[derive(Debug, Default)]
pub struct ConstantDiscrepancy {}
impl DiscrepancyType for ConstantDiscrepancy {
fn compute_discrepancies<S,N,G>(&mut self, s:&mut S, n:&mut DiscrepancyNode<N>) -> Vec<DiscrepancyNode<N>>
where S:TotalNeighborGeneration<N>+GuidedSpace<N,G>, G:Ord {
let d:f64 = n.discrepancies;
let mut neighbors:Vec<N> = s.neighbors(&mut n.node);
neighbors.sort_by_key(|e| Reverse(s.guide(e)));
let mut res:Vec<DiscrepancyNode<N>> = Vec::new();
let mut i = 0;
while !neighbors.is_empty() {
let tmp = neighbors.pop().unwrap();
match i {
0 => res.push(DiscrepancyNode {node:tmp, discrepancies:d}),
_ => res.push(DiscrepancyNode {node:tmp, discrepancies:d+1.}),
}
i += 1;
}
res
}
}
#[derive(Debug, Default)]
pub struct RatioToBestDiscrepancy {}
impl DiscrepancyType for RatioToBestDiscrepancy {
fn compute_discrepancies<S,N,G>(&mut self, s:&mut S, n:&mut DiscrepancyNode<N>) -> Vec<DiscrepancyNode<N>>
where S:TotalNeighborGeneration<N>+GuidedSpace<N,G>, G:Ord+Into<f64>+From<f64> {
let d:f64 = n.discrepancies;
let mut neighbors:Vec<N> = s.neighbors(&mut n.node);
if neighbors.is_empty() {
return Vec::new();
}
neighbors.sort_by_key(|e| Reverse(s.guide(e)));
let neigh:N = neighbors.pop().unwrap();
let g0:f64 = s.guide(&neigh).into();
let mut res:Vec<DiscrepancyNode<N>> = vec![DiscrepancyNode {node:neigh, discrepancies:d}];
while !neighbors.is_empty() {
let neigh2:N = neighbors.pop().unwrap();
let gn:f64 = s.guide(&neigh2).into();
let mut discrepancy_increment = 0.;
if gn > 0. {
discrepancy_increment = (gn-g0)/gn;
}
res.push(DiscrepancyNode {node:neigh2, discrepancies:d+discrepancy_increment});
}
res
}
}