ahc_evaluation/evaluation/
record.rs1use std::path::Path;
2
3use anyhow::{ensure, Context};
4use itertools::Itertools;
5
6#[derive(Debug, Clone, Copy, serde::Serialize)]
7pub struct EvaluationRecord {
8 pub seed: usize,
9 pub score: i64,
10 pub execution_time: f64,
11}
12
13pub fn show_statistics(evaluation_table: &[EvaluationRecord]) -> anyhow::Result<()> {
15 show_score_statistics(evaluation_table)?;
16 println!();
17 show_execution_time_statistics(evaluation_table)?;
18
19 Ok(())
20}
21
22fn show_score_statistics(evaluation_table: &[EvaluationRecord]) -> anyhow::Result<()> {
24 ensure!(
25 !evaluation_table.is_empty(),
26 "The evaluation table is empty."
27 );
28
29 let total_score = evaluation_table
30 .iter()
31 .map(|record| record.score)
32 .sum::<i64>();
33 let avg_score = total_score as f64 / evaluation_table.len() as f64;
34
35 let (min_pos, max_pos) = match evaluation_table
36 .iter()
37 .position_minmax_by_key(|record| record.score)
38 {
39 itertools::MinMaxResult::NoElements => unreachable!(),
40 itertools::MinMaxResult::OneElement(pos) => (pos, pos),
41 itertools::MinMaxResult::MinMax(min_pos, max_pos) => (min_pos, max_pos),
42 };
43
44 let min_record = evaluation_table[min_pos];
45 let max_record = evaluation_table[max_pos];
46
47 print!(
48 "\
49[Score Statistics]
50Total: {}
51Average: {:.3}
52Min: {} (seed = {})
53Max: {} (seed = {})
54",
55 total_score,
56 avg_score,
57 min_record.score,
58 min_record.seed,
59 max_record.score,
60 max_record.seed,
61 );
62
63 Ok(())
64}
65
66fn show_execution_time_statistics(evaluation_table: &[EvaluationRecord]) -> anyhow::Result<()> {
68 ensure!(
69 !evaluation_table.is_empty(),
70 "The evaluation table is empty."
71 );
72
73 let total_exe_time = evaluation_table
74 .iter()
75 .map(|record| record.execution_time)
76 .sum::<f64>();
77 let avg_exe_time = total_exe_time / evaluation_table.len() as f64;
78
79 let (min_pos, max_pos) = match evaluation_table
80 .iter()
81 .position_minmax_by(|x, y| x.execution_time.partial_cmp(&y.execution_time).unwrap())
82 {
83 itertools::MinMaxResult::NoElements => unreachable!(),
84 itertools::MinMaxResult::OneElement(pos) => (pos, pos),
85 itertools::MinMaxResult::MinMax(min_pos, max_pos) => (min_pos, max_pos),
86 };
87
88 let min_record = evaluation_table[min_pos];
89 let max_record = evaluation_table[max_pos];
90
91 print!(
92 "\
93[Execution Time]
94Total: {:.3}
95Average: {:.3}
96Min: {:.3} (seed = {})
97Max: {:.3} (seed = {})
98",
99 total_exe_time,
100 avg_exe_time,
101 min_record.execution_time,
102 min_record.seed,
103 max_record.execution_time,
104 max_record.seed,
105 );
106
107 Ok(())
108}
109
110pub fn write_to_csv<P>(
112 output_file_path: P,
113 evaluation_table: &[EvaluationRecord],
114) -> anyhow::Result<()>
115where
116 P: AsRef<Path>,
117{
118 let mut writer = csv::Writer::from_path(&output_file_path)
119 .with_context(|| "Failed to open file to output evaluation table.")?;
120
121 for record in evaluation_table {
122 writer
123 .serialize(record)
124 .with_context(|| "Failed to serialize the evaluation record.")?;
125 }
126
127 writer
128 .flush()
129 .with_context(|| "Failed to write evaluation table to file.")?;
130
131 Ok(())
132}