Shark Machine Learning Library
  • About Shark
  • Sourceforge
    • Project Summary
    • Downloads
    • Subversion Repository
  • Getting Started
  • Tutorials
  • FAQ
  • Main Modules
    • ReClaM
    • EALib
    • MOO-EALib
    • Fuzzy
  • Tools
    • Mixture
    • Array
    • Rng
    • LinAlg
    • FileUtil
  • Main Page
  • Related Pages
  • Classes

FFNet.cpp

Go to the documentation of this file.
00001 //===========================================================================
00042 //===========================================================================
00043 
00044 #include <SharkDefs.h>
00045 #include <ReClaM/FFNet.h>
00046 #include <sstream>
00047 
00048 
00049 using namespace std;
00050 
00051 //===========================================================================
00067 FFNet::~FFNet()
00068 {
00069     if (z) delete [] z;
00070 }
00071 
00072 //===========================================================================
00111 double FFNet::g(double a)
00112 {
00113     return 1 / (1 + exp(-a));
00114 }
00115 
00116 
00117 //===========================================================================
00144 double FFNet::dg(double ga)
00145 {
00146     return ga *(1 - ga);
00147 }
00148 
00149 
00150 //===========================================================================
00190 double FFNet::gOutput(double a)
00191 {
00192     return 1 / (1 + exp(-a));
00193 }
00194 
00195 //===========================================================================
00223 double FFNet::dgOutput(double ga)
00224 {
00225     return ga *(1 - ga);
00226 }
00227 
00228 //===========================================================================
00254 void FFNet::initWeights(long seed, double l, double h)
00255 {
00256     Rng::seed(seed);
00257     for (unsigned i = inputDimension; i < numberOfNeurons; i++)
00258     {
00259         for (unsigned j = 0; j < i; j++)
00260             if (connection(i, j)) weight(i, j) = Rng::uni(l, h);
00261         if (connectionMatrix(i, bias)) weight(i, bias) = Rng::uni(l, h);
00262     }
00263     writeParameters();
00264 }
00265 
00266 //===========================================================================
00291 inline
00292 void FFNet::initWeights(double l, double h)
00293 {
00294     for (unsigned i = inputDimension; i < numberOfNeurons; i++)
00295     {
00296         for (unsigned j = 0; j < i; j++)
00297             if (connection(i, j)) weight(i, j) = Rng::uni(l, h);
00298         if (connectionMatrix(i, bias)) weight(i, bias) = Rng::uni(l, h);
00299     }
00300     writeParameters();
00301 }
00302 
00303 //===========================================================================
00329 inline
00330 void FFNet::model(const Array<double> &input, Array<double> &output)
00331 {
00332     readParameters();
00333     if (input.ndim() == 1)
00334     {
00335         output.resize(outputDimension, false);
00336         activate(input);
00337         for (unsigned i = firstOutputNeuron, c = 0 ; i < numberOfNeurons; i++, c++)
00338             output(c) = z[i];
00339     }
00340     else
00341     {
00342         output.resize(input.dim(0), outputDimension, false);
00343         for (unsigned pattern = 0; pattern < input.dim(0); pattern++)
00344         {
00345             activate(input[pattern]);
00346             for (unsigned i = firstOutputNeuron, c = 0 ; i < numberOfNeurons; i++, c++)
00347                 output(pattern, c) = z[i];
00348         }
00349     }
00350 }
00351 
00352 //===========================================================================
00374 inline
00375 void FFNet::backprop(Array<double>& derivative)
00376 {
00377     unsigned i, j;  // denote neurons
00378     unsigned c;     // denotes output
00379     unsigned pos;   // the actual position in the Array derivative
00380     double sum;
00381 
00382     // 1. the 'local gradient' deltas for each
00383     //    output are calculated
00384 
00385     // output neurons
00386     for (j = firstOutputNeuron; j < numberOfNeurons; j++)
00387         for (c = 0; c < outputDimension; c++)
00388             if (c + firstOutputNeuron == j)  d(c, j) = dgOutput(z[j]);
00389             else d(c, j) = 0;
00390 
00391     // hidden units
00392     for (j = firstOutputNeuron - 1; j >= inputDimension; j--)
00393     {
00394         for (c = 0; c < outputDimension; c++)
00395         {
00396             sum = 0;
00397             for (i = j + 1; i < numberOfNeurons; i++)
00398             {
00399                 if (connection(i, j)) sum += weight(i, j) * d(c, i);
00400             }
00401             d(c, j) = dg(z[j]) * sum;
00402         }
00403     }
00404 
00405     // 2. the gradient for each output is calculated from
00406     //    delta
00407     pos = 0;
00408     for (i = inputDimension; i < numberOfNeurons; i++)
00409     {
00410         for (j = 0; j < i; j++)
00411         {
00412             if (connection(i, j))
00413             {
00414                 for (c = 0; c < outputDimension; c++)
00415                 {
00416                     derivative(c, pos) += d(c, i) * z[j];
00417                 }
00418                 pos++;
00419             }
00420         }
00421         if (connection(i, bias))
00422         {
00423             for (c = 0; c < outputDimension; c++)
00424             { // bias
00425                 derivative(c, pos) += d(c, i);
00426             }
00427             pos++;
00428         }
00429     }
00430 }
00431 
00432 //===========================================================================
00457 void FFNet::modelDerivative(const Array<double> &input, Array<double> &output, Array<double>& derivative)
00458 {
00459     unsigned i;  // denotes neurons
00460     unsigned c;  // denotes output
00461 
00462     derivative.resize(getOutputDimension(), getParameterDimension(), false);
00463     derivative = 0.;
00464 
00465     readParameters();
00466 
00467     if (input.ndim() == 1)
00468     {
00469         output.resize(getOutputDimension(), false);
00470 
00471         // calculate output
00472         activate(input);
00473 
00474         for (i = firstOutputNeuron, c = 0 ; i < numberOfNeurons; i++, c++) {
00475             output(c) = z[i];
00476         }
00477 
00478         // backpropagation step
00479         backprop(derivative);
00480     }
00481     else
00482     {
00483         output.resize(input.dim(0), getOutputDimension(), false);
00484         for (unsigned pattern = 0; pattern < input.dim(0); pattern++)
00485         {
00486             activate(input[pattern]);
00487             for (i = firstOutputNeuron, c = 0 ; i < numberOfNeurons; i++, c++) {
00488                 output(pattern, c) = z[i];
00489             }
00490             backprop(derivative);
00491         }
00492     }
00493 };
00494 
00495 void FFNet::generalDerivative(const Array<double>& input, const Array<double>& coeffs, Array<double>& derivative)
00496 {
00497     unsigned i, j;  // denote neurons
00498     unsigned c;     // denotes output
00499     unsigned pos;   // the actual position in the Array dedw
00500     double sum;
00501 
00502     for (i = firstOutputNeuron, c = 0 ; i < numberOfNeurons; i++, c++)
00503     {
00504         delta(i) =  coeffs(c) * dgOutput(z[i]);
00505     }
00506 
00507     // hidden units
00508     for (j = firstOutputNeuron - 1; j >= inputDimension; j--)
00509     {
00510         sum = 0;
00511         for (i = j + 1; i < numberOfNeurons; i++)
00512         {
00513             if (connection(i, j)) sum += weight(i, j) * delta(i);
00514         }
00515         delta(j) = dg(z[j]) * sum;
00516     }
00517 
00518     // calculate error gradient
00519     pos = 0;
00520     for (i = inputDimension; i < numberOfNeurons; i++)
00521     {
00522         for (j = 0; j < i; j++)
00523         {
00524             if (connection(i, j))
00525             {
00526                 derivative(pos) -= delta(i) * z[j];
00527                 pos++;
00528             }
00529         }
00530         if (connection(i, bias))
00531         { // bias
00532             derivative(pos) -= delta(i);
00533             pos++;
00534         }
00535     }
00536 };
00537 
00538 //===========================================================================
00566 void FFNet::modelDerivative(const Array<double>& input, Array<double>& derivative)
00567 {
00568     readParameters();
00569 
00570     derivative.resize(getOutputDimension(), getParameterDimension(), false);
00571     derivative = 0.;
00572 
00573     if (input.ndim() == 1)
00574     {
00575         activate(input);
00576         // backpropagation step
00577         backprop(derivative);
00578     }
00579     else
00580     {
00581         stringstream s;
00582         s << "the derivative of the model with respect to more than one input is not defined" << endl;
00583         throw SHARKEXCEPTION(s.str().c_str());
00584     }
00585 };
00586 
00587 
00588 //===========================================================================
00612 void FFNet::resize()
00613 {
00614     numberOfNeurons   = connectionMatrix.dim(0);
00615     bias              = numberOfNeurons;
00616     firstOutputNeuron = numberOfNeurons - outputDimension;
00617 
00618     unsigned numberOfWeights = 0; //numberOfNeurons - inputDimension;
00619     for (unsigned i = 0; i < connectionMatrix.dim(0); i++)
00620     {
00621         for (unsigned j = 0; j < i; j++)
00622             if (connectionMatrix(i, j)) numberOfWeights++;
00623         if (connectionMatrix(i, bias)) numberOfWeights++;
00624     }
00625 
00626     parameter.resize(numberOfWeights, false);
00627     d.resize(outputDimension, numberOfNeurons, false);
00628     delta.resize(numberOfNeurons, false);
00629 
00630     if (z) delete [] z;
00631     if (numberOfNeurons) z = new double[numberOfNeurons];
00632     else z = NULL;
00633 }
00634 
00635 
00636 //===========================================================================
00660 FFNet::FFNet(const unsigned in, const unsigned out)
00661 {
00662     inputDimension   = in;
00663     outputDimension  = out;
00664 
00665     numberOfNeurons   = 0;
00666     bias              = 0;
00667     firstOutputNeuron = 0;
00668 
00669     z = NULL;
00670 }
00671 
00672 
00673 //===========================================================================
00702 FFNet::FFNet(const unsigned in, unsigned out,
00703              const Array<int>& cmat)
00704 {
00705     if (cmat.ndim() != 2)
00706     {
00707         stringstream s;
00708         s << "connection matrix has not dimension two" << endl;
00709         throw SHARKEXCEPTION(s.str().c_str());
00710     }
00711     if (cmat.dim(0) != (cmat.dim(1) - 1))
00712     {
00713         stringstream s;
00714         s << "connection matrix has to be (N + 1) x N" << endl;
00715         throw SHARKEXCEPTION(s.str().c_str());
00716     }
00717 
00718     inputDimension   = in;
00719     outputDimension  = out;
00720     connectionMatrix = cmat;
00721 
00722     weightMatrix.resize(connectionMatrix, false);
00723     weightMatrix     = 0;
00724 
00725     z = NULL;
00726 
00727     resize();
00728     writeParameters();
00729 }
00730 
00731 
00732 //===========================================================================
00760 FFNet::FFNet(const unsigned in, unsigned out,
00761              const Array<int>& cmat, const Array<double>& wmat)
00762 {
00763     if (cmat.ndim() != 2)
00764     {
00765         stringstream s;
00766         s << "connection matrix has not dimension two" << endl;
00767         throw SHARKEXCEPTION(s.str().c_str());
00768     }
00769     if (cmat.dim(0) != (cmat.dim(1) - 1))
00770     {
00771         stringstream s;
00772         s << "connection matrix has to be (N + 1) x N" << endl;
00773         throw SHARKEXCEPTION(s.str().c_str());
00774     }
00775     if (wmat.ndim() != 2)
00776     {
00777         stringstream s;
00778         s << "weight matrix has not dimension two" << endl;
00779         throw SHARKEXCEPTION(s.str().c_str());
00780     }
00781     if (wmat.dim(0) != (wmat.dim(1) - 1))
00782     {
00783         stringstream s;
00784         s << "weight matrix has to be (N + 1) x N" << endl;
00785         throw SHARKEXCEPTION(s.str().c_str());
00786     }
00787 
00788     inputDimension   = in;
00789     outputDimension  = out;
00790     connectionMatrix = cmat;
00791     weightMatrix     = wmat;
00792 
00793     z = NULL;
00794     resize();
00795     writeParameters();
00796 }
00797 
00798 
00799 //===========================================================================
00851 FFNet::FFNet(const string &filename)
00852 {
00853     ifstream input(filename.c_str());
00854     if (!input)
00855     {
00856         stringstream s;
00857         s << "cannot open net file " << filename << endl;
00858         throw SHARKEXCEPTION(s.str().c_str());
00859     }
00860     z = NULL;
00861     input >> *this;
00862     input.close();
00863 }
00864 
00865 
00866 //===========================================================================
00893 void FFNet::setStructure(const Array<int>& cmat, const Array<double>& wmat)
00894 {
00895     if ((cmat.ndim() != 2) ||
00896             (wmat.ndim() != 2))
00897     {
00898         stringstream s;
00899         s << "connection or weight matrix has not dimension two" << endl;
00900         throw SHARKEXCEPTION(s.str().c_str());
00901     }
00902 
00903     if ((cmat.dim(0) != (cmat.dim(1) - 1)) ||
00904             (cmat.dim(0) != wmat.dim(0)) ||
00905             (cmat.dim(1) != wmat.dim(1)))
00906     {
00907         stringstream s;
00908         s << "connection and weight matrices have to be (N + 1) x N" << endl;
00909         throw SHARKEXCEPTION(s.str().c_str());
00910     }
00911 
00912     connectionMatrix = cmat;
00913     weightMatrix     = wmat;
00914 
00915     resize();
00916     writeParameters();
00917 }
00918 
00919 
00920 
00921 //===========================================================================
00957 void FFNet::setStructure(Array<unsigned> &layers,
00958                                                  bool ff_layer,    // all connections between layers?
00959                                                  bool ff_in_out,   // shortcuts from in to out?
00960                                                  bool ff_all,      // all shortcuts?
00961                                                  bool bias)        // bias?
00962 {
00963     unsigned N = 0;  // total number of neurons:
00964     unsigned row,    // connection matrix row    (target neuron)
00965     column, // connection matrix column (start neuron)
00966     k,      // counter.
00967     z_pos,  // first target neuron in next layer
00968     s_pos;  // first start neuron in current layer
00969 
00970 
00971     //
00972     // Calculate total number of neurons from the
00973     // number of neurons per layer:
00974     //
00975     for (k = 0; k < layers.dim(0); k++) N += layers(k);
00976     connectionMatrix.resize(N, N + 1);
00977     connectionMatrix = 0;
00978 
00979     //
00980     // set connections from each neuron of layer i to each
00981     // neuron of layer i + 1 for all layers:
00982     //
00983     if (ff_layer)
00984     {
00985         z_pos = layers(0);
00986         s_pos = 0;
00987         for (k = 0; k < layers.dim(0) - 1; k++)
00988         {
00989             for (row = z_pos; row < z_pos + layers(k + 1); row++)
00990                 for (column = s_pos; column < s_pos + layers(k); column++)
00991                     connectionMatrix(row, column) = 1;
00992             s_pos += layers(k);
00993             z_pos += layers(k + 1);
00994         }
00995     }
00996 
00997     //
00998     // set connections from all input neurons to all output neurons:
00999     //
01000     if (ff_in_out)
01001     {
01002         for (row = N - layers(layers.dim(0) - 1); row < N; row++)
01003             for (column = 0; column < layers(0); column++)
01004                 connectionMatrix(row, column) = 1;
01005     }
01006 
01007     //
01008     // set connections from all neurons of layer i to
01009     // all neurons of layers j with j > i for all layers i:
01010     //
01011     if (ff_all)
01012     {
01013         z_pos = layers(0);
01014         s_pos = 0;
01015         for (k = 0; k < layers.dim(0) - 1; k++)
01016         {
01017             for (row = z_pos; row < z_pos + layers(k + 1); row++)
01018                 for (column = 0; column < s_pos + layers(k); column++)
01019                     connectionMatrix(row, column) = 1;
01020             s_pos += layers(k);
01021             z_pos += layers(k + 1);
01022         }
01023     }
01024 
01025     //
01026     // set connections from all neurons (except the input neurons)
01027     // to the bias values:
01028     //
01029     if (bias)
01030         for (k = layers(0); k < N; k++) connectionMatrix(k, N) = 1;
01031 
01032     weightMatrix.resize(connectionMatrix.dim(0), connectionMatrix.dim(1), false);
01033     weightMatrix = 0.;
01034 
01035 
01036     inputDimension = layers(0);
01037     outputDimension = layers(layers.dim(0) - 1);
01038 
01039     resize();
01040     parameter = 0;
01041 
01042     writeParameters();
01043 }
01044 
01045 
01046 //===========================================================================
01086 void FFNet::setStructure(unsigned in, unsigned hidden, unsigned out,
01087                                                  bool ff_layer,  // all connections beteween layers?
01088                                                  bool ff_in_out, // shortcuts from in to out?
01089                                                  bool ff_all,    // all shortcuts?
01090                                                  bool bias)      // bias?
01091 {
01092     Array<unsigned> layer(3);
01093     layer(0) = in;
01094     layer(1) = hidden;
01095     layer(2) = out;
01096     setStructure(layer, ff_layer, ff_in_out, ff_all, bias);
01097 }
01098 
01099 
01100 //===========================================================================
01141 void FFNet::setStructure(unsigned in, unsigned hidden1, unsigned hidden2, unsigned out,
01142                                                  bool ff_layer,   // all connections beteween layers?
01143                                                  bool ff_in_out,  // shortcuts from in to out?
01144                                                  bool ff_all,     // all shortcuts?
01145                                                  bool bias)       // bias?
01146 {
01147     Array<unsigned> layer(4);
01148     layer(0) = in;
01149     layer(1) = hidden1;
01150     layer(2) = hidden2;
01151     layer(3) = out;
01152     setStructure(layer, ff_layer, ff_in_out, ff_all, bias);
01153 }
01154 
01155 //===========================================================================
01180 void FFNet::setStructure(const Array<int>& cmat)
01181 {
01182     if (cmat.ndim() != 2)
01183     {
01184         stringstream s;
01185         s << "connection matrix has not dimension two" << endl;
01186         throw SHARKEXCEPTION(s.str().c_str());
01187     }
01188     if (cmat.dim(0) != (cmat.dim(1) - 1))
01189     {
01190         stringstream s;
01191         s << "connection matrix has to be (N + 1) x N" << endl;
01192         throw SHARKEXCEPTION(s.str().c_str());
01193     }
01194 
01195     connectionMatrix = cmat;
01196     weightMatrix.resize(cmat.dim(0), cmat.dim(1), false);
01197 
01198     resize();
01199     parameter = 0;
01200 
01201     writeParameters();
01202 }
01203 
01204 
01205 //===========================================================================
01239 void FFNet::setStructure(const Array<double>& wmat, bool preserve)
01240 {
01241     if (wmat.ndim() != 2)
01242     {
01243         stringstream s;
01244         s << "weight matrix has not dimension two" << endl;
01245         throw SHARKEXCEPTION(s.str().c_str());
01246     }
01247     if (wmat.dim(0) != (wmat.dim(1) - 1))
01248     {
01249         stringstream s;
01250         s << "weight matrix has to be (N + 1) x N" << endl;
01251         throw SHARKEXCEPTION(s.str().c_str());
01252     }
01253 
01254     weightMatrix = wmat;
01255     connectionMatrix.resize(wmat.dim(0), wmat.dim(1), false);
01256 
01257     numberOfNeurons   = connectionMatrix.dim(0);
01258     bias              = numberOfNeurons;
01259     firstOutputNeuron = numberOfNeurons - outputDimension;
01260 
01261     unsigned numberOfWeights = 0;
01262     for (unsigned i = 0; i < connectionMatrix.dim(0); i++)
01263     {
01264         for (unsigned j = 0; j < i; j++)
01265         {
01266             if (preserve)
01267             {
01268                 if (weightMatrix(i, j)  != 0.)
01269                 {
01270                     if (connectionMatrix(i, j) == 0)
01271                     {
01272                         stringstream s;
01273                         s << "weight specified for non-existing connection" << endl;
01274                         throw SHARKEXCEPTION(s.str().c_str());
01275                     }
01276                     numberOfWeights++;
01277                 }
01278                 else if (connectionMatrix(i, j) != 0) numberOfWeights++;
01279                 if (weightMatrix(i, bias)  != 0.)
01280                 {
01281                     if (connectionMatrix(i, bias) == 0)
01282                     {
01283                         stringstream s;
01284                         s << "weight specified for non-existing bias" << endl;
01285                         throw SHARKEXCEPTION(s.str().c_str());
01286                     }
01287                     numberOfWeights++;
01288                 }
01289                 else if (connectionMatrix(i, bias) != 0) numberOfWeights++;
01290             }
01291             else
01292             {
01293                 if (weightMatrix(i, j)  != 0.)
01294                 {
01295                     connectionMatrix(i, j) = 1;
01296                     numberOfWeights++;
01297                 }
01298                 else
01299                 {
01300                     connectionMatrix(i, j) = 0;
01301                 }
01302                 if (weightMatrix(i, bias)  != 0.)
01303                 {
01304                     connectionMatrix(i, bias) = 1;
01305                     numberOfWeights++;
01306                 }
01307                 else
01308                 {
01309                     connectionMatrix(i, bias) = 0;
01310                 }
01311             }
01312         }
01313     }
01314 
01315     resize();
01316     writeParameters();
01317 }
01318 
01319 //===========================================================================
01346 void FFNet::writeParameters()
01347 {
01348     for (unsigned k = 0, i = 0; i < connectionMatrix.dim(0); i++)
01349     {
01350         for (unsigned j = 0; j < i; j++)
01351         {
01352             if (connectionMatrix(i, j))
01353             {
01354                 parameter(k) = weight(i, j);
01355                 k++;
01356             }
01357         }
01358         if (i >= inputDimension)
01359         {
01360             if (connectionMatrix(i, bias))
01361             {
01362                 parameter(k) = weight(i, bias);
01363                 k++;
01364             }
01365         }
01366     }
01367 }
01368 
01369 //===========================================================================
01395 void FFNet::readParameters()
01396 {
01397     for (unsigned k = 0, i = 0; i < connectionMatrix.dim(0); i++)
01398     {
01399         for (unsigned j = 0; j < i; j++)
01400         {
01401             if (connectionMatrix(i, j))
01402             {
01403                 weight(i, j) = parameter(k);
01404                 k++;
01405             }
01406         }
01407         if (i >= inputDimension)
01408         {
01409             if (connectionMatrix(i, bias))
01410             {
01411                 weight(i, bias) = parameter(k);
01412                 k++;
01413             }
01414         }
01415     }
01416 }
01417 
01418 
01419 //===========================================================================
01439 const Array< double > &FFNet::getWeights()
01440 {
01441     readParameters();
01442     return weightMatrix;
01443 }
01444 
01445 //===========================================================================
01461 const Array< int > &FFNet::getConnections()
01462 {
01463     return connectionMatrix;
01464 }
01465 
01466 //===========================================================================
01490 void FFNet::write(ostream& os) const
01491 {
01492     os << inputDimension << " " << outputDimension << "\n";
01493     writeArray(connectionMatrix, os, "", "\n", ' ');
01494     writeArray(weightMatrix, os, "", "\n", ' ');
01495 }
01496 
01497 
01498 //===========================================================================
01525 void FFNet::read(istream& is)
01526 {
01527     unsigned i, j, n, pos;
01528     double v, dn;
01529     vector<double> l;
01530 
01531     is >> inputDimension;
01532     is >> outputDimension;
01533 
01534     is >> v;
01535     while (is)
01536     {
01537         l.push_back(v);
01538         is >> v;
01539     }
01540 
01541     if (!l.size())
01542     {
01543         stringstream s;
01544         s << "no matrices given in net file";
01545         throw SHARKEXCEPTION(s.str().c_str());
01546     }
01547 
01548     dn = (sqrt(1. + l.size() * 2.) - 1.) / 2.;
01549     n = unsigned(dn);
01550     if (double(n) == dn)
01551     { // new style with bias
01552         connectionMatrix.resize(n, n + 1, false);
01553         weightMatrix.resize(n, n + 1, false);
01554 
01555         pos = 0;
01556         for (i = 0; i < n; i++)
01557         {
01558             for (j = 0; j < n + 1; j++)
01559             {
01560                 connectionMatrix(i, j) = unsigned(l[pos]);
01561                 pos++;
01562             }
01563         }
01564 
01565         for (i = 0; i < n; i++)
01566         {
01567             for (j = 0; j < n + 1; j++)
01568             {
01569                 weightMatrix(i, j) = l[pos];
01570                 pos++;
01571             }
01572         }
01573     }
01574     else
01575     { // old style without bias
01576         dn = (sqrt(1. + l.size() * 8.) - 1.) / 4.;
01577         n =  unsigned(dn);
01578         if (double(n) == dn)
01579         {
01580             connectionMatrix.resize(n, n + 1, false);
01581             weightMatrix.resize(n, n + 1, false);
01582 
01583             pos = 0;
01584             for (i = 0; i < n; i++)
01585             {
01586                 for (j = 0; j < n; j++)
01587                 {
01588                     connectionMatrix(i, j) = unsigned(l[pos]);
01589                     pos++;
01590                 }
01591                 // handle bias
01592                 if (i >= inputDimension) connectionMatrix(i, n) = 1;
01593                 else connectionMatrix(i, n) = 0;
01594             }
01595             for (i = 0; i < n; i++)
01596             {
01597                 for (j = 0; j < n + 1; j++)
01598                 {
01599                     weightMatrix(i, j) = l[pos];
01600                     pos++;
01601                 }
01602             }
01603         }
01604         else
01605         { // no style
01606             stringstream s;
01607             s << "cannot parse network configuration file" << endl;
01608             throw SHARKEXCEPTION(s.str().c_str());
01609         }
01610     }
01611 
01612     resize();
01613     writeParameters();
01614 }
01615 
01616 
01617 void FFNet::replaceInString(const std::string &str, std::string &newString, const std::string &token, const std::string &newToken1, int newToken2, const std::string &newToken3)
01618 {
01619     std::ostringstream buffer;
01620 
01621     buffer << newToken2;
01622     std::string newToken = newToken1 + buffer.str() + newToken3;
01623 
01624     std::string::size_type pos;
01625     newString = str;
01626 
01627     pos = newString.find(token, 0);
01628     while (pos != std::string::npos)
01629     {
01630         newString.replace(pos, token.length(), newToken);
01631         pos = newString.find(token, 0);
01632     }
01633 }
01634 
01635 void FFNet::writeSource(std::ostream &os, const char *g, const char *gOut, unsigned p)
01636 {
01637     unsigned i, j;
01638     bool first;
01639     std::string str;
01640 
01641     os.precision(p);
01642 
01643     os << "void model(double *in, double *out) {\n";
01644     for (j = 0; j < inputDimension; j++)
01645         os << "  double z" << j << " = in[" << j << "];\n";
01646 
01647     for (i = inputDimension; i < firstOutputNeuron; i++)
01648     {
01649         first = true;
01650         for (j = 0; j < i; j++)
01651             if (connectionMatrix(i, j))
01652             {
01653                 if (first)
01654                 {
01655                     os << "  double z" << i <<  " = z" << j << " * " << weightMatrix(i, j);
01656                     first = false;
01657                 }
01658                 else
01659                 {
01660                     os << " + z" << j << " * " << weightMatrix(i, j);
01661                 }
01662             }
01663 
01664         if( connectionMatrix(i, bias) ) {
01665             if (first)
01666             {
01667                 os  << "double z" << i << " = " << weightMatrix(i, bias); // bias
01668                 first = false;
01669             }
01670             else
01671             {
01672                 os << " + " << weightMatrix(i, bias);
01673             }
01674         }
01675 
01676         if (!first)
01677         {
01678             os << ";\n";
01679             replaceInString(g, str, "#", "z", i, "");
01680             os << "  z" << i << " = " << str << ";\n";
01681         }
01682     }
01683     for (i = firstOutputNeuron; i < numberOfNeurons; i++)
01684     {
01685         first = true;
01686 
01687         for (j = 0; j < i; j++)
01688             if (connectionMatrix(i, j))
01689             {
01690                 if (first)
01691                 {
01692                     os << "  out[" << i - firstOutputNeuron << "] = " << "z" << j
01693                     << " * " << weightMatrix(i, j);
01694                     first = false;
01695                 }
01696                 else
01697                 {
01698                     os << " + z" << j << " * " << weightMatrix(i, j);
01699                 }
01700             }
01701         if( connectionMatrix(i, bias) ) {
01702             if (first)
01703             {
01704                 os << "  out[" << i - firstOutputNeuron << "] = "
01705                 << weightMatrix(i, bias); // bias
01706                 first = false;
01707             }
01708             else
01709             {
01710                 os << " + " << weightMatrix(i, bias); // bias
01711             }
01712         }
01713         
01714         if (!first)
01715         {
01716             os << ";\n";
01717             if((strlen(gOut) != 1) || (*gOut != '#')) { // skip for linear output neurons
01718                 replaceInString(gOut, str, "#", "out[", i - firstOutputNeuron, "]");
01719                 os <<  "  out[" << i - firstOutputNeuron << "] = " << str << ";\n";
01720             }
01721         }
01722     }
01723     os << "};" << std::endl;
01724 }
01725 
01726