solverforge_solver/phase/localsearch/acceptor/
late_acceptance.rs1use std::fmt::Debug;
4
5use solverforge_core::domain::PlanningSolution;
6
7use super::Acceptor;
8
9pub struct LateAcceptanceAcceptor<S: PlanningSolution> {
32 late_acceptance_size: usize,
34 score_history: Vec<Option<S::Score>>,
36 current_index: usize,
38}
39
40impl<S: PlanningSolution> Debug for LateAcceptanceAcceptor<S> {
41 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
42 f.debug_struct("LateAcceptanceAcceptor")
43 .field("late_acceptance_size", &self.late_acceptance_size)
44 .field("current_index", &self.current_index)
45 .finish()
46 }
47}
48
49impl<S: PlanningSolution> Clone for LateAcceptanceAcceptor<S> {
50 fn clone(&self) -> Self {
51 Self {
52 late_acceptance_size: self.late_acceptance_size,
53 score_history: self.score_history.clone(),
54 current_index: self.current_index,
55 }
56 }
57}
58
59impl<S: PlanningSolution> LateAcceptanceAcceptor<S> {
60 pub fn new(late_acceptance_size: usize) -> Self {
69 assert!(
70 late_acceptance_size > 0,
71 "late_acceptance_size must be > 0, got 0"
72 );
73 Self {
74 late_acceptance_size,
75 score_history: vec![None; late_acceptance_size],
76 current_index: 0,
77 }
78 }
79}
80
81impl<S: PlanningSolution> Default for LateAcceptanceAcceptor<S> {
82 fn default() -> Self {
83 Self::new(400)
84 }
85}
86
87impl<S: PlanningSolution> Acceptor<S> for LateAcceptanceAcceptor<S> {
88 fn is_accepted(&mut self, last_step_score: &S::Score, move_score: &S::Score) -> bool {
89 if move_score >= last_step_score {
91 return true;
92 }
93
94 if let Some(late_score) = &self.score_history[self.current_index] {
96 move_score >= late_score
97 } else {
98 true
100 }
101 }
102
103 fn phase_started(&mut self, initial_score: &S::Score) {
104 for slot in &mut self.score_history {
106 *slot = Some(*initial_score);
107 }
108 self.current_index = 0;
109 }
110
111 fn step_ended(&mut self, step_score: &S::Score) {
112 self.score_history[self.current_index] = Some(*step_score);
114 self.current_index = (self.current_index + 1) % self.late_acceptance_size;
115 }
116}