00001 /*!@file ModelNeuron/SimLayer.H Class declarations for partial 00002 implementations of SimStruture for 2-D simulation units. */ 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 J Berg <dberg@usc.edu> 00035 // $HeadURL: svn://isvn.usc.edu:/software/invt/trunk/saliency/src/ModelNeuron/SimLayer.H $ 00036 00037 #ifndef MODELNEURON_SIMLAYER_H_DEFINED 00038 #define MODELNEURON_SIMLAYER_H_DEFINED 00039 00040 #include "Util/SimTime.H" 00041 #include "ModelNeuron/SimUnit.H" 00042 #include "ModelNeuron/SimStructure.H" 00043 #include "ModelNeuron/NeuralSimUtils.H" 00044 00045 class Location; 00046 // ###################################################################### 00047 /*! This partial implementation of SimStructure represents a container for 00048 // SimUnits (See SimUnit.H) that takes 2D input, gives 2D output, and evolves 00049 // the internal states of its SimUnits. This class may have sub structures, but 00050 // this implementation only allows 1 input and output (ie, trying to input or 00051 // get output to a layer > 0 will fail). See Structure.H for a class which 00052 // implements sub structures such that they can be input to our output from. 00053 // 00054 // After a call to evolve(time), the modules internal time will be simulated up 00055 // to 'time' and a call to getOutput() will represent the output of the system 00056 // at 'time'. The logic is the same as SimUnit (see SimUnit.H). Sub structures 00057 // are not required to be simulated at the same time step. */ 00058 //###################################################################### 00059 class SimLayer : public SimStructure 00060 { 00061 public: 00062 //! constructor 00063 SimLayer(const SimTime& timestep, const uint width, const uint height, 00064 const std::string name = "", const std::string units = ""); 00065 00066 //!destructor 00067 virtual ~SimLayer() { }; 00068 00069 // ###################################################################### 00070 // i/o and simulation functions 00071 // ###################################################################### 00072 00073 //!set the input 00074 void input(const Image<double>& in, const int pos = -1); 00075 00076 //!set the excitatory input 00077 void inputExc(const Image<double>& in, const int pos = -1); 00078 00079 //!set the inhibitory input 00080 void inputInh(const Image<double>& in, const int pos = -1); 00081 00082 //!get the current output 00083 Image<double> getOutput(const int pos = -1) const; 00084 00085 //!evolve up to specified time 00086 void evolve(const SimTime& simtime); 00087 00088 // ###################################################################### 00089 // get/set unit functions 00090 // ###################################################################### 00091 00092 //!set the type of neural simulation module to use 00093 virtual void setModule(const SimUnit& mod) = 0; 00094 00095 //!set the type of neural simulation module to use, at a specific 00096 //!position 00097 virtual void setModule(const SimUnit& mod, const Location& pos) = 0; 00098 00099 // ###################################################################### 00100 // change state functions 00101 // ###################################################################### 00102 00103 //reset all counters, output and call doInit() to reset all subclasses 00104 void initialize(); 00105 00106 //set the time 00107 void setTime(const SimTime& time, const bool recurse = true); 00108 00109 // ###################################################################### 00110 // get state functions 00111 // ###################################################################### 00112 00113 //!get current time 00114 const SimTime getTime() const; 00115 00116 00117 //!get simulation time step 00118 const SimTime getTimeStep() const; 00119 00120 //!clone the module 00121 virtual SimLayer* clone() const = 0; 00122 00123 protected: 00124 //protect copy and asignment, use clone 00125 SimLayer(const SimLayer& nlc); 00126 SimLayer& operator=(const SimLayer& nlc); 00127 00128 //the output 00129 Image<double> itsOutput; 00130 00131 private: 00132 //!integrate one time step 00133 virtual void doIntegrate(const SimTime& dt, const Image<double>& inpe, const Image<double>& inpi) = 0; 00134 00135 //!an initializer 00136 virtual void doInit() = 0; 00137 00138 SimTime itsTimeStep, itsT; 00139 uint itsSampScale; 00140 Image<double> itsInpExc, itsInpInh; 00141 }; 00142 00143 // ###################################################################### 00144 //!A class to derive from to create new SimLayers. New 00145 //SimLayer derived types can derive from this class to 00146 //inherit the doClone() function if desired. 00147 /* 00148 Programmer Note: This class uses the 'quriously recursive template 00149 pattern' to simplify creation of new classes for the programmer. As 00150 such, to create a new simulation module, classes should adhear the 00151 following convention: 00152 00153 class mymodule : public SimLayerDerived<mymodule> 00154 { 00155 mymodule(//params//) : SimLayer<mymodule>(//params//) { }; 00156 //...rest of functions 00157 } 00158 */ 00159 // ###################################################################### 00160 template <class Derived> 00161 class SimLayerDerived : public SimLayer 00162 { 00163 protected: 00164 SimLayerDerived(const SimTime& timestep, const uint width, const uint height, 00165 const std::string name = "", const std::string units = "") : 00166 SimLayer(timestep, width, height, name, units) { }; 00167 00168 virtual ~SimLayerDerived() { }; 00169 00170 private: 00171 Derived* clone() const { return new Derived(dynamic_cast<const Derived&>(*this)); } 00172 }; 00173 00174 00175 // ###################################################################### 00176 // SimLayer implementation 00177 // ###################################################################### 00178 inline 00179 SimLayer::SimLayer(const SimTime& timestep, 00180 const uint width, 00181 const uint height, 00182 const std::string name, 00183 const std::string units) : 00184 SimStructure(width, height, name, units), 00185 itsOutput(width, height, ZEROS), itsTimeStep(timestep), 00186 itsT(SimTime::ZERO()), itsSampScale(1), 00187 itsInpExc(width, height, ZEROS), itsInpInh(width, height, ZEROS) 00188 { } 00189 00190 // ###################################################################### 00191 inline 00192 SimLayer::SimLayer(const SimLayer& rhs) : 00193 SimStructure(rhs), 00194 itsOutput(rhs.itsOutput), itsTimeStep(rhs.itsTimeStep), itsT(rhs.itsT), 00195 itsSampScale(rhs.itsSampScale), itsInpExc(rhs.itsInpExc), itsInpInh(rhs.itsInpInh) 00196 { } 00197 00198 // ###################################################################### 00199 inline 00200 SimLayer& SimLayer::operator=(const SimLayer& rhs) 00201 { 00202 if (this != &rhs) 00203 { 00204 SimStructure::operator=(rhs); 00205 00206 itsOutput = rhs.itsOutput; 00207 itsTimeStep = rhs.itsTimeStep; 00208 itsT = rhs.itsT; 00209 itsSampScale = rhs.itsSampScale; 00210 itsInpExc = rhs.itsInpExc; 00211 itsInpInh = rhs.itsInpInh; 00212 } 00213 return *this; 00214 } 00215 00216 // ###################################################################### 00217 inline 00218 void SimLayer::input(const Image<double>& inp, const int pos) 00219 { 00220 ASSERT(inp.getDims() == itsOutput.getDims()); ASSERT(pos < 1); 00221 SimStructure::splitExcInh(inp, itsInpExc, itsInpInh); 00222 } 00223 00224 // ###################################################################### 00225 inline 00226 void SimLayer::inputExc(const Image<double>& inp, const int pos) 00227 { 00228 ASSERT(inp.getDims() == itsOutput.getDims()); ASSERT(pos < 1); 00229 itsInpExc += inp; 00230 } 00231 00232 // ###################################################################### 00233 inline 00234 void SimLayer::inputInh(const Image<double>& inp, const int pos) 00235 { 00236 ASSERT(inp.getDims() == itsOutput.getDims()); ASSERT(pos < 1); 00237 itsInpInh += inp; 00238 } 00239 00240 // ###################################################################### 00241 inline 00242 Image<double> SimLayer::getOutput(const int pos) const 00243 { 00244 ASSERT(pos < 1); 00245 return itsOutput; 00246 } 00247 00248 // ###################################################################### 00249 inline 00250 void SimLayer::evolve(const SimTime& t) 00251 { 00252 // we run our difference equations with a time step of itsTimeStep; 00253 // let's here figure out how many iterations we will need to go from 00254 // itsT to t in an equal number of steps. Each step will be as close 00255 // to itsTimeStep as possible so that we end up at time t after 00256 // iterating for an integer number of time steps. 00257 const SimTime interval(t - itsT); 00258 const int64 nsteps = interval.nsecs() / itsTimeStep.nsecs(); 00259 const int steps = (int)nsteps; 00260 SimTime currTimeStep; 00261 00262 if (steps <= 0) 00263 ++itsSampScale;//keep track of how many times we don't integrate 00264 else 00265 { 00266 //set our current time step 00267 currTimeStep = SimTime::NSECS(interval.nsecs() / nsteps); 00268 00269 if (itsSampScale > 1) 00270 { 00271 //rescale our inputs 00272 itsInpExc /= itsSampScale; 00273 itsInpInh /= itsSampScale; 00274 itsSampScale = 1; 00275 } 00276 00277 for (int ii = 0; ii < steps; ++ii) 00278 { 00279 //update our current time 00280 itsT += currTimeStep; 00281 00282 //integrate our internals 00283 doIntegrate(currTimeStep, itsInpExc, itsInpInh); 00284 } 00285 00286 //reset our input after we evolve to the current time step 00287 itsInpExc.clear(0.0); 00288 itsInpInh.clear(0.0); 00289 } 00290 } 00291 00292 // ###################################################################### 00293 inline 00294 void SimLayer::initialize() 00295 { 00296 itsT = SimTime::ZERO(); 00297 itsSampScale = 1; 00298 itsInpExc.clear(0.0); 00299 itsInpInh.clear(0.0); 00300 itsOutput.clear(0.0); 00301 doInit(); 00302 } 00303 00304 // ###################################################################### 00305 inline 00306 const SimTime SimLayer::getTime() const 00307 { 00308 return itsT; 00309 } 00310 00311 // ###################################################################### 00312 inline 00313 void SimLayer::setTime(const SimTime& time, const bool recurse) 00314 { 00315 itsT = time; 00316 if (recurse) 00317 for (uint ii = 0; ii < numSubs(); ++ii) 00318 editSub(ii).setTime(time); 00319 } 00320 00321 // ###################################################################### 00322 inline 00323 const SimTime SimLayer::getTimeStep() const 00324 { 00325 return itsTimeStep; 00326 } 00327 00328 #endif 00329 // ###################################################################### 00330 /* So things look consistent in everyone's emacs... */ 00331 /* Local Variables: */ 00332 /* indent-tabs-mode: nil */ 00333 /* End: */