lemon/elevator.h
author alpar
Fri, 19 Jan 2007 17:15:15 +0000
changeset 2346 c06a956a92fa
child 2347 0aaa7ada5395
permissions -rw-r--r--
elevator.h: A class for handling item labels in push-relabel type algorithms
alpar@2346
     1
/* -*- C++ -*-
alpar@2346
     2
 *
alpar@2346
     3
 * This file is a part of LEMON, a generic C++ optimization library
alpar@2346
     4
 *
alpar@2346
     5
 * Copyright (C) 2003-2006
alpar@2346
     6
 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
alpar@2346
     7
 * (Egervary Research Group on Combinatorial Optimization, EGRES).
alpar@2346
     8
 *
alpar@2346
     9
 * Permission to use, modify and distribute this software is granted
alpar@2346
    10
 * provided that this copyright notice appears in all copies. For
alpar@2346
    11
 * precise terms see the accompanying LICENSE file.
alpar@2346
    12
 *
alpar@2346
    13
 * This software is provided "AS IS" with no warranty of any kind,
alpar@2346
    14
 * express or implied, and with no claim as to its suitability for any
alpar@2346
    15
 * purpose.
alpar@2346
    16
 *
alpar@2346
    17
 */
alpar@2346
    18
alpar@2346
    19
#ifndef LEMON_ELEVATOR_H
alpar@2346
    20
#define LEMON_ELEVATOR_H
alpar@2346
    21
alpar@2346
    22
///\ingroup auxdat
alpar@2346
    23
///\file
alpar@2346
    24
///\brief Elevator class
alpar@2346
    25
///
alpar@2346
    26
///Elevator class implements an efficient data structure
alpar@2346
    27
///for labeling items in push-relabel type algorithms.
alpar@2346
    28
///
alpar@2346
    29
alpar@2346
    30
#include <test/test_tools.h>
alpar@2346
    31
namespace lemon {
alpar@2346
    32
alpar@2346
    33
  ///Class for hangling "labels" in push-relabel type algorithms.
alpar@2346
    34
  
alpar@2346
    35
  ///A class for hangling "labels" in push-relabel type algorithms.
alpar@2346
    36
  ///
alpar@2346
    37
  ///\ingroup auxdat
alpar@2346
    38
  ///Using this class you can assign "labels" (nonnegativ integer numbers)
alpar@2346
    39
  ///to the edges or nodes of a graph, manipulate and query them through
alpar@2346
    40
  ///operations typically arising in "push-relabel" type algorithms.
alpar@2346
    41
  ///
alpar@2346
    42
  ///Each item is either \em active or not, and you can also choose a
alpar@2346
    43
  ///highest level active item.
alpar@2346
    44
  ///
alpar@2346
    45
  ///\param Graph the underlying graph type
alpar@2346
    46
  ///\param Item Type of the items the data is assigned to (Graph::Node,
alpar@2346
    47
  ///Graph::Edge, Graph::UEdge)
alpar@2346
    48
  template<class Graph, class Item>
alpar@2346
    49
  class Elevator 
alpar@2346
    50
  {
alpar@2346
    51
  public:
alpar@2346
    52
    typedef typename std::vector<Item>::iterator Vit;
alpar@2346
    53
    typedef DefaultMap<Graph,Item,Vit> VitMap;
alpar@2346
    54
    typedef DefaultMap<Graph,Item,int> IntMap;
alpar@2346
    55
alpar@2346
    56
    const Graph &_g;
alpar@2346
    57
    int _max_level;
alpar@2346
    58
    int _item_num;
alpar@2346
    59
    VitMap _where;
alpar@2346
    60
    IntMap _level;
alpar@2346
    61
    std::vector<Item> _items;
alpar@2346
    62
    std::vector<Vit> _first;
alpar@2346
    63
    std::vector<Vit> _last_active;
alpar@2346
    64
alpar@2346
    65
    int _highest_active;
alpar@2346
    66
alpar@2346
    67
    void copy(Item i, Vit p)
alpar@2346
    68
    {
alpar@2346
    69
      _where[*p=i]=p;
alpar@2346
    70
    }
alpar@2346
    71
    void copy(Vit s, Vit p)
alpar@2346
    72
    {
alpar@2346
    73
      if(s!=p) 
alpar@2346
    74
	{
alpar@2346
    75
	  Item i=*s;
alpar@2346
    76
	  *p=i;
alpar@2346
    77
	  _where[i]=p;
alpar@2346
    78
	}
alpar@2346
    79
    }
alpar@2346
    80
    void swap(Vit i, Vit j)
alpar@2346
    81
    {
alpar@2346
    82
      Item ti=*i;
alpar@2346
    83
      Vit ct = _where[ti];
alpar@2346
    84
      _where[ti]=_where[*i=*j];
alpar@2346
    85
      _where[*j]=ct;
alpar@2346
    86
      *j=ti;
alpar@2346
    87
    }
alpar@2346
    88
    
alpar@2346
    89
    void checkDs() 
alpar@2346
    90
    {
alpar@2346
    91
      for(typename ItemSetTraits<Graph,Item>::ItemIt i(_g);i!=INVALID;++i)
alpar@2346
    92
	{
alpar@2346
    93
	  Vit w=_where[i];
alpar@2346
    94
	  int l=_level[i];
alpar@2346
    95
	  check(*w==i,"GEBASZ: CORRUPT DS");
alpar@2346
    96
	  check(_first[l]<=w,"GEBASZ: CORRUPT DS");
alpar@2346
    97
	  check(_first[l+1]>w,"GEBASZ: CORRUPT DS");
alpar@2346
    98
	}
alpar@2346
    99
      check(_highest_active<0 ||
alpar@2346
   100
	    _first[_highest_active]<=_last_active[_highest_active],
alpar@2346
   101
	    "GEBASZ: CORRUPT DS");
alpar@2346
   102
    }
alpar@2346
   103
alpar@2346
   104
  public:
alpar@2346
   105
    ///Constructor with given maximum level.
alpar@2346
   106
alpar@2346
   107
    ///Constructor with given maximum level.
alpar@2346
   108
    ///
alpar@2346
   109
    ///\param g The underlying graph
alpar@2346
   110
    ///\param max_level Set the range of the possible labels to
alpar@2346
   111
    ///[0...\c max_level]
alpar@2346
   112
    Elevator(const Graph &g,int max_level) :
alpar@2346
   113
      _g(g),
alpar@2346
   114
      _max_level(max_level),
alpar@2346
   115
      _item_num(_max_level),
alpar@2346
   116
      _where(g),
alpar@2346
   117
      _level(g,0),
alpar@2346
   118
      _items(_max_level),
alpar@2346
   119
      _first(_max_level+2),
alpar@2346
   120
      _last_active(_max_level+2),
alpar@2346
   121
      _highest_active(-1) {}
alpar@2346
   122
    ///Constructor.
alpar@2346
   123
alpar@2346
   124
    ///Constructor.
alpar@2346
   125
    ///
alpar@2346
   126
    ///\param g The underlying graph
alpar@2346
   127
    ///The range of the possible labels is [0...\c max_level],
alpar@2346
   128
    ///where \c max_level is equal to the number of labeled items in the graph.
alpar@2346
   129
    Elevator(const Graph &g) :
alpar@2346
   130
      _g(g),
alpar@2346
   131
      _max_level(countItems<Graph, Item>(g)),
alpar@2346
   132
      _item_num(_max_level),
alpar@2346
   133
      _where(g),
alpar@2346
   134
      _level(g,0),
alpar@2346
   135
      _items(_max_level),
alpar@2346
   136
      _first(_max_level+2),
alpar@2346
   137
      _last_active(_max_level+2),
alpar@2346
   138
      _highest_active(-1)
alpar@2346
   139
    {
alpar@2346
   140
    }
alpar@2346
   141
  
alpar@2346
   142
    ///Activate item \c i.
alpar@2346
   143
    void activate(Item i)
alpar@2346
   144
    {
alpar@2346
   145
      const int l=_level[i];
alpar@2346
   146
      swap(_where[i],++_last_active[l]);
alpar@2346
   147
      if(l>_highest_active) _highest_active=l;
alpar@2346
   148
    }
alpar@2346
   149
  
alpar@2346
   150
    ///Deactivate item \c i.
alpar@2346
   151
    void deactivate(Item i)  
alpar@2346
   152
    {
alpar@2346
   153
      swap(_where[i],_last_active[_level[i]]--);
alpar@2346
   154
      _last_active[_level[i]]--;
alpar@2346
   155
      while(_highest_active>=0 &&
alpar@2346
   156
	    _last_active[_highest_active]<_first[_highest_active])
alpar@2346
   157
	_highest_active--;
alpar@2346
   158
    }
alpar@2346
   159
alpar@2346
   160
    ///Query whether item \c i is active
alpar@2346
   161
    bool active(Item i) const { return _where[i]<=_last_active[_level[i]]; }
alpar@2346
   162
    
alpar@2346
   163
    ///Return the level of item \c i.
alpar@2346
   164
    int operator[](Item i) const { return _level[i]; }
alpar@2346
   165
alpar@2346
   166
    ///Returns an active item on level \c l.
alpar@2346
   167
alpar@2346
   168
    ///Returns an active item on level \c l.
alpar@2346
   169
    ///
alpar@2346
   170
    ///Returns an active item on level \c l or \ref INVALID if there is no such
alpar@2346
   171
    ///an item. (\c l must be from the range [0...\c max_level].
alpar@2346
   172
    Item operator[](int l) const
alpar@2346
   173
    { 
alpar@2346
   174
      return _last_active[l]>=_first[l]?*_last_active[l]:INVALID;
alpar@2346
   175
    }
alpar@2346
   176
alpar@2346
   177
    ///Return the number of items on level \c l.
alpar@2346
   178
    int &onLevel(int l)
alpar@2346
   179
    {
alpar@2346
   180
      return _first[l+1]-_first[l];
alpar@2346
   181
    }
alpar@2346
   182
    ///Return the number of active items on level \c l.
alpar@2346
   183
    int &activesOnLevel(int l)
alpar@2346
   184
    {
alpar@2346
   185
      return _last_active[l]-_first[l]+1;
alpar@2346
   186
    }
alpar@2346
   187
    ///Return the maximum allowed level.
alpar@2346
   188
    int maxLevel() const 
alpar@2346
   189
    {
alpar@2346
   190
      return _max_level;
alpar@2346
   191
    }    
alpar@2346
   192
alpar@2346
   193
    ///\name Highest Active Item
alpar@2346
   194
    ///Functions for working with the highest level
alpar@2346
   195
    ///active item.
alpar@2346
   196
alpar@2346
   197
    ///@{
alpar@2346
   198
alpar@2346
   199
    ///Return a highest level active item.
alpar@2346
   200
  
alpar@2346
   201
    ///Return a highest level active item.
alpar@2346
   202
    ///
alpar@2346
   203
    ///\return the highest level active item or INVALID if there is no active
alpar@2346
   204
    ///item.
alpar@2346
   205
    Item highestActive() const 
alpar@2346
   206
    {
alpar@2346
   207
      return _highest_active>=0?*_last_active[_highest_active]:INVALID;
alpar@2346
   208
    }
alpar@2346
   209
alpar@2346
   210
    ///Return a highest active level.
alpar@2346
   211
alpar@2346
   212
    ///Return a highest active level.
alpar@2346
   213
    ///
alpar@2346
   214
    ///\return the level of the highest active item or -1 if there is no active
alpar@2346
   215
    ///item.
alpar@2346
   216
    Item highestActiveLevel() const 
alpar@2346
   217
    {
alpar@2346
   218
      return _highest_active;
alpar@2346
   219
    }
alpar@2346
   220
alpar@2346
   221
    ///Lift the highest active item by one.
alpar@2346
   222
alpar@2346
   223
    ///Lift the item returned by highestActive() by one.
alpar@2346
   224
    ///
alpar@2346
   225
    void liftHighestActive() 
alpar@2346
   226
    {
alpar@2346
   227
      ++_level[*_last_active[_highest_active]];
alpar@2346
   228
      swap(_last_active[_highest_active]--,_last_active[_highest_active+1]);
alpar@2346
   229
      --_first[++_highest_active];
alpar@2346
   230
    }
alpar@2346
   231
alpar@2346
   232
    ///Lift the highest active item.
alpar@2346
   233
alpar@2346
   234
    ///Lift the item returned by highestActive() to level \c new_level.
alpar@2346
   235
    ///
alpar@2346
   236
    ///
alpar@2346
   237
    void liftHighestActiveTo(int new_level) 
alpar@2346
   238
    {
alpar@2346
   239
      const Item li = *_last_active[_highest_active];
alpar@2346
   240
      
alpar@2346
   241
      copy(--_first[_highest_active+1],_last_active[_highest_active]--);
alpar@2346
   242
      for(int l=_highest_active+1;l<new_level;l++)
alpar@2346
   243
	{
alpar@2346
   244
	  copy(--_first[l+1],_first[l]);
alpar@2346
   245
	  --_last_active[l];
alpar@2346
   246
	}
alpar@2346
   247
      copy(li,_first[new_level]);
alpar@2346
   248
      _level[li]=new_level;
alpar@2346
   249
	  _highest_active=new_level;
alpar@2346
   250
    }
alpar@2346
   251
    
alpar@2346
   252
    ///@}
alpar@2346
   253
    
alpar@2346
   254
  private:
alpar@2346
   255
    int _init_lev;
alpar@2346
   256
    Vit _init_num;
alpar@2346
   257
alpar@2346
   258
  public:
alpar@2346
   259
alpar@2346
   260
    ///\name Initialization
alpar@2346
   261
    ///Using this function you can initialize the levels of the item.
alpar@2346
   262
    ///\n
alpar@2346
   263
    ///This initializatios is started with calling \c initStart().
alpar@2346
   264
    ///Then the
alpar@2346
   265
    ///items should be listed levels by levels statring with the lowest one
alpar@2346
   266
    ///(with level 0). This is done by using \c initAddItem()
alpar@2346
   267
    ///and \c initNewLevel(). Finally \c initFinish() must be called.
alpar@2346
   268
    ///The items not listes will be put on the highest level.
alpar@2346
   269
    ///@{
alpar@2346
   270
alpar@2346
   271
    ///Starts the initialization process.
alpar@2346
   272
alpar@2346
   273
    void initStart() 
alpar@2346
   274
    {
alpar@2346
   275
      _init_lev=0;
alpar@2346
   276
      _init_num=_items.begin();
alpar@2346
   277
      _first[0]=_items.begin();
alpar@2346
   278
      _last_active[0]=_items.begin()-1;
alpar@2346
   279
      Vit n=_items.begin();
alpar@2346
   280
      for(typename ItemSetTraits<Graph,Item>::ItemIt i(_g);i!=INVALID;++i)
alpar@2346
   281
	{
alpar@2346
   282
	  *n=i;
alpar@2346
   283
	  _where[i]=n;
alpar@2346
   284
	  _level[i]=_max_level;
alpar@2346
   285
	  ++n;
alpar@2346
   286
	}
alpar@2346
   287
    }
alpar@2346
   288
alpar@2346
   289
    ///Add an item to the current level.
alpar@2346
   290
alpar@2346
   291
    void initAddItem(Item i)
alpar@2346
   292
    { 
alpar@2346
   293
     swap(_where[i],_init_num);
alpar@2346
   294
      _level[i]=_init_lev;
alpar@2346
   295
      ++_init_num;
alpar@2346
   296
    }
alpar@2346
   297
alpar@2346
   298
    ///Start a new level.
alpar@2346
   299
alpar@2346
   300
    ///Start a new level.
alpar@2346
   301
    ///It shouldn't be used before the items on level 0 are listed.
alpar@2346
   302
    void initNewLevel() 
alpar@2346
   303
    {
alpar@2346
   304
      _init_lev++;
alpar@2346
   305
      _first[_init_lev]=_init_num;
alpar@2346
   306
      _last_active[_init_lev]=_init_num-1;
alpar@2346
   307
    }
alpar@2346
   308
alpar@2346
   309
    ///Finalizes the initialization process.
alpar@2346
   310
alpar@2346
   311
    void initFinish()
alpar@2346
   312
    {
alpar@2346
   313
      for(_init_lev++;_init_lev<=_max_level;_init_lev++)
alpar@2346
   314
	{
alpar@2346
   315
	  _first[_init_lev]=_init_num;
alpar@2346
   316
	  _last_active[_init_lev]=_init_num-1;
alpar@2346
   317
	}
alpar@2346
   318
      _first[_max_level+1]=_items.begin()+_item_num;
alpar@2346
   319
      _last_active[_max_level+1]=_items.begin()+_item_num-1;
alpar@2346
   320
    }
alpar@2346
   321
alpar@2346
   322
    ///@}
alpar@2346
   323
alpar@2346
   324
  };
alpar@2346
   325
alpar@2346
   326
} //END OF NAMESPACE LEMON
alpar@2346
   327
alpar@2346
   328
#endif
alpar@2346
   329