ddecluster.cpp
1 /********************************************************************************
2  * Neural Network Framework. *
3  * Copyright (C) 2005-2011 Gianluca Massera <emmegian@yahoo.it> *
4  * *
5  * This program is free software; you can redistribute it and/or modify *
6  * it under the terms of the GNU General Public License as published by *
7  * the Free Software Foundation; either version 2 of the License, or *
8  * (at your option) any later version. *
9  * *
10  * This program is distributed in the hope that it will be useful, *
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13  * GNU General Public License for more details. *
14  * *
15  * You should have received a copy of the GNU General Public License *
16  * along with this program; if not, write to the Free Software *
17  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA *
18  ********************************************************************************/
19 
20 #include "ddecluster.h"
21 
22 namespace farsa {
23 
24 DDECluster::DDECluster( const DoubleVector& c, unsigned int numNeurons, QString name )
25  : Cluster( numNeurons, name ), tmpdata(numNeurons), tmpdata2(numNeurons) {
26  setCoeff( c );
27 }
28 
30  : Cluster( params, prefix ), tmpdata(numNeurons()), tmpdata2(numNeurons()) {
31  // coefficients is a vector, that is a list of space-separated values
32  QString str = params.getValue(prefix + "coefficients");
33  if (!str.isEmpty()) {
34  QStringList list = str.split(QRegExp("\\s+"), QString::SkipEmptyParts);
35  coeff.resize( list.size() );
36  for( int i=0; i<list.size(); i++) {
37  bool ok;
38  coeff[i] = list[i].toDouble(&ok);
39  if (!ok) {
40  coeff[i] = 0.0;
41  }
42  }
43  }
44 }
45 
47  /* Nothing to do */
48 }
49 
51  coeff = c;
52  ds.resize( (c.size()>3) ? c.size()-3 : 0 );
53  for( int i=0; i<ds.size(); i++ ) {
54  ds[i].resize( numNeurons() );
55  ds[i].zeroing();
56  }
57 }
58 
60  unsigned int csize = coeff.size();
61  if ( csize == 0 ) {
62  // uscita un po' strana!
63  outputs().zeroing();
64  setNeedReset( true );
65  return;
66  }
67  // --- tmp <- a0
68  tmpdata.setAll( coeff[0] );
69  if ( csize == 1 ) {
70  breakUpdate();
71  return;
72  }
73  // --- tmp <- a0 + a1*f(x)
74  outFunction()->apply( inputs(), tmpdata2 );
75  tmpdata2 *= coeff[1];
76  tmpdata += tmpdata2;
77  if ( csize == 2 ) {
78  breakUpdate();
79  return;
80  }
81  // --- tmp <- a0 + a1*f(x) + a2*x
82  tmpdata2.copyValues( inputs() );
83  tmpdata2 *= coeff[2];
84  tmpdata += tmpdata2;
85  if ( csize == 3 ) {
86  breakUpdate();
87  return;
88  }
89  // --- tmp <- a0 + a1*f(x) + a2*x + a3*y ... aN*y^(n-3)
90  for( int i=0; i<ds.size(); i++ ) {
91  tmpdata2.copyValues( ds[i] );
92  tmpdata2 *= coeff[i+3];
93  tmpdata += tmpdata2;
94  }
95  breakUpdate();
96  return;
97 }
98 
99 void DDECluster::breakUpdate() {
100  outputs().copyValues( tmpdata );
101  updateDs();
102  setNeedReset( true );
103 }
104 
105 void DDECluster::updateDs() {
106  if ( ds.size() == 0 ) return;
107  // --- Le derivate sono semplici differenze:
108  // --- y' = y(t) - y(t-1)
109  // --- y'' = y'(t) - y'(t-1)
110  // --- ... and so on
111  if ( ds.size() == 1 ) {
112  ds[0].copyValues( outputs() );
113  } else if ( ds.size() == 2 ) {
114  subtract( ds[1], outputs(), ds[0] );
115  ds[0].copyValues( outputs() );
116  } else {
117  // ----- Problemi di questo tipo di calcolo:
118  // *** calcola, cmq, anche la derivata ds.size()+1... l'ultimo tmpdata calcolato prima di uscire.
119  tmpdata.copyValues( outputs() );
120  for( int i=0; i<ds.size(); i++ ) {
121  if ( i%2 == 0 ) {
122  // calcola la derivata i+1 per il ciclo successivo
123  subtract( tmpdata2, tmpdata, ds[1] );
124  // memorizza il valore della derivata i calcolata al ciclo precedente i-1
125  ds[i].copyValues( tmpdata );
126  } else {
127  // calcola la derivata i+1 per il ciclo successivo
128  subtract( tmpdata, tmpdata2, ds[i] );
129  // memorizza il valore della derivata i calcolata al ciclo precedente i-1
130  ds[i].copyValues( tmpdata2 );
131  }
132  }
133  }
134 }
135 
136 void DDECluster::save(ConfigurationParameters& params, QString prefix)
137 {
138  Cluster::save( params, prefix );
139  params.startObjectParameters(prefix, "DDECluster", this);
140  // First creating a string list, then transforming to a single string
141  QStringList list;
142  for (unsigned int i = 0; i < coeff.size(); i++) {
143  list.push_back(QString::number(coeff[i]));
144  }
145  params.createParameter(prefix, "coefficients", list.join(" "));
146 }
147 
148 void DDECluster::describe( QString type ) {
149  Cluster::describe( type );
150  Descriptor d = addTypeDescription( type, "A Cluster where the outputs depends on previous value", "The outputs are calculated accordlying with follow equation:\n y(t) <- a0 + a1*f(x) + a2*x(t) + a3*y(t-1) + a4*y'(t-1) + a5*y''(t-1) + a6*y'''(t-1) + ... \n NOTE: a simply leaky-integrator is possible by settings coefficients in the following way:\n a0 <- 0.0 ; a1 <- delta ; a2 <- 0.0 ; a3 <- 1.0-delta\n getting:\n y(t) <- (delta)*f(x) + (1.0-delta)*y(t-1)" );
151  d.describeReal( "coefficients" ).def( 0.0 ).props( IsMandatory | IsList ).help( "The coefficients of the equation" );
152 }
153 
154 }
155