use std::fmt::Debug;
use solverforge_core::domain::PlanningSolution;
use super::Acceptor;
pub struct LateAcceptanceAcceptor<S: PlanningSolution> {
late_acceptance_size: usize,
score_history: Vec<Option<S::Score>>,
current_index: usize,
}
impl<S: PlanningSolution> Debug for LateAcceptanceAcceptor<S> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("LateAcceptanceAcceptor")
.field("late_acceptance_size", &self.late_acceptance_size)
.field("current_index", &self.current_index)
.finish()
}
}
impl<S: PlanningSolution> Clone for LateAcceptanceAcceptor<S> {
fn clone(&self) -> Self {
Self {
late_acceptance_size: self.late_acceptance_size,
score_history: self.score_history.clone(),
current_index: self.current_index,
}
}
}
impl<S: PlanningSolution> LateAcceptanceAcceptor<S> {
pub fn new(late_acceptance_size: usize) -> Self {
assert!(
late_acceptance_size > 0,
"late_acceptance_size must be > 0, got 0"
);
Self {
late_acceptance_size,
score_history: vec![None; late_acceptance_size],
current_index: 0,
}
}
}
impl<S: PlanningSolution> Default for LateAcceptanceAcceptor<S> {
fn default() -> Self {
Self::new(400)
}
}
impl<S: PlanningSolution> Acceptor<S> for LateAcceptanceAcceptor<S> {
fn is_accepted(&mut self, last_step_score: &S::Score, move_score: &S::Score) -> bool {
if move_score >= last_step_score {
return true;
}
if let Some(late_score) = &self.score_history[self.current_index] {
move_score >= late_score
} else {
true
}
}
fn phase_started(&mut self, initial_score: &S::Score) {
for slot in &mut self.score_history {
*slot = Some(*initial_score);
}
self.current_index = 0;
}
fn step_ended(&mut self, step_score: &S::Score) {
self.score_history[self.current_index] = Some(*step_score);
self.current_index = (self.current_index + 1) % self.late_acceptance_size;
}
}