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
00021
00022 const double
00023 LandscapeTopology::
00024 AVOGADRO_CONSTANT_NA = 602214179000000000000000.0;
00025
00026
00027
00028 const double
00029 LandscapeTopology::
00030 GAS_CONSTANT_R = 8.314472;
00031
00032
00033
00034 const double
00035 LandscapeTopology::
00036 BOLTZMANN_CONSTANT_KB = GAS_CONSTANT_R / AVOGADRO_CONSTANT_NA;
00037
00038
00039
00040 const std::string
00041 LandscapeTopology::
00042 OUTPUT_KEY_ELL_HEAD = std::string("ELL_LT");
00043
00044
00045
00046 const std::string
00047 LandscapeTopology::
00048 OUTPUT_KEY_MINIMUM = std::string("MINIMUM");
00049
00050
00051 const std::string
00052 LandscapeTopology::
00053 OUTPUT_KEY_BARRIER = std::string("BARRIER");
00054
00055
00056 const std::string
00057 LandscapeTopology::
00058 OUTPUT_KEY_SADDLE = std::string("SADDLE");
00059
00061
00062
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
00081
00082
00083
00084
00085
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
00094 if (this == lt)
00095 return 0.0;
00096
00097
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
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
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
00129 if (m1.size() == 0 || m2.size() == 0) {
00130
00131 const std::vector<const State*> & m = (m1.size() == 0?m2:m1);
00132
00133 if (m.size() == 0)
00134 return dist;
00135
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
00144 size_t i1 = 0;
00145 size_t i2 = 0;
00146 while (i1<m1.size() && i2<m2.size()) {
00147 numOfDifferentMinima++;
00148 if (*m1[i1] == *m2[i2]) {
00149
00150 i1++;
00151 i2++;
00152 } else if ( State::less(m1[i1],m2[i2]) ) {
00153
00154 dist += MISSING_MINIMUM_PENALTY
00155 * exp( -(m1[i1]->getEnergy()) / BOLTZMANN_KT );
00156 i1++;
00157 } else {
00158
00159 dist += MISSING_MINIMUM_PENALTY
00160 * exp( -(m2[i2]->getEnergy()) / BOLTZMANN_KT );
00161 i2++;
00162 }
00163 }
00164
00165 while (i1 < m1.size()) {
00166 numOfDifferentMinima++;
00167 dist += MISSING_MINIMUM_PENALTY
00168 * exp( -(m1[i1]->getEnergy()) / BOLTZMANN_KT );
00169 i1++;
00170 }
00171
00172 while (i2 < m1.size()) {
00173 numOfDifferentMinima++;
00174 dist += MISSING_MINIMUM_PENALTY
00175 * exp( -(m2[i2]->getEnergy()) / BOLTZMANN_KT );
00176 i2++;
00177 }
00178
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
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
00222 start += 1+OUTPUT_KEY_ELL_HEAD.size();
00223
00224
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
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
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
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
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
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
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
00361
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
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
00380 idx2min[idx] = toFill.addMin(s);
00381
00382
00383 if (s != NULL) {
00384 delete s;
00385 s = NULL;
00386 }
00387
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
00440 out << "//" <<connectionKey<<" " <<std::setw(7) <<index
00441 <<std::setw(3)<<" ";
00442
00443 for (std::vector<size_t>::const_iterator it = minConnected.begin();
00444 it != minConnected.end(); it++)
00445 {
00446 out <<(*it) <<" ";
00447 }
00448
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
00467 std::pair<State*,std::string> parseResult
00468 = parseConnection( line
00469 , templateState
00470 , idx2min
00471 , OUTPUT_KEY_BARRIER
00472 , minima );
00473
00474
00475 if (parseResult.first == NULL) {
00476 return std::pair<int,std::string>(-3, parseResult.second);
00477 }
00478
00479
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
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
00504 std::pair<State*,std::string> parseResult
00505 = parseConnection( line
00506 , templateState
00507 , idx2min
00508 , OUTPUT_KEY_SADDLE
00509 , minima );
00510
00511
00512 if (parseResult.first == NULL) {
00513 return std::pair<int,std::string>(-3, parseResult.second);
00514 }
00515
00516
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
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
00547 minima.clear();
00548
00549
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
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
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
00589
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
00599
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
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
00644 return RETURNTYPE(s,std::string(""));
00645 }
00646
00647 }
00648