use crate::common::*;
use crate::encoding::Binary;
use crate::individual::*;
const EPSILON: f64 = 10e-8;
pub trait EvaluateFitness<G>: Clone
where
G: Genome,
{
fn evaluate(&mut self, indvs: &[Individual<G>]) -> Vec<f64>;
}
#[derive(Clone)]
pub struct Maximize;
impl<G> EvaluateFitness<G> for Maximize
where
G: Genome,
{
fn evaluate(&mut self, indvs: &[Individual<G>]) -> Vec<f64> {
if let Some(score_ref) = indvs.iter().map(|indv| indv.objective_value()).fmin() {
let score_ref = score_ref * (1.0 - EPSILON);
indvs.iter().map(|x| x.objective_value() - score_ref).collect()
} else {
warn!("empty individual list!");
vec![]
}
}
}
#[derive(Clone)]
pub struct Minimize;
impl<G> EvaluateFitness<G> for Minimize
where
G: Genome,
{
fn evaluate(&mut self, indvs: &[Individual<G>]) -> Vec<f64> {
if let Some(score_ref) = indvs.iter().map(|indv| indv.objective_value()).fmax() {
let score_ref = score_ref * (1.0 + EPSILON);
indvs.iter().map(|x| score_ref - x.objective_value()).collect()
} else {
warn!("empty individual list!");
vec![]
}
}
}
use crate::annealing::Annealer;
#[derive(Clone)]
pub struct MinimizeEnergy {
conversion: f64,
annealer: Annealer,
temperature: f64,
}
impl MinimizeEnergy {
pub fn new(temperature: f64) -> Self {
assert!(temperature.is_sign_positive(), "temperature cannot be negative!");
Self {
conversion: 96.0,
annealer: Annealer::new(temperature * 10.0, temperature).cooling_rate(0.99),
temperature,
}
}
pub fn energy_unit(mut self, u: &str) -> Self {
match u {
"eV" => self.conversion = 96.0,
"au" => self.conversion = 2625.5,
"kcal" => self.conversion = 4.184,
"kJ" => self.conversion = 1.0,
_ => panic!("unkonw unit: {}", u),
}
self
}
}
impl<G> EvaluateFitness<G> for MinimizeEnergy
where
G: Genome,
{
fn evaluate(&mut self, indvs: &[Individual<G>]) -> Vec<f64> {
let temperature = if let Some(t) = self.annealer.start().next() {
t
} else {
self.temperature
};
println!("annealing temperature: {}", temperature);
if let Some(score_ref) = indvs.iter().map(|indv| indv.objective_value()).fmin() {
indvs
.iter()
.map(|x| {
let value = self.conversion * (score_ref - x.objective_value());
(value / (temperature * 0.0083145)).exp()
})
.collect()
} else {
warn!("empty individual list!");
vec![]
}
}
}