use crate::solvers::{Search, Solution};
use itertools::Itertools;
use std::error::Error;
use std::fmt::Display;
use std::fs::OpenOptions;
use std::io::Write;
use std::str::FromStr;
pub fn read_vector<'a, T>(
input: &mut impl Iterator<Item = &'a str>,
n: usize,
) -> Result<Vec<T>, <T as FromStr>::Err>
where
T: FromStr,
{
input.take(n).map(|x| x.parse::<T>()).collect()
}
pub fn read_matrix<'a, T>(
input: &mut impl Iterator<Item = &'a str>,
m: usize,
n: usize,
) -> Result<Vec<Vec<T>>, <T as FromStr>::Err>
where
T: FromStr,
{
input
.take(m * n)
.chunks(n)
.into_iter()
.map(|chunk| chunk.into_iter().map(|x| x.parse::<T>()).collect())
.collect()
}
pub fn run_solver_and_dump_solution_history<S, C, L>(
solver: &mut S,
filename: &str,
) -> Result<Solution<C, L>, Box<dyn Error>>
where
S: Search<CostType = C, Label = L>,
C: Display + Copy,
L: Display,
{
let mut file = OpenOptions::new()
.create(true)
.write(true)
.truncate(true)
.open(filename)?;
loop {
let (solution, terminated) = solver.search_next();
if let Some(cost) = solution.cost {
let transitions = solution
.transitions
.iter()
.map(|t| format!("{t}"))
.collect::<Vec<_>>()
.join(" ");
let line = if let Some(bound) = solution.best_bound {
format!(
"{time}, {cost}, {bound}, {transitions}, {expanded}, {generated}\n",
time = solution.time,
expanded = solution.expanded,
generated = solution.generated
)
} else {
format!(
"{time}, {cost}, , {transitions}, {expanded}, {generated}\n",
time = solution.time,
expanded = solution.expanded,
generated = solution.generated
)
};
file.write_all(line.as_bytes())?;
file.flush()?;
}
if terminated {
return Ok(solution);
}
}
}
pub fn print_solution_statistics<C, L>(solution: &Solution<C, L>)
where
C: Copy + Display,
{
if let Some(cost) = solution.cost {
println!("cost: {cost}");
if solution.is_optimal {
println!("optimal cost: {cost}");
}
} else {
println!("No solution is found.");
if solution.is_infeasible {
println!("The problem is infeasible.");
}
}
if let Some(bound) = solution.best_bound {
println!("best bound: {bound}");
}
println!("Search time: {time}s", time = solution.time);
println!("Expanded: {expanded}", expanded = solution.expanded);
println!("Generated: {generated}", generated = solution.generated);
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_read_vector() {
let input = "1 2 3 4 5 6 \n 7 8 \n 9 10 11 12";
let mut lines = input.split_whitespace();
let matrix = read_vector::<i32>(&mut lines, 7);
assert!(matrix.is_ok());
assert_eq!(matrix.unwrap(), vec![1, 2, 3, 4, 5, 6, 7]);
}
#[test]
fn test_read_matrix() {
let input = "1 2 3 4 5 6 \n 7 8 \n 9 10 11 12";
let mut lines = input.split_whitespace();
let matrix = read_matrix::<i32>(&mut lines, 3, 3);
assert!(matrix.is_ok());
assert_eq!(
matrix.unwrap(),
vec![vec![1, 2, 3], vec![4, 5, 6], vec![7, 8, 9]]
);
}
}