00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include "neuralnet.h"
00021
00022 namespace farsa {
00023
00024 NeuralNet::NeuralNet() {
00025 dimUps = 0;
00026 }
00027
00028 NeuralNet::~NeuralNet() {
00029 }
00030
00031 void NeuralNet::addCluster( Cluster* c, bool isInput, bool isOutput ) {
00032 #ifdef FARSA_DEBUG
00033 if ( !c ) {
00034 qWarning() << "Null Pointer passed to addCluster! This operation will be ignored" ;
00035 return;
00036 }
00037 #endif
00038
00039 if ( find( c ) ) {
00040 #ifdef FARSA_DEBUG
00041 qWarning() << "Cluster already added! addCluster will be ignored" ;
00042 #endif
00043 return;
00044 }
00045 clustersv.append( c );
00046 if ( isInput ) {
00047 inclusters.append( c );
00048 }
00049 if ( isOutput ) {
00050 outclusters.append( c );
00051 }
00052 if ( !isInput && !isOutput ) {
00053 hidclusters.append( c );
00054 }
00055 clsMap[c->name()] = c;
00056 return;
00057 }
00058
00059 bool NeuralNet::removeCluster( Cluster* c ) {
00060 #ifdef FARSA_DEBUG
00061 if ( !c ) {
00062 qWarning() << "Null Pointer passed to removeCluster! This operation will return false" ;
00063 return false;
00064 }
00065 #endif
00066 if ( !find( c ) ) {
00067 return false;
00068 }
00069 clustersv.removeOne( c );
00070 inclusters.removeOne( c );
00071 outclusters.removeOne( c );
00072 hidclusters.removeOne( c );
00073 clsMap.remove( c->name() );
00074 return true;
00075 }
00076
00077 void NeuralNet::markAsInput( Cluster* c ) {
00078 #ifdef FARSA_DEBUG
00079 if ( !c ) {
00080 qWarning() << "Null Pointer passed to addCluster! This operation will be ignored" ;
00081 return;
00082 }
00083 #endif
00084
00085 if ( !find( c ) ) {
00086 #ifdef FARSA_DEBUG
00087 qWarning() << "attempt to mark a Cluster not present in this net!" ;
00088 #endif
00089 return;
00090 }
00091 if ( inclusters.contains( c ) ) {
00092 return;
00093 }
00094 inclusters.append( c );
00095 hidclusters.removeOne( c );
00096 }
00097
00098 void NeuralNet::markAsOutput( Cluster* c ) {
00099 #ifdef FARSA_DEBUG
00100 if ( !c ) {
00101 qWarning() << "Null Pointer passed to addCluster! This operation will be ignored" ;
00102 return;
00103 }
00104 #endif
00105
00106 if ( !find( c ) ) {
00107 #ifdef FARSA_DEBUG
00108 qWarning() << "attempt to mark a Cluster not present in this net!" ;
00109 #endif
00110 return;
00111 }
00112 if ( outclusters.contains( c ) ) {
00113 return;
00114 }
00115 outclusters.append( c );
00116 hidclusters.removeOne( c );
00117 }
00118
00119 void NeuralNet::unmark( Cluster* c ) {
00120 #ifdef FARSA_DEBUG
00121 if ( !c ) {
00122 qWarning() << "Null Pointer passed to addCluster! This operation will be ignored" ;
00123 return;
00124 }
00125 #endif
00126
00127 if ( !find( c ) ) {
00128 #ifdef FARSA_DEBUG
00129 qWarning() << "attempt to unmark a Cluster not present in this net!" ;
00130 #endif
00131 return;
00132 }
00133 inclusters.removeOne( c );
00134 outclusters.removeOne( c );
00135 hidclusters.append( c );
00136 return;
00137 }
00138
00139 void NeuralNet::unmarkAll( ) {
00140 inclusters.clear();
00141 outclusters.clear();
00142 hidclusters = clustersv;
00143 return;
00144 }
00145
00146 bool NeuralNet::isIsolated( Cluster* c ) const {
00147 #ifdef FARSA_DEBUG
00148 if ( !c ) {
00149 qWarning() << "Null Pointer passed to isIsolato! This operation will return false" ;
00150 return false;
00151 }
00152 #endif
00153 return ( inLinks.count( c ) == 0 && outLinks.count( c ) == 0 );
00154 }
00155
00156 ClusterList NeuralNet::clusters() const {
00157 return clustersv;
00158 }
00159
00160 ClusterList NeuralNet::inputClusters() const {
00161 return inclusters;
00162 }
00163
00164 ClusterList NeuralNet::outputClusters() const {
00165 return outclusters;
00166 }
00167
00168 ClusterList NeuralNet::hiddenClusters() const {
00169 return hidclusters;
00170 }
00171
00172 void NeuralNet::addLinker( Linker* l ) {
00173 #ifdef FARSA_DEBUG
00174 if ( !l ) {
00175 qWarning() << "Null Pointer passed to addLinker! This operation will be ignored" ;
00176 return;
00177 }
00178 #endif
00179
00180 if ( find( l ) ) {
00181 #ifdef FARSA_DEBUG
00182 qWarning() << "Linker already added! addLinker will be ignored" ;
00183 #endif
00184 return;
00185 }
00186 #ifdef FARSA_DEBUG
00187
00188 if ( ! find( l->from() ) ) {
00189 qWarning() << "The linker that you want add links cluster" << l->from()->name() << "that doesn't exist in this net! This operation will be ignored" ;
00190 return;
00191 }
00192 if ( ! find( l->to() ) ) {
00193 qWarning() << "The linker that you want add links cluster" << l->to()->name() << "that doesn't exist in this net! This operation will be ignored" ;
00194 return;
00195 }
00196 #endif
00197 linkersv.append( l );
00198
00199 outLinks[ l->from() ].append( l );
00200
00201 inLinks[ l->to() ].append( l );
00202 lksMap[l->name()] = l;
00203 return;
00204 }
00205
00206 bool NeuralNet::removeLinker( Linker* l ) {
00207 #ifdef FARSA_DEBUG
00208 if ( !l ) {
00209 qWarning() << "Null Pointer passed to removeLinker! This operation will return false" ;
00210 return false;
00211 }
00212 #endif
00213 if ( !find(l) ) {
00214 return false;
00215 }
00216 linkersv.removeOne( l );
00217 outLinks[ l->from() ].removeOne( l );
00218 inLinks[ l->to() ].removeOne( l );
00219 lksMap.remove( l->name() );
00220 return true;
00221 }
00222
00223 LinkerList NeuralNet::linkers() const {
00224 return linkersv;
00225 }
00226
00227 LinkerList NeuralNet::linkers( Cluster* c, bool out ) const {
00228 #ifdef FARSA_DEBUG
00229 if ( !c ) {
00230 qWarning() << "Null Pointer passed to linkers! This operation will return an empty LinkerList" ;
00231 return LinkerList();
00232 }
00233 #endif
00234 if ( out ) {
00235
00236 if ( outLinks.contains( c ) ) {
00237 return outLinks[c];
00238 }
00239 } else {
00240
00241 if ( inLinks.contains( c ) ) {
00242 return inLinks[c];
00243 }
00244 }
00245 return LinkerList();
00246 }
00247
00248 void NeuralNet::setOrder( Updatable* u[], unsigned int dim ) {
00249 ups.clear();
00250 for( unsigned int i = 0; i<dim; i++ ) {
00251 if ( find( u[i] ) ) {
00252 ups.append( u[i] );
00253 }
00254 #ifdef FARSA_DEBUG
00255 else {
00256 qWarning() << "In the Updatable order list passed there are some Clusters and/or Linkers not present in this NeuralNet";
00257 }
00258 #endif
00259 }
00260 dimUps = ups.size();
00261 return;
00262 }
00263
00264 void NeuralNet::setOrder( const UpdatableList& u ) {
00265 ups.clear();
00266 unsigned int dim = u.size();
00267 for( unsigned int i = 0; i<dim; i++ ) {
00268 if ( find( u[i] ) ) {
00269 ups.append( u[i] );
00270 }
00271 #ifdef FARSA_DEBUG
00272 else {
00273 qWarning() << "In the Updatable order list passed there are some Clusters and/or Linkers not present in this NeuralNet";
00274 }
00275 #endif
00276 }
00277 dimUps = ups.size();
00278 return;
00279 }
00280
00281 void NeuralNet::randomize( double min, double max ) {
00282 int dim = clustersv.size();
00283 for( int i=0; i<dim; i++ ) {
00284 clustersv[i]->randomize( min, max );
00285 }
00286 dim = linkersv.size();
00287 for( int i=0; i<dim; i++ ) {
00288 linkersv[i]->randomize( min, max );
00289 }
00290 }
00291
00292 Updatable* NeuralNet::getByName( QString name ) {
00293 if ( clsMap.contains( name ) ) {
00294 return clsMap[name];
00295 }
00296 if ( lksMap.contains( name ) ) {
00297 return lksMap[name];
00298 }
00299 #ifdef FARSA_DEBUG
00300 qWarning() << "getByName: Updatable " << name << " not present in BaseNeuralNet";
00301 #endif
00302 return NULL;
00303 }
00304
00305 bool NeuralNet::find( const Cluster* cl ) const {
00306 return clustersv.contains( (Cluster*)cl );
00307 }
00308
00309 bool NeuralNet::find( const Linker* l ) const {
00310 return linkersv.contains( (Linker*)l );
00311 }
00312
00313 bool NeuralNet::find( const Updatable* u ) const {
00314 return (
00315 clustersv.contains( (Cluster*)u ) ||
00316 linkersv.contains( (Linker*)u )
00317 );
00318 }
00319
00320 void NeuralNet::configure(ConfigurationParameters& params, QString prefix) {
00321 params.startRememberingGroupObjectAssociations();
00322
00323 QString myname = prefix;
00324 if ( myname.startsWith( ConfigurationParameters::GroupSeparator() ) ) {
00325 myname.remove( 0, 1 );
00326 }
00327 if ( myname.endsWith( ConfigurationParameters::GroupSeparator() ) ) {
00328 myname.chop( 1 );
00329 }
00330 setName( myname );
00331
00332
00333 ClusterList clsToAdd;
00334 ClusterList clsInput;
00335 ClusterList clsOutput;
00336 LinkerList lnsToAdd;
00337
00338
00339 QStringList subgroups;
00340 foreach( QString sub, params.getGroupsList( prefix ) ) {
00341
00342 subgroups << (prefix+sub);
00343 }
00344
00345 QString str = params.getValue(prefix + "clustersList");
00346 if (!str.isEmpty()) {
00347 subgroups << str.split(QRegExp("\\s+"), QString::SkipEmptyParts);
00348 }
00349 str = params.getValue(prefix + "linkersList");
00350 if (!str.isEmpty()) {
00351 subgroups << str.split(QRegExp("\\s+"), QString::SkipEmptyParts);
00352 }
00353 foreach( QString sub, subgroups ) {
00354 Updatable* up = params.getObjectFromGroup<Updatable>( sub, true );
00355
00356 Cluster* cl = dynamic_cast<Cluster*>(up);
00357 if ( cl && !clsToAdd.contains( cl ) ) clsToAdd << cl;
00358
00359 Linker* ln = dynamic_cast<Linker*>(up);
00360 if ( ln && !lnsToAdd.contains( ln ) ) lnsToAdd << ln;
00361 }
00362
00363 str = params.getValue(prefix + "inputClusters");
00364 if (!str.isEmpty()) {
00365 QStringList list = str.split(QRegExp("\\s+"), QString::SkipEmptyParts);
00366 foreach( QString sub, list ) {
00367 Cluster* cl = params.getObjectFromGroup<Cluster>( sub, true );
00368 if ( !clsToAdd.contains( cl ) ) clsToAdd << cl;
00369 clsInput << cl;
00370 }
00371 }
00372
00373 str = params.getValue(prefix + "outputClusters");
00374 if (!str.isEmpty()) {
00375 QStringList list = str.split(QRegExp("\\s+"), QString::SkipEmptyParts);
00376 foreach( QString sub, list ) {
00377 Cluster* cl = params.getObjectFromGroup<Cluster>( sub, true );
00378 if ( !clsToAdd.contains( cl ) ) clsToAdd << cl;
00379 clsOutput << cl;
00380 }
00381 }
00382
00383 str = params.getValue(prefix + "spreadOrder");
00384 if (!str.isEmpty()) {
00385 QStringList list = str.split(QRegExp("\\s+"), QString::SkipEmptyParts);
00386 ups.clear();
00387 foreach( QString sub, list ) {
00388 Updatable* up = params.getObjectFromGroup<Updatable>( sub, true );
00389
00390 Cluster* cl = dynamic_cast<Cluster*>(up);
00391 if ( cl && !clsToAdd.contains( cl ) ) clsToAdd << cl;
00392
00393 Linker* ln = dynamic_cast<Linker*>(up);
00394 if ( ln && !lnsToAdd.contains( ln ) ) lnsToAdd << ln;
00395 ups.append( up );
00396 }
00397 dimUps = ups.size();
00398 }
00399 foreach( Cluster* cl, clsToAdd ) {
00400 addCluster( cl );
00401 }
00402 foreach( Cluster* cl, clsInput ) {
00403 markAsInput( cl );
00404 }
00405 foreach( Cluster* cl, clsOutput ) {
00406 markAsOutput( cl );
00407 }
00408 foreach( Linker* ln, lnsToAdd ) {
00409 addLinker( ln );
00410 }
00411 params.stopRememberingGroupObjectAssociations();
00412 }
00413
00414 void NeuralNet::save(ConfigurationParameters& params, QString prefix) {
00415 params.startObjectParameters( prefix, "NeuralNet", this );
00416
00417 QStringList list;
00418 list.clear();
00419 foreach( Cluster* cl, clustersv ) {
00420 params.createGroup( cl->name() );
00421 cl->save( params, cl->name() );
00422 list << cl->name();
00423 }
00424 params.createParameter( prefix, "clustersList", list.join(" ") );
00425
00426 list.clear();
00427 foreach( Linker* ln, linkersv ) {
00428 params.createGroup( ln->name() );
00429 ln->save( params, ln->name() );
00430 list << ln->name();
00431 }
00432 params.createParameter( prefix, "linkersList", list.join(" ") );
00433
00434 list.clear();
00435 foreach( Cluster* cl, inclusters ) {
00436 list << cl->name();
00437 }
00438 params.createParameter( prefix, "inputClusters", list.join(" ") );
00439
00440 list.clear();
00441 foreach( Cluster* cl, outclusters ) {
00442 list << cl->name();
00443 }
00444 params.createParameter( prefix, "outputClusters", list.join(" ") );
00445
00446 list.clear();
00447 foreach( Updatable* up, ups ) {
00448 list << up->name();
00449 }
00450 params.createParameter( prefix, "spreadOrder", list.join(" ") );
00451 }
00452
00453 void NeuralNet::describe( QString type ) {
00454 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" );
00455 d.describeObject( "clustersList" ).type( "Cluster" ).props( IsList ).help( "The list of all Clusters" );
00456 d.describeObject( "linkersList" ).type( "Linker" ).props( IsList ).help( "The list of all Linkers" );
00457 d.describeObject( "inputClusters" ).type( "Cluster" ).props( IsList ).help( "The list of Clusters marked as input of the neural network" );
00458 d.describeObject( "outputClusters" ).type( "Cluster" ).props( IsList ).help( "The list of Clusters marked as output of the neural network" );
00459 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" );
00460 }
00461
00462 }