nnfw/src/cluster.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 "cluster.h"
00021 #include "liboutputfunctions.h"
00022 #include "configurationhelper.h"
00023 #include <exception>
00024 
00025 namespace farsa {
00026 
00027 Cluster::Cluster( unsigned int numNeurons, QString name )
00028     : Updatable(name), inputdata(numNeurons,true), outputdata(numNeurons,true), stateDelegates() {
00029     //--- create the delegates for inputs and outputs vector
00030     setDelegateFor<Cluster, &Cluster::inputs>( "inputs" );
00031     setDelegateFor<Cluster, &Cluster::outputs>( "outputs" );
00032     this->numneurons = numNeurons;
00033     inputdataptr = &inputdata;
00034     inputdata.zeroing();
00035     outputdataptr = &outputdata;
00036     outputdata.zeroing();
00037     accOff = true;
00038     setNeedReset( false );
00039     // SigmoidFunction as Default
00040     setOutFunction(new SigmoidFunction( 1.0 ));
00041 }
00042 
00043 Cluster::Cluster( ConfigurationParameters& params, QString prefix ) :
00044     Updatable(params, prefix), stateDelegates()
00045 {
00046     //--- create the delegates for inputs and outputs vector
00047     setDelegateFor<Cluster, &Cluster::inputs>( "inputs" );
00048     setDelegateFor<Cluster, &Cluster::outputs>( "outputs" );
00049     numneurons = ConfigurationHelper::getInt( params, prefix + "numNeurons", 1 );
00050     // Creating inputdata and outputdata
00051     inputdata = DoubleVector(numneurons, true );
00052     inputdataptr = &inputdata;
00053     inputdata.zeroing();
00054     outputdata = DoubleVector(numneurons, true );
00055     outputdataptr = &outputdata;
00056     outputdata.zeroing();
00057 
00058     accOff = !ConfigurationHelper::getBool( params, prefix + "accumulate" );
00059 
00060     QString vectorSizeErrorTmpl( "The number of elements of the %1 vector in configuration file (%1) is different from the number of neurons (%2)");
00061     // inputs is a vector, that is a list of space-separated values
00062     QVector<double> vect = ConfigurationHelper::getVector( params, prefix + "inputs" );
00063 #ifdef FARSA_DEBUG
00064     if ( !vect.isEmpty() && vect.size() != (int)numneurons ) {
00065         qWarning() << vectorSizeErrorTmpl.arg( "inputs" ).arg( vect.size() ).arg( numneurons );
00066     }
00067 #endif
00068     inputdataptr->copyValues( vect );
00069 
00070     // outputs is a vector, that is a list of space-separated values
00071     vect = ConfigurationHelper::getVector( params, prefix + "outputs" );
00072 #ifdef FARSA_DEBUG
00073     if ( !vect.isEmpty() && vect.size() != (int)numneurons ) {
00074         qWarning() << vectorSizeErrorTmpl.arg( "outputs" ).arg( vect.size() ).arg( numneurons );
00075     }
00076 #endif
00077     outputdataptr->copyValues( vect );
00078 
00079     // The group for the outputFunction is "prefix/OutFunction"
00080     try {
00081         setOutFunction(params.getObjectFromGroup<OutputFunction>( prefix + "OutFunction", true ));
00082     } catch( std::exception& /*e*/) {
00083         // SigmoidFunction as Default
00084         setOutFunction(new SigmoidFunction( 1.0 ));
00085     }
00086     setNeedReset( false );
00087 }
00088 
00089 Cluster::~Cluster() {
00090     // No need to delete anything else, we use auto_ptr
00091 }
00092 
00093 void Cluster::setOutFunction( OutputFunction *up ) {
00094     updater.reset(up);
00095     updater->setCluster( this );
00096 }
00097 
00098 void Cluster::setInput( unsigned int neuron, double value ) {
00099     (*inputdataptr)[neuron] = value;
00100 }
00101 
00102 void Cluster::setInputs( const DoubleVector& inputs ) {
00103     inputdataptr->copyValues( inputs );
00104 }
00105 
00106 void Cluster::setAllInputs( double value ) {
00107     inputdataptr->setAll( value );
00108     setNeedReset( false );
00109 }
00110 
00111 void Cluster::resetInputs() {
00112     inputdataptr->zeroing();
00113     setNeedReset( false );
00114 }
00115 
00116 double Cluster::getInput( unsigned int neuron ) const {
00117     return (*inputdataptr)[neuron];
00118 }
00119 
00120 void Cluster::setOutput( unsigned int neuron, double value ) {
00121     (*outputdataptr)[neuron] = value;
00122 }
00123 
00124 void Cluster::setOutputs( const DoubleVector& outputs ) {
00125     outputdataptr->copyValues( outputs );
00126 }
00127 
00128 double Cluster::getOutput( unsigned int neuron ) const {
00129     return (*outputdataptr)[neuron];
00130 }
00131 
00132 void Cluster::save(ConfigurationParameters& params, QString prefix)
00133 {
00134     Updatable::save( params, prefix );
00135     params.startObjectParameters(prefix, "Cluster", this);
00136     params.createParameter(prefix, "numNeurons", QString::number(numneurons));
00137     params.createParameter(prefix, "accumulate", (isAccumulate() ? "True" : "False"));
00138     // First creating a string list, then transforming to a single string
00139     QStringList list;
00140     for (unsigned int i = 0; i < inputdataptr->size(); i++) {
00141         list.push_back(QString::number((*inputdataptr)[i]));
00142     }
00143     params.createParameter(prefix, "inputs", list.join(" "));
00144     // Doing the same with outputdata
00145     list.clear();
00146     for (unsigned int i = 0; i < outputdataptr->size(); i++) {
00147         list.push_back(QString::number((*outputdataptr)[i]));
00148     }
00149     params.createParameter(prefix, "outputs", list.join(" "));
00150     // and finally the outfunction will be saved in the group "prefix/OutFunction"
00151     updater->save( params, params.createSubGroup(prefix, "OutFunction") );
00152 }
00153 
00154 void Cluster::describe( QString type ) {
00155     Updatable::describe( type );
00156     Descriptor d = addTypeDescription( type, "A Cluster of neurons" );
00157     d.describeInt( "numNeurons" ).limits( 1, INT_MAX ).props( IsMandatory ).help( "The number of neurons contained by the Cluster" );
00158     d.describeBool( "accumulate" ).def( false ).help( "If true new inputs will be added to the previous values" );
00159     d.describeReal( "inputs" ).props( IsList ).help( "The input values of the neurons" );
00160     d.describeReal( "outputs" ).props( IsList ).help( "The output values of the neurons" );
00161     d.describeObject( "OutFunction" ).type( "OutputFunction" ).help( "The output function used to calculate the output values" );
00162 }
00163 
00164 }