~ruther/ctu-fee-eoa

b1a2bbaa8489931da4881507e68f74e41f79a1a9 — Rutherther 2 months ago f6dd4b7
refactor: extend local search to accept any inputs

Instead of accepting only BinaryString, accept anything.
Extend the operators to accept anything.
2 files changed, 42 insertions(+), 39 deletions(-)

M env/src/local_search/mod.rs
M env/src/terminating/mod.rs
M env/src/local_search/mod.rs => env/src/local_search/mod.rs +17 -17
@@ 7,41 7,41 @@ use crate::comparison::BetterThanOperator;

// Functions
#[derive(Debug, Clone, PartialEq)]
pub struct LocalSearchCandidate<T>
    where T: Clone
pub struct LocalSearchCandidate<TInput, TResult>
{
    pub fit: T,
    pub pos: BinaryString,
    pub fit: TResult,
    pub pos: TInput,
    pub cycle: usize
}

#[derive(Debug, Clone, PartialEq)]
pub struct LocalSearchResult<T>
    where T: Clone
pub struct LocalSearchResult<TInput, TResult>
    where TResult: Clone
{
    pub best_candidate: LocalSearchCandidate<T>,
    pub best_candidate: LocalSearchCandidate<TInput, TResult>,

    // How many cycles there were
    pub cycles: usize,

    // statistics
    pub best_candidates: Vec<LocalSearchCandidate<T>>
    pub best_candidates: Vec<LocalSearchCandidate<TInput, TResult>>
}

fn local_search_first_improving<
        T, TErr, TFit, TTerminatingCondition, TPerturbationOperator, TBetterThanOperator>(
        TInput, TResult, TErr, TFit, TTerminatingCondition, TPerturbationOperator, TBetterThanOperator>(
    fit: &TFit,
    terminating_condition: &mut TTerminatingCondition,
    perturbation_operator: &mut TPerturbationOperator,
    better_than_operator: &TBetterThanOperator,
    initial: &BinaryString
) -> Result<LocalSearchResult<T>, TErr>
    initial: &TInput
) -> Result<LocalSearchResult<TInput, TResult>, TErr>
where
    T: Clone,
    TFit: FitnessFunction<In = BinaryString, Out = T, Err = TErr>,
    TTerminatingCondition: TerminatingCondition<T>,
    TPerturbationOperator: PerturbationOperator<Chromosome = BinaryString>,
    TBetterThanOperator: BetterThanOperator<T>,
    TResult: Clone,
    TInput: Clone,
    TFit: FitnessFunction<In = TInput, Out = TResult, Err = TErr>,
    TTerminatingCondition: TerminatingCondition<TInput, TResult>,
    TPerturbationOperator: PerturbationOperator<Chromosome = TInput>,
    TBetterThanOperator: BetterThanOperator<TResult>,
{
    let mut best_candidate = LocalSearchCandidate {
        pos: initial.clone(),


@@ 49,7 49,7 @@ where
        cycle: 0
    };

    let mut stats: Vec<LocalSearchCandidate<T>> = vec![];
    let mut stats: Vec<LocalSearchCandidate<TInput, TResult>> = vec![];
    let mut cycle: usize = 0;

    while !terminating_condition.should_terminate(&best_candidate, &stats, cycle) {

M env/src/terminating/mod.rs => env/src/terminating/mod.rs +25 -22
@@ 1,24 1,23 @@
use crate::{binary_string::BinaryString, local_search::LocalSearchCandidate};

pub trait TerminatingCondition<T>
    where T: Clone
pub trait TerminatingCondition<TInput, TResult>
{
    fn should_terminate(
        self: &mut Self,
        candidate: &LocalSearchCandidate<T>,
        stats: &Vec<LocalSearchCandidate<T>>,
        candidate: &LocalSearchCandidate<TInput, TResult>,
        stats: &Vec<LocalSearchCandidate<TInput, TResult>>,
        cycle: usize
    ) -> bool;
}

pub struct EqualTerminatingCondition {
    target: BinaryString,
pub struct EqualTerminatingCondition<T> {
    target: T,
    remember_match: bool,
    matched: bool,
}

impl EqualTerminatingCondition {
    pub fn new(target: BinaryString) -> Self {
impl<T> EqualTerminatingCondition<T> {
    pub fn new(target: T) -> Self {
        Self {
            target,
            remember_match: false,


@@ 26,7 25,7 @@ impl EqualTerminatingCondition {
        }
    }

    pub fn new_remembered(target: BinaryString) -> Self {
    pub fn new_remembered(target: T) -> Self {
        Self {
            target,
            remember_match: true,


@@ 39,11 38,15 @@ impl EqualTerminatingCondition {
    }
}

impl<T: Clone> TerminatingCondition<T> for EqualTerminatingCondition {
impl<TInput, TResult> TerminatingCondition<TInput, TResult> for EqualTerminatingCondition<TInput>
where
    TInput: Clone + PartialEq,
    TResult: Clone
{
    fn should_terminate(
        self: &mut Self,
        candidate: &LocalSearchCandidate<T>,
        _: &Vec<LocalSearchCandidate<T>>,
        candidate: &LocalSearchCandidate<TInput, TResult>,
        _: &Vec<LocalSearchCandidate<TInput, TResult>>,
        _: usize
    ) -> bool {
        let matched = candidate.pos == self.target;


@@ 68,23 71,23 @@ impl NoBetterForCyclesTerminatingCondition {
    }
}

pub struct AndTerminatingConditions<'a, T: Clone> {
    terminating_conditions: Vec<&'a mut dyn TerminatingCondition<T>>
pub struct AndTerminatingConditions<'a, TInput, TResult> {
    terminating_conditions: Vec<&'a mut dyn TerminatingCondition<TInput, TResult>>
}

impl<'a, T: Clone> AndTerminatingConditions<'a, T> {
    pub fn new(terminating_conditions: Vec<&'a mut dyn TerminatingCondition<T>>) -> Self {
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, T: Clone> TerminatingCondition<T> for AndTerminatingConditions<'a, T> {
impl<'a, TInput, TResult> TerminatingCondition<TInput, TResult> for AndTerminatingConditions<'a, TInput, TResult> {
    fn should_terminate(
        self: &mut Self,
        candidate: &LocalSearchCandidate<T>,
        stats: &Vec<LocalSearchCandidate<T>>,
        candidate: &LocalSearchCandidate<TInput, TResult>,
        stats: &Vec<LocalSearchCandidate<TInput, TResult>>,
        cycle: usize
    ) -> bool {
        return self.terminating_conditions.iter_mut()


@@ 94,11 97,11 @@ impl<'a, T: Clone> TerminatingCondition<T> for AndTerminatingConditions<'a, T> {
    }
}

impl<T: Clone> TerminatingCondition<T> for NoBetterForCyclesTerminatingCondition {
impl<TInput, TResult> TerminatingCondition<TInput, TResult> for NoBetterForCyclesTerminatingCondition {
    fn should_terminate (
        self: &mut Self,
        candidate: &LocalSearchCandidate<T>,
        _: &Vec<LocalSearchCandidate<T>>,
        candidate: &LocalSearchCandidate<TInput, TResult>,
        _: &Vec<LocalSearchCandidate<TInput, TResult>>,
        cycle: usize
    ) -> bool {
        (cycle - candidate.cycle) > self.cycles