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
use std::{
ops::{Div, Sub},
time::Duration,
};
use crate::core::{Evaluation, Objective, Problem};
use super::Battery;
pub struct Statistics<'a, P: Problem> {
value_sum: f64,
time_sum: Duration,
battery: &'a Battery<P>,
}
impl<'a, P: Problem> Statistics<'a, P>
where
P::Value: Into<f64>,
{
pub fn new(battery: &'a Battery<P>) -> Self {
let score_sum = battery
.evaluations()
.iter()
.map(|(_, e, _)| e.value().into())
.sum();
let time_sum = battery.evaluations().iter().map(|(_, _, t)| t).sum();
Self {
value_sum: score_sum,
time_sum,
battery,
}
}
pub fn average_value(&self) -> f64 {
self.value_sum / self.battery.executions as f64
}
pub fn average_time(&self) -> Duration {
self.time_sum / self.battery.executions as u32
}
pub fn best(&self) -> &(usize, Evaluation<P>, Duration) {
let iter = self.battery.evaluations().iter();
match P::OBJECTIVE {
Objective::Min => iter.min_by_key(|(_, e, _)| e.value()),
Objective::Max => iter.max_by_key(|(_, e, _)| e.value()),
}
.expect("A Battery should always have at least one execution")
}
}
pub trait Gap<F: Into<f64>>: Copy + Sub<Output = Self> + Div<Output = F> {
fn gap(self, other: Self) -> f64 {
((self - other) / other).into() * 100.0
}
}
impl<V: Copy + Sub<Output = Self> + Div<Output = f64>> Gap<f64> for V {}