00001 /*!@file Neuro/WinnerTakeAllStdOptim.C Optimized version of WinnerTakeAllStd */ 00002 00003 // //////////////////////////////////////////////////////////////////// // 00004 // The iLab Neuromorphic Vision C++ Toolkit - Copyright (C) 2000-2005 // 00005 // by the University of Southern California (USC) and the iLab at USC. // 00006 // See http://iLab.usc.edu for information about this project. // 00007 // //////////////////////////////////////////////////////////////////// // 00008 // Major portions of the iLab Neuromorphic Vision Toolkit are protected // 00009 // under the U.S. patent ``Computation of Intrinsic Perceptual Saliency // 00010 // in Visual Environments, and Applications'' by Christof Koch and // 00011 // Laurent Itti, California Institute of Technology, 2001 (patent // 00012 // pending; application number 09/912,225 filed July 23, 2001; see // 00013 // http://pair.uspto.gov/cgi-bin/final/home.pl for current status). // 00014 // //////////////////////////////////////////////////////////////////// // 00015 // This file is part of the iLab Neuromorphic Vision C++ Toolkit. // 00016 // // 00017 // The iLab Neuromorphic Vision C++ Toolkit is free software; you can // 00018 // redistribute it and/or modify it under the terms of the GNU General // 00019 // Public License as published by the Free Software Foundation; either // 00020 // version 2 of the License, or (at your option) any later version. // 00021 // // 00022 // The iLab Neuromorphic Vision C++ Toolkit is distributed in the hope // 00023 // that it will be useful, but WITHOUT ANY WARRANTY; without even the // 00024 // implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // 00025 // PURPOSE. See the GNU General Public License for more details. // 00026 // // 00027 // You should have received a copy of the GNU General Public License // 00028 // along with the iLab Neuromorphic Vision C++ Toolkit; if not, write // 00029 // to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, // 00030 // Boston, MA 02111-1307 USA. // 00031 // //////////////////////////////////////////////////////////////////// // 00032 // 00033 // Primary maintainer for this file: Rob Peters <rjpeters at usc dot edu> 00034 // $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/Neuro/WinnerTakeAllStdOptim.C $ 00035 // $Id: WinnerTakeAllStdOptim.C 10729 2009-02-02 03:44:27Z itti $ 00036 // 00037 00038 #ifndef NEURO_WINNERTAKEALLSTDOPTIM_C_DEFINED 00039 #define NEURO_WINNERTAKEALLSTDOPTIM_C_DEFINED 00040 00041 #include "Neuro/WinnerTakeAllStdOptim.H" 00042 00043 #include "Util/JobWithSemaphore.H" 00044 #include "Util/MainJobServer.H" 00045 #include "rutz/trace.h" 00046 00047 struct WinnerTakeAllStdOptim::EvolveJob : public JobWithSemaphore 00048 { 00049 EvolveJob(Image<float>::iterator vitr_, 00050 Image<float>::iterator vstop_, 00051 Image<float>::const_iterator initr_, 00052 const float ginput_, 00053 const float dt_c_, 00054 const float gsum_, 00055 const float isum_, 00056 const float Ei_, 00057 const float Vth_) 00058 : 00059 vitr(vitr_), 00060 vstop(vstop_), 00061 initr(initr_), 00062 ginput(ginput_), 00063 dt_c(dt_c_), 00064 gsum(gsum_), 00065 isum(isum_), 00066 Ei(Ei_), 00067 Vth(Vth_), 00068 vwinner() 00069 {} 00070 00071 virtual ~EvolveJob() 00072 {} 00073 00074 virtual void run() 00075 { 00076 while (vitr != vstop) 00077 { 00078 const float Iin = ginput * (*initr++); 00079 00080 // Integrate : all units MKSA 00081 (*vitr) += dt_c * (Iin - (*vitr) * gsum + isum); 00082 00083 // Check if the potential is lower than Ei -> if so, then clamp: 00084 if ((*vitr) < Ei) (*vitr) = Ei; 00085 00086 // Check if voltage has exceeded threshold -> if so, then fire: 00087 if ((*vitr) >= Vth) { vwinner = vitr; *vitr = 0.0F; } 00088 00089 ++vitr; 00090 } 00091 00092 this->markFinished(); 00093 } 00094 00095 virtual const char* jobType() const 00096 { return "WinnerTakeAllStdOptimEvolveJob"; } 00097 00098 Image<float>::iterator vitr; 00099 Image<float>::iterator vstop; 00100 Image<float>::const_iterator initr; 00101 const float ginput; 00102 const float dt_c; 00103 const float gsum; 00104 const float isum; 00105 const float Ei; 00106 const float Vth; 00107 Image<float>::iterator vwinner; 00108 }; 00109 00110 // ###################################################################### 00111 // ###################################################################### 00112 // ########## WinnerTakeAllStdOptim implementation 00113 // ###################################################################### 00114 // ###################################################################### 00115 00116 WinnerTakeAllStdOptim::WinnerTakeAllStdOptim(OptionManager& mgr, 00117 const std::string& descrName, 00118 const std::string& tagName) : 00119 WinnerTakeAllAdapter(mgr, descrName, tagName), 00120 itsTimeStep(SimTime::SECS(0.0001)), 00121 itsEl(0.0F), 00122 itsEe(100.0e-3F), 00123 itsEi(-20.0e-3F), 00124 itsC(1.0E-9F), 00125 itsVth(0.001F), 00126 itsV(), 00127 itsT(), 00128 itsGleak(1.0e-8F), 00129 itsGinh(1.0e-2F), 00130 itsGinput(5.0e-8F), 00131 itsGIN_Gl(1.0e-8F), // in Siemens 00132 itsGIN_Ge(0.0F), // in Siemens 00133 itsGIN_El(0.0F), // in Volts 00134 itsGIN_Ee(100.0e-3F), // in Volts 00135 itsGIN_Ei(-20.0e-3F), // in Volts 00136 itsGIN_C(1.0E-9F), // in Farads 00137 itsGIN_Vth(0.001F), // in Volts 00138 itsGIN_V(itsGIN_Ei), 00139 itsInputCopy() 00140 { 00141 GVX_TRACE(__PRETTY_FUNCTION__); 00142 } 00143 00144 // ###################################################################### 00145 WinnerTakeAllStdOptim::~WinnerTakeAllStdOptim() 00146 { 00147 GVX_TRACE(__PRETTY_FUNCTION__); 00148 } 00149 00150 // ###################################################################### 00151 void WinnerTakeAllStdOptim::reset1() 00152 { 00153 GVX_TRACE(__PRETTY_FUNCTION__); 00154 itsV.freeMem(); 00155 itsInputCopy.freeMem(); 00156 itsT = SimTime::ZERO(); 00157 00158 WinnerTakeAllAdapter::reset1(); 00159 } 00160 00161 // ###################################################################### 00162 void WinnerTakeAllStdOptim::input(const Image<float>& in) 00163 { 00164 GVX_TRACE(__PRETTY_FUNCTION__); 00165 if (itsV.initialized() == false) 00166 { 00167 // first input, let's initialize our array 00168 itsV.resize(in.getDims(), NO_INIT); 00169 itsV.clear(itsEi); 00170 00171 itsGe = 0.0F; 00172 itsGi = itsGinh; 00173 } 00174 00175 // keep a copy of the input for use in evolve(): 00176 itsInputCopy = in; 00177 } 00178 00179 // ###################################################################### 00180 void WinnerTakeAllStdOptim::integrate(const SimTime& t, Point2D<int>& winner) 00181 { 00182 GVX_TRACE(__PRETTY_FUNCTION__); 00183 winner.i = -1; 00184 00185 // the array of neurons receive excitatory inputs from outside. 00186 // here we update the inputs and let the neurons evolve 00187 00188 // we run our difference equations with a time step of itsTimeStep; 00189 // let's here figure out how many iterations we will need to go from 00190 // itsT to t. We will iterate for a number of equal steps, with each 00191 // step as close to itsTimeStep as possible to that we end up at 00192 // time tt after iterating for an integer number of time steps: 00193 const SimTime dt = SimTime::computeDeltaT(t - itsT, itsTimeStep); 00194 const float dt_c = float(dt.secs()) / itsC; 00195 00196 for (SimTime tt = itsT; tt < t; tt += dt) 00197 { 00198 if (tt == SimTime::ZERO()) 00199 continue; 00200 00201 ASSERT(dt != SimTime::ZERO()); 00202 00203 const float gsum = itsGleak + itsGe + itsGi; 00204 const float isum = itsGleak * itsEl + itsGe * itsEe + itsGi * itsEi; 00205 00206 JobServer& srv = getMainJobServer(); 00207 00208 const unsigned int ntiles = srv.getParallelismHint(); 00209 00210 std::vector<rutz::shared_ptr<EvolveJob> > jobs; 00211 00212 for (unsigned int i = 0; i < ntiles; ++i) 00213 { 00214 const int start = (i*itsV.getSize()) / ntiles; 00215 const int end = ((i+1)*itsV.getSize()) / ntiles; 00216 00217 jobs.push_back 00218 (rutz::make_shared(new EvolveJob 00219 (itsV.beginw() + start, 00220 itsV.beginw() + end, 00221 itsInputCopy.begin() + start, 00222 itsGinput, 00223 dt_c, 00224 gsum, 00225 isum, 00226 itsEi, 00227 itsVth))); 00228 00229 srv.enqueueJob(jobs.back()); 00230 } 00231 00232 for (size_t i = 0; i < jobs.size(); ++i) 00233 { 00234 jobs[i]->wait(); 00235 00236 if (jobs[i]->vwinner != Image<float>::iterator()) 00237 { 00238 const size_t offset = jobs[i]->vwinner - itsV.beginw(); 00239 winner.i = offset % itsV.getWidth(); 00240 winner.j = offset / itsV.getWidth(); 00241 00242 // we got a winner, so let's trigger the global inhibition: 00243 itsGIN_Ge = itsGleak * 10.0F; 00244 } 00245 } 00246 00247 itsGe = 0.0F; 00248 itsGi = 0.0F; 00249 00250 // when the global inhibition fires, it triggers inhibitory 00251 // conductances for one time step in the array of excited 00252 // neurons, shuts off excitatory conductances, and turns itself 00253 // off: 00254 00255 // Integrate GIN 00256 const float dt_c2 = float(dt.secs()) / itsGIN_C; 00257 00258 itsGIN_V += dt_c2 * 00259 (- itsGIN_Gl * (itsGIN_V - itsGIN_El) 00260 - itsGIN_Ge * (itsGIN_V - itsGIN_Ee)); 00261 00262 // Check if the GIN potential is lower than Ei -> if so, then clamp: 00263 if (itsGIN_V < itsGIN_Ei) itsGIN_V = itsGIN_Ei; 00264 00265 // Check if GIN voltage has exceeded threshold -> if so, then fire: 00266 if (itsGIN_V >= itsGIN_Vth) 00267 { 00268 itsGIN_V = 0.0F; 00269 this->inhibit(); 00270 } 00271 } 00272 00273 // we are done, just keep track of new current time: 00274 itsT = t; 00275 } 00276 00277 // ###################################################################### 00278 Image<float> WinnerTakeAllStdOptim::getV() const 00279 { 00280 GVX_TRACE(__PRETTY_FUNCTION__); 00281 return itsV; 00282 } 00283 00284 // ###################################################################### 00285 void WinnerTakeAllStdOptim::inhibit() 00286 { 00287 GVX_TRACE(__PRETTY_FUNCTION__); 00288 itsGe = 0.0F; 00289 itsGi = itsGinh; 00290 itsGIN_Ge = 0.0F; 00291 LDEBUG("WTA inhibition firing..."); 00292 } 00293 00294 // ###################################################################### 00295 void WinnerTakeAllStdOptim::saccadicSuppression(const bool on) 00296 { 00297 GVX_TRACE(__PRETTY_FUNCTION__); 00298 if (itsUseSaccadicSuppression.getVal() == false) return; 00299 if (on) inhibit(); 00300 LINFO("------- WTA saccadic suppression %s -------", on ? "on":"off"); 00301 } 00302 00303 // ###################################################################### 00304 void WinnerTakeAllStdOptim::blinkSuppression(const bool on) 00305 { 00306 GVX_TRACE(__PRETTY_FUNCTION__); 00307 if (itsUseBlinkSuppression.getVal() == false) return; 00308 if (on) inhibit(); 00309 LINFO("------- WTA blink suppression %s -------", on ? "on":"off"); 00310 } 00311 00312 // ###################################################################### 00313 /* So things look consistent in everyone's emacs... */ 00314 /* Local Variables: */ 00315 /* mode: c++ */ 00316 /* indent-tabs-mode: nil */ 00317 /* End: */ 00318 00319 #endif // NEURO_WINNERTAKEALLSTDOPTIM_C_DEFINED