use crate::{binary_string::BinaryString, local_search::LocalSearchCandidate}; pub trait TerminatingCondition where T: Clone { fn should_terminate( self: &mut Self, candidate: &LocalSearchCandidate, stats: &Vec>, cycle: usize ) -> bool; } pub struct EqualTerminatingCondition { target: BinaryString, remember_match: bool, matched: bool, } impl EqualTerminatingCondition { pub fn new(target: BinaryString) -> Self { Self { target, remember_match: false, matched: false, } } pub fn new_remembered(target: BinaryString) -> Self { Self { target, remember_match: true, matched: false, } } pub fn reset_match(self: &mut Self) { self.matched = false; } } impl TerminatingCondition for EqualTerminatingCondition { fn should_terminate( self: &mut Self, candidate: &LocalSearchCandidate, _: &Vec>, _: usize ) -> bool { let matched = candidate.pos == self.target; if matched && self.remember_match { self.matched = true; } matched || self.matched } } pub struct NoBetterForCyclesTerminatingCondition { cycles: usize } impl NoBetterForCyclesTerminatingCondition { pub fn new(cycles: usize) -> Self { Self { cycles } } } pub struct AndTerminatingConditions<'a, T: Clone> { terminating_conditions: Vec<&'a mut dyn TerminatingCondition> } impl<'a, T: Clone> AndTerminatingConditions<'a, T> { pub fn new(terminating_conditions: Vec<&'a mut dyn TerminatingCondition>) -> Self { Self { terminating_conditions } } } impl<'a, T: Clone> TerminatingCondition for AndTerminatingConditions<'a, T> { fn should_terminate( self: &mut Self, candidate: &LocalSearchCandidate, stats: &Vec>, cycle: usize ) -> bool { return self.terminating_conditions.iter_mut() .all( |cond| cond.should_terminate(candidate, stats, cycle) ) } } impl TerminatingCondition for NoBetterForCyclesTerminatingCondition { fn should_terminate ( self: &mut Self, candidate: &LocalSearchCandidate, _: &Vec>, cycle: usize ) -> bool { (cycle - candidate.cycle) > self.cycles } }