lemon/concepts/heap.h
author Peter Kovacs <kpeter@inf.elte.hu>
Tue, 15 Mar 2011 19:32:21 +0100
changeset 936 ddd3c0d3d9bf
parent 817 b87f0504cdbe
child 976 426a704d7483
permissions -rw-r--r--
Implement the scaling Price Refinement heuristic in CostScaling (#417)
instead of Early Termination.

These two heuristics are similar, but the newer one is faster
and not only makes it possible to skip some epsilon phases, but
it can improve the performance of the other phases, as well.
     1 /* -*- mode: C++; indent-tabs-mode: nil; -*-
     2  *
     3  * This file is a part of LEMON, a generic C++ optimization library.
     4  *
     5  * Copyright (C) 2003-2010
     6  * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
     7  * (Egervary Research Group on Combinatorial Optimization, EGRES).
     8  *
     9  * Permission to use, modify and distribute this software is granted
    10  * provided that this copyright notice appears in all copies. For
    11  * precise terms see the accompanying LICENSE file.
    12  *
    13  * This software is provided "AS IS" with no warranty of any kind,
    14  * express or implied, and with no claim as to its suitability for any
    15  * purpose.
    16  *
    17  */
    18 
    19 #ifndef LEMON_CONCEPTS_HEAP_H
    20 #define LEMON_CONCEPTS_HEAP_H
    21 
    22 ///\ingroup concept
    23 ///\file
    24 ///\brief The concept of heaps.
    25 
    26 #include <lemon/core.h>
    27 #include <lemon/concept_check.h>
    28 
    29 namespace lemon {
    30 
    31   namespace concepts {
    32 
    33     /// \addtogroup concept
    34     /// @{
    35 
    36     /// \brief The heap concept.
    37     ///
    38     /// This concept class describes the main interface of heaps.
    39     /// The various \ref heaps "heap structures" are efficient
    40     /// implementations of the abstract data type \e priority \e queue.
    41     /// They store items with specified values called \e priorities
    42     /// in such a way that finding and removing the item with minimum
    43     /// priority are efficient. The basic operations are adding and
    44     /// erasing items, changing the priority of an item, etc.
    45     ///
    46     /// Heaps are crucial in several algorithms, such as Dijkstra and Prim.
    47     /// Any class that conforms to this concept can be used easily in such
    48     /// algorithms.
    49     ///
    50     /// \tparam PR Type of the priorities of the items.
    51     /// \tparam IM A read-writable item map with \c int values, used
    52     /// internally to handle the cross references.
    53     /// \tparam CMP A functor class for comparing the priorities.
    54     /// The default is \c std::less<PR>.
    55 #ifdef DOXYGEN
    56     template <typename PR, typename IM, typename CMP>
    57 #else
    58     template <typename PR, typename IM, typename CMP = std::less<PR> >
    59 #endif
    60     class Heap {
    61     public:
    62 
    63       /// Type of the item-int map.
    64       typedef IM ItemIntMap;
    65       /// Type of the priorities.
    66       typedef PR Prio;
    67       /// Type of the items stored in the heap.
    68       typedef typename ItemIntMap::Key Item;
    69 
    70       /// \brief Type to represent the states of the items.
    71       ///
    72       /// Each item has a state associated to it. It can be "in heap",
    73       /// "pre-heap" or "post-heap". The latter two are indifferent from the
    74       /// heap's point of view, but may be useful to the user.
    75       ///
    76       /// The item-int map must be initialized in such way that it assigns
    77       /// \c PRE_HEAP (<tt>-1</tt>) to any element to be put in the heap.
    78       enum State {
    79         IN_HEAP = 0,    ///< = 0. The "in heap" state constant.
    80         PRE_HEAP = -1,  ///< = -1. The "pre-heap" state constant.
    81         POST_HEAP = -2  ///< = -2. The "post-heap" state constant.
    82       };
    83 
    84       /// \brief Constructor.
    85       ///
    86       /// Constructor.
    87       /// \param map A map that assigns \c int values to keys of type
    88       /// \c Item. It is used internally by the heap implementations to
    89       /// handle the cross references. The assigned value must be
    90       /// \c PRE_HEAP (<tt>-1</tt>) for each item.
    91 #ifdef DOXYGEN
    92       explicit Heap(ItemIntMap &map) {}
    93 #else
    94       explicit Heap(ItemIntMap&) {}
    95 #endif
    96 
    97       /// \brief Constructor.
    98       ///
    99       /// Constructor.
   100       /// \param map A map that assigns \c int values to keys of type
   101       /// \c Item. It is used internally by the heap implementations to
   102       /// handle the cross references. The assigned value must be
   103       /// \c PRE_HEAP (<tt>-1</tt>) for each item.
   104       /// \param comp The function object used for comparing the priorities.
   105 #ifdef DOXYGEN
   106       explicit Heap(ItemIntMap &map, const CMP &comp) {}
   107 #else
   108       explicit Heap(ItemIntMap&, const CMP&) {}
   109 #endif
   110 
   111       /// \brief The number of items stored in the heap.
   112       ///
   113       /// This function returns the number of items stored in the heap.
   114       int size() const { return 0; }
   115 
   116       /// \brief Check if the heap is empty.
   117       ///
   118       /// This function returns \c true if the heap is empty.
   119       bool empty() const { return false; }
   120 
   121       /// \brief Make the heap empty.
   122       ///
   123       /// This functon makes the heap empty.
   124       /// It does not change the cross reference map. If you want to reuse
   125       /// a heap that is not surely empty, you should first clear it and
   126       /// then you should set the cross reference map to \c PRE_HEAP
   127       /// for each item.
   128       void clear() {}
   129 
   130       /// \brief Insert an item into the heap with the given priority.
   131       ///
   132       /// This function inserts the given item into the heap with the
   133       /// given priority.
   134       /// \param i The item to insert.
   135       /// \param p The priority of the item.
   136       /// \pre \e i must not be stored in the heap.
   137 #ifdef DOXYGEN
   138       void push(const Item &i, const Prio &p) {}
   139 #else
   140       void push(const Item&, const Prio&) {}
   141 #endif
   142 
   143       /// \brief Return the item having minimum priority.
   144       ///
   145       /// This function returns the item having minimum priority.
   146       /// \pre The heap must be non-empty.
   147       Item top() const { return Item(); }
   148 
   149       /// \brief The minimum priority.
   150       ///
   151       /// This function returns the minimum priority.
   152       /// \pre The heap must be non-empty.
   153       Prio prio() const { return Prio(); }
   154 
   155       /// \brief Remove the item having minimum priority.
   156       ///
   157       /// This function removes the item having minimum priority.
   158       /// \pre The heap must be non-empty.
   159       void pop() {}
   160 
   161       /// \brief Remove the given item from the heap.
   162       ///
   163       /// This function removes the given item from the heap if it is
   164       /// already stored.
   165       /// \param i The item to delete.
   166       /// \pre \e i must be in the heap.
   167 #ifdef DOXYGEN
   168       void erase(const Item &i) {}
   169 #else
   170       void erase(const Item&) {}
   171 #endif
   172 
   173       /// \brief The priority of the given item.
   174       ///
   175       /// This function returns the priority of the given item.
   176       /// \param i The item.
   177       /// \pre \e i must be in the heap.
   178 #ifdef DOXYGEN
   179       Prio operator[](const Item &i) const {}
   180 #else
   181       Prio operator[](const Item&) const { return Prio(); }
   182 #endif
   183 
   184       /// \brief Set the priority of an item or insert it, if it is
   185       /// not stored in the heap.
   186       ///
   187       /// This method sets the priority of the given item if it is
   188       /// already stored in the heap. Otherwise it inserts the given
   189       /// item into the heap with the given priority.
   190       ///
   191       /// \param i The item.
   192       /// \param p The priority.
   193 #ifdef DOXYGEN
   194       void set(const Item &i, const Prio &p) {}
   195 #else
   196       void set(const Item&, const Prio&) {}
   197 #endif
   198 
   199       /// \brief Decrease the priority of an item to the given value.
   200       ///
   201       /// This function decreases the priority of an item to the given value.
   202       /// \param i The item.
   203       /// \param p The priority.
   204       /// \pre \e i must be stored in the heap with priority at least \e p.
   205 #ifdef DOXYGEN
   206       void decrease(const Item &i, const Prio &p) {}
   207 #else
   208       void decrease(const Item&, const Prio&) {}
   209 #endif
   210 
   211       /// \brief Increase the priority of an item to the given value.
   212       ///
   213       /// This function increases the priority of an item to the given value.
   214       /// \param i The item.
   215       /// \param p The priority.
   216       /// \pre \e i must be stored in the heap with priority at most \e p.
   217 #ifdef DOXYGEN
   218       void increase(const Item &i, const Prio &p) {}
   219 #else
   220       void increase(const Item&, const Prio&) {}
   221 #endif
   222 
   223       /// \brief Return the state of an item.
   224       ///
   225       /// This method returns \c PRE_HEAP if the given item has never
   226       /// been in the heap, \c IN_HEAP if it is in the heap at the moment,
   227       /// and \c POST_HEAP otherwise.
   228       /// In the latter case it is possible that the item will get back
   229       /// to the heap again.
   230       /// \param i The item.
   231 #ifdef DOXYGEN
   232       State state(const Item &i) const {}
   233 #else
   234       State state(const Item&) const { return PRE_HEAP; }
   235 #endif
   236 
   237       /// \brief Set the state of an item in the heap.
   238       ///
   239       /// This function sets the state of the given item in the heap.
   240       /// It can be used to manually clear the heap when it is important
   241       /// to achive better time complexity.
   242       /// \param i The item.
   243       /// \param st The state. It should not be \c IN_HEAP.
   244 #ifdef DOXYGEN
   245       void state(const Item& i, State st) {}
   246 #else
   247       void state(const Item&, State) {}
   248 #endif
   249 
   250 
   251       template <typename _Heap>
   252       struct Constraints {
   253       public:
   254         void constraints() {
   255           typedef typename _Heap::Item OwnItem;
   256           typedef typename _Heap::Prio OwnPrio;
   257           typedef typename _Heap::State OwnState;
   258 
   259           Item item;
   260           Prio prio;
   261           item=Item();
   262           prio=Prio();
   263           ignore_unused_variable_warning(item);
   264           ignore_unused_variable_warning(prio);
   265 
   266           OwnItem own_item;
   267           OwnPrio own_prio;
   268           OwnState own_state;
   269           own_item=Item();
   270           own_prio=Prio();
   271           ignore_unused_variable_warning(own_item);
   272           ignore_unused_variable_warning(own_prio);
   273           ignore_unused_variable_warning(own_state);
   274 
   275           _Heap heap1(map);
   276           _Heap heap2 = heap1;
   277           ignore_unused_variable_warning(heap1);
   278           ignore_unused_variable_warning(heap2);
   279 
   280           int s = heap.size();
   281           ignore_unused_variable_warning(s);
   282           bool e = heap.empty();
   283           ignore_unused_variable_warning(e);
   284 
   285           prio = heap.prio();
   286           item = heap.top();
   287           prio = heap[item];
   288           own_prio = heap.prio();
   289           own_item = heap.top();
   290           own_prio = heap[own_item];
   291 
   292           heap.push(item, prio);
   293           heap.push(own_item, own_prio);
   294           heap.pop();
   295 
   296           heap.set(item, prio);
   297           heap.decrease(item, prio);
   298           heap.increase(item, prio);
   299           heap.set(own_item, own_prio);
   300           heap.decrease(own_item, own_prio);
   301           heap.increase(own_item, own_prio);
   302 
   303           heap.erase(item);
   304           heap.erase(own_item);
   305           heap.clear();
   306 
   307           own_state = heap.state(own_item);
   308           heap.state(own_item, own_state);
   309 
   310           own_state = _Heap::PRE_HEAP;
   311           own_state = _Heap::IN_HEAP;
   312           own_state = _Heap::POST_HEAP;
   313         }
   314 
   315         _Heap& heap;
   316         ItemIntMap& map;
   317       };
   318     };
   319 
   320     /// @}
   321   } // namespace lemon
   322 }
   323 #endif