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