Robot Simulator of the Robotics Group for Self-Organization of Control: templatevalueanalysation.h Source File

# templatevalueanalysation.h

Go to the documentation of this file.

    00001 /***************************************************************************
    00002  *   Copyright (C) 2005-2011 LpzRobots development team                    *
    00003  *    Georg Martius  <georg dot martius at web dot de>                     *
    00004  *    Frank Guettler <guettler at informatik dot uni-leipzig dot de        *
    00005  *    Frank Hesse    <frank at nld dot ds dot mpg dot de>                  *
    00006  *    Ralf Der       <ralfder at mis dot mpg dot 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  ***************************************************************************/
    00024
    00025 #ifndef TEMPLATEVALUEANALYSATION_H_
    00026 #define TEMPLATEVALUEANALYSATION_H_
    00027
    00028 //macros
    00029 #define ANALYSATION_CONTEXT TemplateValueAnalysation<type,zero,lower,higher,doubleDiv,doubleMul,add,sub,mul,div>
    00030 #define DOUBLE_ANALYSATION_CONTEXT TemplateValueAnalysation<double,defaultZero>
    00031
    00032 //includes
    00033 #include <vector>
    00034 #include <list>
    00035
    00036 /**
    00037  * default function for "lower as" operation.
    00038  * @param a operator a
    00039  * @param b operator b
    00040  * @return (bool) true if a lower than b
    00041  */
    00042 template
    00043 <class type>
    00044 bool defaultLower(const type& a, const type& b) {
    00045         if(a<b)
    00046                 return true;
    00047
    00048         return false;
    00049 }
    00050
    00051 /**
    00052  * default function for divide by a double value.
    00053  * @param a operator a
    00054  * @param b (double) the double value
    00055  * @return the result of the division
    00056  */
    00057 template
    00058 <class type>
    00059 type defaultDoubleDiv(const type& a, const double& b) {
    00060         return a/b;
    00061 }
    00062
    00063 /**
    00064  * default function for mul. with a double value.
    00065  * @param a operator a
    00066  * @param b (double) the double value
    00067  * @return the result of the mul.
    00068  */
    00069 template
    00070 <class type>
    00071 type defaultDoubleMul(const type& a, const double& b) {
    00072         return a*b;
    00073 }
    00074
    00075 /**
    00076  * default function for "higher than" operation.
    00077  * @param a operator a
    00078  * @param b operator b
    00079  * @return (bool) true if a higher than b
    00080  */
    00081 template
    00082 <class type>
    00083 bool defaultHigher(const type& a,const type& b) {
    00084         if(a>b)
    00085                 return true;
    00086
    00087         return false;
    00088 }
    00089
    00090 /**
    00091  * default function for add two values
    00092  * @param a operator a
    00093  * @param b operator b
    00094  * @return the result of the add.
    00095  */
    00096 template
    00097 <class type>
    00098 type defaultAdd(const type& a, const type& b) {
    00099         return a+b;
    00100 }
    00101
    00102 /**
    00103  * default function for sub. two values
    00104  * @param a operator a
    00105  * @param b operator b
    00106  * @return the result of the sub.
    00107  */
    00108 template
    00109 <class type>
    00110 type defaultSub(const type& a, const type& b) {
    00111         return a-b;
    00112 }
    00113
    00114 /**
    00115  * default function for mul. of two values
    00116  * @param a operator a
    00117  * @param b operator b
    00118  * @return the result of the mul.
    00119  */
    00120 template
    00121 <class type>
    00122 type defaultMul(const type& a, const type& b) {
    00123         return a*b;
    00124 }
    00125
    00126 /**
    00127  * default function for div. of two values
    00128  * @param a operator a
    00129  * @param b operator b
    00130  * @return the result of the div.
    00131  */
    00132 template
    00133 <class type>
    00134 type defaultDiv(const type& a, const type& b) {
    00135         return a/b;
    00136 }
    00137
    00138 /**
    00139  * default function for zero double value
    00140  * @return (double) 0.0
    00141  */
    00142 double defaultZero();
    00143
    00144 /**
    00145  * This template class give you some methods to calculate some statistical values like average, min, max, upper quartil,
    00146  * lower quartil and many more.
    00147  *
    00148  * All functions are implemented in the header because by generating the library it isn't known which type are later used.
    00149  * And a later compiling needs the implementation two!
    00150  */
    00151 template
    00152 <class type,                                                                                                                    //data type of the calculation
    00153 type zero(void),                                                                                                                //gives the zero of this data type back
    00154 bool lower(const type&, const type&)=defaultLower<type>,                                //test if one element of the type lower than the other
    00155 bool higher(const type&, const type&)=defaultHigher<type>,                      //test if one element of the type higher than the other
    00156 type doubleDiv(const type&, const double&)=defaultDoubleDiv<type>,      //divide a element of the type by a double value
    00157 type doubleMul(const type&, const double&)=defaultDoubleMul<type>,      //mul. a element of the type by a double value
    00158 type add(const type&, const type&)=defaultAdd<type>,                                    //add two elements of type
    00159 type sub(const type&, const type&)=defaultSub<type>,                                    //sub two elements of type
    00160 type mul(const type&, const type&)=defaultMul<type>,                                    //mul two elements of type
    00161 type div(const type&, const type&)=defaultDiv<type> >                           //div two elements of type
    00162 class TemplateValueAnalysation {
    00163 public:
    00164         /**
    00165          * constructor
    00166          * Needs a set of values for which the statistical values will calculate.
    00167          * @param values (vector<type>& the set)
    00168          */
    00169         TemplateValueAnalysation(std::vector<type>& values) : m_vector(values), m_list(), m_listCreated(false) {}
    00170
    00171         /**
    00172          * default destructor
    00173          */
    00174         ~TemplateValueAnalysation() {}
    00175
    00176         /**
    00177          * this function calculate the average of the giving set
    00178          *
    00179          * It used zero, add and doubleDiv to calculate the average.
    00180          * @return the average
    00181          */
    00182         type getAvg() {
    00183                 type avg=zero();                                                                                                                                                //by begin the average is zero
    00184                 __gnu_cxx::__normal_iterator<type*,std::vector<type,std::allocator<type> > > iter;
    00185
    00186                 for(iter = m_vector.begin(); iter != m_vector.end(); iter++) {
    00187                         avg = add(avg,(*iter));                                                                                                                         //for all elements in the set add it to the average.
    00188                                                                                                                                                                                                 //So we become the sum. of all elements in the set.
    00189                 }
    00190
    00191                 if(m_vector.size()!=0)
    00192                         avg = doubleDiv(avg,m_vector.size());                                                                                           //now devide the sum by the count of elements in the set.
    00193
    00194                 return avg;                                                                                                                                                             //return the result
    00195         }
    00196
    00197         /**
    00198          * this function search the min. value in the set
    00199          *
    00200          * For this it use lower
    00201          * @return the minimum
    00202          */
    00203         type getMin() {
    00204                 type min = m_vector[0];                 //the lowest element is at begin the first element
    00205                 __gnu_cxx::__normal_iterator<type*,std::vector<type,std::allocator<type> > > iter = m_vector.begin();
    00206
    00207                 for(iter++; iter != m_vector.end(); iter++) {
    00208                         if(lower((*iter),min))          //if a element lower than min, so reset the min to the lower value.
    00209                                 min=(*iter);
    00210                 }
    00211
    00212                 return min;                                             //return the lowest element
    00213         }
    00214
    00215         /**
    00216          * this function search the max. value in the set
    00217          *
    00218          * For this it use lower
    00219          * @return the minimum
    00220          */
    00221         type getMax() {
    00222                 type max = m_vector[0];                 //the highest element is at begin the first element
    00223                 __gnu_cxx::__normal_iterator<type*,std::vector<type,std::allocator<type> > > iter = m_vector.begin();
    00224
    00225                 for(iter++; iter != m_vector.end(); iter++) {
    00226                         if(lower(max,(*iter)))          //if a element higher than max, so reset the max to the higher value.
    00227                                 max=(*iter);
    00228                 }
    00229
    00230                 return max;                                             //return the lowest element
    00231         }
    00232
    00233         /**
    00234          * this function calculate the range of all values. For this he search the mibn and max and calculate from this values.
    00235          *
    00236          * use sub
    00237          * @return the range of the values in the set
    00238          */
    00239         type getRange() {
    00240                 type dMax = getMax();                   //become max
    00241                 type dMin = getMin();                   //become min
    00242
    00243                 return sub(dMax,dMin);                  //range=max-min
    00244         }
    00245
    00246         /**
    00247          * this function search the median of the giving set of values.
    00248          *
    00249          * use add and doubleMul
    00250          * @return the median
    00251          */
    00252         type getMedian() {
    00253                 type median;
    00254                 int x;
    00255                 int num = m_vector.size()/2;
    00256                 std::_List_iterator<TYPE_SAVE> iter;
    00257
    00258                 if(!m_listCreated)
    00259                         sort();                                                         //sort the set. to define the middle
    00260
    00261                 iter = m_list.begin();                                  //go to the middle
    00262                 for(x=0;x<num;x++) iter++;
    00263
    00264                 if(m_vector.size() % 2 == 0) {                  //if the real middle between two values add this values and calculate the arithmetical middle.
    00265                         median = (*iter->pointer);
    00266                         iter--;
    00267                         median = add(median,(*iter->pointer));
    00268                         median = doubleMul(median,0.5);
    00269                 }
    00270
    00271                 else {
    00272                         median = (*iter->pointer);                      //else gives the middle back
    00273                 }
    00274
    00275                 return median;
    00276         }
    00277
    00278         /**
    00279          * this function calculate the under quartil
    00280          *
    00281          * use add and doubleMul
    00282          * @return the under quartil
    00283          */
    00284         type getQuartil1() {
    00285                 type q;
    00286                 int x;
    00287                 int num = m_vector.size()/4;
    00288                 std::_List_iterator<TYPE_SAVE> iter;
    00289
    00290                 if(!m_listCreated)
    00291                         sort();                                                         //sort the set.
    00292
    00293                 iter = m_list.begin();                                  //go to the under quartil
    00294                 for(x=0;x<num;x++) iter++;
    00295
    00296                 if(m_vector.size() % 4 == 0) {                  //if the real under quartil between two values add this values and calculate the arithmetical middle.
    00297                         q = (*iter->pointer);
    00298                         iter--;
    00299                         q = add(q,(*iter->pointer));
    00300                         q = doubleMul(q,0.5);
    00301                 }
    00302                 else {                                                                  //else return the quartil
    00303                         q = (*iter->pointer);
    00304                 }
    00305
    00306                 return q;
    00307         }
    00308
    00309         /**
    00310          * this function calculate the upper quartil.
    00311          *
    00312          * use add and doubleMul
    00313          * @return the upper quartil
    00314          */
    00315         type getQuartil3() {
    00316                 type q;
    00317                 int x;
    00318                 int num = m_vector.size()*3/4;
    00319                 std::_List_iterator<TYPE_SAVE> iter;
    00320
    00321                 if(!m_listCreated)
    00322                         sort();                                                         //sort the set.
    00323
    00324                 iter = m_list.begin();
    00325                 for(x=0;x<num;x++) iter++;                              //go to the upper quartil
    00326
    00327                 if(m_vector.size() % 4 == 0) {                  //if the real upper quartil between two values add this values and calculate the arithmetical middle.
    00328                         q = (*iter->pointer);
    00329                         iter--;
    00330                         q = add(q,(*iter->pointer));
    00331                         q = doubleMul(q,0.5);
    00332                 }
    00333                 else {                                                                  //else return the quartil
    00334                         q = (*iter->pointer);
    00335                 }
    00336
    00337                 return q;
    00338         }
    00339
    00340         /**
    00341          * this function calculate the range between the upper and under quartil. This range is called inter-quartil-range.
    00342          *
    00343          * use sub
    00344          * @return the IQR
    00345          */
    00346         type getIQR() {
    00347                 type q1 = getQuartil1();                        //calculate the under quartil
    00348                 type q3 = getQuartil3();                        //calculate the upper quartil
    00349
    00350                 return sub(q3,q1);                                      //IQR = Q3 - Q1
    00351         }
    00352
    00353         /**
    00354          * this function calculate the whisker distance
    00355          *
    00356          * use doubleMul
    00357          * @param factor (double) the factor for this distance
    00358          * @return the result
    00359          */
    00360         type getWhisker(double factor) {
    00361                 type dIqr = getIQR();                   //calculate the IQR
    00362
    00363                 return doubleMul(dIqr,factor);  //WHISKER distance is factor*IQR
    00364         }
    00365
    00366         /**
    00367          * this function search the lowest value in the set which is from under quartil inside the whisker distance
    00368          *
    00369          * use sub, lower and zero
    00370          * @param factor (double) this factor is for calculating the whisker distance.
    00371          * @return the lowest value inside
    00372          */
    00373         type getWhisker1(double factor) {
    00374                 type dW = getWhisker(factor);                           //calculate the whisker distance
    00375                 type dQ1 = getQuartil1();                                       //calculate the under quartil
    00376                                                                                                         //TODO for optimization: getWhisker use getIQR and this calculate Q1 so it will be calculate two times!!!
    00377                 type dBorder = sub(dQ1,dW);                                     //where is the border for the lowest value
    00378                 std::_List_iterator<TYPE_SAVE> iter = m_list.begin();
    00379
    00380                 while(lower((*iter->pointer),dBorder) && iter!=m_list.end()) {          //search
    00381                         iter++;
    00382                         if(iter==m_list.end())
    00383                                 break;
    00384                 }
    00385
    00386                 if(iter==m_list.end())          // ERROR
    00387                         return zero();
    00388
    00389                 return (*iter->pointer);
    00390         }
    00391
    00392         /**
    00393          * this function search the highest value in the set which is from the upper quartil inside the whisker distance
    00394          *
    00395          * use add and lower
    00396          * @param factor (double) this factor is for calculating the whisker distance.
    00397          * @return the highest value inside
    00398          */
    00399         type getWhisker3(double factor) {
    00400                 type dW = getWhisker(factor);                           //calculate the whisker distance
    00401                 type dQ3 = getQuartil3();                                       //calculate the upper quartil
    00402                                                                                                         //TODO for optimization: getWhisker use getIQR and this calculate Q3 so it will be calculate two times!!!
    00403                 type dBorder = add(dQ3,dW);                                     //where is the border for the lowest value
    00404                 std::_List_iterator<TYPE_SAVE> iter = m_list.begin();
    00405
    00406                 while(lower((*iter->pointer),dBorder) && iter!=m_list.end()) {          //search
    00407                         iter++;
    00408                         if(iter==m_list.end())
    00409                                 break;
    00410                 }
    00411
    00412                 if(iter!=m_list.begin())
    00413                         iter--;
    00414
    00415                 return (*iter->pointer);
    00416         }
    00417
    00418         /**
    00419          * this function give you the number of elements in the giving set, which aren't in the whisker distance
    00420          *
    00421          * use lower and higher
    00422          * @param factor (double) this factor is for calculating the whisker distance
    00423          * @return (int) the number of extreme values in the set
    00424          */
    00425         unsigned int getNumExtrems(double factor) {
    00426                 unsigned int result = 0;
    00427                 type dW1 = getWhisker1(factor);                                                         //find W1
    00428                 type dW3 = getWhisker3(factor);                                                         //find W3
    00429                 std::_List_iterator<TYPE_SAVE> iter = m_list.begin();
    00430
    00431                 while(lower((*iter->pointer),dW1) && iter!=m_list.end()) {      //count all elements which are lower than W1
    00432                         iter++;
    00433                         if(iter==m_list.end())
    00434                                 break;
    00435                         result++;
    00436                 }
    00437
    00438                 while(!higher((*iter->pointer),dW3) && iter!=m_list.end()) {    //go from W1 to W3
    00439                         iter++;
    00440                         if(iter==m_list.end())
    00441                                 break;
    00442                 }
    00443
    00444                 while(iter!=m_list.end()) {                                                                     //count all element which are higher than W3
    00445                         iter++;
    00446                         result++;
    00447                 }
    00448
    00449                 return result;
    00450         }
    00451
    00452         /**
    00453          * this function gives one extreme value back
    00454          *
    00455          * use lower, higher and zero
    00456          * @param factor (double) the factor for the whisker distance
    00457          * @param i (unsigned int) the index of the searched extreme value
    00458          * @return the founded extreme value
    00459          */
    00460         type getExtrem(double factor, unsigned int i) {
    00461                 type dW1 = getWhisker1(factor);                                                 //find W1
    00462                 type dW3 = getWhisker3(factor);                                                 //find W3
    00463                 std::_List_iterator<TYPE_SAVE> iter = m_list.begin();
    00464
    00465                 while(lower((*iter->pointer),dW1) && iter!=m_list.end()) {                      //search in lower area
    00466                         i--;
    00467
    00468                         if(i==0)
    00469                                 return (*iter->pointer);
    00470
    00471                         iter++;
    00472                         if(iter==m_list.end())
    00473                                 break;
    00474                 }
    00475
    00476                 while(!higher((*iter->pointer),dW3) && iter!=m_list.end()) {            //go from W1 to W3
    00477                         iter++;
    00478                         if(iter==m_list.end())
    00479                                 break;
    00480                 }
    00481
    00482                 while(iter!=m_list.end()) {                                                                                     //search in upper area
    00483                         i--;
    00484
    00485                         if(i==0)
    00486                                 return (*iter->pointer);
    00487
    00488                         iter++;
    00489                 }
    00490
    00491                 return zero();          //not found                                                                             //if not found return zero
    00492         }
    00493
    00494         /**
    00495          * this function search the value which is next to zero.
    00496          *
    00497          * use zero, sub and lower
    00498          * @return the best value
    00499          */
    00500         type getBest(void) {
    00501                 type z = zero();                                                                                        //test value is zero
    00502                 type* l;
    00503                 type* h;
    00504
    00505                 if(!m_listCreated)
    00506                         sort();                                                                                                 //sort the list
    00507
    00508                 std::_List_iterator<TYPE_SAVE> iter = m_list.begin();
    00509
    00510                 while(lower((*iter->pointer),z) && iter!=m_list.end()) {        //search the element which is as first higher than zero
    00511                         iter++;
    00512                         if(iter==m_list.end())
    00513                                 break;
    00514                 }
    00515
    00516                 if(iter!=m_list.end())
    00517                         //return (*iter->pointer);
    00518                         h = iter->pointer;
    00519
    00520                 else {
    00521                         iter--;
    00522                         //return (*iter->pointer);
    00523                         h = iter->pointer;
    00524                 }
    00525
    00526                 while(!lower((*iter->pointer),z) && iter!= m_list.begin()) {    //search the element which is as first lower than zero
    00527                         iter--;
    00528                         if(iter==m_list.begin())
    00529                                 break;
    00530                 }
    00531
    00532                 l = iter->pointer;
    00533
    00534                 if(lower(sub(*h,z),sub(z,*l)))          //test which is next to zero
    00535                         return *h;
    00536                 else
    00537                         return *l;
    00538         }
    00539
    00540 protected:
    00541
    00542         /**
    00543          * help structur for sorting the set.
    00544          * define the lower than operator
    00545          */
    00546         struct TYPE_SAVE {
    00547                 TYPE_SAVE(type& a) : pointer(&a) {}
    00548
    00549                 type* pointer;
    00550
    00551                 bool operator<(const TYPE_SAVE& other) {
    00552                         return lower((*pointer),(*other.pointer));
    00553                 }
    00554         };
    00555
    00556         /**
    00557          * this vector save the giving set.
    00558          */
    00559         std::vector<type>& m_vector;
    00560
    00561         /**
    00562          * this list saves the sorted set
    00563          */
    00564         std::list<TYPE_SAVE> m_list;
    00565
    00566         /**
    00567          * this variable remember if the sorted list is created
    00568          */
    00569         bool m_listCreated;
    00570
    00571         /**
    00572          * this function create the sorted list
    00573          */
    00574         void sort(void) {
    00575                 __gnu_cxx::__normal_iterator<type*,std::vector<type,std::allocator<type> > > iter;
    00576
    00577                 for(iter = m_vector.begin(); iter != m_vector.end(); iter++) {                  //fill the sorted list with elements of the help structur
    00578                         m_list.push_back(TYPE_SAVE((*iter)));
    00579                 }
    00580
    00581                 m_list.sort();                          //sort the list
    00582                 m_listCreated = true;           //remember that it is created.
    00583         }
    00584 };
    00585
    00586 #endif /* TEMPLATEVALUEANALYSATION_H_ */