00001 /*!@file Neuro/LeakyIntFireAdp.H Class declarations for an adaptive leaky integrator neuron */ 00002 00003 // //////////////////////////////////////////////////////////////////// // 00004 // The iLab Neuromorphic Vision C++ Toolkit - Copyright (C) 2001 by the // 00005 // 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: Laurent Itti <itti@usc.edu> 00034 // $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/Neuro/LeakyIntFireAdp.H $ 00035 // $Id: LeakyIntFireAdp.H 10729 2009-02-02 03:44:27Z itti $ 00036 // 00037 00038 #ifndef LEAKY_INTFIRE_ADP_H_DEFINED 00039 #define LEAKY_INTFIRE_ADP_H_DEFINED 00040 00041 #include "Util/SimTime.H" 00042 00043 // ###################################################################### 00044 //! A leaky integrate & fire neuron, used by standard winner-take-all (WTA) 00045 // ###################################################################### 00046 /*! This is the integrate & fire neuron used in conjunction with WTA 00047 which is a 2D array of LeakyIntFire. It has a slightly more 00048 complicated Euler equation then LeakyIntegrator used by SM but the 00049 basic idea is the same. All parameters are in MKSA (SI) units 00050 (i.e., volts, amperes, siemens, etc). This neuron uses an Euler 00051 integration of the following form: 00052 00053 At each time step, 00054 00055 \f[ V \leftarrow V + \frac{\delta t}{C} \left(I - G_{leak}(V - E_{leak}) - 00056 G_{ex}(V - E_{ex}) - G_{inh}(V - E_{inh})\right) \f] 00057 00058 V is also clamped to never become smaller than \f$E_{inh}\f$ and 00059 a spike is generated when \f$V \ge V_{th}\f$ (and V is then reset to zero).*/ 00060 class LeakyIntFireAdp 00061 { 00062 public: 00063 //! constructor 00064 /*! Constructor with default params 00065 @param timeStep is the integration time step, in s. 00066 See the general description for the other params. */ 00067 inline LeakyIntFireAdp(const SimTime timeStep = SimTime::SECS(0.0001), 00068 const float El = 0.0F, // in Volts 00069 const float Ee = 100.0e-3F, // in Volts 00070 const float Ei = -20.0e-3F, // in Volts 00071 const float Gl = 5.0e-8F, // in Siemens 00072 const float Ge = 0.0F, // in Siemens 00073 const float Gi = 0.0F, // in Siemens 00074 const float Vth = 0.001F, // in Volts 00075 const float C = 1.0E-9F, // in Farads 00076 const float VthMod = 1.0F, 00077 const float VthDec = 0.01F, 00078 const float VthBase = 0.001F, 00079 const float Vfire = 0.0F); 00080 00081 //! set input current (A) 00082 inline void input(const float current); 00083 00084 //! set membrane potential to given value relative to Ei (in Volts) 00085 inline void setV(const double val); 00086 00087 //! integrate for up to given time (in s) 00088 /*! Returns true if a spike was generated. */ 00089 inline bool integrate(const SimTime& t); 00090 00091 //! get current membrane potential (in V) 00092 inline float getV() const; 00093 00094 //! get current membrane potential threshold 00095 inline float getVth() const; 00096 00097 //! get current membrane potential at time of fire 00098 inline float getVfire() const; 00099 00100 //! set excitatory and inhibitory conductances (S) 00101 inline void setG(const float Exc, const float Inh); 00102 00103 //! set leak conductance (S) 00104 inline void setGleak(const float Leak); 00105 00106 //! return our internal time step: 00107 inline SimTime getTimeStep() const; 00108 00109 //! get the logistic sigmoid of the input value 00110 inline float logsig(const float x, const float o, const float b) const; 00111 00112 //! change the threshold for firing 00113 /*! We change the fire threshold based on three primary factors 00114 (1) How salient is this location - salVal 00115 (2) At what voltage did the winner fire at - VfireVal 00116 (3) How far am I from the winner - dist 00117 00118 Thus, the new Vth is increased based on these three factors 00119 */ 00120 inline void setNewVth(const float salVal, const float VfireVal, 00121 const float dist); 00122 00123 private: 00124 inline void reset();// reset when a spike occurs 00125 00126 SimTime itsTimeStep;// time step to use for difference equations (in s) 00127 float itsV; // membrane potential in Volts 00128 float itsI; // input current in Amperes 00129 float itsGl; // leak conductance in Siemens 00130 float itsGe; // excitatory conductance in Siemens 00131 float itsGi; // inhibitory conductance in Siemens 00132 float itsC; // capacitance in Farads 00133 float itsEl; // driving potential for leak part, in Volts 00134 float itsEe; // driving potential for excitatory part, in Volts 00135 float itsEi; // driving potential for inhibitory part, in Volts 00136 float itsVth; // spike threshold voltage in Volts 00137 float itsVthMod; // How much to modulate V threshold 00138 float itsVthDecay; // How much to decay V threshold 00139 float itsVthBase; // Smallest V threshold 00140 float itsVfire; // what V did we fire at? 00141 SimTime itsT; // time of last integration 00142 }; 00143 00144 // ###################################################################### 00145 // ##### Inline functions for LeakyIntFireAdp: 00146 // ###################################################################### 00147 00148 inline LeakyIntFireAdp::LeakyIntFireAdp(const SimTime timeStep, 00149 const float El, 00150 const float Ee, 00151 const float Ei, 00152 const float Gl, 00153 const float Ge, 00154 const float Gi, 00155 const float Vth, 00156 const float C, 00157 const float VthMod, 00158 const float VthDec, 00159 const float VthBase, 00160 const float Vfire) : 00161 itsTimeStep(timeStep), itsV(Ei), itsI(0.0), itsGl(Gl), itsGe(Ge), itsGi(Gi), 00162 itsC(C), itsEl(El), itsEe(Ee), itsEi(Ei), itsVth(Vth), itsVthMod(VthMod), 00163 itsVthDecay(VthDec), itsVthBase(VthBase), itsVfire(0), itsT(SimTime::ZERO()) 00164 { } 00165 00166 // ###################################################################### 00167 inline void LeakyIntFireAdp::input(const float current) 00168 { itsI = current; } 00169 00170 // ###################################################################### 00171 inline bool LeakyIntFireAdp::integrate(const SimTime& t) 00172 { 00173 // we run our difference equations with a time step of itsTimeStep; 00174 // let's here figure out how many iterations we will need to go from 00175 // itsT to t. We will iterate for a number of equal steps, with each 00176 // step as close to itsTimeStep as possible to that we end up at 00177 // time t after iterating for an integer number of time steps: 00178 const SimTime dt = SimTime::computeDeltaT((t - itsT), itsTimeStep); 00179 const float dtsc = float(dt.secs()) / itsC; 00180 00181 bool spike = false; 00182 for (SimTime tt = itsT; tt < t; tt += dt) 00183 { 00184 // Integrate : all units MKSA 00185 itsV += dtsc * (itsI - itsGl * (itsV - itsEl) - 00186 itsGe * (itsV - itsEe) - itsGi * (itsV - itsEi)); 00187 00188 // Check if the potential is lower than Ei -> if so, then clamp: 00189 if (itsV < itsEi) itsV = itsEi; 00190 00191 // Check if voltage has exceeded threshold -> if so, then fire: 00192 if (itsV >= itsVth) 00193 { 00194 // raise the threshold proportionally to spike voltage 00195 // Use this one once we test the simple version 00196 //itsVth += itsVthMod * logsig(itsV - itsVth,0.0001,100); 00197 // simple version 00198 LINFO("itsVth %f",itsVth); 00199 LINFO("SETTING Vfire %f to V %f",itsVfire,itsV); 00200 itsVfire = itsV; 00201 spike = true; 00202 reset(); 00203 } 00204 00205 const float change = itsVth + dt.secs() * itsVthDecay; 00206 //LINFO("CHANGED VTH from %f to %f",itsVth,change); 00207 if(change >= itsVthBase) 00208 itsVth = change; 00209 // clamp the Vth base 00210 if(itsVth < itsVthBase) 00211 itsVth = itsVthBase; 00212 } 00213 00214 // we are done, just keep track of new current time: 00215 itsT = t; 00216 return spike; 00217 } 00218 00219 // ###################################################################### 00220 inline void LeakyIntFireAdp::setV(const double val) 00221 { itsV = val + itsEi; } 00222 00223 // ###################################################################### 00224 inline float LeakyIntFireAdp::getV() const 00225 { return itsV; } 00226 00227 // ###################################################################### 00228 inline float LeakyIntFireAdp::getVth() const 00229 { return itsVth; } 00230 00231 // ###################################################################### 00232 inline float LeakyIntFireAdp::getVfire() const 00233 { return itsVfire; } 00234 00235 // ###################################################################### 00236 inline void LeakyIntFireAdp::setG(const float Exc, const float Inh) 00237 { itsGe = Exc; itsGi = Inh; } 00238 00239 // ###################################################################### 00240 inline void LeakyIntFireAdp::setGleak(const float Leak) 00241 { itsGl = Leak; } 00242 00243 // ###################################################################### 00244 inline void LeakyIntFireAdp::reset() 00245 { itsV = 0.0F; } 00246 00247 // ###################################################################### 00248 inline SimTime LeakyIntFireAdp::getTimeStep() const 00249 { return itsTimeStep; } 00250 00251 // ###################################################################### 00252 inline float LeakyIntFireAdp::logsig(const float x, const float o, 00253 const float b) const 00254 { 00255 return 1/(1+pow(2.718281,-(b*(x-o)))); 00256 } 00257 00258 // ###################################################################### 00259 inline void LeakyIntFireAdp::setNewVth(const float salVal, 00260 const float VfireVal, 00261 const float dist) 00262 { 00263 // add more features later, just test with VfireVal alone for now 00264 LINFO("%f %f %f",salVal,VfireVal,dist); 00265 00266 const float newVal = (1 + salVal + VfireVal)/(dist + 1); 00267 00268 LINFO("OLD Vth %f new %f",itsVth,itsVth+newVal); 00269 itsVth += newVal; 00270 if(itsVth < itsVthBase) 00271 itsVth = itsVthBase; 00272 } 00273 #endif 00274 00275 // ###################################################################### 00276 /* So things look consistent in everyone's emacs... */ 00277 /* Local Variables: */ 00278 /* indent-tabs-mode: nil */ 00279 /* End: */