1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
use core::panic;

use crate::{Adaptable, Neural, Responsive};

pub type BoxedTrainable<N, A, R> = Box<dyn Trainable<N, A, R> + Send>;
/// Interface for structures encapsulating algorithms for training from data sets
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);
                // println!("{}:{}: {},{}", epoch, i,rate, influence);
            }
        }
    }

    fn clone_dyn(&self) -> Box<dyn Trainable<N, A, R> + Send> {
        Box::new(self.clone()) // Forward to the derive(Clone) impl    }
    }
}

#[cfg(test)]
mod tests {

    #[test]
    fn it_works() {
        let result = 2 + 2;
        assert_eq!(result, 4);
    }
}