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