Generated on Mon Jun 23 17:17:53 2008 for ell-2.3.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 "ell/util/PriorityQueue.hh"
00004 #include <biu/assertbiu.hh>
00005 #include <list>
00006 
00007 
00008 namespace ell
00009 {
00010 
00011     Basin::QueueVal::QueueVal()
00012      :  minNeigh(), minNeighE(0.0), minNeighGWE(UINT_MAX)
00013     {
00014     }
00015     
00016     Basin::QueueVal::~QueueVal()
00017     {
00018     }
00019 
00020 
00021     Basin::Basin(   const double maxE_, 
00022                     const double deltaE_, 
00023                     const size_t maxToStore_)
00024       : maxE(maxE_),
00025         deltaE(deltaE_),
00026         maxToStore(maxToStore_)
00027     {}
00028     
00029     double
00030     Basin::flood(   const ell::State* const localMin, 
00031                     StateCollector* scBasin,
00032                     StateCollector* scSurface)
00033     {
00034         return Basin::basin( localMin, scBasin, 
00035                                 maxE, deltaE, maxToStore, scSurface);
00036     }
00037 
00038     double 
00039     Basin::basin(   const State* const localMin, 
00040             StateCollector* scBasin,
00041             const double maxE_, 
00042             const double deltaE, 
00043             const size_t maxToStore, 
00044             StateCollector* scSurface
00045             ) 
00046     {
00047         assertbiu( localMin != NULL, "No local Min given! (==NULL)"); 
00048         assertbiu( scBasin != NULL, "No StateCollector given! (scBasin==NULL)"); 
00049         assertbiu( localMin->getEnergy() < maxE_, "E(localMin) >= maxE");
00050         
00051         using namespace ell::util;
00052         
00053           // the priority queue to store neighbors to handle in
00054         PriorityQueue<QueueVal> pq;
00055           // init using the given local minimum
00056         PriorityQueue<QueueVal>::iterator it = pq.insert(localMin);
00057         it->second.minNeigh.clear(); // has no minimal neighbor (is min)
00058         it->second.minNeighE = it->first.E;
00059         it->second.minNeighGWE = 0;  
00060         
00061         double maxE = maxE_;
00062         
00063         typedef std::list< PriorityQueue<QueueVal>::QueueKey  > NeighList;
00064         
00065         while (!pq.empty()) {
00066               // get top element
00067             PriorityQueue<QueueVal>::const_iterator top = pq.top();
00068               // uncompress top element into new State
00069             State* s = localMin->uncompress(top->first.s, NULL);
00070             CSequence minNeigh; // neighbor with minimal energy
00071             double minNeighE = (double)INT_MAX; // energy of the minimal neighbor
00072              
00073             
00074               // get neighbor list
00075             State::NeighborListPtr neighbors = s->getNeighborList();
00076             State::NeighborList::Iterator it = neighbors->begin();
00077                 // contains all neighbors with E(top) < E < maxE
00078             NeighList toStore;
00079               // iterate through all neighbors
00080             while (neighbors->end() != it) 
00081             {
00082                   // get neighbor data
00083                 double nextE = it->getEnergy();
00084                 CSequence next = it->compress();
00085                   // increase iterator for next iteration
00086                 ++it;
00087 
00088                   // check for lowest neighbor
00089                 if (    (nextE < minNeighE) ||
00090                         (nextE == minNeighE && next < minNeigh ) ) 
00091                 {
00092                     minNeigh = next;
00093                     minNeighE = nextE;
00094                 }
00095                   // neighbor rejection
00096                 if (    nextE < maxE    // energy does not exceed maxE
00097                         && ( nextE > top->first.E  // energy higher than top or
00098                         || (nextE == top->first.E && next > top->first.s) 
00099                                 // greater in sequence order 
00100                         ) ) 
00101                 {
00102                     // store neighbor with higher energy that has to be added to pq
00103                     toStore.push_front(NeighList::value_type(nextE, next));
00104                 }
00105                     
00106             }
00107               // handle top depending on its basin membership           
00108             if (    (minNeighE == top->second.minNeighE 
00109                     && minNeigh == top->second.minNeigh)   // belongs to the basin
00110                     || top->second.minNeigh.empty() ) // top is the local minimum
00111             {
00112                   // store because top belongs to the basin 
00113                 scBasin->add(*s);
00114                 
00115                 PriorityQueue<QueueVal>::iterator toFill;
00116                   // sort list with increasing energy
00117                 toStore.sort();
00118                 for (   NeighList::const_iterator n = toStore.begin(); 
00119                         n != toStore.end() && n->E < maxE; 
00120                         n++) 
00121                 {
00122                     toFill = pq.find(*n);
00123                     if (toFill == pq.end()) {
00124                           // insert empty value object
00125                         toFill = pq.insert(*n);
00126                           // feed data
00127                         toFill->second.minNeigh = top->first.s;
00128                         toFill->second.minNeighE = top->first.E;
00129                         toFill->second.minNeighGWE = top->second.minNeighGWE;
00130                           // check queue size and reduce if necessary
00131                         if ( pq.size() >= maxToStore ) { // queue to big
00132                               // get current maximal E in queue
00133                             double curMaxE = pq.getMaxE();
00134                               // reduce maximally allowed energy below cur. max
00135                             do { maxE -= deltaE; } while (maxE > curMaxE);
00136                               // erase all elements >= maxE from the queue;
00137                             pq.reduceMaxE(maxE);
00138                         }
00139                     } else  // update of entry if this one is smaller
00140                         if (    toFill->second.minNeighE > top->first.E ||
00141                                 ( toFill->second.minNeighE == top->first.E &&
00142                                   toFill->second.minNeigh > top->first.s) )
00143                     {
00144                           // feed data
00145                         toFill->second.minNeigh = top->first.s;
00146                         toFill->second.minNeighE = top->first.E;
00147                         toFill->second.minNeighGWE = top->second.minNeighGWE;
00148                     }
00149                 }
00150                 
00151             } else { // belongs NOT to the basin but is surface
00152                 if (scSurface != NULL) {
00153                       // store as processed state 
00154                     scSurface->add(*s);
00155                 }
00156             } 
00157 
00158               // clear memory
00159             delete s;
00160               // remove top element
00161             pq.pop();           
00162         }
00163          
00164         return maxE;
00165     }
00166 
00167 
00168 }