use core::panic;
use crate::{Adaptable, Neural, Responsive};
pub type BoxedTrainable<N, A, R> = Box<dyn Trainable<N, A, R> + Send>;
pub trait Trainable<N, A, R>
where
N: Neural,
A: Adaptable<N, R>,
R: Responsive<N>,
{
fn train(
&mut self,
neurons: &mut N,
adaptation: &mut A,
feature: &mut R,
patterns: &ArrayView2<f64>,
);
fn clone_dyn(&self) -> Box<dyn Trainable<N, A, R> + Send>;
}
impl<N, A, R> Trainable<N, A, R> for Box<dyn Trainable<N, A, R> + Send>
where
N: Neural,
A: Adaptable<N, R>,
R: Responsive<N>,
{
fn train(
&mut self,
neurons: &mut N,
adaptation: &mut A,
feature: &mut R,
patterns: &ArrayView2<f64>,
) {
(**self).train(neurons, adaptation, feature, patterns)
}
fn clone_dyn(&self) -> Box<dyn Trainable<N, A, R> + Send> {
panic!()
}
}
impl<N, A, R> Clone for Box<dyn Trainable<N, A, R> + Send>
where
N: Neural,
A: Adaptable<N, R>,
R: Responsive<N>,
{
fn clone(&self) -> Self {
(**self).clone_dyn()
}
}
#[derive(Clone)]
pub struct IncrementalLearning {
pub radii: (f64, f64),
pub rates: (f64, f64),
pub epochs: usize,
}
use ndarray::{prelude::*, Data};
impl<N, A, R> Trainable<N, A, R> for IncrementalLearning
where
N: Neural,
A: Adaptable<N, R>,
R: Responsive<N>,
{
fn train(
&mut self,
neurons: &mut N,
adaptation: &mut A,
tuning: &mut R,
patterns: &ArrayView2<f64>,
) {
let n_samples = patterns.len_of(Axis(0));
for epoch in 0..self.epochs {
println!("{}", epoch);
for (i, pattern) in patterns.outer_iter().enumerate() {
let progress =
((epoch * n_samples + i) as f64) / ((self.epochs * n_samples) as f64);
let rate = self.rates.0 * (self.rates.1 / self.rates.0).powf(progress);
let influence = self.radii.0 * (self.radii.1 / self.radii.0).powf(progress);
adaptation.adapt(neurons, tuning, &pattern, influence, rate);
}
}
}
fn clone_dyn(&self) -> Box<dyn Trainable<N, A, R> + Send> {
Box::new(self.clone()) }
}
#[cfg(test)]
mod tests {
#[test]
fn it_works() {
let result = 2 + 2;
assert_eq!(result, 4);
}
}