00001 /*!@file ModelNeuron/Layer.H Class declarations for a layer of 00002 SimUnits that supports lateral interactions, in a 2D grid. */ 00003 00004 // //////////////////////////////////////////////////////////////////// // 00005 // The iLab Neuromorphic Vision C++ Toolkit - Copyright (C) 2001 by the // 00006 // University of Southern California (USC) and the iLab at USC. // 00007 // See http://iLab.usc.edu for information about this project. // 00008 // //////////////////////////////////////////////////////////////////// // 00009 // Major portions of the iLab Neuromorphic Vision Toolkit are protected // 00010 // under the U.S. patent ``Computation of Intrinsic Perceptual Saliency // 00011 // in Visual Environments, and Applications'' by Christof Koch and // 00012 // Laurent Itti, California Institute of Technology, 2001 (patent // 00013 // pending; application number 09/912,225 filed July 23, 2001; see // 00014 // http://pair.uspto.gov/cgi-bin/final/home.pl for current status). // 00015 // //////////////////////////////////////////////////////////////////// // 00016 // This file is part of the iLab Neuromorphic Vision C++ Toolkit. // 00017 // // 00018 // The iLab Neuromorphic Vision C++ Toolkit is free software; you can // 00019 // redistribute it and/or modify it under the terms of the GNU General // 00020 // Public License as published by the Free Software Foundation; either // 00021 // version 2 of the License, or (at your option) any later version. // 00022 // // 00023 // The iLab Neuromorphic Vision C++ Toolkit is distributed in the hope // 00024 // that it will be useful, but WITHOUT ANY WARRANTY; without even the // 00025 // implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // 00026 // PURPOSE. See the GNU General Public License for more details. // 00027 // // 00028 // You should have received a copy of the GNU General Public License // 00029 // along with the iLab Neuromorphic Vision C++ Toolkit; if not, write // 00030 // to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, // 00031 // Boston, MA 02111-1307 USA. // 00032 // //////////////////////////////////////////////////////////////////// // 00033 // 00034 // Primary maintainer for this file: David Berg <dberg@usc.edu> 00035 // $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/ModelNeuron/Layer.H $ 00036 00037 #ifndef MODELNEURON_LAYER_H_DEFINED 00038 #define MODELNEURON_LAYER_H_DEFINED 00039 00040 #include "ModelNeuron/SimLayer.H" 00041 #include "ModelNeuron/Location.H" 00042 #include "ModelNeuron/Weights.H" 00043 #include "ModelNeuron/SimUnit.H" 00044 #include "ModelNeuron/NeuralSimUtils.H" 00045 00046 // ###################################################################### 00047 // Layer 00048 // ###################################################################### 00049 // A SimLayer (see SimLayer.H) that models a 00050 // 2-dimensional layer of cortex. Neurons are placed on a grid, with 00051 // laterial interactions computed by a Weights (see Weights.H) 00052 // object. 00053 // ###################################################################### 00054 template<class T, class W> 00055 class Layer : public SimLayer 00056 { 00057 public: 00058 //! constructor 00059 Layer(const SimTime& timestep, const uint width, const uint height, 00060 const std::string& name = "", const std::string& units = ""); 00061 00062 //! constructor for weights with 1 param 00063 Layer(const double& param1, const SimTime& timestep, const uint width, const uint height, 00064 const std::string& name = "", const std::string& units = ""); 00065 00066 //! constructor for weights with two params, center and boarder options 00067 Layer(const double& param1, const double& param2, 00068 const bool doSubCenter, const BorderPolicy bp, 00069 const SimTime& timestep, const uint width, const uint height, 00070 const std::string& name = "", const std::string& units = ""); 00071 00072 //! constructor for weights with three params, center and boarder options 00073 Layer(const double& param1, const double& param2, 00074 const double& param3, const bool doSubCenter, 00075 const BorderPolicy bp, 00076 const SimTime& timestep, const uint width, const uint height, 00077 const std::string& name = "", const std::string& units = ""); 00078 00079 //! constructor for weights with three params, center and boarder options 00080 Layer(const double& param1, const double& param2, 00081 const double& param3, const double& param4, 00082 const bool subCenter, const BorderPolicy bp, 00083 const SimTime& timestep, const uint width, const uint height, 00084 const std::string& name = "", const std::string& units = ""); 00085 00086 //!copy constructor 00087 Layer(const Layer& nlc); 00088 00089 //assignment 00090 Layer& operator=(const Layer& nlc); 00091 00092 //!destructor 00093 virtual ~Layer(); 00094 00095 //!get the current display output 00096 Image<double> getDisplayOutput(const int pos = -1) const; 00097 00098 //!get unit(s) at desired location 00099 void getSimUnit(const Location& loc, std::vector<const SimUnit*>& units); 00100 00101 //!edit unit(s) at the desired output position 00102 void editSimUnit(const Location& loc, std::vector<SimUnit*>& units); 00103 00104 //!number of simunits - just returns getOutSize() 00105 const uint numSimUnits() const; 00106 00107 //!get the unit at desired position [pos / w, pos % w], 00108 //!(where '/' is integer division, '%' is modulus, and w is the 00109 //!width of the layer) 00110 const SimUnit& getSimUnit(const uint pos) const; 00111 00112 //get the unit, mutable version 00113 SimUnit& editSimUnit(const uint pos); 00114 00115 //!set type of simulation module 00116 void setModule(const SimUnit& nsm); 00117 00118 //!set type of simulation module at the position 00119 void setModule(const SimUnit& nsm, const Location& p); 00120 00121 //!set the time of this structure and all contained SimUnits if true 00122 void setTime(const SimTime& time, const bool recursive = true); 00123 00124 //!set the lateral interaction weights, which describe how activity 00125 //!is spread throughout the layer. 00126 void setWeights(const W& weights); 00127 00128 //clone the object 00129 Layer<T,W>* clone () const; 00130 00131 private: 00132 //!integrate one time step 00133 void doIntegrate(const SimTime& dt, const Image<double>& inpe, const Image<double>& inpi); 00134 00135 //!reset this object and all the SimUnits in the layer 00136 void doInit(); 00137 00138 //!is our layer full? 00139 const bool isFull(const Location& pos = Location(-1)); 00140 00141 //set the module non-polymorphic 00142 void setModule(const SimUnit& nsm, nsu::Int2Type<false>); 00143 void setModule(const SimUnit& nsm, const Location& pos, nsu::Int2Type<false>); 00144 00145 //set the module polymorphic 00146 void setModule(const SimUnit& nsm, nsu::Int2Type<true>); 00147 void setModule(const SimUnit& nsm, const Location& pos, nsu::Int2Type<true>); 00148 00149 template <class U> struct non_pointer_type { typedef U Type; }; 00150 template <class U> struct non_pointer_type<U*> { typedef U Type; }; 00151 00152 //! an iterator into the layer 00153 typedef typename nsu::vector<T>::iterator iterator; 00154 typedef typename nsu::vector<T>::const_iterator const_iterator; 00155 00156 //!iterator for images 00157 typedef typename Image<double>::iterator d_iterator; 00158 typedef typename Image<double>::const_iterator const_d_iterator; 00159 00160 //if we are polymorhic, get the pointee type 00161 typedef typename non_pointer_type<T>::Type cast_type; 00162 00163 nsu::vector<T> itsL; //the layer 00164 W itsW; //weight interaction 00165 00166 std::vector<bool> itsFilled; //vector of which units are assigned modules 00167 bool itsFull; //true if the entire layer is filled 00168 00169 Location itsProbe; //copy of the probe, if one 00170 }; 00171 00172 // ###################################################################### 00173 // Layer implementation 00174 // ###################################################################### 00175 template<class T, class W> 00176 Layer<T,W>::Layer(const SimTime& timestep, const uint width, const uint height, 00177 const std::string& name, const std::string& units) : 00178 SimLayer(timestep, width, height, name, units), 00179 itsL(), itsW(), itsFilled(width * height, false), 00180 itsFull(false), itsProbe() { itsProbe.setHyperCubeDims(width, height); } 00181 00182 // ###################################################################### 00183 template<class T, class W> 00184 Layer<T,W>::Layer(const double& param1, const SimTime& timestep, 00185 const uint width, const uint height, 00186 const std::string& name, const std::string& units) 00187 : SimLayer(timestep, width, height, name, units), 00188 itsL(), itsW(param1), itsFilled(width * height, false), itsFull(false), itsProbe() 00189 { itsProbe.setHyperCubeDims(width, height); } 00190 00191 // ###################################################################### 00192 template<class T, class W> 00193 Layer<T,W>::Layer(const double& param1, const double& param2, 00194 const bool doSubCenter, const BorderPolicy bp, 00195 const SimTime& timestep, 00196 const uint width, const uint height, 00197 const std::string& name, const std::string& units) 00198 : SimLayer(timestep, width, height, name, units), 00199 itsL(), itsW(param1,param2,doSubCenter,bp), 00200 itsFilled(width * height, false), itsFull(false), itsProbe() 00201 { itsProbe.setHyperCubeDims(width, height); } 00202 00203 // ###################################################################### 00204 template<class T, class W> 00205 Layer<T,W>::Layer(const double& param1, const double& param2, 00206 const double& param3, const bool doSubCenter, 00207 const BorderPolicy bp, const SimTime& timestep, 00208 const uint width, const uint height, 00209 const std::string& name, const std::string& units) 00210 : SimLayer(timestep, width, height, name, units), 00211 itsL(), itsW(param1,param2,param3,doSubCenter,bp), 00212 itsFilled(width * height, false), itsFull(false), itsProbe() 00213 { itsProbe.setHyperCubeDims(width, height); } 00214 00215 // ###################################################################### 00216 template<class T, class W> 00217 Layer<T,W>::Layer(const double& param1, const double& param2, 00218 const double& param3, const double& param4, 00219 const bool doSubCenter, 00220 const BorderPolicy bp,const SimTime& timestep, 00221 const uint width, const uint height, 00222 const std::string& name, 00223 const std::string& units) : 00224 SimLayer(timestep, width, height, name, units), 00225 itsL(), itsW(param1,param2,param3,param4,doSubCenter,bp), 00226 itsFilled(width * height, false), itsFull(false), itsProbe() 00227 { itsProbe.setHyperCubeDims(width, height); } 00228 00229 // ###################################################################### 00230 template<class T, class W> 00231 Layer<T,W>::Layer(const Layer<T,W>& rhs) : 00232 SimLayer(rhs), itsL(rhs.itsL), itsW(rhs.itsW), 00233 itsFilled(rhs.itsFilled), itsFull(rhs.itsFull), itsProbe(rhs.itsProbe) 00234 { } 00235 00236 // ###################################################################### 00237 template<class T, class W> 00238 Layer<T,W>& Layer<T,W>::operator=(const Layer<T,W>& rhs) 00239 { 00240 if (this != &rhs) 00241 { 00242 SimLayer::operator=(rhs); 00243 itsL = rhs.itsL; 00244 itsW = rhs.itsW; 00245 itsFilled = rhs.itsFilled; 00246 itsFull = rhs.itsFull; 00247 itsProbe = rhs.itsProbe; 00248 } 00249 return *this; 00250 } 00251 00252 // ###################################################################### 00253 template<class T, class W> 00254 Layer<T,W>::~Layer() 00255 { } 00256 00257 // ###################################################################### 00258 template<class T, class W> 00259 Image<double> Layer<T,W>::getDisplayOutput(const int pos) const 00260 { 00261 ASSERT(pos < 1); 00262 Image<double> out(getOutDims(), NO_INIT); 00263 if (itsFull) 00264 { 00265 d_iterator outiter(out.beginw()); 00266 const_iterator nsmptr(itsL.begin()), end(itsL.end()); 00267 00268 while (nsmptr != end) 00269 *outiter++ = (nsmptr++)->getDisplayOutput(); 00270 } 00271 return out; 00272 } 00273 00274 // ###################################################################### 00275 template<class T, class W> 00276 void Layer<T,W>::getSimUnit(const Location& loc, std::vector<const SimUnit*>& units) 00277 { 00278 //update our location and get the vector of points, the hypercube dims have been set already 00279 itsProbe.setLocation(loc); 00280 const std::vector<int>& locs = itsProbe.getLinearPos(); 00281 00282 //loop through all the locations 00283 std::vector<int>::const_iterator iter(locs.begin()); 00284 while (iter != locs.end()) 00285 units.push_back(&getSimUnit(*iter++)); 00286 } 00287 00288 // ###################################################################### 00289 template<class T, class W> 00290 void Layer<T,W>::editSimUnit(const Location& loc, std::vector<SimUnit*>& units) 00291 { 00292 //update our location and get the vector of points, the hypercube dims have been set already 00293 itsProbe.setLocation(loc); 00294 const std::vector<int>& locs = itsProbe.getLinearPos(); 00295 00296 std::vector<int>::const_iterator iter(locs.begin()); 00297 while (iter != locs.end()) 00298 units.push_back(&editSimUnit(*iter++)); 00299 } 00300 00301 // ###################################################################### 00302 template<class T, class W> 00303 const uint Layer<T,W>::numSimUnits() const 00304 { 00305 return getOutSize(); 00306 } 00307 00308 // ###################################################################### 00309 template<class T, class W> 00310 const SimUnit& Layer<T,W>::getSimUnit(const uint pos) const 00311 { 00312 if (pos > itsL.size()) 00313 if (itsL.isNull(pos)) 00314 LFATAL("That unit has not yet been assigned"); 00315 return itsL[pos]; 00316 } 00317 00318 // ###################################################################### 00319 template<class T, class W> 00320 SimUnit& Layer<T,W>::editSimUnit(const uint pos) 00321 { 00322 if (pos > itsL.size()) 00323 if (itsL.isNull(pos)) 00324 LFATAL("That unit has not yet been assigned"); 00325 return itsL[pos]; 00326 } 00327 // ###################################################################### 00328 template<class T, class W> 00329 void Layer<T,W>::setModule(const SimUnit& mod) 00330 { 00331 setModule(mod, nsu::Int2Type<nsu::TypeTraits<T>::isPointer >()); 00332 } 00333 00334 00335 // ###################################################################### 00336 template<class T, class W> 00337 void Layer<T,W>::setModule(const SimUnit& mod, const Location& pos) 00338 { 00339 setModule(mod, pos, nsu::Int2Type<nsu::TypeTraits<T>::isPointer >()); 00340 } 00341 00342 // ###################################################################### 00343 template<class T, class W> 00344 void Layer<T,W>::setWeights(const W& weights) 00345 { 00346 itsW = weights; 00347 } 00348 00349 // ###################################################################### 00350 template<class T, class W> 00351 void Layer<T,W>::setTime(const SimTime& time, const bool recursive) 00352 { 00353 //call the base class version, but with no recursion since we wont have any subs. 00354 SimLayer::setTime(time, false); 00355 00356 if (recursive) 00357 { 00358 iterator nsmptr(itsL.begin()), end(itsL.end()); 00359 std::vector<bool>::const_iterator fptr(itsFilled.begin()); 00360 00361 while (nsmptr != end) 00362 { 00363 if (*fptr) 00364 nsmptr->setTime(time, true); 00365 00366 ++fptr; ++nsmptr; 00367 } 00368 } 00369 } 00370 00371 // ###################################################################### 00372 template<class T, class W> 00373 void Layer<T,W>::doIntegrate(const SimTime& dt, const Image<double>& inpe, const Image<double>& inpi) 00374 { 00375 if (itsFull && itsW.initialized()) 00376 { 00377 //compute any neighborhood activity 00378 const Image<double> neighborhood = itsW.compute( itsOutput ); 00379 const_d_iterator i_n(neighborhood.begin()); 00380 00381 //get an iterator for our layer 00382 iterator i_l(itsL.begin()), end(itsL.end()); 00383 00384 //output iterator 00385 d_iterator i_out(itsOutput.beginw()); 00386 00387 //input iterators 00388 const_d_iterator i_exc(inpe.begin()), i_inh(inpi.begin()); 00389 00390 //update each of our SimUnits input and evolve 00391 while (i_l != end) 00392 { 00393 //inputs need to be seperated as excitatory and inhibitory 00394 //are dealt with differently 00395 i_l->input(*i_n++); 00396 i_l->inputExc(*i_exc++); 00397 i_l->inputInh(*i_inh++); 00398 i_l->evolve(getTime()); 00399 *i_out++ = (i_l++)->getOutput(); 00400 } 00401 } 00402 else 00403 { LFATAL("All positions in the layer have not been filled with modules" 00404 " or the weights have not yet been setup"); 00405 } 00406 } 00407 00408 // ###################################################################### 00409 template<class T, class W> 00410 void Layer<T,W>::doInit() 00411 { 00412 for (uint i = 0; i < itsL.size(); ++i) 00413 if (~itsL.isNull(i)) 00414 itsL[i].initialize(); 00415 } 00416 00417 // ###################################################################### 00418 template<class T, class W> 00419 Layer<T,W>* Layer<T,W>::clone () const 00420 { return new Layer<T,W>(*this); }; 00421 00422 // ###################################################################### 00423 template<class T, class W> 00424 void Layer<T,W>::setModule(const SimUnit& nsm, nsu::Int2Type<false>) 00425 { 00426 this->setUnits(nsm.getUnits()); 00427 const cast_type temp = dynamic_cast<const cast_type&>(nsm); 00428 itsL.clear(); 00429 for (uint i = 0; i < getOutSize(); ++i) 00430 itsL.push_back(temp); 00431 itsFull = true; 00432 itsFilled = std::vector<bool>(itsFilled.size(), true); 00433 } 00434 00435 // ###################################################################### 00436 template<class T, class W> 00437 void Layer<T,W>::setModule(const SimUnit& nsm, nsu::Int2Type<true>) 00438 { 00439 this->setUnits(nsm.getUnits()); 00440 itsL.clear(); 00441 for (uint i = 0; i < getOutSize(); ++i) 00442 itsL.push_back(nsm); 00443 itsFull = true; 00444 itsFilled = std::vector<bool>(itsFilled.size(), true); 00445 } 00446 00447 // ###################################################################### 00448 template<class T, class W> 00449 void Layer<T,W>::setModule(const SimUnit& nsm, const Location& pos, nsu::Int2Type<false>) 00450 { 00451 const cast_type temp = dynamic_cast<const cast_type&>(nsm); 00452 Location p = pos; 00453 const std::vector<int>& locs = p.getLinearPos(getOutWidth(), getOutHeight()); 00454 std::vector<int>::const_iterator iter(locs.begin()); 00455 while (iter != locs.end()) 00456 { 00457 if (*iter < (int)itsL.size()) 00458 itsL.set_at(*iter, temp); 00459 else 00460 for (int i = itsL.size(); i <= *iter; ++i) 00461 itsL.push_back(temp); 00462 00463 itsFilled[*iter++] = true; 00464 } 00465 itsFull = isFull(); 00466 } 00467 00468 // ###################################################################### 00469 template<class T, class W> 00470 void Layer<T,W>::setModule(const SimUnit& nsm, const Location& pos, nsu::Int2Type<true>) 00471 { 00472 Location p = pos; 00473 const std::vector<int>& locs = p.getLinearPos(getOutWidth(), getOutHeight()); 00474 std::vector<int>::const_iterator iter(locs.begin()); 00475 while (iter != locs.end()) 00476 { 00477 if (*iter < (int)itsL.size()) 00478 itsL.set_at(*iter, nsm); 00479 else 00480 for (int i = (int)itsL.size(); i <= *iter; ++i) 00481 itsL.push_back(nsm); 00482 00483 itsFilled[*iter++] = true; 00484 } 00485 itsFull = isFull(); 00486 } 00487 00488 // ###################################################################### 00489 template<class T, class W> 00490 const bool Layer<T,W>::isFull(const Location& pos) 00491 { 00492 std::vector<bool>::const_iterator i(itsFilled.begin()), end(itsFilled.end()); 00493 while (i != end) 00494 if (*i++ == false) 00495 return false; 00496 00497 return true; 00498 } 00499 00500 #endif 00501 00502 // ###################################################################### 00503 /* So things look consistent in everyone's emacs... */ 00504 /* Local Variables: */ 00505 /* indent-tabs-mode: nil */ 00506 /* End: */