1 module des.isys.neiro.func;
2 
3 import std.math;
4 
5 import des.isys.neiro.traits;
6 
7 interface Function(X,Y) { Y opCall( X x ) const; }
8 
9 class HeavisideFunction(X,Y) : Function!(X,Y)
10     if( canComparison!X )
11 {
12     Y a, b;
13     X lim;
14 
15     this( Y a, Y b, X lim )
16     {
17         this.a = a;
18         this.b = b;
19         this.lim = lim;
20     }
21 
22     Y opCall( X x ) const { return x < lim ? a : b; }
23 }
24 
25 class HeavisideMeanFunction(X,Y) : HeavisideFunction!(X,Y)
26     if( canFindMean!Y )
27 {
28     this( Y a, Y b, X lim ) { super(a,b,lim); }
29     override Y opCall( X x ) const
30     {
31         if( x == lim ) return ( a + b ) / 2;
32         return super.opCall(x);
33     }
34 }
35 
36 unittest
37 {
38     auto H = new HeavisideFunction!(float,float)(0,1,0);
39     assert( H(0) == 1 );
40     assert( H(1) == 1 );
41     assert( H(-1) == 0 );
42     auto HM = new HeavisideMeanFunction!(float,float)(-1,1,0);
43     assert( HM(0) == 0 );
44     assert( HM(10) == 1 );
45     assert( HM(-2) == -1 );
46 }
47 
48 interface DerivativeFunction(T) : Function!(T,T)
49     if( isFloatingPoint!T )
50 { T dx( T x ) const; }
51 
52 class LinearDependence(T) : DerivativeFunction!T
53     if( isFloatingPoint!T )
54 {
55     T k;
56     this( T k=1 ) { this.k = k; }
57     T opCall( T x ) const { return x * k; }
58     T dx( T x ) const { return k; };
59 }
60 
61 unittest
62 {
63     auto ld = new LinearDependence!float(2);
64     assert( ld(1) == 2 );
65     assert( ld(2) == 4 );
66 }
67 
68 /+ f -> (0,1) +/
69 class ExponentialSigmoid(T) : DerivativeFunction!T
70     if( isFloatingPoint!T )
71 {
72     T alpha;
73     this( T alpha=1.0 ) { this.alpha = alpha; }
74 
75     const
76     {
77         T opCall( T x )
78         { return 1.0 / ( 1.0 + pow( E, -alpha * x ) ); }
79 
80         T dx( T x )
81         {
82             auto eax = pow( E, alpha * x );
83             return alpha * eax / ( ( eax + 1 )^^2 );
84         }
85     }
86 }
87 
88 unittest
89 {
90     auto fes = new ExponentialSigmoid!float;
91     assert( fes(0) == .5 );
92 }
93 
94 /+ f -> (-1,1) +/
95 class RationalSigmoid(T) : DerivativeFunction!T
96     if( isFloatingPoint!T )
97 {
98     T alpha;
99     this( T alpha=1.0 ) { this.alpha = alpha; }
100 
101     const
102     {
103         T opCall( T x )
104         { return x / ( abs(x) + alpha ); }
105 
106         T dx( T x )
107         {
108             auto aax = alpha + abs(x);
109             return alpha / ( ( abs(x) + alpha )^^2 );
110         }
111     }
112 }
113 
114 unittest
115 {
116     auto frs = new RationalSigmoid!float;
117     assert( frs(0) == 0 );
118 }
119 
120 /+ f -> (-pi/2,pi/2) +/
121 class AtanSigmoid(T) : DerivativeFunction!T
122     if( isFloatingPoint!T )
123 {
124     const
125     {
126         T opCall( T x ) { return atan(x); }
127         T dx( T x ) { return 1.0 / ( x*x + 1.0 ); }
128     }
129 }
130 
131 unittest
132 {
133     auto fas = new AtanSigmoid!float;
134     assert( fas(0) == 0 );
135 }