use crate::{Best, Contextful, Evolution, Group, NestedMover, ParticleInitDependent, SetTo, Unit};
use rand::Rng;
pub trait Searcher: Contextful {
type TUnit: Unit;
fn init(&mut self, particles: &mut Group<Self::TUnit>);
fn next(&mut self, particles: &mut Group<Self::TUnit>) -> &Best<Self::TUnit>;
fn reseed<R: Rng>(&mut self, rng: &mut R);
#[must_use]
fn nested<TInit>(
self,
max_iteration: usize,
particle_init: TInit,
) -> NestedMover<<Self::TUnit as SetTo>::TTarget, Self::TUnit, Self, TInit>
where
Self: Sized,
Self::TUnit: SetTo,
TInit: ParticleInitDependent<TIn = <Self::TUnit as SetTo>::TTarget, TOut = Self::TUnit>,
{
NestedMover::new(max_iteration, self, particle_init)
}
fn iter<'a>(
&'a mut self,
max_iteration: usize,
group: &'a mut Group<Self::TUnit>,
evolution: Option<&'a mut Evolution<Self::TUnit>>,
) -> SearcherIter<'a, Self::TUnit, Self>
where
Self: Sized,
{
SearcherIter::new(max_iteration, self, group, evolution)
}
}
pub struct SearcherIter<'a, TUnit, TSearcher>
where
TUnit: Unit,
TSearcher: Searcher<TUnit = TUnit>,
{
max_iteration: usize,
iteration: usize,
searcher: &'a mut TSearcher,
group: &'a mut Group<TUnit>,
evolution: Option<&'a mut Evolution<TUnit>>,
}
impl<'a, TUnit, TSearcher> SearcherIter<'a, TUnit, TSearcher>
where
TUnit: Unit,
TSearcher: Searcher<TUnit = TUnit>,
{
pub fn new(
max_iteration: usize,
searcher: &'a mut TSearcher,
group: &'a mut Group<TUnit>,
evolution: Option<&'a mut Evolution<TUnit>>,
) -> Self {
searcher.init(group);
SearcherIter {
max_iteration,
iteration: 0,
searcher,
group,
evolution,
}
}
}
impl<TUnit: Unit, TSearcher: Searcher<TUnit = TUnit>> Iterator
for SearcherIter<'_, TUnit, TSearcher>
{
type Item = Best<TUnit>;
fn next(&mut self) -> Option<Self::Item> {
if self.iteration >= self.max_iteration {
return None;
}
self.iteration += 1;
self.searcher
.set_iteration(self.iteration, self.max_iteration);
let r = self.searcher.next(self.group);
if let Some(e) = &mut self.evolution {
e.push_snapshot(self.group);
}
Some(*r)
}
}