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

src/ell/Basin.cc

Go to the documentation of this file.
00001 
00002 #include "ell/Basin.hh"
00003 #include <biu/assertbiu.hh>
00004 
00005 //##############################################################################
00006 //##############################################################################
00007 
00008 namespace ell
00009 {
00010 
00011     Basin::~Basin()
00012     {}
00013 
00014 
00015 } // namespace ell
00016 
00017 //##############################################################################
00018 //##############################################################################
00019 
00020 #include "ell/util/PriorityQueue.hh"
00021 #include <list>
00022 
00023 namespace ell {
00024 
00025     Basin_FME::QueueVal::QueueVal()
00026      :  minNeigh(), minNeighE(0.0), minNeighGWE(UINT_MAX)
00027     {
00028     }
00029     
00030     Basin_FME::QueueVal::~QueueVal()
00031     {
00032     }
00033 
00034 
00035     Basin_FME::Basin_FME(   const double maxE_, 
00036                     const double deltaE_, 
00037                     const size_t maxToStore_)
00038       : maxE(maxE_),
00039         deltaE(deltaE_),
00040         maxToStore(maxToStore_)
00041     {}
00042     
00043     Basin_FME::~Basin_FME()
00044     {}
00045     
00046     double
00047     Basin_FME::enumerate(   const State* const localMin, 
00048                             StateCollector* scBasin,
00049                             StatePairCollector* scSurface)
00050     {
00051         return Basin_FME::flood( localMin, scBasin, 
00052                                 maxE, deltaE, maxToStore, scSurface);
00053     }
00054 
00055     double 
00056     Basin_FME::flood(   
00057                         const State* const localMin, 
00058                         StateCollector* scBasin,
00059                         const double maxE_, 
00060                         const double deltaE, 
00061                         const size_t maxToStore, 
00062                         StatePairCollector* scSurface
00063             ) 
00064     {
00065         assertbiu( localMin != NULL, "No local Min given! (==NULL)"); 
00066         assertbiu( scBasin != NULL, "No StateCollector given! (scBasin==NULL)"); 
00067         assertbiu( localMin->getEnergy() <= maxE_, "E(localMin) <= maxE");
00068         
00069         using namespace ell::util;
00070         
00071           // the priority queue to store neighbors to handle in
00072         PriorityQueue<QueueVal> pq;
00073           // init using the given local minimum
00074         PriorityQueue<QueueVal>::InsertResult it = pq.insert(localMin);
00075         it.first->second.minNeigh.clear(); // has no minimal neighbor (is min)
00076         it.first->second.minNeighE = it.first->first.E;
00077         it.first->second.minNeighGWE = 0;  
00078         
00079         double maxE = maxE_;
00080         
00081         typedef std::list< PriorityQueue<QueueVal>::QueueKey  > NeighList;
00082         
00083         State* topState = localMin->clone();
00084         
00085         while (!pq.empty()) {
00086               // get top element
00087             PriorityQueue<QueueVal>::const_iterator top = pq.top();
00088               // uncompress top element into new State
00089             topState->uncompress(top->first.s);
00090             CSequence minNeigh; // neighbor with minimal energy
00091             double minNeighE = (double)INT_MAX; // energy of the minimal neighbor
00092              
00093             
00094               // get neighbor list
00095             State::NeighborListPtr neighbors = topState->getNeighborList();
00096             State::NeighborList::Iterator it = neighbors->begin();
00097               // contains all neighbors with E(top) < E <= maxE
00098             NeighList toStore;
00099               // the compressed sequence of the current neighbor checked
00100             CSequence next;
00101               // iterate through all neighbors
00102             while (neighbors->end() != it) 
00103             {
00104                   // get neighbor data
00105                 double nextE = it->getEnergy();
00106                 next = it->compress( next );
00107                   // increase iterator for next iteration
00108                 ++it;
00109 
00110                   // check for lowest neighbor
00111                 if (    (nextE < minNeighE) ||
00112                         (nextE == minNeighE && next < minNeigh ) ) 
00113                 {
00114                     minNeigh = next;
00115                     minNeighE = nextE;
00116                 }
00117                   // neighbor rejection
00118                 if (    nextE <= maxE   // energy does not exceed maxE
00119                         && ( nextE > top->first.E  // energy higher than top or
00120                         || (nextE == top->first.E && next > top->first.s) 
00121                                 // greater in sequence order 
00122                         ) ) 
00123                 {
00124                     // store neighbor with higher energy that has to be added to pq
00125                     toStore.push_front(NeighList::value_type(nextE, next));
00126                 }
00127                     
00128             }
00129               // handle top depending on its basin membership           
00130             if (    (minNeighE == top->second.minNeighE 
00131                     && minNeigh == top->second.minNeigh)   // belongs to the basin
00132                     || top->second.minNeigh.empty() ) // top is the local minimum
00133             {
00134                   // store because top belongs to the basin 
00135                 scBasin->add(*topState);
00136                 
00137                 PriorityQueue<QueueVal>::iterator toFill;
00138                   // sort list with increasing energy
00139                 toStore.sort();
00140                 for (   NeighList::const_iterator n = toStore.begin(); 
00141                         n != toStore.end() && n->E <= maxE; 
00142                         n++) 
00143                 {
00144                     toFill = pq.find(*n);
00145                     if (toFill == pq.end()) {
00146                           // insert empty value object
00147                         toFill = pq.insert(*n).first;
00148                           // feed data
00149                         toFill->second.minNeigh = top->first.s;
00150                         toFill->second.minNeighE = top->first.E;
00151                         toFill->second.minNeighGWE = top->second.minNeighGWE;
00152                           // check queue size and reduce if necessary
00153                         if ( pq.size() >= maxToStore ) { // queue to big
00154                               // get current maximal E in queue
00155                             double curMaxE = pq.getMaxE();
00156                               // reduce maximally allowed energy below cur. max
00157                             do { maxE -= deltaE; } while (maxE > curMaxE);
00158                               // erase all elements > maxE from the queue;
00159                             pq.reduceMaxE(maxE+0.00000001);  // <-- this is a HACK
00160                         }
00161                     } else  // update of entry if this one is smaller
00162                         if (    toFill->second.minNeighE > top->first.E ||
00163                                 ( toFill->second.minNeighE == top->first.E &&
00164                                   toFill->second.minNeigh > top->first.s) )
00165                     {
00166                           // feed data
00167                         toFill->second.minNeigh = top->first.s;
00168                         toFill->second.minNeighE = top->first.E;
00169                         toFill->second.minNeighGWE = top->second.minNeighGWE;
00170                     }
00171                 }
00172                 
00173 //          } else { // belongs NOT to the basin but is surface
00174                 
00175                 // UNFORTUNATELY WE DONT KNOW WHAT STATES OF THE BASIN ARE 
00176                 // NEIGHBORED TO THIS STATE --> SO NO REPORT TO THE SURFACE
00177                 // COLLECTOR IS DONE
00178             } 
00179 
00180               // remove top element
00181             pq.pop();           
00182         }
00183           // clear memory
00184         delete topState;
00185          
00186         return maxE;
00187     }
00188 
00189 } // namespace ell
00190 
00191 //##############################################################################
00192 //##############################################################################
00193 
00194 
00195 #include "ell/util/PriorityQueue.hh"
00196 #include <list>
00197 #include <set>
00198 
00199 namespace ell {
00200 
00201     Basin_F::QueueVal::QueueVal()
00202      :  minNeigh(), minNeighE(0.0), minNeighGWE(UINT_MAX)
00203     {
00204     }
00205     
00206     Basin_F::QueueVal::~QueueVal()
00207     {
00208     }
00209 
00210 
00211     Basin_F::Basin_F(   const double maxE_, 
00212                         const double deltaE_, 
00213                         const size_t maxToStore_ )
00214       : maxE(maxE_),
00215         deltaE(deltaE_),
00216         maxToStore(maxToStore_)
00217     {}
00218     
00219     Basin_F::~Basin_F()
00220     {}
00221     
00222     double
00223     Basin_F::enumerate( const State* const localMin, 
00224                             StateCollector* scBasin,
00225                             StatePairCollector* scSurface)
00226     {
00227         return Basin_F::flood( localMin, scBasin, 
00228                                 maxE, deltaE, maxToStore, scSurface);
00229     }
00230 
00231     double 
00232     Basin_F::flood( 
00233                         const State* const localMin, 
00234                         StateCollector* scBasin,
00235                         const double maxE_, 
00236                         const double deltaE, 
00237                         const size_t maxToStore, 
00238                         StatePairCollector* scSurface
00239             ) 
00240     {
00241         assertbiu( localMin != NULL, "No local Min given! (==NULL)"); 
00242         assertbiu( scBasin != NULL, "No StateCollector given! (scBasin==NULL)"); 
00243         assertbiu( localMin->getEnergy() <= maxE_, "E(localMin) <= maxE");
00244         
00245         using namespace ell::util;
00246         
00247           // the priority queue to store neighbors to handle in
00248         PriorityQueue<QueueVal> pq;
00249           // the hash to store seen elements of the basin
00250         typedef std::set<CSequence> BasinHash;
00251         BasinHash handled;
00252           // init using the given local minimum
00253         PriorityQueue<QueueVal>::InsertResult it = pq.insert(localMin);
00254         it.first->second.minNeigh.clear(); // has no minimal neighbor (is min)
00255         it.first->second.minNeighE = it.first->first.E;
00256         it.first->second.minNeighGWE = 0;  
00257         
00258         double maxE = maxE_;
00259         
00260         typedef std::list< PriorityQueue<QueueVal>::QueueKey  > NeighList;
00261         
00262           // create temporary objects that are altered during the flooding
00263         State* topState = localMin->clone();
00264         State* curNeigh = localMin->clone();
00265         
00266         while (!pq.empty()) {
00267               // get top element
00268             PriorityQueue<QueueVal>::const_iterator top = pq.top();
00269               // uncompress top element into new State
00270             topState->uncompress(top->first.s);
00271             CSequence minNeigh; // neighbor with minimal energy
00272             double minNeighE = (double)INT_MAX; // energy of the minimal neighbor
00273              
00274             
00275               // get neighbor list
00276             State::NeighborListPtr neighbors = topState->getNeighborList();
00277             State::NeighborList::Iterator it = neighbors->begin();
00278               // contains all neighbors with E(top) < E <= maxE
00279             NeighList toStore;
00280               // contains all neighbors with E < E(top) 
00281             NeighList toCheck;
00282               // the compressed sequence of the current neighbor checked
00283             CSequence next;
00284               // iterate through all neighbors
00285             while (neighbors->end() != it) 
00286             {
00287                   // get neighbor data
00288                 double nextE = it->getEnergy();
00289                 next = it->compress( next );
00290                   // increase iterator for next iteration
00291                 ++it;
00292 
00293                   // check for lowest neighbor
00294                 if (    (nextE < minNeighE) ||
00295                         (nextE == minNeighE && next < minNeigh ) ) 
00296                 {
00297                     minNeigh = next;
00298                     minNeighE = nextE;
00299                 }
00300                   // check if neighbor is of interest and not rejected
00301                 if ( nextE <= maxE )    // energy does not exceed maxE
00302                 {
00303                       // check if neighbor is of higher order --> to PQ
00304                     if (    nextE > top->first.E  // energy higher than top or
00305                             || (nextE == top->first.E && next > top->first.s) ) 
00306                     {        // greater in sequence order
00307                         // store neighbor with higher energy that has to be added to pq
00308                         toStore.push_front(NeighList::value_type(nextE, next));
00309                         
00310                     } else if (scSurface != NULL) {
00311                         // store all neighbors with lower energy 
00312                         toCheck.push_back(NeighList::value_type(nextE, next));
00313                     }
00314                 }
00315                 
00316             }
00317               // handle top depending on its basin membership           
00318             if (    (minNeighE == top->second.minNeighE 
00319                     && minNeigh == top->second.minNeigh)   // belongs to the basin
00320                     || top->second.minNeigh.empty() ) // top is the local minimum
00321             {
00322                   // store because top belongs to the basin 
00323                 scBasin->add(*topState);
00324                   // add to hashed elements and mark that part of the basin
00325                 handled.insert(top->first.s);
00326                 
00327                   // put all neighbors with higher energy to PQ
00328                 PriorityQueue<QueueVal>::iterator toFill;
00329                   // sort list with increasing energy
00330                 toStore.sort();
00331                 for (   NeighList::const_iterator n = toStore.begin(); 
00332                         n != toStore.end() && n->E <= maxE; 
00333                         n++) 
00334                 {
00335                     toFill = pq.find(*n);
00336                     if (toFill == pq.end()) {
00337                           // insert empty value object
00338                         toFill = pq.insert(*n).first;
00339                           // feed data
00340                         toFill->second.minNeigh = top->first.s;
00341                         toFill->second.minNeighE = top->first.E;
00342                         toFill->second.minNeighGWE = top->second.minNeighGWE;
00343                           // check queue size and reduce if necessary
00344                         if ( pq.size() >= maxToStore ) { // queue to big
00345                               // get current maximal E in queue
00346                             double curMaxE = pq.getMaxE();
00347                               // reduce maximally allowed energy below cur. max
00348                             do { maxE -= deltaE; } while (maxE > curMaxE);
00349                               // erase all elements >= maxE from the queue;
00350                             pq.reduceMaxE(maxE);
00351                         }
00352                     } else  // update of entry if this one is smaller
00353                         if (    toFill->second.minNeighE > top->first.E ||
00354                                 ( toFill->second.minNeighE == top->first.E &&
00355                                   toFill->second.minNeigh > top->first.s) )
00356                     {
00357                           // feed data
00358                         toFill->second.minNeigh = top->first.s;
00359                         toFill->second.minNeighE = top->first.E;
00360                         toFill->second.minNeighGWE = top->second.minNeighGWE;
00361                     }
00362                 }
00363                   // check if surface / contact plane is of interest
00364                 if (scSurface != NULL) {
00365                       // check all neighbors with lower energy if NOT part of the
00366                       // basin to enumerate the surface of the basin
00367                     for (   NeighList::const_iterator n = toCheck.begin(); 
00368                             n != toCheck.end(); n++) 
00369                     {
00370                           // check if neighbor is NOT part of basin
00371                         if ( handled.find(n->s) == handled.end() ) {
00372                               // uncompress neighbor
00373                             curNeigh->uncompress(n->s);
00374                               // add to surface reporter
00375                             scSurface->add( topState, curNeigh );
00376                         }
00377                     }
00378                 }
00379                 
00380             } else { // belongs NOT to the basin but in surface
00381                 
00382                   // check if surface / contact plane is of interest
00383                 if (scSurface != NULL) {
00384                       // check all neighbors with lower energy IF part of the
00385                       // basin to enumerate the surface of the basin
00386                     for (   NeighList::const_iterator n = toCheck.begin(); 
00387                             n != toCheck.end(); n++) 
00388                     {
00389                           // check if neighbor IS part of basin
00390                         if ( handled.find(n->s) != handled.end() ) {
00391                               // uncompress neighbor
00392                             curNeigh->uncompress(n->s);
00393                               // add to surface reporter
00394                             scSurface->add( curNeigh, topState );
00395                         }
00396                     }
00397                 }
00398             } 
00399 
00400               // remove top element
00401             pq.pop();           
00402         }
00403           // clear memory
00404         delete topState;
00405         delete curNeigh;
00406          
00407         return maxE;
00408     }
00409 
00410 } // namespace ell
00411 
00412 //##############################################################################
00413 //##############################################################################
00414