#[cfg(test)]
#[path = "../../../tests/unit/solver/objectives/total_transport_test.rs"]
mod total_transport_test;
use super::*;
use crate::algorithms::nsga2::Objective;
use crate::construction::constraints::{TOTAL_DISTANCE_KEY, TOTAL_DURATION_KEY};
use crate::models::common::Cost;
use crate::models::problem::TargetObjective;
use crate::utils::compare_floats;
use std::ops::Deref;
use std::sync::Arc;
pub struct TotalCost;
impl TotalCost {
pub fn minimize() -> TargetObjective {
Box::new(TotalTransport { fitness: Arc::new(|insertion_ctx| insertion_ctx.solution.get_total_cost()) })
}
}
pub struct TotalDistance;
impl TotalDistance {
pub fn minimize() -> TargetObjective {
new_with_route_state_key(TOTAL_DISTANCE_KEY)
}
}
pub struct TotalDuration;
impl TotalDuration {
pub fn minimize() -> TargetObjective {
new_with_route_state_key(TOTAL_DURATION_KEY)
}
}
struct TotalTransport {
fitness: Arc<dyn Fn(&InsertionContext) -> f64 + Send + Sync>,
}
impl Objective for TotalTransport {
type Solution = InsertionContext;
fn total_order(&self, a: &Self::Solution, b: &Self::Solution) -> Ordering {
compare_floats(self.fitness(a), self.fitness(b))
}
fn distance(&self, a: &Self::Solution, b: &Self::Solution) -> f64 {
self.fitness(a) - self.fitness(b)
}
fn fitness(&self, solution: &Self::Solution) -> f64 {
self.fitness.deref()(solution)
}
}
fn new_with_route_state_key(key: i32) -> TargetObjective {
Box::new(TotalTransport {
fitness: Arc::new(move |insertion_ctx| {
insertion_ctx
.solution
.routes
.iter()
.fold(Cost::default(), move |acc, rc| acc + rc.state.get_route_state::<f64>(key).cloned().unwrap_or(0.))
}),
})
}