Generated on Tue Dec 16 13:34:01 2008 for ell-3.0.0 by doxygen 1.5.1

src/ell/LandscapeTopology.cc

Go to the documentation of this file.
00001 
00002 #include "ell/LandscapeTopology.hh"
00003 
00004 #include "biu/assertbiu.hh"
00005 
00006 #include <sstream>
00007 #include <vector>
00008 #include <iomanip>
00009 #include <cmath>
00010 #include <algorithm>
00011 
00012 namespace ell {
00013 
00015 
00016     const size_t 
00017     LandscapeTopology::
00018 	INVALID_INDEX = UINT_MAX;
00019     
00020     // Avogadro constant N_A = 6.02214179 * 10^(23)
00021     // unit : 1/mol
00022     const double
00023     LandscapeTopology::
00024 	AVOGADRO_CONSTANT_NA = 602214179000000000000000.0;
00025     
00026     // Gas constant R = 8.314472
00027     // unit : Joule / (Kelvin * mol)
00028     const double
00029     LandscapeTopology::
00030 	GAS_CONSTANT_R = 8.314472;
00031     
00032     // Boltzmann constant  = R / N_A = 1.3806504 * 10^(-23) 
00033     // unit : Joule / Kelvin
00034     const double
00035     LandscapeTopology::
00036 	BOLTZMANN_CONSTANT_KB = GAS_CONSTANT_R / AVOGADRO_CONSTANT_NA;
00037     
00038       // keyword used by the read and write method to identify information 
00039       // on the landscape topology type etc.
00040     const std::string 
00041     LandscapeTopology::
00042 	OUTPUT_KEY_ELL_HEAD = std::string("ELL_LT");
00043     
00044       // keyword used by the read and write method to identify information 
00045       // on a minimum
00046     const std::string 
00047     LandscapeTopology::
00048 	OUTPUT_KEY_MINIMUM = std::string("MINIMUM");
00049       // keyword used by the read and write method to identify information 
00050       // on a barrier
00051     const std::string 
00052     LandscapeTopology::
00053 	OUTPUT_KEY_BARRIER = std::string("BARRIER");
00054       // keyword used by the read and write method to identify information 
00055       // on a saddle point
00056     const std::string 
00057     LandscapeTopology::
00058 	OUTPUT_KEY_SADDLE = std::string("SADDLE");
00059     
00061     
00062     // temperature T = 37 Celsius = 310.15 Kelvin
00063     double 
00064     LandscapeTopology::
00065 	BOLTZMANN_KT = BOLTZMANN_CONSTANT_KB * 310.15;
00066 
00067     double 
00068     LandscapeTopology::
00069 	MISSING_MINIMUM_PENALTY = 1.0;
00070     
00071 
00073     LandscapeTopology::~LandscapeTopology() 
00074     
00075     {
00076     }
00077 
00078     
00080     // Calculates the relative 'distance' between landscape topologies.
00081     // On the LandscapeTopology level it is done on the minima only. For each
00082     // minimum m present in only one of the two LTs a value of 
00083     // MISSING_MINIMUM_PENALTY*(e^(-energy(m)/BOLTZMANN_KT)) 
00084     // @param lt the landscape topology to calculate the distance to
00085     // @return the distance
00086     double
00087     LandscapeTopology::
00088 	getDistance(const LandscapeTopology* const lt) const
00090     {
00091         assertbiu(lt!=NULL, "given LandscapeTopology to compare to is NULL!");
00092         
00093           // check if comparing with itself
00094         if (this == lt)
00095             return 0.0;
00096         
00097           // get access to all minima
00098         typedef std::vector<const State*> StateVec;
00099         StateVec m1(this->getMinCount(),NULL);
00100         for (size_t i=0; i<m1.size(); i++) {
00101             m1[i] = this->getMin(i);
00102         }
00103         StateVec m2(lt->getMinCount(),NULL);
00104         for (size_t i=0; i<m2.size(); i++) {
00105             m2[i] = lt->getMin(i);
00106         }
00107           // ensure that ordered
00108         if (!this->isSorted()) {
00109             std::sort(m1.begin(), m1.end(), State::less);
00110         }
00111         if (!lt->isSorted()) {
00112             std::sort(m2.begin(), m2.end(), State::less);
00113         }
00114         
00115           // calculate distance via helper function
00116         return getSortedMinimaDistance(m1,m2);
00117     }
00118     
00119     double
00120     LandscapeTopology::
00121 	getSortedMinimaDistance(   const std::vector<const State*> & m1,
00122                                 const std::vector<const State*> & m2 )
00124     {
00125         double dist = 0.0;
00126         size_t numOfDifferentMinima = 0;
00127         
00128           // check if one set is empty
00129         if (m1.size() == 0 || m2.size() == 0) {
00130               // set m to the non-empty one
00131             const std::vector<const State*> & m = (m1.size() == 0?m2:m1);
00132               // check if both are empty
00133             if (m.size() == 0)
00134                 return dist;
00135               // calc the penalty for all in the non-empty one
00136             for (size_t i=0; i<m.size(); i++) {
00137                 dist += MISSING_MINIMUM_PENALTY 
00138                         * exp( -(m[i]->getEnergy()) / BOLTZMANN_KT );
00139             }
00140             return dist / (double)m.size();
00141         }
00142         
00143           // find all minima that are unique in one of the two topologies
00144         size_t i1 = 0;  // current index in m1 that is checked
00145         size_t i2 = 0;  // current index in m2 that is checked
00146         while (i1<m1.size() && i2<m2.size()) {
00147             numOfDifferentMinima++;
00148             if (*m1[i1] == *m2[i2]) {
00149                   // minimum in both topologies present --> go to next
00150                 i1++;
00151                 i2++;
00152             } else if ( State::less(m1[i1],m2[i2]) ) {
00153                   // smaller minimum only in m1 present --> handle distance
00154                 dist += MISSING_MINIMUM_PENALTY 
00155                         * exp( -(m1[i1]->getEnergy()) / BOLTZMANN_KT );
00156                 i1++;
00157             } else {
00158                   // smaller minimum only in m2 present --> handle distance
00159                 dist += MISSING_MINIMUM_PENALTY 
00160                         * exp( -(m2[i2]->getEnergy()) / BOLTZMANN_KT );
00161                 i2++;
00162             }
00163         }
00164           // handle remaining minima only present in m1
00165         while (i1 < m1.size()) {
00166             numOfDifferentMinima++;
00167             dist += MISSING_MINIMUM_PENALTY 
00168                     * exp( -(m1[i1]->getEnergy()) / BOLTZMANN_KT );
00169             i1++;
00170         }
00171           // handle remaining minima only present in m2
00172         while (i2 < m1.size()) {
00173             numOfDifferentMinima++;
00174             dist += MISSING_MINIMUM_PENALTY 
00175                     * exp( -(m2[i2]->getEnergy()) / BOLTZMANN_KT );
00176             i2++;
00177         }
00178           // normalize distance sum by number of different minima present in both
00179         if (numOfDifferentMinima == 0)
00180             return dist;
00181         else
00182             return dist / (double)numOfDifferentMinima;
00183     }
00184     
00186     void
00187     LandscapeTopology::
00188 	writeHeader(   std::ostream & out, 
00189                     const std::string& LT_ID,
00190                     const size_t minNumber,
00191                     const std::string & StateDescription )
00193     {
00194         out <<"//" <<OUTPUT_KEY_ELL_HEAD <<"("
00195             <<LT_ID <<","
00196             <<minNumber <<","
00197             <<StateDescription 
00198             <<")\n";
00199     }
00200     
00202     std::pair<int,std::string>
00203     LandscapeTopology::
00204 	parseHeader(   const std::string& line, 
00205                     std::string& LT_ID,
00206                     size_t& minNumber,
00207                     std::string & StateDescription )
00209     {
00210         typedef std::pair<int,std::string> RETURNTYPE;
00211         size_t start=0, end=0;
00212         std::stringstream sstr;
00213         
00214           // check if this line really encodes a barrier
00215         start = line.find(OUTPUT_KEY_ELL_HEAD);
00216         if(start == std::string::npos) {
00217             sstr.clear();
00218             sstr <<"no header description in given line";
00219             return RETURNTYPE(-3,sstr.str());
00220         }
00221           // jump over leading '(' of content
00222         start += 1+OUTPUT_KEY_ELL_HEAD.size();
00223             
00224           // read LT_ID index
00225         start = line.find_first_not_of(' ',start);
00226         end = line.find_first_of(',',start);
00227         if (start == end || start == std::string::npos) {
00228             sstr.clear();
00229             sstr <<OUTPUT_KEY_ELL_HEAD <<" found but no LT_ID given";
00230             return RETURNTYPE(-3,sstr.str());
00231         }
00232         LT_ID = line.substr(start, end-start);
00233         
00234           // read minNumber
00235         start = line.find_first_not_of(' ',end+1);
00236         end = line.find_first_of(',',start);
00237         if (start == end || start == std::string::npos) {
00238             sstr.clear();
00239             sstr <<OUTPUT_KEY_ELL_HEAD
00240                 <<" found but no number of minima given";
00241             return RETURNTYPE(-1,sstr.str());
00242         }
00243         size_t num = INT_MAX;
00244         sstr.clear(); 
00245         sstr.str(line.substr(start, end-start));
00246         sstr >> num;
00247         if (num == INT_MAX) {
00248             sstr.clear();
00249             sstr <<OUTPUT_KEY_ELL_HEAD 
00250                 <<" found but minima number not parsable into integer";
00251             return RETURNTYPE(-1,sstr.str());
00252         }
00253         if (num < 0) {
00254             sstr.clear();
00255             sstr <<OUTPUT_KEY_ELL_HEAD 
00256                 <<" found but minima number smaller than zero";
00257             return RETURNTYPE(-1,sstr.str());
00258         }
00259         minNumber = num;
00260         
00261           // read StateDescriptor
00262         start = line.find_first_not_of(' ',end+1);
00263         end = line.find_last_of(')');
00264         end = line.find_last_not_of(' ', end);
00265         if (start >= end) {
00266             sstr.clear();
00267             sstr <<OUTPUT_KEY_ELL_HEAD 
00268                 <<" found but no state description given";
00269             return RETURNTYPE(-1,sstr.str());
00270         }
00271         StateDescription = line.substr(start, end-start);
00272 
00273           // no error occured so far --> return new connection state s 
00274         return RETURNTYPE(0,std::string(""));
00275     }
00276     
00278     void
00279     LandscapeTopology::
00280 	writeMinimum(  std::ostream & out, 
00281                     const State* const minimum,
00282                     const size_t index )
00284     {
00285         out << "//" <<OUTPUT_KEY_MINIMUM <<' '
00286             <<std::setw(7) <<index 
00287             <<std::setw(3)<<' '
00288             <<minimum->toString()
00289             <<"\n";
00290     }
00291 
00292     
00294     void
00295     LandscapeTopology::
00296 	writeMinimum(  std::ostream & out, 
00297                     const std::vector<const State*>& minima,
00298                     const size_t index )
00300     {
00301         out << "//" <<OUTPUT_KEY_MINIMUM <<' '
00302             <<std::setw(7) <<index 
00303             <<std::setw(3)<<' ';
00304          // write all minima to stream
00305         for (size_t i=0; i<minima.size(); i++) {
00306             out <<minima[i]->toString() <<' ';
00307         }
00308         out <<"\n";
00309     }
00310 
00311 
00313     std::pair<int,std::string>
00314     LandscapeTopology::
00315 	parseMinimum(  LandscapeTopology & toFill,
00316                     const std::string & line, 
00317                     const State * const templateState,
00318                     Int2SizeT_MAP & idx2min  )
00320     {
00321         typedef std::pair<int,std::string> RETURNTYPE;
00322         size_t start=0, end=0;
00323         State* s = NULL;
00324         std::stringstream sstr;
00325         
00326           // check if this line really encodes a barrier
00327         start = line.find(OUTPUT_KEY_MINIMUM);
00328         if(start == std::string::npos) {
00329             sstr.clear();
00330             sstr <<"no minimum description";
00331             return RETURNTYPE(-3,sstr.str());
00332         }
00333             
00334           // read minimum index
00335         start = line.find_first_not_of(' ',start+7);
00336         if (start == std::string::npos) {
00337             sstr.clear();
00338             sstr <<OUTPUT_KEY_MINIMUM <<" found but no index given";
00339             return RETURNTYPE(-3,sstr.str());
00340         }
00341         end = line.find_first_of(' ',start);
00342         int idx = INT_MAX;
00343         sstr.clear(); 
00344         sstr.str(line.substr(start, end-start));
00345         sstr >> idx;
00346         if (idx == INT_MAX) {
00347             sstr.clear();
00348             sstr <<OUTPUT_KEY_MINIMUM 
00349                 <<" found but index not parsable into integer";
00350             return RETURNTYPE(-3,sstr.str());
00351         }
00352         if (idx2min.find(idx) != idx2min.end()) {
00353             sstr.clear();
00354             sstr <<OUTPUT_KEY_MINIMUM <<" index '"
00355                 <<idx
00356                 <<"' was used before (not unique)";
00357             return RETURNTYPE(-3,sstr.str());
00358         }
00359         
00360           // read first string representation from minima state list
00361           // and add to tree
00362         start = line.find_first_not_of(' ',end);
00363         if (start == std::string::npos) {
00364             sstr.clear();
00365             sstr <<OUTPUT_KEY_MINIMUM 
00366                 <<" found but no state string representation given";
00367             return RETURNTYPE(-3,sstr.str());
00368         }
00369         end = line.find_first_of(' ',start+1);
00370         
00371           // create new state
00372         s = templateState->fromString( line.substr(start, end-start) );
00373         if(s == NULL) {
00374                 sstr.clear();
00375                 sstr <<OUTPUT_KEY_MINIMUM 
00376                     <<" state could not be generated from string representation";
00377             return RETURNTYPE(-3,sstr.str());
00378         }
00379           // add the new minimum to the landscape and store the mapping
00380         idx2min[idx] = toFill.addMin(s);
00381         
00382           // garbage collection
00383         if (s != NULL) {
00384             delete s;
00385             s = NULL;
00386         }
00387           // no error occured so far, return remaining line content
00388         if (end < line.size()) {
00389             return RETURNTYPE(0,line.substr(end));
00390         } else {
00391             return RETURNTYPE(0,std::string(""));
00392         }
00393     }
00394     
00396     void
00397     LandscapeTopology::
00398 	writeBarrier(  std::ostream & out, 
00399                     const State* const barrier,
00400                     const size_t index,
00401                     const std::vector<size_t> & minConnected )
00403     {
00404         writeConnection(    out
00405                             , barrier
00406                             , index
00407                             , minConnected
00408                             , OUTPUT_KEY_BARRIER );
00409     }
00410 
00412     void
00413     LandscapeTopology::
00414 	writeSaddle(   std::ostream & out, 
00415                     const State* const saddle,
00416                     const size_t index,
00417                     const std::vector<size_t> & minConnected )
00419     {
00420         writeConnection(    out
00421                             , saddle
00422                             , index
00423                             , minConnected
00424                             , OUTPUT_KEY_SADDLE );
00425     }
00426 
00428     void
00429     LandscapeTopology::
00430 	writeConnection(   std::ostream & out, 
00431                         const State* const conState,
00432                         const size_t index,
00433                         const std::vector<size_t> & minConnected,
00434                         const std::string& connectionKey )
00436     {
00437         assertbiu(conState!=NULL, "no connection state given (==NULL)");
00438         
00439           // print connection index
00440         out << "//" <<connectionKey<<" " <<std::setw(7) <<index
00441             <<std::setw(3)<<" ";
00442           // print connected minima
00443         for (std::vector<size_t>::const_iterator it = minConnected.begin();
00444                 it != minConnected.end(); it++) 
00445         {
00446             out <<(*it) <<" ";
00447         }
00448           // print connection object
00449         out <<conState->toString()
00450             <<"\n";
00451 
00452     }
00453 
00454 
00456     std::pair<int,std::string>
00457     LandscapeTopology::
00458 	parseBarrier(  LandscapeTopology & toFill,
00459                     const std::string & line, 
00460                     const State * const templateState,
00461                     const Int2SizeT_MAP & idx2min  )
00463     {
00464         std::vector<size_t> minima;
00465         
00466           // forward parsing to non-specific member
00467         std::pair<State*,std::string> parseResult
00468             = parseConnection(  line
00469                                 , templateState
00470                                 , idx2min 
00471                                 , OUTPUT_KEY_BARRIER
00472                                 , minima );
00473         
00474           // check if a parsing error occured
00475         if (parseResult.first == NULL) {
00476             return std::pair<int,std::string>(-3, parseResult.second);
00477         }
00478         
00479           // add barrier to the landscape (only FIRST to ALL)
00480         size_t m0 = idx2min.find(minima[0])->second; 
00481         for (size_t m=1; m<minima.size(); m++) {
00482             toFill.addSaddle(   m0
00483                                 , idx2min.find(minima[m])->second
00484                                 , parseResult.first );
00485         }
00486 
00487           // parsing was successfull
00488         return std::pair<int,std::string>(0,std::string(""));
00489     }
00490         
00492     std::pair<int,std::string>
00493     LandscapeTopology::
00494 	parseSaddle(   LandscapeTopology & toFill,
00495                     const std::string & line, 
00496                     const State * const templateState,
00497                     const Int2SizeT_MAP & idx2min  )
00499     {
00500         
00501         std::vector<size_t> minima;
00502         
00503           // forward parsing to non-specific member
00504         std::pair<State*,std::string> parseResult 
00505             = parseConnection(  line
00506                                 , templateState
00507                                 , idx2min 
00508                                 , OUTPUT_KEY_SADDLE
00509                                 , minima );
00510         
00511           // check if a parsing error occured
00512         if (parseResult.first == NULL) {
00513             return std::pair<int,std::string>(-3, parseResult.second);
00514         }
00515         
00516           // add the saddle to the landscape (all to all)
00517         for (size_t m1=0; m1<minima.size(); m1++) {
00518             for (size_t m2=m1+1; m2<minima.size(); m2++) {
00519                 toFill.addSaddle(   idx2min.find(minima[m1])->second
00520                                     , idx2min.find(minima[m2])->second
00521                                     , parseResult.first );
00522             }
00523         }
00524 
00525           // parsing was successfull
00526         return std::pair<int,std::string>(0,std::string(""));
00527     }
00528         
00529 
00531     std::pair<State*,std::string>
00532     LandscapeTopology::
00533 	parseConnection(   const std::string & line, 
00534                         const State * const templateState,
00535                         const Int2SizeT_MAP & idx2min,
00536                         const std::string& connectionKey,
00537                         std::vector<size_t> & minima )
00539     {
00540         
00541         typedef std::pair<State*,std::string> RETURNTYPE;
00542         size_t start=0, end=0;
00543         State* s = NULL;
00544         std::stringstream sstr;
00545         
00546           // clear output parameter where the minima are stored 
00547         minima.clear();
00548         
00549           // check if this line really encodes a connection of the given type
00550         start = line.find(connectionKey);
00551         if(start == std::string::npos) {
00552             sstr.clear();
00553             sstr <<"no " <<connectionKey
00554                 <<" connection description present";
00555             return RETURNTYPE(NULL,sstr.str());
00556         }
00557         
00558           // read connection index
00559         start = line.find_first_not_of(' ',start+connectionKey.size());
00560         if (start == std::string::npos) {
00561             sstr.clear();
00562             sstr <<connectionKey
00563                 <<" found but no connection index given";
00564             return RETURNTYPE(NULL,sstr.str());
00565         }
00566         end = line.find_first_of(' ',start);
00567         size_t idx = INT_MAX;
00568         sstr.clear(); 
00569         sstr.str(line.substr(start, end-start));
00570         sstr >> idx;
00571         if (idx == INT_MAX) {
00572             sstr.clear();
00573             sstr <<connectionKey 
00574                 <<" found but connection index not parsable into integer";
00575             return RETURNTYPE(NULL,sstr.str());
00576         }
00577         
00578           // find substring that contains connection State string representation
00579         size_t s_end = line.find_last_not_of(' ')+1;
00580         if (s_end < end) {
00581             sstr.clear();
00582             sstr <<connectionKey 
00583                 <<" found but no state string representation given";
00584             return RETURNTYPE(NULL,sstr.str());
00585         }
00586         size_t s_start = line.find_last_of(' ', s_end -1) +1;
00587         
00588           // read first string representation and add to tree
00589           // create new state
00590         s = templateState->fromString( line.substr(s_start, s_end-s_start) );
00591         if(s == NULL) {
00592                 sstr.clear();
00593                 sstr <<connectionKey 
00594                     <<" state could not be generated from string representation";
00595             return RETURNTYPE(NULL,sstr.str());
00596         }
00597         
00598           // get all minima to add barriers for
00599           // get string limits that hold all minima
00600         start = line.find_first_not_of(' ', end);
00601         end = line.find_last_not_of(' ', s_start -1)+1;
00602         if (start >= end) {
00603                 sstr.clear();
00604                 sstr <<connectionKey 
00605                     <<" found but no minima that are connected given";
00606                 delete s;
00607                 return RETURNTYPE(NULL,sstr.str());
00608         }
00609         sstr.clear();
00610         sstr.str(line.substr(start, end-start));
00611           // read all minima
00612         while (!sstr.fail()) {
00613             idx = INT_MAX;
00614             sstr >>idx;
00615             if (idx != INT_MAX) {
00616                 if (idx2min.find(idx) == idx2min.end()) {
00617                         sstr.clear();
00618                         sstr <<connectionKey 
00619                             <<" found but connected minimum '"
00620                             <<idx <<"' not known so far";
00621                         delete s;
00622                         return RETURNTYPE(NULL,sstr.str());
00623                 }
00624                 minima.push_back(idx);
00625             } else {
00626                 break;
00627             }
00628         }
00629         if (minima.size() == 0) {
00630                 sstr.clear();
00631                 sstr <<connectionKey 
00632                     <<" found but minima indices are not parsable";
00633                 delete s;
00634                 return RETURNTYPE(NULL,sstr.str());
00635         } else if (minima.size() == 1) {
00636                 sstr.clear();
00637                 sstr <<connectionKey 
00638                     <<" found but only ONE minimum index was parsable";
00639                 delete s;
00640                 return RETURNTYPE(NULL,sstr.str());
00641         }
00642         
00643           // no error occured so far --> return new connection state s 
00644         return RETURNTYPE(s,std::string(""));
00645     }
00646 
00647 } // namespace ell
00648