use std::error::Error;
use nalgebra::Dim;
use rand::RngCore;
use crate::{comparison::BetterThanOperator, evolutionary_strategy::EvolutionaryStrategy, fitness::FitnessFunction, initializer::Initializer, local_search::{LocalSearchCandidate, LocalSearchResult, LocalSearchStats}, perturbation::PerturbationOperator, terminating::TerminatingCondition};
pub fn random_search<
D: Dim,
TInput,
TResult,
TFit,
TTerminatingCondition,
TPerturbationOperator,
TBetterThanOperator,
TEvolutionaryStrategy,
TInitializer>(
fit: &TFit,
terminating_condition: &mut TTerminatingCondition,
better_than_operator: &TBetterThanOperator,
initializer: &TInitializer,
size: D,
rng: &mut dyn RngCore
) -> Result<LocalSearchResult<TInput, TResult>, Box<dyn Error>>
where
TResult: Clone,
TInput: Clone,
TFit: FitnessFunction<In = TInput, Out = TResult>,
TTerminatingCondition: TerminatingCondition<TInput, TResult>,
TPerturbationOperator: PerturbationOperator<Chromosome = TInput>,
TEvolutionaryStrategy: EvolutionaryStrategy<TResult, TPerturbationOperator>,
TBetterThanOperator: BetterThanOperator<TResult>,
TInitializer: Initializer<D, TInput>
{
let initial = initializer.initialize_single(size, rng);
let mut best_candidate = LocalSearchCandidate {
fit: fit.fit(&initial)?,
pos: initial,
cycle: 0
};
let mut stats = LocalSearchStats::new();
let mut cycle: usize = 0;
while !terminating_condition.should_terminate(&best_candidate, &stats, cycle) {
let next = initializer.initialize_single(size, rng);
let next_fit = fit.fit(&next)?;
// Minimize
if better_than_operator.better_than(&next_fit, &best_candidate.fit) {
best_candidate = LocalSearchCandidate {
pos: next,
fit: next_fit,
cycle
};
stats.append(best_candidate.clone());
}
cycle += 1;
}
Ok(LocalSearchResult {
best_candidate,
stats,
cycles: cycle
})
}