lemon/elevator.h
author alpar
Tue, 24 Apr 2007 09:39:01 +0000
changeset 2436 0c941c524b47
parent 2373 134639e6ea45
child 2512 371cf309fc3c
permissions -rw-r--r--
Integer parameters also convert to double
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@2391
     5
 * Copyright (C) 2003-2007
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@2347
    33
  ///Class for handling "labels" in push-relabel type algorithms.
alpar@2346
    34
  
alpar@2347
    35
  ///A class for handling "labels" in push-relabel type algorithms.
alpar@2346
    36
  ///
alpar@2346
    37
  ///\ingroup auxdat
alpar@2352
    38
  ///Using this class you can assign "labels" (nonnegative 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@2348
    89
    void checkDs() const
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@2348
    99
      for(int l=0;l<=_max_level;++l) 
alpar@2348
   100
	{
alpar@2348
   101
	  check(_first[l]<=_last_active[l]+1,"GEBASZ: CORRUPT DS");
alpar@2348
   102
	  check(_last_active[l]<_first[l+1],"GEBASZ: CORRUPT DS");
alpar@2348
   103
	  check(_first[l]<=_first[l+1],"GEBASZ: CORRUPT DS");
alpar@2348
   104
	}
alpar@2346
   105
      check(_highest_active<0 ||
alpar@2346
   106
	    _first[_highest_active]<=_last_active[_highest_active],
alpar@2346
   107
	    "GEBASZ: CORRUPT DS");
alpar@2346
   108
    }
alpar@2346
   109
alpar@2346
   110
  public:
alpar@2346
   111
    ///Constructor with given maximum level.
alpar@2346
   112
alpar@2346
   113
    ///Constructor with given maximum level.
alpar@2346
   114
    ///
alpar@2346
   115
    ///\param g The underlying graph
alpar@2346
   116
    ///\param max_level Set the range of the possible labels to
alpar@2346
   117
    ///[0...\c max_level]
alpar@2346
   118
    Elevator(const Graph &g,int max_level) :
alpar@2346
   119
      _g(g),
alpar@2346
   120
      _max_level(max_level),
alpar@2346
   121
      _item_num(_max_level),
alpar@2346
   122
      _where(g),
alpar@2346
   123
      _level(g,0),
alpar@2346
   124
      _items(_max_level),
alpar@2346
   125
      _first(_max_level+2),
alpar@2346
   126
      _last_active(_max_level+2),
alpar@2346
   127
      _highest_active(-1) {}
alpar@2346
   128
    ///Constructor.
alpar@2346
   129
alpar@2346
   130
    ///Constructor.
alpar@2346
   131
    ///
alpar@2346
   132
    ///\param g The underlying graph
alpar@2346
   133
    ///The range of the possible labels is [0...\c max_level],
alpar@2346
   134
    ///where \c max_level is equal to the number of labeled items in the graph.
alpar@2346
   135
    Elevator(const Graph &g) :
alpar@2346
   136
      _g(g),
alpar@2346
   137
      _max_level(countItems<Graph, Item>(g)),
alpar@2346
   138
      _item_num(_max_level),
alpar@2346
   139
      _where(g),
alpar@2346
   140
      _level(g,0),
alpar@2346
   141
      _items(_max_level),
alpar@2346
   142
      _first(_max_level+2),
alpar@2346
   143
      _last_active(_max_level+2),
alpar@2346
   144
      _highest_active(-1)
alpar@2346
   145
    {
alpar@2346
   146
    }
alpar@2346
   147
  
alpar@2346
   148
    ///Activate item \c i.
alpar@2373
   149
alpar@2373
   150
    ///Activate item \c i.
alpar@2373
   151
    ///\pre Item \c i shouldn't be active before.
alpar@2346
   152
    void activate(Item i)
alpar@2346
   153
    {
alpar@2346
   154
      const int l=_level[i];
alpar@2346
   155
      swap(_where[i],++_last_active[l]);
alpar@2346
   156
      if(l>_highest_active) _highest_active=l;
alpar@2346
   157
    }
alpar@2346
   158
  
alpar@2346
   159
    ///Deactivate item \c i.
alpar@2373
   160
alpar@2373
   161
    ///Deactivate item \c i.
alpar@2373
   162
    ///\pre Item \c i must be active before.
alpar@2346
   163
    void deactivate(Item i)  
alpar@2346
   164
    {
alpar@2346
   165
      swap(_where[i],_last_active[_level[i]]--);
alpar@2346
   166
      while(_highest_active>=0 &&
alpar@2346
   167
	    _last_active[_highest_active]<_first[_highest_active])
alpar@2346
   168
	_highest_active--;
alpar@2346
   169
    }
alpar@2346
   170
alpar@2346
   171
    ///Query whether item \c i is active
alpar@2346
   172
    bool active(Item i) const { return _where[i]<=_last_active[_level[i]]; }
alpar@2346
   173
    
alpar@2346
   174
    ///Return the level of item \c i.
alpar@2346
   175
    int operator[](Item i) const { return _level[i]; }
alpar@2346
   176
alpar@2346
   177
    ///Returns an active item on level \c l.
alpar@2346
   178
alpar@2346
   179
    ///Returns an active item on level \c l.
alpar@2346
   180
    ///
alpar@2346
   181
    ///Returns an active item on level \c l or \ref INVALID if there is no such
alpar@2346
   182
    ///an item. (\c l must be from the range [0...\c max_level].
alpar@2346
   183
    Item operator[](int l) const
alpar@2346
   184
    { 
alpar@2346
   185
      return _last_active[l]>=_first[l]?*_last_active[l]:INVALID;
alpar@2346
   186
    }
alpar@2346
   187
alpar@2346
   188
    ///Return the number of items on level \c l.
alpar@2348
   189
    int onLevel(int l) const
alpar@2346
   190
    {
alpar@2346
   191
      return _first[l+1]-_first[l];
alpar@2346
   192
    }
alpar@2348
   193
    ///Return the number of items above level \c l.
alpar@2348
   194
    int aboveLevel(int l) const
alpar@2348
   195
    {
alpar@2348
   196
      return _first[_max_level+1]-_first[l+1];
alpar@2348
   197
    }
alpar@2346
   198
    ///Return the number of active items on level \c l.
alpar@2348
   199
    int activesOnLevel(int l) const
alpar@2346
   200
    {
alpar@2346
   201
      return _last_active[l]-_first[l]+1;
alpar@2346
   202
    }
alpar@2346
   203
    ///Return the maximum allowed level.
alpar@2346
   204
    int maxLevel() const 
alpar@2346
   205
    {
alpar@2346
   206
      return _max_level;
alpar@2346
   207
    }    
alpar@2346
   208
alpar@2346
   209
    ///\name Highest Active Item
alpar@2346
   210
    ///Functions for working with the highest level
alpar@2346
   211
    ///active item.
alpar@2346
   212
alpar@2346
   213
    ///@{
alpar@2346
   214
alpar@2346
   215
    ///Return a highest level active item.
alpar@2346
   216
  
alpar@2346
   217
    ///Return a highest level active item.
alpar@2346
   218
    ///
alpar@2346
   219
    ///\return the highest level active item or INVALID if there is no active
alpar@2346
   220
    ///item.
alpar@2346
   221
    Item highestActive() const 
alpar@2346
   222
    {
alpar@2346
   223
      return _highest_active>=0?*_last_active[_highest_active]:INVALID;
alpar@2346
   224
    }
alpar@2346
   225
alpar@2346
   226
    ///Return a highest active level.
alpar@2346
   227
alpar@2346
   228
    ///Return a highest active level.
alpar@2346
   229
    ///
alpar@2346
   230
    ///\return the level of the highest active item or -1 if there is no active
alpar@2346
   231
    ///item.
athos@2349
   232
    int highestActiveLevel() const 
alpar@2346
   233
    {
alpar@2346
   234
      return _highest_active;
alpar@2346
   235
    }
alpar@2346
   236
alpar@2346
   237
    ///Lift the highest active item by one.
alpar@2346
   238
alpar@2346
   239
    ///Lift the item returned by highestActive() by one.
alpar@2346
   240
    ///
alpar@2346
   241
    void liftHighestActive() 
alpar@2346
   242
    {
alpar@2346
   243
      ++_level[*_last_active[_highest_active]];
alpar@2346
   244
      swap(_last_active[_highest_active]--,_last_active[_highest_active+1]);
alpar@2346
   245
      --_first[++_highest_active];
alpar@2346
   246
    }
alpar@2346
   247
alpar@2346
   248
    ///Lift the highest active item.
alpar@2346
   249
alpar@2346
   250
    ///Lift the item returned by highestActive() to level \c new_level.
alpar@2346
   251
    ///
alpar@2348
   252
    ///\warning \c new_level must be strictly higher
alpar@2348
   253
    ///than the current level.
alpar@2346
   254
    ///
alpar@2346
   255
    void liftHighestActiveTo(int new_level) 
alpar@2346
   256
    {
alpar@2346
   257
      const Item li = *_last_active[_highest_active];
alpar@2346
   258
      
alpar@2346
   259
      copy(--_first[_highest_active+1],_last_active[_highest_active]--);
alpar@2346
   260
      for(int l=_highest_active+1;l<new_level;l++)
alpar@2346
   261
	{
alpar@2346
   262
	  copy(--_first[l+1],_first[l]);
alpar@2346
   263
	  --_last_active[l];
alpar@2346
   264
	}
alpar@2346
   265
      copy(li,_first[new_level]);
alpar@2346
   266
      _level[li]=new_level;
alpar@2348
   267
      _highest_active=new_level;
alpar@2346
   268
    }
alpar@2346
   269
    
alpar@2346
   270
    ///@}
alpar@2346
   271
    
alpar@2348
   272
    ///Lift an active item to a higher level.
alpar@2348
   273
alpar@2348
   274
    ///Lift an active item to a higher level.
alpar@2350
   275
    ///\param i The item to be lifted. It must be active.
alpar@2350
   276
    ///\param new_level The new level of \c i. It must be strictly higher
alpar@2348
   277
    ///than the current level.
alpar@2348
   278
    ///
alpar@2348
   279
    void liftTo(Item i, int new_level) 
alpar@2348
   280
    {
alpar@2348
   281
      const int lo = _level[i];
alpar@2348
   282
      const Vit w = _where[i];
alpar@2348
   283
alpar@2348
   284
      copy(_last_active[lo],w);
alpar@2348
   285
      copy(--_first[lo+1],_last_active[lo]--);
alpar@2348
   286
      for(int l=lo+1;l<new_level;l++)
alpar@2348
   287
	{
alpar@2348
   288
	  copy(_last_active[l],_first[l]);
alpar@2348
   289
	  copy(--_first[l+1],_last_active[l]--);
alpar@2348
   290
	}
alpar@2348
   291
      copy(i,_first[new_level]);
alpar@2348
   292
      _level[i]=new_level;
alpar@2348
   293
      if(new_level>_highest_active) _highest_active=new_level;
alpar@2348
   294
    }
alpar@2348
   295
alpar@2348
   296
//     void liftToTop(int l) 
alpar@2348
   297
//     {
alpar@2348
   298
//       const Vit f=_first[l];
alpar@2348
   299
//       for(int i=l;i<=_max_level;i++)
alpar@2348
   300
// 	{
alpar@2348
   301
// 	  _first[i]=f;
alpar@2348
   302
// 	  _last_active[i]=f-1;
alpar@2348
   303
// 	}
alpar@2348
   304
//       for(Vit i=f;i!=_items.end();++i)
alpar@2348
   305
// 	_level[*i]=_max_level;
alpar@2348
   306
//       for(_highest_active=l-1;
alpar@2348
   307
// 	  _highest_active>=0 &&
alpar@2348
   308
// 	    _last_active[_highest_active]<_first[_highest_active];
alpar@2348
   309
// 	  _highest_active--) ;
alpar@2348
   310
//     }
alpar@2348
   311
    
alpar@2348
   312
    ///Lift all nodes on and above a level to the top (and deactivate them).
alpar@2348
   313
alpar@2348
   314
    ///This function lifts all nodes on and above level \c l to \c maxLevel(),
alpar@2348
   315
    ///and
alpar@2348
   316
    ///also deactivates them.
alpar@2348
   317
    void liftToTop(int l) 
alpar@2348
   318
    {
alpar@2348
   319
      const Vit f=_first[l];
alpar@2348
   320
      const Vit tl=_first[_max_level];
alpar@2348
   321
      for(Vit i=f;i!=tl;++i)
alpar@2348
   322
	_level[*i]=_max_level;
alpar@2348
   323
      for(int i=l;i<=_max_level;i++)
alpar@2348
   324
	{
alpar@2348
   325
	  _first[i]=f;
alpar@2348
   326
	  _last_active[i]=f-1;
alpar@2348
   327
	}
alpar@2348
   328
      for(_highest_active=l-1;
alpar@2348
   329
	  _highest_active>=0 &&
alpar@2348
   330
	    _last_active[_highest_active]<_first[_highest_active];
alpar@2348
   331
	  _highest_active--) ;
alpar@2348
   332
    }
alpar@2348
   333
    
alpar@2346
   334
  private:
alpar@2346
   335
    int _init_lev;
alpar@2346
   336
    Vit _init_num;
alpar@2346
   337
alpar@2346
   338
  public:
alpar@2346
   339
alpar@2346
   340
    ///\name Initialization
alpar@2346
   341
    ///Using this function you can initialize the levels of the item.
alpar@2346
   342
    ///\n
alpar@2346
   343
    ///This initializatios is started with calling \c initStart().
alpar@2346
   344
    ///Then the
alpar@2346
   345
    ///items should be listed levels by levels statring with the lowest one
alpar@2346
   346
    ///(with level 0). This is done by using \c initAddItem()
alpar@2346
   347
    ///and \c initNewLevel(). Finally \c initFinish() must be called.
alpar@2348
   348
    ///The items not listed will be put on the highest level.
alpar@2346
   349
    ///@{
alpar@2346
   350
alpar@2348
   351
    ///Start the initialization process.
alpar@2346
   352
alpar@2346
   353
    void initStart() 
alpar@2346
   354
    {
alpar@2346
   355
      _init_lev=0;
alpar@2346
   356
      _init_num=_items.begin();
alpar@2346
   357
      _first[0]=_items.begin();
alpar@2346
   358
      _last_active[0]=_items.begin()-1;
alpar@2346
   359
      Vit n=_items.begin();
alpar@2346
   360
      for(typename ItemSetTraits<Graph,Item>::ItemIt i(_g);i!=INVALID;++i)
alpar@2346
   361
	{
alpar@2346
   362
	  *n=i;
alpar@2346
   363
	  _where[i]=n;
alpar@2346
   364
	  _level[i]=_max_level;
alpar@2346
   365
	  ++n;
alpar@2346
   366
	}
alpar@2346
   367
    }
alpar@2346
   368
alpar@2346
   369
    ///Add an item to the current level.
alpar@2346
   370
alpar@2346
   371
    void initAddItem(Item i)
alpar@2346
   372
    { 
alpar@2346
   373
     swap(_where[i],_init_num);
alpar@2346
   374
      _level[i]=_init_lev;
alpar@2346
   375
      ++_init_num;
alpar@2346
   376
    }
alpar@2346
   377
alpar@2346
   378
    ///Start a new level.
alpar@2346
   379
alpar@2346
   380
    ///Start a new level.
alpar@2346
   381
    ///It shouldn't be used before the items on level 0 are listed.
alpar@2346
   382
    void initNewLevel() 
alpar@2346
   383
    {
alpar@2346
   384
      _init_lev++;
alpar@2346
   385
      _first[_init_lev]=_init_num;
alpar@2346
   386
      _last_active[_init_lev]=_init_num-1;
alpar@2346
   387
    }
alpar@2346
   388
alpar@2348
   389
    ///Finalize the initialization process.
alpar@2346
   390
alpar@2346
   391
    void initFinish()
alpar@2346
   392
    {
alpar@2346
   393
      for(_init_lev++;_init_lev<=_max_level;_init_lev++)
alpar@2346
   394
	{
alpar@2346
   395
	  _first[_init_lev]=_init_num;
alpar@2346
   396
	  _last_active[_init_lev]=_init_num-1;
alpar@2346
   397
	}
alpar@2346
   398
      _first[_max_level+1]=_items.begin()+_item_num;
alpar@2346
   399
      _last_active[_max_level+1]=_items.begin()+_item_num-1;
alpar@2346
   400
    }
alpar@2346
   401
alpar@2346
   402
    ///@}
alpar@2346
   403
alpar@2346
   404
  };
alpar@2346
   405
alpar@2346
   406
} //END OF NAMESPACE LEMON
alpar@2346
   407
alpar@2346
   408
#endif
alpar@2346
   409