use crate::inference::inference_status::InferenceStatusReport;
use crate::inference::inference_type::InferenceType;
use crate::inference::update_fn_details::MAX_UPDATE_FN_COUNT;
use crate::sketchbook::JsonSerde;
use serde::{Deserialize, Serialize};
use std::{collections::HashMap, time::Duration};
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
pub struct InferenceResults {
pub analysis_type: InferenceType,
pub num_sat_networks: u128,
pub comp_time: u128,
pub summary_message: String,
pub progress_statuses: Vec<InferenceStatusReport>,
pub num_update_fns_per_var: HashMap<String, usize>,
}
impl<'de> JsonSerde<'de> for InferenceResults {}
impl InferenceResults {
pub fn new(
analysis_type: InferenceType,
num_sat_networks: u128,
comp_time: Duration,
summary_message: &str,
progress_statuses: Vec<InferenceStatusReport>,
num_update_fns_per_var: HashMap<String, usize>,
) -> InferenceResults {
InferenceResults {
analysis_type,
num_sat_networks,
comp_time: comp_time.as_millis(),
summary_message: summary_message.to_string(),
progress_statuses,
num_update_fns_per_var,
}
}
pub fn extend_summary(&mut self, new_message: &str) {
self.summary_message.push_str(new_message);
}
pub fn format_to_report(&self) -> String {
let mut output = String::new();
output.push_str(&format!(
"Number of satisfying candidates: {}\n",
self.num_sat_networks
));
output.push_str(&format!(
"Computation time: {} milliseconds\n\n",
self.comp_time
));
output.push_str("--------------\n");
output.push_str("Extended summary:\n");
output.push_str("--------------\n");
output.push_str(&format!("{}\n", self.summary_message));
output.push_str("--------------\n");
output.push_str("Number of admissible update functions per variable:\n");
output.push_str("--------------\n");
let mut sorted_vars: Vec<_> = self.num_update_fns_per_var.iter().collect();
sorted_vars.sort_by_key(|&(var, _)| var);
for (var, &count) in sorted_vars {
let count_display = if count >= MAX_UPDATE_FN_COUNT {
format!("more than {MAX_UPDATE_FN_COUNT}")
} else {
count.to_string()
};
output.push_str(&format!("{}: {}\n", var, count_display));
}
output.push_str("--------------\n");
output.push_str("Detailed progress report:\n");
output.push_str("--------------\n");
for report in &self.progress_statuses {
output.push_str(&report.message);
output.push('\n');
}
output
}
}
#[cfg(test)]
mod tests {
use std::collections::HashMap;
use std::time::Duration;
use crate::inference::inference_results::InferenceResults;
use crate::inference::inference_status::{InferenceStatus, InferenceStatusReport};
use crate::inference::inference_type::InferenceType;
#[test]
fn test_inference_results_summary_and_report() {
let mut inference_results = InferenceResults::new(
InferenceType::FullInference,
5,
Duration::from_millis(1500),
"Initial summary.",
vec![
InferenceStatusReport::new(InferenceStatus::Created, None, 0, "Started"),
InferenceStatusReport::new(
InferenceStatus::FinishedSuccessfully,
Some(5),
1500,
"Finished",
),
],
HashMap::from([("var1".to_string(), 3), ("var2".to_string(), 7)]),
);
inference_results.extend_summary(" Additional details.");
assert_eq!(
inference_results.summary_message,
"Initial summary. Additional details."
);
let report = inference_results.format_to_report();
assert!(report.contains("Number of satisfying candidates: 5"));
assert!(report.contains("Computation time: 1500 milliseconds"));
assert!(report.contains("Initial summary. Additional details."));
assert!(report.contains("var1: 3"));
assert!(report.contains("var2: 7"));
assert!(report.contains("Started"));
assert!(report.contains("Finished"));
}
}