1 module des.isys.neiro.neiron;
2 
3 import std.algorithm;
4 
5 import des.isys.neiro.traits;
6 
7 interface Neiron(T)
8 {
9     @property T output() const;
10     void process();
11 }
12 
13 abstract class FakeNeiron(T) : Neiron!T
14 { void process(){} }
15 
16 class ValueNeiron(T) : FakeNeiron!T
17 {
18     T value;
19     this( T value ) { this.value = value; }
20     @property T output() const { return value; }
21 }
22 
23 class ReferenceNeiron(T) : FakeNeiron!T
24 {
25     Neiron!T neiron;
26     this( Neiron!T neiron )
27     in{ assert( neiron !is null ); } body
28     { this.neiron = neiron; }
29     @property T output() const { return neiron.output; }
30 }
31 
32 unittest
33 {
34     auto vn = new ValueNeiron!float(3.1415);
35     auto rn = new ReferenceNeiron!float( vn );
36     import std.math;
37     assert( abs(rn.output - 3.1415) < float.epsilon*2 );
38 }
39 
40 class FunctionNeiron(T) : FakeNeiron!T
41 {
42     T delegate() func;
43     this( T delegate() func )
44     in{ assert( func !is null ); } body
45     { this.func = func; }
46     @property T output() const { return func(); }
47 }
48 
49 interface Link(T) { @property T value(); }
50 
51 abstract class BaseNeiron(T) : Neiron!T
52     if( canSummate!T )
53 {
54 protected:
55     T value;
56 
57     abstract T activate( T );
58     abstract @property Link!T[] links();
59 
60 public:
61 
62     this( T initial = T.init )
63     { value = initial; }
64 
65     final @property T output() const { return value; }
66 
67     void process()
68     { value = activate( reduce!((s,v)=>s+v)( map!"a.value"(links) ) ); }
69 }
70 
71 version(unittest)
72 {
73     private
74     {
75         import std.conv;
76         class TestNeiron : BaseNeiron!float
77         {
78         protected:
79 
80             override float activate( float x ) { return x * coef; }
81             override @property Link!float[] links() { return _links; }
82             Link!float[] _links;
83             float coef;
84         public:
85             this( float ac, Link!float[] lnks ) { coef = ac; _links = lnks; }
86         }
87     }
88 }
89 
90 unittest
91 {
92     static class TestLink : Link!float
93     { @property float value() { return 1; } }
94 
95     TestLink[] buf;
96     foreach( i; 0 .. 10 ) buf ~= new TestLink;
97 
98     auto tn = new TestNeiron( .25, to!(Link!float[])(buf) );
99 
100     tn.process();
101     assert( tn.output == 2.5 );
102 }
103 
104 abstract class WeightLink(T,N) : Link!T
105     if( canMultiplicate!(T,N) )
106 {
107     @property 
108     {
109         abstract protected T source() const;
110 
111         abstract N weight() const;
112         abstract void weight( N );
113 
114         final T value() { return source * weight; }
115     }
116 }
117 
118 unittest
119 {
120     static class TestLink : WeightLink!(float,float)
121     {
122         float w;
123         override @property
124         {
125             protected float source() const { return 1; }
126 
127             float weight() const { return w; }
128             void weight( float nw ) { w = nw; }
129         }
130 
131         this( float W ) { w = W; }
132     }
133 
134     TestLink[] buf;
135     foreach( i; 0 .. 10 ) buf ~= new TestLink( 0.25 );
136 
137     auto tn = new TestNeiron( 1, to!(Link!float[])(buf) );
138 
139     tn.process();
140     assert( tn.output == 2.5 );
141 
142 }