nnfw/src/matrixlinker.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 "matrixlinker.h"
00021 #include "randomgenerator.h"
00022 
00023 namespace farsa {
00024 
00025 MatrixLinker::MatrixLinker( Cluster* from, Cluster* to, QString name )
00026     : Linker(from, to, name), nrows(from->numNeurons()), ncols(to->numNeurons()), w(nrows, ncols, true) {
00027     w.zeroing();
00028 }
00029 
00030 MatrixLinker::MatrixLinker( ConfigurationParameters& params, QString prefix )
00031     : Linker( params, prefix ), nrows(from()->numNeurons()), ncols(to()->numNeurons()), w(nrows, ncols, true) {
00032     // the weights are read from a single vector of data supposing they are row-major arranged
00033     QString str = params.getValue(prefix + "weights");
00034     if (!str.isEmpty()) {
00035         QStringList list = str.split(QRegExp("\\s+"), QString::SkipEmptyParts);
00036         int cycleLength = nrows*ncols;
00037         if (list.size() != cycleLength) {
00038 #ifdef FARSA_DEBUG
00039             qWarning() << "The number of elements of the weights in configuration file (" << list.size()
00040                        << ") is different from the total number of weights (" << cycleLength << ").";
00041 #endif
00042             cycleLength = std::min(list.size(), cycleLength);
00043         }
00044         for( int i=0; i<cycleLength; i++) {
00045             bool ok;
00046             unsigned int r = i/ncols; //--- division may be expensive
00047             unsigned int c = i%ncols; //--- module may be expensive
00048             w[r][c] = list[i].toDouble(&ok);
00049             if (!ok) {
00050                 w[r][c] = 0.0;
00051             }
00052         }
00053     }
00054 }
00055 
00056 MatrixLinker::~MatrixLinker() {
00057 }
00058 
00059 unsigned int MatrixLinker::size() const {
00060     return nrows*ncols;
00061 }
00062 
00063 void MatrixLinker::randomize( double min, double max ) {
00064     for ( unsigned int i = 0; i<nrows; i++ ) {
00065         for ( unsigned int j = 0; j<ncols; j++ ) {
00066             w[i][j] = globalRNG->getDouble( min, max );
00067         }
00068     }
00069 }
00070 
00071 void MatrixLinker::setWeight( unsigned int from, unsigned int to, double weight ) {
00072     w[from][to] = weight;
00073 }
00074 
00075 double MatrixLinker::weight( unsigned int from, unsigned int to ) {
00076     return w[from][to];
00077 }
00078 
00079 void MatrixLinker::connect( unsigned int from, unsigned int to ) {
00080     w.unsteady( from, to );
00081 }
00082 
00083 void MatrixLinker::connectRandom( double prob, bool zeroDiagonal, bool symmetric ) {
00084     if ( symmetric ) {
00085         //--- SYMMETRIC TRUE
00086 #ifdef FARSA_DEBUG
00087         if ( nrows != ncols ) {
00088             qWarning() << "connectRandom with symmetric to TRUE is allowed only with square matrix" ;
00089             return;
00090         }
00091 #endif
00092         for( unsigned int r=0; r<rows(); r++ ) {
00093             for( unsigned int c=r; c<cols(); c++ ) {
00094                 //--- clear any previous steadyness before to steady some values
00095                 w.unsteady( r, c );
00096                 w.unsteady( c, r );
00097                 if ( r==c && zeroDiagonal ) {
00098                     w[r][c] = 0.0;
00099                     w.steady( r, c );
00100                     continue;
00101                 }
00102                 if ( !globalRNG->getBool( prob ) ) {
00103                     w[r][c] = 0.0;
00104                     w.steady( r, c );
00105                     w[c][r] = 0.0;
00106                     w.steady( c, r );
00107                 }
00108             }
00109         }
00110     } else {
00111         //--- SYMMETRIC FALSE
00112         for( unsigned int r=0; r<rows(); r++ ) {
00113             for( unsigned int c=0; c<cols(); c++ ) {
00114                 //--- clear any previous steadyness before to steady some values
00115                 w.unsteady( r, c );
00116                 if ( r==c && zeroDiagonal ) {
00117                     w[r][c] = 0.0;
00118                     w.steady( r, c );
00119                     continue;
00120                 }
00121                 if ( !globalRNG->getBool( prob ) ) {
00122                     w[r][c] = 0.0;
00123                     w.steady( r, c );
00124                 }
00125             }
00126         }
00127     }
00128 }
00129 
00130 void MatrixLinker::connectAll() {
00131     for( unsigned int r=0; r<rows(); r++ ) {
00132         for( unsigned int c=0; c<cols(); c++ ) {
00133             w.unsteady( r, c );
00134         }
00135     }
00136 }
00137 
00138 void MatrixLinker::disconnect( unsigned int from, unsigned int to ) {
00139     w.unsteady( from, to );
00140     w[from][to] = 0.0;
00141     w.steady( from, to );
00142 }
00143 
00144 void MatrixLinker::disconnectAll() {
00145     for( unsigned int r=0; r<rows(); r++ ) {
00146         for( unsigned int c=0; c<cols(); c++ ) {
00147             w.unsteady( r, c );
00148             w[r][c] = 0.0;
00149             w.steady( r, c );
00150         }
00151     }
00152 }
00153 
00154 void MatrixLinker::save(ConfigurationParameters& params, QString prefix) {
00155     Linker::save( params, prefix );
00156     params.startObjectParameters( prefix, "MatrixLinker", this );
00157     // First creating a string list, then transforming to a single string
00158     QStringList list;
00159     for( unsigned int r=0; r<rows(); r++ ) {
00160         for( unsigned int c=0; c<cols(); c++ ) {
00161             list.push_back(QString::number(w[r][c]));
00162         }
00163     }
00164     params.createParameter(prefix, "weights", list.join(" "));
00165 }
00166 
00167 }