WinnerTakeAllPopulation.cpp

Go to the documentation of this file.
00001 /************************************************************************
00002 * Verve                                                                 *
00003 * Copyright (C) 2004-2006                                               *
00004 * Tyler Streeter  tylerstreeter@gmail.com                               *
00005 * All rights reserved.                                                  *
00006 * Web: http://verve-agents.sourceforge.net                              *
00007 *                                                                       *
00008 * This library is free software; you can redistribute it and/or         *
00009 * modify it under the terms of EITHER:                                  *
00010 *   (1) The GNU Lesser General Public License as published by the Free  *
00011 *       Software Foundation; either version 2.1 of the License, or (at  *
00012 *       your option) any later version. The text of the GNU Lesser      *
00013 *       General Public License is included with this library in the     *
00014 *       file license-LGPL.txt.                                          *
00015 *   (2) The BSD-style license that is included with this library in     *
00016 *       the file license-BSD.txt.                                       *
00017 *                                                                       *
00018 * This library is distributed in the hope that it will be useful,       *
00019 * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
00020 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files    *
00021 * license-LGPL.txt and license-BSD.txt for more details.                *
00022 ************************************************************************/
00023 
00024 #include "WinnerTakeAllPopulation.h"
00025 #include "Neuron.h"
00026 
00027 namespace verve
00028 {
00029         WinnerTakeAllPopulation::WinnerTakeAllPopulation()
00030         : UltraSparseCodePopulation()
00031         {
00032         }
00033 
00034         WinnerTakeAllPopulation::~WinnerTakeAllPopulation()
00035         {
00036         }
00037 
00038         void WinnerTakeAllPopulation::updateFiringRatesWTA()
00039         {
00040                 // IDEA: This could be a little more efficient if we could avoid 
00041                 // updating all of the Neurons' targets (post-synaptic Neurons) 
00042                 // until the end.  Right now, we are updating all firing rates 
00043                 // twice.
00044 
00045                 // Compute new firing rates from the synaptic input sums.  Use 
00046                 // a sigmoidal activation.
00047                 unsigned int size = (unsigned int)mNeurons.size();
00048                 for (unsigned int i = 0; i < size; ++i)
00049                 {
00050                         mNeurons[i]->updateFiringRateSigmoid();
00051                 }
00052 
00053                 // Now pick the "winner" Neuron; set its firing rate to 1 and the 
00054                 // rest to 0.  Save the index of the winner.
00055                 mActiveIndex = computeWinnerIndex();
00056 
00057                 // Set the winner's firing rate to 1 and the rest to 0.
00058                 for (unsigned int i = 0; i < size; ++i)
00059                 {
00060                         if (i == mActiveIndex)
00061                         {
00062                                 mNeurons[i]->setFiringRate(1);
00063                         }
00064                         else
00065                         {
00066                                 mNeurons[i]->setFiringRate(0);
00067                         }
00068                 }
00069         }
00070 
00071         unsigned int WinnerTakeAllPopulation::computeWinnerIndex()
00072         {
00073                 unsigned int winnerIndex = 0;
00074                 unsigned int size = (unsigned int)mNeurons.size();
00075 
00076                 // We will use a roulette selection method to choose the winner.  
00077                 // First we find the total firing rate and count the number of 
00078                 // inactive Neurons.
00079                 real totalFiringRate = 0;
00080                 unsigned int numInactiveNeurons = 0;
00081                 for (unsigned int i = 0; i < size; ++i)
00082                 {
00083                         real firingRate = mNeurons[i]->getFiringRate();
00084                         if (0 == firingRate)
00085                         {
00086                                 ++numInactiveNeurons;
00087                         }
00088                         else
00089                         {
00090                                 totalFiringRate += firingRate;
00091                         }
00092                 }
00093 
00094                 // We need to add a little to the total for each inactive Neuron.  
00095                 // This ensures that the 'defaults::minActionSelectionProb' exactly 
00096                 // specifies the minimum action selection probability.
00097                 real extra = 0;
00098                 if (defaults::minActionSelectionProb > 0)
00099                 {
00100                         // The purpose of using this extra variable is to avoid 
00101                         // compiler (e.g. gcc 3.4.4) warnings about division by 
00102                         // zero.  For example, when defaults::minActionSelectionProb 
00103                         // is zero, the calculation below looks like a divide by 
00104                         // zero problem, but this will never happen because of 
00105                         // the 'if' check above.
00106                         real minProb = defaults::minActionSelectionProb;
00107 
00108                         // The restriction on 'defaults::minActionSelectionProb' ensure 
00109                         // that the following quantity is a valid positive number.
00110                         extra = totalFiringRate / (1 / minProb - numInactiveNeurons);
00111                 }
00112                 totalFiringRate += numInactiveNeurons * extra;
00113 
00114                 // Generate a random number uniformly between 0 and 
00115                 // 'totalFiringRate.'
00116                 real randomValue = globals::randomRealUniform(0, 
00117                         totalFiringRate);
00118 
00119                 // Pick a "winner" probabilistically.  A higher firing 
00120                 // rate means a higher chance of being chosen as the 
00121                 // winner.
00122                 real currentTotal = 0;
00123                 for (unsigned int i = 0; i < size; ++i)
00124                 {
00125                         // We need to add some activation to the inactive Neurons to 
00126                         // make the 'defaults::minActionSelectionProb' valid.
00127                         real firingRate = mNeurons[i]->getFiringRate();
00128                         if (0 == firingRate)
00129                         {
00130                                 firingRate = extra;
00131                         }
00132 
00133                         if (randomValue <= firingRate + currentTotal)
00134                         {
00135                                 winnerIndex = i;
00136                                 break;
00137                         }
00138                         else
00139                         {
00140                                 currentTotal += firingRate;
00141                         }
00142                 }
00143 
00144                 return winnerIndex;
00145         }
00146 }

Generated on Tue Jan 24 21:46:38 2006 for Verve by  doxygen 1.4.6-NO