matrixlinker.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 "matrixlinker.h"
21 #include "randomgenerator.h"
22 
23 namespace farsa {
24 
25 MatrixLinker::MatrixLinker( Cluster* from, Cluster* to, QString name )
26  : Linker(from, to, name), nrows(from->numNeurons()), ncols(to->numNeurons()), w(nrows, ncols, true) {
27  w.zeroing();
28 }
29 
31  : Linker( params, prefix ), nrows(from()->numNeurons()), ncols(to()->numNeurons()), w(nrows, ncols, true) {
32  // the weights are read from a single vector of data supposing they are row-major arranged
33  QString str = params.getValue(prefix + "weights");
34  if (!str.isEmpty()) {
35  QStringList list = str.split(QRegExp("\\s+"), QString::SkipEmptyParts);
36  int cycleLength = nrows*ncols;
37  if (list.size() != cycleLength) {
38 #ifdef FARSA_DEBUG
39  qWarning() << "The number of elements of the weights in configuration file (" << list.size()
40  << ") is different from the total number of weights (" << cycleLength << ").";
41 #endif
42  cycleLength = std::min(list.size(), cycleLength);
43  }
44  for( int i=0; i<cycleLength; i++) {
45  bool ok;
46  unsigned int r = i/ncols; //--- division may be expensive
47  unsigned int c = i%ncols; //--- module may be expensive
48  w[r][c] = list[i].toDouble(&ok);
49  if (!ok) {
50  w[r][c] = 0.0;
51  }
52  }
53  }
54 }
55 
57 }
58 
59 unsigned int MatrixLinker::size() const {
60  return nrows*ncols;
61 }
62 
63 void MatrixLinker::randomize( double min, double max ) {
64  for ( unsigned int i = 0; i<nrows; i++ ) {
65  for ( unsigned int j = 0; j<ncols; j++ ) {
66  w[i][j] = globalRNG->getDouble( min, max );
67  }
68  }
69 }
70 
71 void MatrixLinker::setWeight( unsigned int from, unsigned int to, double weight ) {
72  w[from][to] = weight;
73 }
74 
75 double MatrixLinker::weight( unsigned int from, unsigned int to ) {
76  return w[from][to];
77 }
78 
79 void MatrixLinker::connect( unsigned int from, unsigned int to ) {
80  w.unsteady( from, to );
81 }
82 
83 void MatrixLinker::connectRandom( double prob, bool zeroDiagonal, bool symmetric ) {
84  if ( symmetric ) {
85  //--- SYMMETRIC TRUE
86 #ifdef FARSA_DEBUG
87  if ( nrows != ncols ) {
88  qWarning() << "connectRandom with symmetric to TRUE is allowed only with square matrix" ;
89  return;
90  }
91 #endif
92  for( unsigned int r=0; r<rows(); r++ ) {
93  for( unsigned int c=r; c<cols(); c++ ) {
94  //--- clear any previous steadyness before to steady some values
95  w.unsteady( r, c );
96  w.unsteady( c, r );
97  if ( r==c && zeroDiagonal ) {
98  w[r][c] = 0.0;
99  w.steady( r, c );
100  continue;
101  }
102  if ( !globalRNG->getBool( prob ) ) {
103  w[r][c] = 0.0;
104  w.steady( r, c );
105  w[c][r] = 0.0;
106  w.steady( c, r );
107  }
108  }
109  }
110  } else {
111  //--- SYMMETRIC FALSE
112  for( unsigned int r=0; r<rows(); r++ ) {
113  for( unsigned int c=0; c<cols(); c++ ) {
114  //--- clear any previous steadyness before to steady some values
115  w.unsteady( r, c );
116  if ( r==c && zeroDiagonal ) {
117  w[r][c] = 0.0;
118  w.steady( r, c );
119  continue;
120  }
121  if ( !globalRNG->getBool( prob ) ) {
122  w[r][c] = 0.0;
123  w.steady( r, c );
124  }
125  }
126  }
127  }
128 }
129 
131  for( unsigned int r=0; r<rows(); r++ ) {
132  for( unsigned int c=0; c<cols(); c++ ) {
133  w.unsteady( r, c );
134  }
135  }
136 }
137 
138 void MatrixLinker::disconnect( unsigned int from, unsigned int to ) {
139  w.unsteady( from, to );
140  w[from][to] = 0.0;
141  w.steady( from, to );
142 }
143 
145  for( unsigned int r=0; r<rows(); r++ ) {
146  for( unsigned int c=0; c<cols(); c++ ) {
147  w.unsteady( r, c );
148  w[r][c] = 0.0;
149  w.steady( r, c );
150  }
151  }
152 }
153 
154 void MatrixLinker::save(ConfigurationParameters& params, QString prefix) {
155  Linker::save( params, prefix );
156  params.startObjectParameters( prefix, "MatrixLinker", this );
157  // First creating a string list, then transforming to a single string
158  QStringList list;
159  for( unsigned int r=0; r<rows(); r++ ) {
160  for( unsigned int c=0; c<cols(); c++ ) {
161  list.push_back(QString::number(w[r][c]));
162  }
163  }
164  params.createParameter(prefix, "weights", list.join(" "));
165 }
166 
167 }