pub mod local_improver;
use std::sync::Arc;
use std::time as stdtime;
use crate::objective::EvaluatedSolution;
use crate::objective::Objective;
use local_improver::LocalImprover;
use self::local_improver::Minimizer;
use super::common::default_function_between_steps;
use super::common::FunctionBetweenSteps;
use super::common::Neighborhood;
use super::Solver;
pub struct LocalSearchSolver<S> {
objective: Arc<Objective<S>>,
local_improver: Box<dyn LocalImprover<S>>,
function_between_steps: FunctionBetweenSteps<S>,
time_limit: Option<stdtime::Duration>,
iteration_limit: Option<u32>,
}
impl<S: 'static> LocalSearchSolver<S> {
pub fn initialize(
neighborhood: Arc<dyn Neighborhood<S>>,
objective: Arc<Objective<S>>,
) -> Self {
Self::with_options(neighborhood, objective, None, None, None, None)
}
pub fn with_options(
neighborhood: Arc<dyn Neighborhood<S>>,
objective: Arc<Objective<S>>,
local_improver: Option<Box<dyn LocalImprover<S>>>,
function_between_steps: Option<FunctionBetweenSteps<S>>,
time_limit: Option<stdtime::Duration>,
iteration_limit: Option<u32>,
) -> Self {
let local_improver = match local_improver {
Some(local_improver) => local_improver,
None => Box::new(Minimizer::new(neighborhood, objective.clone()))
as Box<dyn LocalImprover<S>>,
};
Self {
objective,
local_improver,
function_between_steps: function_between_steps
.unwrap_or(default_function_between_steps()),
time_limit,
iteration_limit,
}
}
}
impl<S> Solver<S> for LocalSearchSolver<S> {
fn solve(&self, initial_solution: S) -> EvaluatedSolution<S> {
let start_time = stdtime::Instant::now();
let mut current_solution = self.objective.evaluate(initial_solution);
let mut iteration_counter = 1;
while let Some(new_solution) = self.local_improver.improve(¤t_solution) {
(self.function_between_steps)(
iteration_counter,
&new_solution,
Some(¤t_solution),
self.objective.clone(),
Some(start_time),
self.time_limit,
self.iteration_limit,
);
current_solution = new_solution;
if let Some(time_limit) = self.time_limit {
if stdtime::Instant::now().duration_since(start_time) > time_limit {
println!("Time limit reached.");
break;
}
}
if let Some(iteration_limit) = self.iteration_limit {
if iteration_counter >= iteration_limit {
println!("Iteration limit reached.");
break;
}
}
iteration_counter += 1;
}
current_solution
}
}