use crate::point::*;
use crate::search_space::*;
use std::hash::{Hash, Hasher};
use std::rc::Rc;
use ordered_float::OrderedFloat;
use num_traits::Float;
#[derive(Clone)]
pub struct Simplex<CoordFloat: Float, ValueFloat: Float>
{
pub corners: Vec<Rc<Point<CoordFloat, ValueFloat>>>,
pub center: Coordinates<CoordFloat>
}
impl<CoordFloat: Float, ValueFloat: Float> Simplex<CoordFloat, ValueFloat>
{
fn new(corners: Vec<Rc<Point<CoordFloat, ValueFloat>>>) -> Self
{
let center = Point::average_coordinate(&corners);
Simplex { corners, center }
}
pub fn initial_simplex(search_space: &SearchSpace<CoordFloat, ValueFloat>)
-> Simplex<CoordFloat, ValueFloat>
{
let origin = vec![CoordFloat::zero(); search_space.dimension].into_boxed_slice();
let mut corners: Vec<Rc<Point<CoordFloat, ValueFloat>>> = (0..search_space.dimension).map(|i| {
let mut coordinates = origin.clone();
coordinates[i] = CoordFloat::one();
let value =
search_space.evaluate(&coordinates);
Rc::new(Point { coordinates, value })
})
.collect();
let min_corner = Point { value: search_space.evaluate(&origin), coordinates: origin };
corners.push(Rc::new(min_corner));
Simplex::new(corners)
}
pub fn split(self, new_point: Rc<Point<CoordFloat, ValueFloat>>) -> Vec<Self>
{
let mut result = vec![];
for i in 0..self.corners.len()
{
let mut corners = self.corners.clone();
corners[i] = new_point.clone();
let simplex = Simplex::new(corners);
result.push(simplex);
}
result
}
pub fn evaluate(&self, k: ValueFloat) -> ValueFloat
{
self.corners
.iter()
.map(|corner| corner.evaluate_upper_bound(&self.center, k))
.min_by_key(|&value| OrderedFloat(value))
.expect("You need at least one corner in order to evaluate a simplex!")
}
}
impl<CoordFloat: Float, ValueFloat: Float> Hash for Simplex<CoordFloat, ValueFloat>
{
fn hash<H: Hasher>(&self, state: &mut H)
{
self.center.iter().map(|&x| x.to_f64().unwrap().to_bits()).collect::<Box<[u64]>>().hash(state);
}
}
impl<CoordFloat: Float, ValueFloat: Float> PartialEq for Simplex<CoordFloat, ValueFloat>
{
fn eq(&self, other: &Self) -> bool
{
self.center == other.center
}
}
impl<CoordFloat: Float, ValueFloat: Float> Eq for Simplex<CoordFloat, ValueFloat> {}