PostureTransition.cc

00001 /* -*- mode:c++ -*- ********************************************************
00002  * file:        PostureTransition.cc
00003  *
00004  * author:      Majid Nabi <m.nabi@tue.nl>
00005  *
00006  *              http://www.es.ele.tue.nl/nes
00007  *
00008  *
00009  * copyright:   (C) 2010 Electronic Systems group(ES),
00010  *              Eindhoven University of Technology (TU/e), the Netherlands.
00011  *
00012  *
00013  *              This program is free software; you can redistribute it
00014  *              and/or modify it under the terms of the GNU General Public
00015  *              License as published by the Free Software Foundation; either
00016  *              version 2 of the License, or (at your option) any later
00017  *              version.
00018  *              For further information see file COPYING
00019  *              in the top level directory
00020  ***************************************************************************
00021  * part of:    MoBAN (Mobility Model for wireless Body Area Networks)
00022  * description: A class to manage and store the posture transition matrices
00023  ***************************************************************************
00024  * Citation of the following publication is appreciated if you use MoBAN for
00025  * a publication of your own.
00026  *
00027  * M. Nabi, M. Geilen, T. Basten. MoBAN: A Configurable Mobility Model for Wireless Body Area Networks.
00028  * In Proc. of the 4th Int'l Conf. on Simulation Tools and Techniques, SIMUTools 2011, Barcelona, Spain, 2011.
00029  *
00030  * BibTeX:
00031  *    @inproceedings{MoBAN,
00032  *    author = "M. Nabi and M. Geilen and T. Basten.",
00033  *    title = "{MoBAN}: A Configurable Mobility Model for Wireless Body Area Networks.",
00034  *      booktitle = "Proceedings of the 4th Int'l Conf. on Simulation Tools and Techniques.",
00035  *      series = {SIMUTools '11},
00036  *      isbn = {978-963-9799-41-7},
00037  *      year = {2011},
00038  *      location = {Barcelona, Spain},
00039  *      publisher = {ICST} }
00040  *
00041  **************************************************************************/
00042 
00043 
00044 
00045 #include <PostureTransition.h>
00046 #include <stdio.h>
00047 #include <string.h>
00048 #include <FWMath.h>
00049 #include <assert.h>
00050 
00056 PostureTransition::PostureTransition(int numPosture)
00057 {
00058   numPos = numPosture;
00059   defaultMatrixID = 0; // if no default matrix found, the first one will be supposed as the default matrix.
00060 }
00061 
00066 int PostureTransition::addMatrix(std::string name, double** matrix, bool thisDefault)
00067 {
00068 
00069   //check if the name is repetitive
00070   TransMatrixList::const_iterator matrixIt;
00071   for (matrixIt = matrixList.begin(); matrixIt != matrixList.end(); matrixIt++)
00072   {
00073     if ((*matrixIt)->name == name )
00074     {
00075       std::string str = "There are multiple matrices with the same name: " + name + " in the configuration file!";
00076       opp_error (str.c_str());
00077     }
00078   }
00079 
00080 
00081   // verify if the given matrix is Markovian
00082   if ( !isMarkovian(matrix) )
00083   {
00084     std::string str = "Given transition matrix " + name + " is not Markovian!";
00085     opp_error (str.c_str());
00086   }
00087 
00088   TransMatrix* mat = new TransMatrix;
00089 
00090   mat->name = name;
00091   mat->matrix = new double* [numPos];
00092   for (int i=0;i<numPos;++i)
00093   {
00094     mat->matrix[i] = new double [numPos];
00095     for (int j=0;j<numPos;++j)
00096       mat->matrix[i][j] = matrix[i][j];
00097   }
00098 
00099   matrixList.push_back(mat);
00100 
00101   if (thisDefault)
00102     defaultMatrixID = matrixList.size()-1;
00103 
00104   return 0;
00105 }
00106 
00112 int PostureTransition::addSteadyState(std::string name, double* iVector)
00113 {
00114   //check if the name is repetitive
00115   TransMatrixList::const_iterator matrixIt;
00116   for (matrixIt = matrixList.begin(); matrixIt != matrixList.end(); matrixIt++)
00117   {
00118     if ((*matrixIt)->name == name )
00119     {
00120       std::string str = "There are multiple matrices with the same name: " + name + " in the configuration file!";
00121       opp_error (str.c_str());
00122     }
00123   }
00124 
00125   // check if the given matrix is Markovian
00126   if ( !isMarkovian(iVector) )
00127   {
00128     std::string str = "Given steady state vector " + name + " cannot be true!";
00129     opp_error (str.c_str());
00130   }
00131 
00132   // make a local copy of the input steady state vector
00133   double *steady = new double[numPos];
00134   for (int i=0; i < numPos; ++i)
00135     steady[i] = iVector[i];
00136 
00137   TransMatrix* mat = new TransMatrix;
00138   mat->name = name;
00139   mat->matrix = extractMatrixFromSteadyState(steady);
00140 
00141   matrixList.push_back(mat);
00142 
00143   return 0;
00144 }
00145 
00150 int PostureTransition::addAreaType(std::string name)
00151 {
00152 
00153   //Check if the name is repetitive
00154   AreaTypeList::const_iterator areaIt;
00155   for (areaIt = areaTypeList.begin(); areaIt != areaTypeList.end(); areaIt++)
00156   {
00157     if ((*areaIt)->name == name )
00158     {
00159       std::string str = "There are multiple area types with the same name: " + name + " in the configuration file!";
00160       opp_error (str.c_str());
00161     }
00162   }
00163 
00164   AreaType* area = new AreaType;
00165   area->name = name;
00166   areaTypeList.push_back(area);
00167   return areaTypeList.size()-1;
00168 }
00169 
00173 bool PostureTransition::setAreaBoundry(int id, Coord lowBound, Coord highBound)
00174 {
00175   AreaBound* bound=new AreaBound;
00176   bound->low = lowBound;
00177   bound->high = highBound;
00178 
00179   areaTypeList.at(id)->boundries.push_back(bound);
00180 
00181   return true;
00182 }
00183 
00188 int PostureTransition::addTimeDomain(std::string name)
00189 {
00190   //Check if the name is repetitive
00191   TimeDomainList::const_iterator timeIt;
00192   for (timeIt = timeDomainList.begin(); timeIt != timeDomainList.end(); timeIt++)
00193   {
00194     if ((*timeIt)->name == name )
00195     {
00196       std::string str = "There are multiple time domains with the same name: " + name + " in the configuration file!";
00197       opp_error (str.c_str());
00198     }
00199   }
00200 
00201   TimeDomainType* time = new TimeDomainType;
00202   time->name = name;
00203   timeDomainList.push_back(time);
00204   return timeDomainList.size()-1;
00205 }
00206 
00210 bool PostureTransition::setTimeBoundry(int id, simtime_t lowBound, simtime_t highBound)
00211 {
00212   TimeBound* bound=new TimeBound;
00213   bound->low = lowBound;
00214   bound->high = highBound;
00215 
00216   timeDomainList.at(id)->boundries.push_back(bound);
00217 
00218   return true;
00219 }
00220 
00227 bool PostureTransition::addCombination(std::string areaName,std::string timeName,std::string matrixName)
00228 {
00229   int thisID;
00230   CombinationType* comb = new CombinationType;
00231   comb->areaID = -1;
00232   comb->timeID = -1;
00233   comb->matrixID = -1;
00234 
00235   // look for matching area type name.
00236   thisID = 0;
00237   AreaTypeList::const_iterator areaIt;
00238   for (areaIt = areaTypeList.begin(); areaIt != areaTypeList.end(); areaIt++)
00239   {
00240     if (areaName == (*areaIt)->name )
00241     {
00242       comb->areaID = thisID;
00243       break;
00244     }
00245     ++thisID;
00246   }
00247 
00248   // in the input name is empty, it means that no area type is specified for this combination.
00249   if (comb->areaID == -1 && !areaName.empty())
00250   {
00251     std::string str = "Undefined area type name is given in a combinations: " + areaName + ", " + timeName + ", " + matrixName;
00252     opp_error (str.c_str());
00253   }
00254 
00255 
00256   // look for matching time domain name.
00257   thisID = 0;
00258   TimeDomainList::const_iterator timeIt;
00259   for (timeIt = timeDomainList.begin(); timeIt != timeDomainList.end(); timeIt++)
00260   {
00261     if (timeName == (*timeIt)->name )
00262     {
00263       comb->timeID = thisID;
00264       break;
00265     }
00266     ++thisID;
00267   }
00268   if (comb->timeID == -1 && !timeName.empty())
00269   {
00270     std::string str = "Undefined time domain name is given in a combinations: " + areaName + ", " + timeName + ", " + matrixName;
00271     opp_error (str.c_str());
00272   }
00273 
00274 
00275   if (comb->areaID == -1 && comb->timeID == -1)
00276     opp_error ("Both area type and time domain is unspecified in a combination." );
00277 
00278   // look for matching transition matrix name.
00279   thisID = 0;
00280   TransMatrixList::const_iterator matrixIt;
00281   for (matrixIt = matrixList.begin(); matrixIt != matrixList.end(); matrixIt++)
00282   {
00283     if (matrixName == (*matrixIt)->name )
00284     {
00285       comb->matrixID = thisID;
00286       break;
00287     }
00288     ++thisID;
00289   }
00290   if (comb->matrixID == -1)
00291     opp_error ("Undefined matrix name is given in the combinations" );
00292 
00293   combinationList.push_back(comb);
00294 
00295   return true;
00296 }
00297 
00303 double** PostureTransition::getMatrix(simtime_t iTime, Coord iLocation)
00304 {
00305   int timeID,locationID,matrixID;
00306 
00307   timeID = findTimeDomain(iTime);
00308   locationID = findAreaType(iLocation);
00309 
00310 
00311   matrixID = defaultMatrixID;
00312 
00313   CombinationList::const_iterator combIt;
00314   for (combIt = combinationList.begin(); combIt != combinationList.end(); combIt++)
00315   {
00316     if ( (*combIt)->timeID == timeID && (*combIt)->areaID == locationID)
00317     {
00318       matrixID = (*combIt)->matrixID;
00319       break;
00320     }
00321   }
00322 
00323   EV << "The corresponding Markov matrix for time" << iTime.dbl() <<" and location " << iLocation.info() << " is: " << matrixList.at(matrixID)->name << endl;
00324 
00325   return matrixList.at(matrixID)->matrix;
00326 }
00327 
00332 int PostureTransition::findTimeDomain(simtime_t iTime)
00333 {
00334   int timeID=0;
00335   TimeDomainList::const_iterator timeIt;
00336   for (timeIt = timeDomainList.begin(); timeIt != timeDomainList.end(); timeIt++)
00337   {
00338     std::vector<TimeBound*> boundList = (*timeIt)->boundries;
00339 
00340     std::vector<TimeBound*>::const_iterator bound;
00341     for (bound = boundList.begin(); bound != boundList.end(); bound++)
00342     {
00343       if ( iTime >= (*bound)->low && iTime < (*bound)->high)
00344         return timeID;
00345     }
00346     ++timeID;
00347   }
00348   EV << "Time domain not found" << endl;
00349   return -1;
00350 }
00351 
00356 int PostureTransition::findAreaType(Coord iLocation)
00357 {
00358   int locationID=0;
00359   AreaTypeList::const_iterator areaIt;
00360   for (areaIt = areaTypeList.begin(); areaIt != areaTypeList.end(); areaIt++)
00361   {
00362     std::vector<AreaBound*> boundList = (*areaIt)->boundries;
00363 
00364     std::vector<AreaBound*>::const_iterator bound;
00365     for (bound = boundList.begin(); bound != boundList.end(); bound++)
00366     {
00367       if ( iLocation.isInBoundary( (*bound)->low ,(*bound)->high ) )
00368         return locationID;
00369     }
00370     ++locationID;
00371   }
00372   EV << "Area Type not found" << endl;
00373   return -1;
00374 }
00375 
00380 bool PostureTransition::isMarkovian(double** matrix)
00381 {
00382   double sumCol;
00383   for (int j=0;j<numPos;++j)
00384   {
00385     sumCol = 0;
00386     for (int i=0;i<numPos;++i)
00387     {
00388       if (matrix[i][j] < 0 || matrix[i][j] > 1)
00389         return false;
00390       sumCol += matrix[i][j];
00391     }
00392 
00393     if (!FWMath::close(sumCol , 1.0 ))
00394       return false;
00395   }
00396 
00397   return true;
00398 }
00399 
00404 bool PostureTransition::isMarkovian(double* vec)
00405 {
00406   double sumCol=0;
00407   for (int i=0;i<numPos;++i)
00408   {
00409     if (vec[i] < 0 || vec[i]> 1)
00410       return false;
00411     sumCol += vec[i];
00412   }
00413 
00414   if ( !FWMath::close(sumCol , 1.0 ) )
00415     return false;
00416   else
00417     return true;
00418 }
00419 
00423 void PostureTransition::multMatrix(double** mat1, double** mat2,double** res)
00424 {
00425 
00426   int i,j,l;
00427   for(i=0; i < numPos; i++)
00428   {
00429     for(j=0; j < numPos ; j++)
00430     {
00431       res[i][j]=0;
00432       for(l=0; l < numPos ; l++)
00433         res[i][j] += mat1[i][l] * mat2[l][j];
00434     }
00435   }
00436 
00437 }
00438 
00442 void PostureTransition::addMatrix(double** mat1, double** mat2,double** res)
00443 {
00444   int i,j;
00445   for(i=0; i < numPos; i++)
00446   {
00447     for(j=0; j < numPos ; j++)
00448       res[i][j] = mat1[i][j] + mat2[i][j];
00449   }
00450 
00451 }
00452 
00456 void PostureTransition::subtractMatrix(double** mat1, double** mat2,double** res)
00457 {
00458   int i,j;
00459   for(i=0; i < numPos; i++)
00460   {
00461     for(j=0; j < numPos ; j++)
00462       res[i][j] = mat1[i][j] - mat2[i][j];
00463   }
00464 
00465 }
00466 
00470 void PostureTransition::multVector(double* vec,double** res)
00471 {
00472   int i,j;
00473   for(i=0; i < numPos; i++)
00474   {
00475     for(j=0; j < numPos ; j++)
00476       res[i][j] = vec[i] * vec[j];
00477   }
00478 
00479 }
00480 
00485 double** PostureTransition::extractMatrixFromSteadyState(double* vec)
00486 {
00487   int i,j;
00488   double** dafaultMat;
00489 
00490   //make output matrix and an identity matrix and a temp
00491   double** mat= new double* [numPos];
00492   double** temp1= new double* [numPos];
00493   double** temp2= new double* [numPos];
00494   double** temp3= new double* [numPos];
00495   double** identity = new double* [numPos];
00496   int** change = new int* [numPos];
00497   for (int i=0;i<numPos;++i)
00498   {
00499     mat[i] = new double [numPos];
00500     temp1[i] = new double [numPos];
00501     temp2[i] = new double [numPos];
00502     temp3[i] = new double [numPos];
00503     identity[i] = new double [numPos];
00504     change[i] = new int [numPos];
00505 
00506   }
00507 
00508   for(i=0; i < numPos; i++)
00509     for(j=0; j < numPos ; j++)
00510       if (i==j)
00511         identity[i][j] = 1;
00512       else
00513         identity[i][j] = 0;
00514 
00515 
00516   double* sum= new double [numPos];
00517   int* changeSum= new int [numPos];
00518 
00519 
00520   dafaultMat = matrixList.at(defaultMatrixID)->matrix;
00521 
00522 
00523   for (int numTry=0;numTry<400;++numTry)
00524   {
00525     subtractMatrix(identity,dafaultMat,temp1);
00526     multVector(vec,temp2);
00527     multMatrix(temp1,temp2,temp3);
00528     addMatrix(dafaultMat,temp3,mat);
00529 
00530     //remember if it has not changed
00531     for(i=0; i < numPos; i++)
00532       for(j=0; j < numPos ; j++)
00533         change[i][j] = 1;
00534 
00535     for(j=0; j < numPos; j++)
00536       for(i=0; i < numPos ; i++)
00537       {
00538         if ( mat[i][j] < 0 ){
00539           mat[i][j] = 0;
00540           change[i][j]=0;
00541         }
00542         if ( mat[i][j] > 1 ){
00543           mat[i][j] = 1;
00544           change[i][j]=0;
00545         }
00546       }
00547 
00548 
00549     for(j=0; j < numPos; j++)
00550     {
00551       sum[j] = 0;
00552       changeSum[j]=0;
00553       for(i=0; i < numPos ; i++)
00554       {
00555         sum[j] += mat[i][j];
00556         changeSum[j] += change[i][j];
00557       }
00558     }
00559 
00560     for(j=0; j < numPos; j++)
00561       for(i=0; i < numPos ; i++)
00562       {
00563         if (change[i][j] == 1)
00564           mat[i][j] = mat[i][j]+ (1-sum[j])/changeSum[j];
00565       }
00566 
00567     dafaultMat = mat;
00568   }
00569 
00570   for(j=0; j < numPos; j++)
00571     for(i=0; i < numPos ; i++)
00572     {
00573       if ( mat[i][j] < 0 )
00574         mat[i][j] = 0;
00575       if ( mat[i][j] > 1 )
00576         mat[i][j] = 1;
00577     }
00578 
00579 
00580   EV << "Generated Markov matrix from the steady state: "<< endl;
00581   for (int k=0;k < numPos; ++k)
00582   {
00583     for (int f=0; f<numPos ;++f)
00584       EV << mat[k][f]<<"       ";
00585     EV << endl;
00586   }
00587 
00588   for (int i=0;i<numPos;++i)
00589   {
00590     delete temp1[i]; delete temp2[i]; delete temp3[i];
00591     delete identity[i];
00592     delete change[i];
00593   }
00594   delete temp1; delete temp2; delete temp3;
00595   delete identity;
00596   delete change;
00597   delete sum;
00598   delete changeSum;
00599 
00600 
00601   return mat;
00602 }