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