use std::fmt::Debug;
use solverforge_core::domain::PlanningSolution;
use super::Acceptor;
pub struct EntityTabuAcceptor {
entity_tabu_size: usize,
entity_tabu_list: Vec<u64>,
current_step_entities: Vec<u64>,
}
impl Debug for EntityTabuAcceptor {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("EntityTabuAcceptor")
.field("entity_tabu_size", &self.entity_tabu_size)
.field("tabu_list_len", &self.entity_tabu_list.len())
.finish()
}
}
impl Clone for EntityTabuAcceptor {
fn clone(&self) -> Self {
Self {
entity_tabu_size: self.entity_tabu_size,
entity_tabu_list: self.entity_tabu_list.clone(),
current_step_entities: self.current_step_entities.clone(),
}
}
}
impl EntityTabuAcceptor {
pub fn new(entity_tabu_size: usize) -> Self {
assert!(entity_tabu_size > 0, "entity_tabu_size must be > 0, got 0");
Self {
entity_tabu_size,
entity_tabu_list: Vec::with_capacity(entity_tabu_size),
current_step_entities: Vec::new(),
}
}
pub fn record_entity_move(&mut self, entity_id: u64) {
self.current_step_entities.push(entity_id);
}
pub fn is_entity_tabu(&self, entity_id: u64) -> bool {
self.entity_tabu_list.contains(&entity_id)
}
}
impl Default for EntityTabuAcceptor {
fn default() -> Self {
Self::new(7)
}
}
impl<S: PlanningSolution> Acceptor<S> for EntityTabuAcceptor {
fn is_accepted(&mut self, last_step_score: &S::Score, move_score: &S::Score) -> bool {
if move_score > last_step_score {
return true;
}
if move_score >= last_step_score {
return true;
}
false
}
fn phase_started(&mut self, _initial_score: &S::Score) {
self.entity_tabu_list.clear();
self.current_step_entities.clear();
}
fn phase_ended(&mut self) {
self.entity_tabu_list.clear();
}
fn step_started(&mut self) {
self.current_step_entities.clear();
}
fn step_ended(&mut self, _step_score: &S::Score) {
for entity_id in &self.current_step_entities {
if self.entity_tabu_list.len() >= self.entity_tabu_size {
self.entity_tabu_list.remove(0);
}
self.entity_tabu_list.push(*entity_id);
}
self.current_step_entities.clear();
}
}