1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
#[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.))
}),
})
}