sat-solver/Heap.h
00001 /******************************************************************************************[Heap.h]
00002 MiniSat -- Copyright (c) 2003-2006, Niklas Een, Niklas Sorensson
00003 
00004 Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
00005 associated documentation files (the "Software"), to deal in the Software without restriction,
00006 including without limitation the rights to use, copy, modify, merge, publish, distribute,
00007 sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
00008 furnished to do so, subject to the following conditions:
00009 
00010 The above copyright notice and this permission notice shall be included in all copies or
00011 substantial portions of the Software.
00012 
00013 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
00014 NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
00015 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
00016 DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
00017 OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
00018 **************************************************************************************************/
00019 
00020 #ifndef Heap_h
00021 #define Heap_h
00022 
00023 #include "Vec.h"
00024 
00025 //=================================================================================================
00026 // A heap implementation with support for decrease/increase key.
00027 
00028 
00029 template<class Comp>
00030 class Heap {
00031     Comp     lt;
00032     vec<int> heap;     // heap of ints
00033     vec<int> indices;  // int -> index in heap
00034 
00035     // Index "traversal" functions
00036     static inline int left  (int i) { return i*2+1; }
00037     static inline int right (int i) { return (i+1)*2; }
00038     static inline int parent(int i) { return (i-1) >> 1; }
00039 
00040 
00041     inline void percolateUp(int i)
00042     {
00043         int x = heap[i];
00044         while (i != 0 && lt(x, heap[parent(i)])){
00045             heap[i]          = heap[parent(i)];
00046             indices[heap[i]] = i;
00047             i                = parent(i);
00048         }
00049         heap   [i] = x;
00050         indices[x] = i;
00051     }
00052 
00053 
00054     inline void percolateDown(int i)
00055     {
00056         int x = heap[i];
00057         while (left(i) < heap.size()){
00058             int child = right(i) < heap.size() && lt(heap[right(i)], heap[left(i)]) ? right(i) : left(i);
00059             if (!lt(heap[child], x)) break;
00060             heap[i]          = heap[child];
00061             indices[heap[i]] = i;
00062             i                = child;
00063         }
00064         heap   [i] = x;
00065         indices[x] = i;
00066     }
00067 
00068 
00069     bool heapProperty (int i) const {
00070         return i >= heap.size()
00071             || ((i == 0 || !lt(heap[i], heap[parent(i)])) && heapProperty(left(i)) && heapProperty(right(i))); }
00072 
00073 
00074   public:
00075     Heap(const Comp& c) : lt(c) { }
00076 
00077     int  size      ()          const { return heap.size(); }
00078     bool empty     ()          const { return heap.size() == 0; }
00079     bool inHeap    (int n)     const { return n < indices.size() && indices[n] >= 0; }
00080     int  operator[](int index) const { assert(index < heap.size()); return heap[index]; }
00081 
00082     void decrease  (int n) { assert(inHeap(n)); percolateUp(indices[n]); }
00083 
00084     // RENAME WHEN THE DEPRECATED INCREASE IS REMOVED.
00085     void increase_ (int n) { assert(inHeap(n)); percolateDown(indices[n]); }
00086 
00087 
00088     void insert(int n)
00089     {
00090         indices.growTo(n+1, -1);
00091         assert(!inHeap(n));
00092 
00093         indices[n] = heap.size();
00094         heap.push(n);
00095         percolateUp(indices[n]); 
00096     }
00097 
00098     void init_identical(int n)
00099     {
00100         indices.growTo(n+1, -1);
00101         heap.growTo(n);
00102         for(int i=0; i<n; i++)
00103         {
00104                 indices[i] = i;
00105                 heap[i] = i;
00106         }
00107 
00108     }
00109 
00110 
00111     int  removeMin()
00112     {
00113         int x            = heap[0];
00114         heap[0]          = heap.last();
00115         indices[heap[0]] = 0;
00116         indices[x]       = -1;
00117         heap.pop();
00118         if (heap.size() > 1) percolateDown(0);
00119         return x; 
00120     }
00121 
00122 
00123     void clear(bool dealloc = false) 
00124     { 
00125         for (int i = 0; i < heap.size(); i++)
00126             indices[heap[i]] = -1;
00127 #ifdef NDEBUG
00128         for (int i = 0; i < indices.size(); i++)
00129             assert(indices[i] == -1);
00130 #endif
00131         heap.clear(dealloc); 
00132     }
00133 
00134 
00135     // Fool proof variant of insert/decrease/increase
00136     void update (int n)
00137     {
00138         if (!inHeap(n))
00139             insert(n);
00140         else {
00141             percolateUp(indices[n]);
00142             percolateDown(indices[n]);
00143         }
00144     }
00145 
00146 
00147     // Delete elements from the heap using a given filter function (-object).
00148     // *** this could probaly be replaced with a more general "buildHeap(vec<int>&)" method ***
00149     template <class F>
00150     void filter(const F& filt) {
00151         int i,j;
00152         for (i = j = 0; i < heap.size(); i++)
00153             if (filt(heap[i])){
00154                 heap[j]          = heap[i];
00155                 indices[heap[i]] = j++;
00156             }else
00157                 indices[heap[i]] = -1;
00158 
00159         heap.shrink(i - j);
00160         for (int i = heap.size() / 2 - 1; i >= 0; i--)
00161             percolateDown(i);
00162 
00163         assert(heapProperty());
00164     }
00165 
00166 
00167     // DEBUG: consistency checking
00168     bool heapProperty() const {
00169         return heapProperty(1); }
00170 
00171 
00172     // COMPAT: should be removed
00173     void setBounds (int n) { }
00174     void increase  (int n) { decrease(n); }
00175     int  getmin    ()      { return removeMin(); }
00176 
00177 };
00178 
00179 
00180 //=================================================================================================
00181 #endif