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