neuralnet.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 "neuralnet.h"
21 #include "neuralnetui.h"
22 
23 #ifdef FARSA_USE_GRAPHVIZ
24  #include "neuralnetconfwidget.h"
25 #endif
26 
27 namespace farsa {
28 
30  dimUps = 0;
31 }
32 
34 }
35 
37 #ifdef FARSA_USE_GRAPHVIZ
38  return new NeuralNetUI( this );
39 #else
40  return NULL;
41 #endif
42 }
43 
45  if ( observers.contains(observer) ) return;
46  observers.append( observer );
47 }
48 
50  observers.removeAll( observer );
51 }
52 
53 void NeuralNet::addCluster( Cluster* c, bool isInput, bool isOutput ) {
54 #ifdef FARSA_DEBUG
55  if ( !c ) {
56  qWarning() << "Null Pointer passed to addCluster! This operation will be ignored" ;
57  return;
58  }
59 #endif
60  // Check if the Cluster is already added
61  if ( find( c ) ) {
62 #ifdef FARSA_DEBUG
63  qWarning() << "Cluster already added! addCluster will be ignored" ;
64 #endif
65  return;
66  }
67  clustersv.append( c );
68  if ( isInput ) {
69  inclusters.append( c );
70  }
71  if ( isOutput ) {
72  outclusters.append( c );
73  }
74  if ( !isInput && !isOutput ) {
75  hidclusters.append( c );
76  }
77  clsMap[c->name()] = c;
78  return;
79 }
80 
82 #ifdef FARSA_DEBUG
83  if ( !c ) {
84  qWarning() << "Null Pointer passed to removeCluster! This operation will return false" ;
85  return false;
86  }
87 #endif
88  if ( !find( c ) ) {
89  return false;
90  }
91  clustersv.removeOne( c );
92  inclusters.removeOne( c );
93  outclusters.removeOne( c );
94  hidclusters.removeOne( c );
95  clsMap.remove( c->name() );
96  return true;
97 }
98 
100 #ifdef FARSA_DEBUG
101  if ( !c ) {
102  qWarning() << "Null Pointer passed to addCluster! This operation will be ignored" ;
103  return;
104  }
105 #endif
106  // Check if the Cluster exists
107  if ( !find( c ) ) {
108 #ifdef FARSA_DEBUG
109  qWarning() << "attempt to mark a Cluster not present in this net!" ;
110 #endif
111  return;
112  }
113  if ( inclusters.contains( c ) ) {
114  return;
115  }
116  inclusters.append( c );
117  hidclusters.removeOne( c );
118 }
119 
121 #ifdef FARSA_DEBUG
122  if ( !c ) {
123  qWarning() << "Null Pointer passed to addCluster! This operation will be ignored" ;
124  return;
125  }
126 #endif
127  // Check if the Cluster exists
128  if ( !find( c ) ) {
129 #ifdef FARSA_DEBUG
130  qWarning() << "attempt to mark a Cluster not present in this net!" ;
131 #endif
132  return;
133  }
134  if ( outclusters.contains( c ) ) {
135  return;
136  }
137  outclusters.append( c );
138  hidclusters.removeOne( c );
139 }
140 
142 #ifdef FARSA_DEBUG
143  if ( !c ) {
144  qWarning() << "Null Pointer passed to addCluster! This operation will be ignored" ;
145  return;
146  }
147 #endif
148  // Check if the Cluster exists
149  if ( !find( c ) ) {
150 #ifdef FARSA_DEBUG
151  qWarning() << "attempt to unmark a Cluster not present in this net!" ;
152 #endif
153  return;
154  }
155  inclusters.removeOne( c );
156  outclusters.removeOne( c );
157  hidclusters.append( c );
158  return;
159 }
160 
162  inclusters.clear();
163  outclusters.clear();
165  return;
166 }
167 
168 bool NeuralNet::isIsolated( Cluster* c ) const {
169 #ifdef FARSA_DEBUG
170  if ( !c ) {
171  qWarning() << "Null Pointer passed to isIsolato! This operation will return false" ;
172  return false;
173  }
174 #endif
175  return ( inLinks.count( c ) == 0 && outLinks.count( c ) == 0 );
176 }
177 
178 ClusterList NeuralNet::clusters() const {
179  return clustersv;
180 }
181 
182 ClusterList NeuralNet::inputClusters() const {
183  return inclusters;
184 }
185 
186 ClusterList NeuralNet::outputClusters() const {
187  return outclusters;
188 }
189 
190 ClusterList NeuralNet::hiddenClusters() const {
191  return hidclusters;
192 }
193 
195 #ifdef FARSA_DEBUG
196  if ( !l ) {
197  qWarning() << "Null Pointer passed to addLinker! This operation will be ignored" ;
198  return;
199  }
200 #endif
201  // Check if the Linker is already added
202  if ( find( l ) ) {
203 #ifdef FARSA_DEBUG
204  qWarning() << "Linker already added! addLinker will be ignored" ;
205 #endif
206  return;
207  }
208 #ifdef FARSA_DEBUG
209  // --- Check: Are There in this net the Clusters that linker l connects ???
210  if ( ! find( l->from() ) ) {
211  qWarning() << "The linker that you want add links cluster" << l->from()->name() << "that doesn't exist in this net! This operation will be ignored" ;
212  return;
213  }
214  if ( ! find( l->to() ) ) {
215  qWarning() << "The linker that you want add links cluster" << l->to()->name() << "that doesn't exist in this net! This operation will be ignored" ;
216  return;
217  }
218 #endif
219  linkersv.append( l );
220  // Adding information in outLinks map
221  outLinks[ l->from() ].append( l );
222  // Adding information in inLinks map
223  inLinks[ l->to() ].append( l );
224  lksMap[l->name()] = l;
225  return;
226 }
227 
229 #ifdef FARSA_DEBUG
230  if ( !l ) {
231  qWarning() << "Null Pointer passed to removeLinker! This operation will return false" ;
232  return false;
233  }
234 #endif
235  if ( !find(l) ) {
236  return false;
237  }
238  linkersv.removeOne( l );
239  outLinks[ l->from() ].removeOne( l );
240  inLinks[ l->to() ].removeOne( l );
241  lksMap.remove( l->name() );
242  return true;
243 }
244 
245 LinkerList NeuralNet::linkers() const {
246  return linkersv;
247 }
248 
249 LinkerList NeuralNet::linkers( Cluster* c, bool out ) const {
250 #ifdef FARSA_DEBUG
251  if ( !c ) {
252  qWarning() << "Null Pointer passed to linkers! This operation will return an empty LinkerList" ;
253  return LinkerList();
254  }
255 #endif
256  if ( out ) {
257  // Return outgoing linkers
258  if ( outLinks.contains( c ) ) {
259  return outLinks[c];
260  }
261  } else {
262  // Return incoming linkers
263  if ( inLinks.contains( c ) ) {
264  return inLinks[c];
265  }
266  }
267  return LinkerList();
268 }
269 
270 void NeuralNet::setOrder( Updatable* u[], unsigned int dim ) {
271  ups.clear();
272  for( unsigned int i = 0; i<dim; i++ ) {
273  if ( find( u[i] ) ) {
274  ups.append( u[i] );
275  }
276 #ifdef FARSA_DEBUG
277  else {
278  qWarning() << "In the Updatable order list passed there are some Clusters and/or Linkers not present in this NeuralNet";
279  }
280 #endif
281  }
282  dimUps = ups.size();
283  return;
284 }
285 
286 void NeuralNet::setOrder( const UpdatableList& u ) {
287  ups.clear();
288  unsigned int dim = u.size();
289  for( unsigned int i = 0; i<dim; i++ ) {
290  if ( find( u[i] ) ) {
291  ups.append( u[i] );
292  }
293 #ifdef FARSA_DEBUG
294  else {
295  qWarning() << "In the Updatable order list passed there are some Clusters and/or Linkers not present in this NeuralNet";
296  }
297 #endif
298  }
299  dimUps = ups.size();
300  return;
301 }
302 
303 void NeuralNet::randomize( double min, double max ) {
304  int dim = clustersv.size();
305  for( int i=0; i<dim; i++ ) {
306  clustersv[i]->randomize( min, max );
307  }
308  dim = linkersv.size();
309  for( int i=0; i<dim; i++ ) {
310  linkersv[i]->randomize( min, max );
311  }
312 }
313 
314 Updatable* NeuralNet::getByName( QString name ) {
315  if ( clsMap.contains( name ) ) {
316  return clsMap[name];
317  }
318  if ( lksMap.contains( name ) ) {
319  return lksMap[name];
320  }
321 #ifdef FARSA_DEBUG
322  qWarning() << "getByName: Updatable " << name << " not present in BaseNeuralNet";
323 #endif
324  return NULL;
325 }
326 
327 bool NeuralNet::find( const Cluster* cl ) const {
328  return clustersv.contains( (Cluster*)cl );
329 }
330 
331 bool NeuralNet::find( const Linker* l ) const {
332  return linkersv.contains( (Linker*)l );
333 }
334 
335 bool NeuralNet::find( const Updatable* u ) const {
336  return (
337  clustersv.contains( (Cluster*)u ) ||
338  linkersv.contains( (Linker*)u )
339  );
340 }
341 
342 void NeuralNet::configure(ConfigurationParameters& params, QString prefix) {
344  // the name will correspond to the group where the declaration of NeuralNet is
345  QString myname = prefix;
346  if ( myname.startsWith( ConfigurationParameters::GroupSeparator() ) ) {
347  myname.remove( 0, 1 );
348  }
349  if ( myname.endsWith( ConfigurationParameters::GroupSeparator() ) ) {
350  myname.chop( 1 );
351  }
352  setName( myname );
353 
354  // All Cluster has to be added before the creation of linkers, that's why the insertion is done after
355  ClusterList clsToAdd;
356  ClusterList clsInput;
357  ClusterList clsOutput;
358  LinkerList lnsToAdd;
359 
360  //--- get all subgroups, merge this list with clustersList and linkersList
361  QStringList subgroups;
362  foreach( QString sub, params.getGroupsList( prefix ) ) {
363  // append the full path
364  subgroups << (prefix+sub);
365  }
366  //--- clustersList and linkersList are supposed to be full path
367  QString str = params.getValue(prefix + "clustersList");
368  if (!str.isEmpty()) {
369  subgroups << str.split(QRegExp("\\s+"), QString::SkipEmptyParts);
370  }
371  str = params.getValue(prefix + "linkersList");
372  if (!str.isEmpty()) {
373  subgroups << str.split(QRegExp("\\s+"), QString::SkipEmptyParts);
374  }
375  foreach( QString sub, subgroups ) {
376  Updatable* up = params.getObjectFromGroup<Updatable>( sub, true );
377  //--- check if is a Cluster
378  Cluster* cl = dynamic_cast<Cluster*>(up);
379  if ( cl && !clsToAdd.contains( cl ) ) clsToAdd << cl;
380  //--- check if is a Linker
381  Linker* ln = dynamic_cast<Linker*>(up);
382  if ( ln && !lnsToAdd.contains( ln ) ) lnsToAdd << ln;
383  }
384  //--- parse the parameter inputClusters
385  str = params.getValue(prefix + "inputClusters");
386  if (!str.isEmpty()) {
387  QStringList list = str.split(QRegExp("\\s+"), QString::SkipEmptyParts);
388  foreach( QString sub, list ) {
389  Cluster* cl = params.getObjectFromGroup<Cluster>( sub, true );
390  if ( !clsToAdd.contains( cl ) ) clsToAdd << cl;
391  clsInput << cl;
392  }
393  }
394  //--- parse the parameter outputClusters
395  str = params.getValue(prefix + "outputClusters");
396  if (!str.isEmpty()) {
397  QStringList list = str.split(QRegExp("\\s+"), QString::SkipEmptyParts);
398  foreach( QString sub, list ) {
399  Cluster* cl = params.getObjectFromGroup<Cluster>( sub, true );
400  if ( !clsToAdd.contains( cl ) ) clsToAdd << cl;
401  clsOutput << cl;
402  }
403  }
404  //--- parse the parameter spreadOrder
405  str = params.getValue(prefix + "spreadOrder");
406  if (!str.isEmpty()) {
407  QStringList list = str.split(QRegExp("\\s+"), QString::SkipEmptyParts);
408  ups.clear();
409  foreach( QString sub, list ) {
410  Updatable* up = params.getObjectFromGroup<Updatable>( sub, true );
411  // add it to the list of objects to add
412  Cluster* cl = dynamic_cast<Cluster*>(up);
413  if ( cl && !clsToAdd.contains( cl ) ) clsToAdd << cl;
414  //--- check if is a Linker
415  Linker* ln = dynamic_cast<Linker*>(up);
416  if ( ln && !lnsToAdd.contains( ln ) ) lnsToAdd << ln;
417  ups.append( up );
418  }
419  dimUps = ups.size();
420  }
421  foreach( Cluster* cl, clsToAdd ) {
422  addCluster( cl );
423  }
424  foreach( Cluster* cl, clsInput ) {
425  markAsInput( cl );
426  }
427  foreach( Cluster* cl, clsOutput ) {
428  markAsOutput( cl );
429  }
430  foreach( Linker* ln, lnsToAdd ) {
431  addLinker( ln );
432  }
434 }
435 
436 void NeuralNet::save(ConfigurationParameters& params, QString prefix) {
437  params.startObjectParameters( prefix, "NeuralNet", this );
438  //--- save all Clusters and generate parameter clustersList
439  QStringList list;
440  list.clear();
441  foreach( Cluster* cl, clustersv ) {
442  params.createGroup( cl->name() );
443  cl->save( params, cl->name() );
444  list << cl->name();
445  }
446  params.createParameter( prefix, "clustersList", list.join(" ") );
447  //--- save all Linkers and generate parameter linkersList
448  list.clear();
449  foreach( Linker* ln, linkersv ) {
450  params.createGroup( ln->name() );
451  ln->save( params, ln->name() );
452  list << ln->name();
453  }
454  params.createParameter( prefix, "linkersList", list.join(" ") );
455  //--- save parameter inputClusters
456  list.clear();
457  foreach( Cluster* cl, inclusters ) {
458  list << cl->name();
459  }
460  params.createParameter( prefix, "inputClusters", list.join(" ") );
461  //--- save parameter outputClusters
462  list.clear();
463  foreach( Cluster* cl, outclusters ) {
464  list << cl->name();
465  }
466  params.createParameter( prefix, "outputClusters", list.join(" ") );
467  //--- save parameter spreadOrder
468  list.clear();
469  foreach( Updatable* up, ups ) {
470  list << up->name();
471  }
472  params.createParameter( prefix, "spreadOrder", list.join(" ") );
473 }
474 
475 void NeuralNet::describe( QString type ) {
476  Descriptor d = addTypeDescription( type, "Neural Network", "The neural network is a container for Clusters and Linkers. The topology and connectivity of the neural network is specified by the Linkers contained, while the order on which the Clusters and Linkers are updated is specified by the spreadOrder parameter of neural network" );
477  d.describeObject( "clustersList" ).type( "Cluster" ).props( IsList ).help( "The list of all Clusters" );
478  d.describeObject( "linkersList" ).type( "Linker" ).props( IsList ).help( "The list of all Linkers" );
479  d.describeObject( "inputClusters" ).type( "Cluster" ).props( IsList ).help( "The list of Clusters marked as input of the neural network" );
480  d.describeObject( "outputClusters" ).type( "Cluster" ).props( IsList ).help( "The list of Clusters marked as output of the neural network" );
481  d.describeObject( "spreadOrder" ).type( "Updatable" ).props( IsMandatory | IsList ).help( "The order on which the Clusters and Linkers are updated", "All Clusters and Linkers specified here are also automatically added into the neural network. If this list contains all Clusters and Linkers, then the clustersList and the linkersList parameters are superfluous" );
482 
483 #ifdef FARSA_USE_GRAPHVIZ
484  // set the graphical editor
485  setGraphicalEditor<NeuralNetConfWidget>(type);
486 #endif
487 
488 }
489 
490 }
void addLinker(Linker *l)
Add Linker.
Definition: neuralnet.cpp:194
static void describe(QString type)
Add to Factory::typeDescriptions() the descriptions of all parameters and subgroups.
Definition: neuralnet.cpp:475
ClusterList outclusters
Output Clusters.
Definition: neuralnet.h:377
virtual void configure(ConfigurationParameters &params, QString prefix)
Configures the object using a ConfigurationParameters object.
Definition: neuralnet.cpp:342
ClusterList clustersv
Clusters.
Definition: neuralnet.h:373
ClustersMap clsMap
map name -> Cluster*
Definition: neuralnet.h:385
void addCluster(Cluster *c, bool isInput=false, bool isOutput=false)
Add a Cluster into the neural network If isInput is true then the Cluster will be considered as an I...
Definition: neuralnet.cpp:53
~NeuralNet()
Destructor.
Definition: neuralnet.cpp:33
void unmarkAll()
Eliminate the marks from all Cluster present in this networks.
Definition: neuralnet.cpp:161
ClusterList inclusters
Input Clusters.
Definition: neuralnet.h:375
bool isIsolated(Cluster *c) const
Return true if there isn't any Linker connected with Cluster c.
Definition: neuralnet.cpp:168
NeuralNet()
Construct an empty neural network.
Definition: neuralnet.cpp:29
void markAsOutput(Cluster *c)
Mark a Cluster as an Output Cluster of this network.
Definition: neuralnet.cpp:120
LinkerList linkersv
Linkers.
Definition: neuralnet.h:381
LinkerList linkers() const
Returns the array of Linkers contained.
Definition: neuralnet.cpp:245
Cluster * to() const
Return the Cluster to.
Definition: linker.h:49
ClusterList hiddenClusters() const
Returns the vector of Hidden Clusters contained (i.e.
Definition: neuralnet.cpp:190
FARSA_UTIL_TEMPLATE const T max(const T &t1, const U &t2)
virtual void save(ConfigurationParameters &params, QString prefix)
Save the actual status of parameters into the ConfigurationParameters object passed.
Definition: neuralnet.cpp:436
virtual void save(ConfigurationParameters &params, QString prefix)
Save the actual status of parameters into the ConfigurationParameters object passed.
Definition: linker.cpp:58
Cluster * from() const
Return the Cluster From.
Definition: linker.h:45
ParameterSettableUI * getUIManager()
return the UI Manager for accessing to the viewers of NeuralNet
Definition: neuralnet.cpp:36
ClusterList outputClusters() const
Returns the vector of Output Clusters contained.
Definition: neuralnet.cpp:186
Updatables objects.
Definition: updatable.h:37
QString name()
return the name of the NeuralNet
Definition: neuralnet.h:235
void unmark(Cluster *c)
Eliminate the marks from Cluster passed.
Definition: neuralnet.cpp:141
LinkersMap lksMap
map name -> Linker*
Definition: neuralnet.h:395
bool removeLinker(Linker *)
Remove Linker.
Definition: neuralnet.cpp:228
void createGroup(QString groupPath)
ClusterList hidclusters
unmarked Clusters
Definition: neuralnet.h:379
Define the common interface among Clusters.
Definition: cluster.h:73
virtual void save(ConfigurationParameters &params, QString prefix)
Save the actual status of parameters into the ConfigurationParameters object passed.
Definition: cluster.cpp:129
bool startObjectParameters(QString groupPath, QString typeName, ParameterSettable *object)
An observer interface called during NeuralNet operations.
Definition: neuralnet.h:39
static Descriptor addTypeDescription(QString type, QString shortHelp, QString longHelp=QString(""))
QString getValue(QString path, bool alsoMatchParents=false) const
LinkVecMap outLinks
map of outgoing linkers (cluster -> vettore linkers uscenti)
Definition: neuralnet.h:391
bool find(const Cluster *) const
Return true if the Cluster is in this net.
Definition: neuralnet.cpp:327
void randomize(double min, double max)
This randomize the free parameters of the all elements of the neural net This method call randomize ...
Definition: neuralnet.cpp:303
TypeToCreate * getObjectFromGroup(QString group, bool configure=true, bool forceObjectCreation=false)
bool removeCluster(Cluster *c)
Remove a Cluster from the network.
Definition: neuralnet.cpp:81
Abstract Linker Class.
Definition: linker.h:38
QStringList getGroupsList(QString group) const
FARSA_UTIL_TEMPLATE const T min(const T &t1, const U &t2)
void addObserver(NeuralNetObserver *observer)
add the observer to the list of current observers
Definition: neuralnet.cpp:44
ClusterList inputClusters() const
Returns the vector of Input Clusters contained.
Definition: neuralnet.cpp:182
ClusterList clusters() const
Returns the vector of Clusters contained.
Definition: neuralnet.cpp:178
void setName(QString name)
Set the name of the NeuralNet It's useful when loading from ConfigurationParameters more than NeuralN...
Definition: neuralnet.h:231
QString name() const
Return its name.
Definition: updatable.cpp:52
static QString GroupSeparator()
UpdatableList ups
Array of Updateables ordered as specified.
Definition: neuralnet.h:398
Updatable * getByName(QString)
Return the Updatable with the name specified Returns NULL-pointer if there's no updatable object whi...
Definition: neuralnet.cpp:314
void removeObserver(NeuralNetObserver *observer)
remove the observer from the list of current observers
Definition: neuralnet.cpp:49
void createParameter(QString groupPath, QString parameter)
This file contains the declaration of Neural Network Class.
QList< NeuralNetObserver * > observers
the List of Observers
Definition: neuralnet.h:402
void markAsInput(Cluster *c)
Mark a Cluster as an Input Cluster of this network.
Definition: neuralnet.cpp:99
LinkVecMap inLinks
mappa dei linkers entranti (cluster -> vettore linkers entranti)
Definition: neuralnet.h:389
void setOrder(Updatable *updatables[], unsigned int dim)
Set the order.
Definition: neuralnet.cpp:270