00001 /*!@file ModelNeuron/NeuralColumn.H Class declaration for a neural 00002 column, which is a collection of neural simulation units that can 00003 interact in an arbitrary connection pattern. */ 00004 00005 // //////////////////////////////////////////////////////////////////// // 00006 // The iLab Neuromorphic Vision C++ Toolkit - Copyright (C) 2001 by the // 00007 // University of Southern California (USC) and the iLab at USC. // 00008 // See http://iLab.usc.edu for information about this project. // 00009 // //////////////////////////////////////////////////////////////////// // 00010 // Major portions of the iLab Neuromorphic Vision Toolkit are protected // 00011 // under the U.S. patent ``Computation of Intrinsic Perceptual Saliency // 00012 // in Visual Environments, and Applications'' by Christof Koch and // 00013 // Laurent Itti, California Institute of Technology, 2001 (patent // 00014 // pending; application number 09/912,225 filed July 23, 2001; see // 00015 // http://pair.uspto.gov/cgi-bin/final/home.pl for current status). // 00016 // //////////////////////////////////////////////////////////////////// // 00017 // This file is part of the iLab Neuromorphic Vision C++ Toolkit. // 00018 // // 00019 // The iLab Neuromorphic Vision C++ Toolkit is free software; you can // 00020 // redistribute it and/or modify it under the terms of the GNU General // 00021 // Public License as published by the Free Software Foundation; either // 00022 // version 2 of the License, or (at your option) any later version. // 00023 // // 00024 // The iLab Neuromorphic Vision C++ Toolkit is distributed in the hope // 00025 // that it will be useful, but WITHOUT ANY WARRANTY; without even the // 00026 // implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // 00027 // PURPOSE. See the GNU General Public License for more details. // 00028 // // 00029 // You should have received a copy of the GNU General Public License // 00030 // along with the iLab Neuromorphic Vision C++ Toolkit; if not, write // 00031 // to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, // 00032 // Boston, MA 02111-1307 USA. // 00033 // //////////////////////////////////////////////////////////////////// // 00034 // 00035 // Primary maintainer for this file: David J. Berg <dberg@usc.edu> 00036 // $HeadURL:svn://ilab.usc.edu/trunk/saliency/src/ModelNeuron/NeuralColumn.H$ 00037 00038 #ifndef MODELNEURON_NEURALCOLUMN_H_DEFINED 00039 #define MODELNEURON_NEURALCOLUMN_H_DEFINED 00040 00041 #include "ModelNeuron/NeuralSimUtils.H" 00042 #include "ModelNeuron/SimUnit.H" 00043 00044 typedef SimUnit::RateType RateType; 00045 // ###################################################################### 00046 //NeuralColumn 00047 //###################################################################### 00048 //! A container for a column of SimUnits. The user can specify 00049 // an arbitrary connection pattern between modules. The output will be 00050 // a weighted sum of all units with output weights (see addWeight(), 00051 // below). Instead of overriding doIntegrate in derived modules, one 00052 // can add column specific operations by overriding doExtraIntegrate. 00053 // One can also override combineOutput to combine outputs from different 00054 // modules in a way other than a weighted sum. 00055 //###################################################################### 00056 template<class T> 00057 class NeuralColumn : public SimUnit 00058 { 00059 public: 00060 //!constructor 00061 NeuralColumn(const SimTime& timestep, const RateType ratetype = SimUnit::NORMAL, 00062 const std::string& name = "", const std::string& units = ""); 00063 00064 //!destructor 00065 virtual ~NeuralColumn(); 00066 00067 //!get the number of sub units 00068 const uint numSubs() const; 00069 00070 //!get sub unit const version 00071 const SimUnit& getSub(const uint i) const; 00072 00073 //!add a subunit. 00074 void addSub(const SimUnit& sub, uint repeat = 1); 00075 00076 //!adds a weighted connection between two units. Use -1 as the 00077 //!'from' argument to accept inputs to a unit. Use -1 as the 'to' 00078 //!argument to contributed to the weighted summed output 00079 void addWeight(const int from, const int to, const float weight); 00080 00081 protected: 00082 //!get sub unit const version 00083 SimUnit& editSub(const uint i); 00084 00085 00086 private: 00087 struct Weights 00088 { 00089 int from, to; 00090 float str; 00091 }; 00092 00093 typedef typename nsu::vector<T> vector; 00094 typedef typename std::vector<Weights> weights_vector; 00095 typedef typename nsu::vector<T>::Type cast_type; 00096 00097 //! integrate our internals a single time step (in msecs) 00098 const double doIntegrate(const SimTime& dt, const double& exc, const double& inh); 00099 00100 //!integrate any dynamics of our container a single time step (in msecs) 00101 virtual void doExtraIntegrate(const SimTime& dt, const double& exc, const double& inh); 00102 00103 //!combine outputs of submodules for system output, default is to multiply paramteter 00104 //! by value and add to total (weighted sum of submodules). 00105 virtual void combineOutput(double& total, const double& value, const double& parameter); 00106 00107 //! perform any additional initialization or reset 00108 void doInit(); 00109 00110 //!perform a deep copy 00111 NeuralColumn* doClone() const; 00112 00113 //! private implementations of addSub, where 'true' and 'false' 00114 //! indicate if the type is polymorphic. 00115 void addSub(const SimUnit& sub, nsu::Int2Type<false>); 00116 void addSub(const SimUnit& sub, nsu::Int2Type<true>); 00117 00118 vector itsM; //!hold our units 00119 00120 //weights 00121 weights_vector itsInputW, itsW, itsOutputW; 00122 }; 00123 00124 // ###################################################################### 00125 //! implementation of NeuralColumn functions 00126 // ###################################################################### 00127 template<class T> inline 00128 NeuralColumn<T>::NeuralColumn(const SimTime& timestep, 00129 const RateType ratetype, 00130 const std::string& name, 00131 const std::string& units) : 00132 SimUnit(timestep, ratetype, name, units), itsM(), 00133 itsInputW(), itsW(), itsOutputW() 00134 { } 00135 00136 // ###################################################################### 00137 template<class T> inline 00138 NeuralColumn<T>::~NeuralColumn() 00139 { } 00140 00141 // ###################################################################### 00142 template<class T> inline 00143 const uint NeuralColumn<T>::numSubs() const 00144 { 00145 return (uint)itsM.size(); 00146 } 00147 00148 // ###################################################################### 00149 template<class T> 00150 const SimUnit& NeuralColumn<T>::getSub(const uint i) const 00151 { 00152 if (i < itsM.size()) 00153 { 00154 return itsM[i]; 00155 } 00156 else 00157 { 00158 LFATAL("no units added to this column"); 00159 return itsM[0];//will never execute 00160 } 00161 } 00162 00163 // ###################################################################### 00164 template<class T> 00165 SimUnit& NeuralColumn<T>::editSub(const uint i) 00166 { 00167 if (i < itsM.size()) 00168 { 00169 return itsM[i]; 00170 } 00171 else 00172 { 00173 LFATAL("no units added to this column"); 00174 return itsM[0];//will never execute 00175 } 00176 } 00177 00178 // ###################################################################### 00179 template <class T> inline 00180 void NeuralColumn<T>::addSub(const SimUnit& sub, uint repeat) 00181 { 00182 for (uint i = 0; i < repeat; ++i) 00183 addSub(sub, nsu::Int2Type<nsu::vector<T>::isPointer >()); 00184 } 00185 00186 // ###################################################################### 00187 template <class T> inline 00188 void NeuralColumn<T>::addSub(const SimUnit& sub, nsu::Int2Type<false>) 00189 { 00190 const cast_type temp = dynamic_cast<const cast_type&>(sub); 00191 itsM.push_back(temp); 00192 } 00193 00194 // ###################################################################### 00195 template <class T> inline 00196 void NeuralColumn<T>::addSub(const SimUnit& sub, nsu::Int2Type<true>) 00197 { 00198 itsM.push_back(sub); 00199 } 00200 00201 // ###################################################################### 00202 template <class T> 00203 void NeuralColumn<T>::addWeight(const int from, const int to, 00204 const float weight) 00205 { 00206 if ( (from == to) && (from == -1) ) 00207 LFATAL("It doesn't make since to map inputs directly to outputs"); 00208 00209 if ( (from < (int)itsM.size()) && (to < (int)itsM.size()) ) 00210 { 00211 Weights temp = {from, to, weight}; 00212 if (to == -1) 00213 itsOutputW.push_back(temp); 00214 else if (from == -1) 00215 itsInputW.push_back(temp); 00216 else 00217 itsW.push_back(temp); 00218 } 00219 else 00220 LFATAL("A weight between these two modules cannot be added as at least " 00221 "one of them is out of range."); 00222 } 00223 00224 // ###################################################################### 00225 template <class T> 00226 const double NeuralColumn<T>::doIntegrate(const SimTime& dt, 00227 const double& exc, const double& inh) 00228 { 00229 //add the inputs 00230 typename weights_vector::const_iterator iter(itsInputW.begin()); 00231 while (iter != itsInputW.end()) 00232 { 00233 itsM[iter->to].inputExc( exc * (iter)->str ); 00234 itsM[iter->to].inputInh( inh * (iter)->str ); 00235 ++iter; 00236 } 00237 00238 //handle columnar interactions 00239 iter = itsW.begin(); 00240 while (iter != itsW.end()) 00241 { 00242 itsM[iter->to].input( itsM[iter->from].getOutput() * iter->str ); 00243 ++iter; 00244 } 00245 00246 //do any derived class specific integration 00247 doExtraIntegrate(dt, exc, inh); 00248 00249 //integrate submodules 00250 typename vector::iterator ii(itsM.begin()), end(itsM.end()); 00251 while (ii != end) 00252 (ii++)->evolve(getTime()); 00253 00254 //set output 00255 double out = 0.0; 00256 iter = itsOutputW.begin(); 00257 while (iter != itsOutputW.end()) 00258 { 00259 combineOutput(out, itsM[(iter)->from].getOutput(), iter->str); 00260 ++iter; 00261 } 00262 return out; 00263 } 00264 00265 // ###################################################################### 00266 template <class T> 00267 void NeuralColumn<T>::doExtraIntegrate(const SimTime& dt, const double& exc, const double& inh) 00268 { } 00269 00270 // ###################################################################### 00271 template <class T> 00272 void NeuralColumn<T>::combineOutput(double& total, const double& value, const double& parameter) 00273 { 00274 total += value * parameter; 00275 } 00276 00277 // ###################################################################### 00278 template <class T> 00279 void NeuralColumn<T>::doInit() 00280 { 00281 itsInputW.clear(); 00282 itsW.clear(); 00283 itsOutputW.clear(); 00284 00285 typename vector::iterator ii(itsM.begin()), end(itsM.end()); 00286 while (ii != end) 00287 (ii++)->initialize(); 00288 } 00289 00290 // ###################################################################### 00291 template <class T> inline 00292 NeuralColumn<T>* NeuralColumn<T>::doClone() const 00293 { 00294 return new NeuralColumn(*this); 00295 } 00296 00297 #endif 00298 // ###################################################################### 00299 /* So things look consistent in everyone's emacs... */ 00300 /* Local Variables: */ 00301 /* indent-tabs-mode: nil */ 00302 /* End: */