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 }