nnfw/src/ddecluster.cpp

00001 /********************************************************************************
00002  *  Neural Network Framework.                                                   *
00003  *  Copyright (C) 2005-2011 Gianluca Massera <emmegian@yahoo.it>                *
00004  *                                                                              *
00005  *  This program is free software; you can redistribute it and/or modify        *
00006  *  it under the terms of the GNU General Public License as published by        *
00007  *  the Free Software Foundation; either version 2 of the License, or           *
00008  *  (at your option) any later version.                                         *
00009  *                                                                              *
00010  *  This program is distributed in the hope that it will be useful,             *
00011  *  but WITHOUT ANY WARRANTY; without even the implied warranty of              *
00012  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the               *
00013  *  GNU General Public License for more details.                                *
00014  *                                                                              *
00015  *  You should have received a copy of the GNU General Public License           *
00016  *  along with this program; if not, write to the Free Software                 *
00017  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA  *
00018  ********************************************************************************/
00019 
00020 #include "ddecluster.h"
00021 
00022 namespace farsa {
00023 
00024 DDECluster::DDECluster( const DoubleVector& c, unsigned int numNeurons, QString name )
00025     : Cluster( numNeurons, name ), tmpdata(numNeurons), tmpdata2(numNeurons) {
00026     setCoeff( c );
00027 }
00028 
00029 DDECluster::DDECluster( ConfigurationParameters& params, QString prefix )
00030     : Cluster( params, prefix ), tmpdata(numNeurons()), tmpdata2(numNeurons()) {
00031     // coefficients is a vector, that is a list of space-separated values
00032     QString str = params.getValue(prefix + "coefficients");
00033     if (!str.isEmpty()) {
00034         QStringList list = str.split(QRegExp("\\s+"), QString::SkipEmptyParts);
00035         coeff.resize( list.size() );
00036         for( int i=0; i<list.size(); i++) {
00037             bool ok;
00038             coeff[i] = list[i].toDouble(&ok);
00039             if (!ok) {
00040                 coeff[i] = 0.0;
00041             }
00042         }
00043     }
00044 }
00045 
00046 DDECluster::~DDECluster() {
00047     /* Nothing to do */
00048 }
00049 
00050 void DDECluster::setCoeff( const DoubleVector& c ) {
00051     coeff = c;
00052     ds.resize( (c.size()>3) ? c.size()-3 : 0 );
00053     for( int i=0; i<ds.size(); i++ ) {
00054         ds[i].resize( numNeurons() );
00055         ds[i].zeroing();
00056     }
00057 }
00058 
00059 void DDECluster::update() {
00060     unsigned int csize = coeff.size();
00061     if ( csize == 0 ) {
00062         // uscita un po' strana!
00063         outputs().zeroing();
00064         setNeedReset( true );
00065         return;
00066     }
00067     // --- tmp <- a0
00068     tmpdata.setAll( coeff[0] );
00069     if ( csize == 1 ) {
00070         breakUpdate();
00071         return;
00072     }
00073     // --- tmp <- a0 + a1*f(x)
00074     outFunction()->apply( inputs(), tmpdata2 );
00075     tmpdata2 *= coeff[1];
00076     tmpdata += tmpdata2;
00077     if ( csize == 2 ) {
00078         breakUpdate();
00079         return;
00080     }
00081     // --- tmp <- a0 + a1*f(x) + a2*x
00082     tmpdata2.copyValues( inputs() );
00083     tmpdata2 *= coeff[2];
00084     tmpdata += tmpdata2;
00085     if ( csize == 3 ) {
00086         breakUpdate();
00087         return;
00088     }
00089     // --- tmp <- a0 + a1*f(x) + a2*x + a3*y ... aN*y^(n-3)
00090     for( int i=0; i<ds.size(); i++ ) {
00091         tmpdata2.copyValues( ds[i] );
00092         tmpdata2 *= coeff[i+3];
00093         tmpdata += tmpdata2;
00094     }
00095     breakUpdate();
00096     return;
00097 }
00098 
00099 void DDECluster::breakUpdate() {
00100     outputs().copyValues( tmpdata );
00101     updateDs();
00102     setNeedReset( true );
00103 }
00104 
00105 void DDECluster::updateDs() {
00106     if ( ds.size() == 0 ) return;
00107     // --- Le derivate sono semplici differenze:
00108     // --- y'  = y(t) - y(t-1)
00109     // --- y'' = y'(t) - y'(t-1)
00110     // ---  ... and so on
00111     if ( ds.size() == 1 ) {
00112         ds[0].copyValues( outputs() );
00113     } else if ( ds.size() == 2 ) {
00114         subtract( ds[1], outputs(), ds[0] );
00115         ds[0].copyValues( outputs() );
00116     } else {
00117         // ----- Problemi di questo tipo di calcolo:
00118         // *** calcola, cmq, anche la derivata ds.size()+1... l'ultimo tmpdata calcolato prima di uscire.
00119         tmpdata.copyValues( outputs() );
00120         for( int i=0; i<ds.size(); i++ ) {
00121             if ( i%2 == 0 ) {
00122                 // calcola la derivata i+1 per il ciclo successivo
00123                 subtract( tmpdata2, tmpdata, ds[1] );
00124                 // memorizza il valore della derivata i calcolata al ciclo precedente i-1
00125                 ds[i].copyValues( tmpdata );
00126             } else {
00127                 // calcola la derivata i+1 per il ciclo successivo
00128                 subtract( tmpdata, tmpdata2, ds[i] );
00129                 // memorizza il valore della derivata i calcolata al ciclo precedente i-1
00130                 ds[i].copyValues( tmpdata2 );
00131             }
00132         }
00133     }
00134 }
00135 
00136 void DDECluster::save(ConfigurationParameters& params, QString prefix)
00137 {
00138     Cluster::save( params, prefix );
00139     params.startObjectParameters(prefix, "DDECluster", this);
00140     // First creating a string list, then transforming to a single string
00141     QStringList list;
00142     for (unsigned int i = 0; i < coeff.size(); i++) {
00143         list.push_back(QString::number(coeff[i]));
00144     }
00145     params.createParameter(prefix, "coefficients", list.join(" "));
00146 }
00147 
00148 void DDECluster::describe( QString type ) {
00149     Cluster::describe( type );
00150     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)" );
00151     d.describeReal( "coefficients" ).def( 0.0 ).props( IsMandatory | IsList ).help( "The coefficients of the equation" );
00152 }
00153 
00154 }
00155