1 module des.isys.neiro.layer.structure;
2 
3 import std.traits;
4 import std.conv;
5 
6 import des.isys.neiro.func;
7 import des.isys.neiro.neiron;
8 import des.isys.neiro.layer.neiron;
9 
10 class BPLayer(T) if( isFloatingPoint!T )
11 {
12 package:
13     BPNeiron!T[] neirons;
14 public:
15     this( BPNeiron!T[] nn ) { neirons = nn; }
16 
17     void process() { foreach( n; neirons ) n.process(); }
18 
19     void correct( T nu, T alpha )
20     {
21         foreach( neiron; neirons )
22             neiron.correct( nu, alpha );
23     }
24 }
25 
26 interface NetStructure(T)
27     if( isFloatingPoint!T )
28 {
29     @property
30     {
31         ValueNeiron!T[] input();
32         BPLayer!T[] layers();
33     }
34 }
35 
36 interface NetWeight(T)
37     if( isFloatingPoint!T )
38 { T opIndex( size_t layer, size_t left, size_t right ); }
39 
40 class RandomWeight(T) : NetWeight!T
41 {
42     import des.isys.neiro.layer.rand;
43     T lim, gap;
44 
45     this( T lim=0.2, T gap=0.1 )
46     {
47         this.lim = lim;
48         this.gap = gap;
49     }
50 
51     T opIndex( size_t layer, size_t input, size_t neiron )
52     { return gap_symmetry_uniform(lim,gap); }
53 }
54 
55 /++
56 ConsistentlyAssociatedLayereNetStructure
57 
58 input neiron set(ins) + unitary neiron(un) -> first layer (L1)
59     ins + un + L1 -> L2
60     ins + un + L1 + L2 -> L3
61     ins + un + L1 + L2 + L3 -> output
62 
63 +/
64 
65 class ConsistentlyAssociatedLayereNetStructure(T) : NetStructure!T
66     if( isFloatingPoint!T )
67 {
68 protected:
69 
70     ValueNeiron!T[] in_neirons;
71     BPNeiron!T[] neirons;
72     BPLayer!T[] net_layers;
73     DerivativeFunction!T func;
74 
75 public:
76 
77     this( DerivativeFunction!T func, size_t[] sizes, NetWeight!T weight=null )
78     in
79     {
80         assert( func !is null );
81         assert( sizes.length > 1 );
82     }
83     body
84     {
85         this.func = func;
86 
87         addUnitaryNeiron();
88         addInputNeirons( sizes[0] );
89         if( weight is null ) weight = new RandomWeight!T;
90         addLayers( sizes[1..$], weight );
91     }
92 
93     @property
94     {
95         ValueNeiron!T[] input() { return in_neirons; }
96         BPLayer!T[] layers() { return net_layers; }
97     }
98 
99 protected:
100 
101     void addUnitaryNeiron() { neirons ~= new ReferenceBPNeiron!T( new ValueNeiron!T(1) ); }
102 
103     void addInputNeirons( size_t count )
104     {
105         foreach( i; 0 .. count )
106         {
107             auto buf = new ValueNeiron!T(0);
108             in_neirons ~= buf;
109             neirons ~= new ReferenceBPNeiron!T(buf);
110         }
111     }
112 
113     void addLayers( size_t[] net_struct, NetWeight!T weight )
114     {
115         foreach( i; 0 .. net_struct.length )
116             addLayer( net_struct[i], (size_t j, size_t k){ return weight[i,j,k]; } );
117     }
118 
119     void addLayer( size_t size, T delegate(size_t, size_t) weight )
120     {
121         auto ln = createNeirons( size );
122 
123         linkNeirons( ln, neirons, weight );
124 
125         auto nln = to!(BPNeiron!T[])(ln);
126 
127         neirons ~= nln;
128         net_layers ~= new BPLayer!T( nln );
129     }
130 
131     auto createNeirons( size_t count )
132     {
133         auto ret = new BaseBPNeiron!T[](count);
134         ret[] = new BaseBPNeiron!T(func);
135         return to!(BPNeiron!T[])(ret);
136     }
137 
138     /+ function weight(a,b) must return weight of link from input neiron lnk[a] to neiron ns[b] +/
139     void linkNeirons( BPNeiron!T[] ns, BPNeiron!T[] lnk, T delegate(size_t,size_t) weight )
140     in { assert( weight !is null ); } body
141     { foreach( i, n; ns ) n.setLinks( createLinks( lnk, (size_t j){ return weight(j,i); } ) ); }
142 
143     BPLink!T[] createLinks( BPNeiron!T[] inn, T delegate(size_t) weight )
144     in { assert( weight !is null ); } body
145     {
146         auto links = new BaseBPLink!T[](inn.length);
147         foreach( j; 0 .. inn.length )
148             links[j] = new BaseBPLink!T( inn[j], weight(j) );
149         return to!(BPLink!T[])( links );
150     }
151 }
152 
153 unittest
154 {
155     auto nw = new class NetWeight!float
156     { float opIndex(size_t,size_t,size_t) { return 1; } };
157 
158     auto calns = new ConsistentlyAssociatedLayereNetStructure!float(
159                          new LinearDependence!float(2), [1,1], nw );
160 
161     calns.input[0].value = 1;
162     calns.layers[0].process();
163 
164     assert( calns.layers[0].neirons[0].output == 2 );
165 }