00001 /*************************************************************************** 00002 * Copyright (C) 2005 by Robot Group Leipzig * 00003 * martius@informatik.uni-leipzig.de * 00004 * fhesse@informatik.uni-leipzig.de * 00005 * der@informatik.uni-leipzig.de * 00006 * guettler@mis.mpg.de * 00007 * * 00008 * This program is free software; you can redistribute it and/or modify * 00009 * it under the terms of the GNU General Public License as published by * 00010 * the Free Software Foundation; either version 2 of the License, or * 00011 * (at your option) any later version. * 00012 * * 00013 * This program is distributed in the hope that it will be useful, * 00014 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 00015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 00016 * GNU General Public License for more details. * 00017 * * 00018 * You should have received a copy of the GNU General Public License * 00019 * along with this program; if not, write to the * 00020 * Free Software Foundation, Inc., * 00021 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * 00022 * * 00023 * $Log: mutualinformationcontroller.h,v $ 00024 * Revision 1.7 2010/04/28 08:06:29 guettler 00025 * if not initialized, return dummy value 00026 * 00027 * Revision 1.6 2008/04/17 14:54:45 martius 00028 * randomGen added, which is a random generator with long period and an 00029 * internal state. Each Agent has an instance and passed it to the controller 00030 * and the wiring. This is good for 00031 * a) repeatability on agent basis, 00032 * b) parallel execution as done in ode_robots 00033 * 00034 * Revision 1.5 2007/12/12 10:26:14 der 00035 * MI: calculation of H(X) and H(Y|X) added 00036 * 00037 * Revision 1.4 2007/09/27 10:58:52 robot3 00038 * MI: disabled old calculation method, additionally minor bugfixes 00039 * std_adds.h: Template abs is now here (instead of mathutils.h) 00040 * 00041 * Revision 1.3 2007/09/25 07:50:12 robot3 00042 * old MI calculation disabled (but is still present) 00043 * new MI update rule is used, costs O(1) 00044 * 00045 * Revision 1.2 2007/04/19 13:48:20 robot3 00046 * inserted new MI update function - needs O(1) instead of O(n^2) 00047 * 00048 * Revision 1.1 2007/03/22 08:16:52 robot3 00049 * passive controller for calculating the mutual information from sensor values. 00050 * See ode_robots/simulations/MI_Simu for an example. 00051 * 00052 00053 * * 00054 ***************************************************************************/ 00055 #ifndef __MUTUALINFORMATIONCONTROLLER_H 00056 #define __MUTUALINFORMATIONCONTROLLER_H 00057 00058 #include "abstractcontroller.h" 00059 #include "matrix.h" 00060 00061 /** 00062 * This is a controller who is passive at the moment, that means, he will not 00063 * generate any motor values. This controller calculates the mutual information 00064 * from one to the next time step. Note that many steps are neccessary for a good 00065 * prediction of the mutual information. 00066 */ 00067 class MutualInformationController : public AbstractController 00068 { 00069 00070 public: 00071 00072 /** 00073 * Constructs the mutual information controller. At this time the 00074 * controller is not yet initialized (this does the Agent). 00075 * @param minSensorValue is the minimum value the sensors can become 00076 * @param maxSensorValue is the maximum value the sensors can become 00077 * @param sensorIntervalCount is the number of the intervals used. This 00078 * is important for generating the internal matrices. 00079 * 00080 */ 00081 MutualInformationController(int sensorIntervalCount, double minSensorValue=-1, double maxSensorValue=1); 00082 00083 virtual ~MutualInformationController() {}; 00084 00085 virtual double& getMI(int index) { if (!initialized) return dummyVal; assert(index<sensorNumber); return MI[index]; } 00086 00087 virtual double& getH_x(int index) { if (!initialized) return dummyVal; assert(index<sensorNumber); return H_x[index]; } 00088 00089 virtual double& getH_yx(int index) { if (!initialized) return dummyVal; assert(index<sensorNumber); return H_yx[index]; } 00090 00091 virtual double& getH_Xsi(int index) { if (!initialized) return dummyVal; assert(index<sensorNumber); return H_Xsi[index]; } 00092 00093 /** 00094 * we like to calculate the entropy of the xsi, therefore we need for the (self calculated) update rule 00095 * x_t+1=-a * tanh(c * x_t) the a and c, which should be set in the main.cpp. 00096 */ 00097 virtual void setAandCandCalcH_xsi(double ainit, double cinit); 00098 00099 00100 /****************************************************************************/ 00101 /* BEGIN methods of AbstractController */ 00102 /****************************************************************************/ 00103 00104 /** initialisation of the controller with the given sensor/ motornumber 00105 * Must NORMALLY be called before use. For all ControllerAdapters 00106 * call first AbstractControllerAdapter::init(sensornumber,motornumber) 00107 * if you overwrite this method 00108 */ 00109 virtual void init(int sensornumber, int motornumber, RandGen* randGen = 0); 00110 00111 /** @return Number of sensors the controller 00112 was initialised with or 0 if not initialised */ 00113 virtual int getSensorNumber() const { return sensorNumber; } 00114 00115 /** @return Number of motors the controller 00116 was initialised with or 0 if not initialised */ 00117 virtual int getMotorNumber() const { return motorNumber; } 00118 00119 /** performs one step (includes learning). 00120 Calculates motor commands from sensor inputs. 00121 @param sensors sensors inputs scaled to [-1,1] 00122 @param sensornumber length of the sensor array 00123 @param motors motors outputs. MUST have enough space for motor values! 00124 @param motornumber length of the provided motor array 00125 */ 00126 virtual void step(const sensor* sensors, int sensornumber, 00127 motor* motors, int motornumber); 00128 00129 /** performs one step without learning. 00130 @see step 00131 */ 00132 virtual void stepNoLearning(const sensor* sensors , int sensornumber, 00133 motor* motors, int motornumber); 00134 00135 /****************************************************************************/ 00136 /* END methods of AbstractController */ 00137 /****************************************************************************/ 00138 00139 00140 /****************************************************************************/ 00141 /* BEGIN methods of Inspectable */ 00142 /****************************************************************************/ 00143 00144 /** The list of the names of all internal parameters given by getInternalParams(). 00145 The naming convention is "v[i]" for vectors 00146 and "A[i][j]" for matrices, where i, j start at 0. 00147 @return: list of keys 00148 */ 00149 virtual iparamkeylist getInternalParamNames() const; 00150 00151 /** @return: list of values 00152 */ 00153 virtual iparamvallist getInternalParams() const; 00154 00155 /****************************************************************************/ 00156 /* END methods of Inspectable */ 00157 /****************************************************************************/ 00158 00159 /****************************************************************************/ 00160 /* BEGIN methods of Storeable */ 00161 /****************************************************************************/ 00162 00163 /** stores the object to the given file stream (binary). 00164 */ 00165 virtual bool store(FILE* f) const { return true; } 00166 00167 /** loads the object from the given file stream (binary). 00168 */ 00169 virtual bool restore(FILE* f) { return true; } 00170 00171 /****************************************************************************/ 00172 /* END methods of Storeable */ 00173 /****************************************************************************/ 00174 00175 00176 /****************************************************************************/ 00177 /* BEGIN methods of Configurable */ 00178 /****************************************************************************/ 00179 00180 Configurable::paramval getParam(const paramkey& key) const; 00181 00182 bool setParam(const paramkey& key, paramval val); 00183 00184 Configurable::paramlist getParamList() const; 00185 00186 /****************************************************************************/ 00187 /* END methods of Configurable */ 00188 /****************************************************************************/ 00189 00190 00191 protected: 00192 paramval showF; 00193 paramval showP; 00194 bool initialized; // tells wether the controller is already initialized by the agent 00195 bool useXsiCalculation; 00196 00197 double minSensorValue; 00198 double maxSensorValue; 00199 int sensorIntervalCount; 00200 int sensorNumber; 00201 int motorNumber; 00202 std::list<matrix::Matrix*> freqMatrixList; // stores the number of occurances of t-1 to t (frequency) 00203 std::list<matrix::Matrix*> probMatrixList; // stores the probability of state to state occurances of t-1 to t 00204 std::list<matrix::Matrix*> xsiFreqMatrixList; // stores the number of occurances of xsi(x) (frequency) 00205 00206 double* oldSensorStates; // stores the sensor states for next step (t+1) 00207 int t; // indicates the step (time) 00208 00209 double* MI; // mutual information = MI(X_{t-1},X_t) 00210 double* H_x; // H(x) = H(X_{t-1}) 00211 double* H_yx; // H(X_t|X_{t-1}) 00212 double* H_Xsi; // H(Xsi) 00213 00214 // the next two variables are only used if Xsi_x is calculated 00215 double ainit; 00216 double cinit; 00217 00218 double dummyVal; //< is used to be returned if controller isn't initialized yet (possible in ecb_robots) 00219 00220 /** 00221 * Calculates the mutual information 00222 * This is made by normal formula, which 00223 * needs O(n^2) costs. 00224 */ 00225 virtual void calculateMIs(double* MI); 00226 00227 /** 00228 * Calculates the entropy of x 00229 * This is made by normal formula, which 00230 * needs O(n) costs. 00231 */ 00232 virtual void calculateH_x(double* H); 00233 00234 00235 /** 00236 * Calculates the conditional entropy of y|x 00237 * This is made by normal formula, which 00238 * needs O(n²) costs. 00239 */ 00240 virtual void calculateH_yx(double* H_yx); 00241 00242 00243 /** 00244 * Updates the xsi frequency matrix list 00245 */ 00246 virtual void updateXsiFreqMatrixList(const sensor* sensors); 00247 00248 /** 00249 * Calculates the entropy of H(Xsi) 00250 * This is made by normal formula, which 00251 * needs O(n) costs. 00252 */ 00253 virtual void calculateH_Xsi(double* H_Xsi); 00254 00255 00256 00257 /** 00258 * Updates the mutual information 00259 * This is made by a difference term, which 00260 * is added to the old MI(t-1). 00261 * This function needs the OLD MI(t-1) AND 00262 * the OLD F matrix, so update the MI with this 00263 * function first before updating the F matrix! 00264 * calculation costs: O(1) 00265 */ 00266 virtual void updateMIs(const sensor* sensors); 00267 00268 00269 00270 /** 00271 * Returns the appropiate state which belongs to the given sensorValue. 00272 */ 00273 virtual int getState(double sensorValue); 00274 00275 }; 00276 00277 #endif