cluster.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 "cluster.h"
21 #include "liboutputfunctions.h"
22 #include "configurationhelper.h"
23 #include <exception>
24 
25 using namespace Eigen;
26 
27 namespace farsa {
28 
29 Cluster::Cluster( unsigned int numNeurons, QString name ) :
30  Updatable(name),
31  inputdata(VectorXd::Zero(numNeurons)),
32  outputdata(VectorXd::Zero(numNeurons)),
33  stateDelegates() {
34  //--- create the delegates for inputs and outputs vector
35  setDelegateFor<Cluster, &Cluster::inputs>( "inputs" );
36  setDelegateFor<Cluster, &Cluster::outputs>( "outputs" );
37  this->numneurons = numNeurons;
38  accOff = true;
39  setNeedReset( false );
40  // SigmoidFunction as Default
41  setOutFunction(new SigmoidFunction( 1.0 ));
42 }
43 
44 Cluster::Cluster( ConfigurationParameters& params, QString prefix ) :
45  Updatable(params, prefix),
46  numneurons(ConfigurationHelper::getInt( params, prefix + "numNeurons", 1 )),
47  inputdata(VectorXd::Zero(numneurons)),
48  outputdata(VectorXd::Zero(numneurons)),
49  stateDelegates()
50 {
51  //--- create the delegates for inputs and outputs vector
52  setDelegateFor<Cluster, &Cluster::inputs>( "inputs" );
53  setDelegateFor<Cluster, &Cluster::outputs>( "outputs" );
54 
55  accOff = !ConfigurationHelper::getBool( params, prefix + "accumulate" );
56 
57  QString vectorSizeErrorTmpl( "The number of elements of the %1 vector in configuration file (%1) is different from the number of neurons (%2)");
58  // inputs is a vector, that is a list of space-separated values
59  QVector<double> vect = ConfigurationHelper::getVector( params, prefix + "inputs" );
60 #ifdef FARSA_DEBUG
61  if ( !vect.isEmpty() && vect.size() != (int)numneurons ) {
62  qWarning() << vectorSizeErrorTmpl.arg( "inputs" ).arg( vect.size() ).arg( numneurons );
63  }
64 #endif
65  inputdata = Eigen::Map<VectorXd>(vect.data(), numneurons);
66 
67  // outputs is a vector, that is a list of space-separated values
68  vect = ConfigurationHelper::getVector( params, prefix + "outputs" );
69 #ifdef FARSA_DEBUG
70  if ( !vect.isEmpty() && vect.size() != (int)numneurons ) {
71  qWarning() << vectorSizeErrorTmpl.arg( "outputs" ).arg( vect.size() ).arg( numneurons );
72  }
73 #endif
74  outputdata = Eigen::Map<VectorXd>(vect.data(), numneurons);
75 
76  // The group for the outputFunction is "prefix/OutFunction"
77  if ( ConfigurationHelper::hasGroup( params, prefix+"OutFunction" ) ) {
78  setOutFunction(params.getObjectFromGroup<OutputFunction>( prefix + "OutFunction", true ));
79  } else {
80  // SigmoidFunction as Default
81  setOutFunction(new SigmoidFunction( 1.0 ));
82  }
83  setNeedReset( false );
84 }
85 
87  // No need to delete anything else, we use auto_ptr
88 }
89 
91  updater.reset(up);
92  updater->setCluster( this );
93 }
94 
95 void Cluster::setInput( unsigned int neuron, double value ) {
96  inputdata[neuron] = value;
97 }
98 
99 void Cluster::setInputs( const DoubleVector& inputs ) {
100  inputdata = inputs;
101 }
102 
103 void Cluster::setAllInputs( double value ) {
104  inputdata.setConstant( value );
105  setNeedReset( false );
106 }
107 
109  inputdata.setZero();
110  setNeedReset( false );
111 }
112 
113 double Cluster::getInput( unsigned int neuron ) const {
114  return inputdata[neuron];
115 }
116 
117 void Cluster::setOutput( unsigned int neuron, double value ) {
118  outputdata[neuron] = value;
119 }
120 
121 void Cluster::setOutputs( const DoubleVector& outputs ) {
122  outputdata = outputs;
123 }
124 
125 double Cluster::getOutput( unsigned int neuron ) const {
126  return outputdata[neuron];
127 }
128 
129 void Cluster::save(ConfigurationParameters& params, QString prefix)
130 {
131  Updatable::save( params, prefix );
132  params.startObjectParameters(prefix, "Cluster", this);
133  params.createParameter(prefix, "numNeurons", QString::number(numneurons));
134  params.createParameter(prefix, "accumulate", (isAccumulate() ? "True" : "False"));
135  // First creating a string list, then transforming to a single string
136  QStringList list;
137  for (int i = 0; i < inputdata.size(); i++) {
138  list.push_back(QString::number(inputdata[i]));
139  }
140  params.createParameter(prefix, "inputs", list.join(" "));
141  // Doing the same with outputdata
142  list.clear();
143  for (int i = 0; i < outputdata.size(); i++) {
144  list.push_back(QString::number(outputdata[i]));
145  }
146  params.createParameter(prefix, "outputs", list.join(" "));
147  // and finally the outfunction will be saved in the group "prefix/OutFunction"
148  updater->save( params, params.createSubGroup(prefix, "OutFunction") );
149 }
150 
151 void Cluster::describe( QString type ) {
152  Updatable::describe( type );
153  Descriptor d = addTypeDescription( type, "A Cluster of neurons" );
154  d.describeInt( "numNeurons" ).limits( 1, INT_MAX ).props( IsMandatory ).help( "The number of neurons contained by the Cluster" );
155  d.describeBool( "accumulate" ).def( false ).help( "If true new inputs will be added to the previous values" );
156  d.describeReal( "inputs" ).props( IsList ).help( "The input values of the neurons" );
157  d.describeReal( "outputs" ).props( IsList ).help( "The output values of the neurons" );
158  d.describeSubgroup( "OutFunction" ).type( "OutputFunction" ).help( "The output function used to calculate the output values" );
159 }
160 
161 }