lemon/elevator.h
author Alpar Juttner <alpar@cs.elte.hu>
Fri, 21 Nov 2008 10:41:36 +0000
changeset 382 61fbd77f0f44
parent 381 b04e431907bc
child 383 a8a22a96d495
permissions -rw-r--r--
Don't assume that the default maps are reference maps (in Elevator)
alpar@379
     1
/* -*- mode: C++; indent-tabs-mode: nil; -*-
alpar@379
     2
 *
alpar@379
     3
 * This file is a part of LEMON, a generic C++ optimization library.
alpar@379
     4
 *
alpar@379
     5
 * Copyright (C) 2003-2008
alpar@379
     6
 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
alpar@379
     7
 * (Egervary Research Group on Combinatorial Optimization, EGRES).
alpar@379
     8
 *
alpar@379
     9
 * Permission to use, modify and distribute this software is granted
alpar@379
    10
 * provided that this copyright notice appears in all copies. For
alpar@379
    11
 * precise terms see the accompanying LICENSE file.
alpar@379
    12
 *
alpar@379
    13
 * This software is provided "AS IS" with no warranty of any kind,
alpar@379
    14
 * express or implied, and with no claim as to its suitability for any
alpar@379
    15
 * purpose.
alpar@379
    16
 *
alpar@379
    17
 */
alpar@379
    18
alpar@379
    19
#ifndef LEMON_ELEVATOR_H
alpar@379
    20
#define LEMON_ELEVATOR_H
alpar@379
    21
alpar@379
    22
///\ingroup auxdat
alpar@379
    23
///\file
alpar@379
    24
///\brief Elevator class
alpar@379
    25
///
alpar@379
    26
///Elevator class implements an efficient data structure
alpar@379
    27
///for labeling items in push-relabel type algorithms.
alpar@379
    28
///
alpar@379
    29
alpar@379
    30
#include <test/test_tools.h>
alpar@379
    31
namespace lemon {
alpar@379
    32
alpar@379
    33
  ///Class for handling "labels" in push-relabel type algorithms.
alpar@379
    34
alpar@379
    35
  ///A class for handling "labels" in push-relabel type algorithms.
alpar@379
    36
  ///
alpar@379
    37
  ///\ingroup auxdat
alpar@379
    38
  ///Using this class you can assign "labels" (nonnegative integer numbers)
alpar@379
    39
  ///to the edges or nodes of a graph, manipulate and query them through
alpar@379
    40
  ///operations typically arising in "push-relabel" type algorithms.
alpar@379
    41
  ///
alpar@379
    42
  ///Each item is either \em active or not, and you can also choose a
alpar@379
    43
  ///highest level active item.
alpar@379
    44
  ///
alpar@379
    45
  ///\sa LinkedElevator
alpar@379
    46
  ///
alpar@379
    47
  ///\param Graph the underlying graph type
alpar@379
    48
  ///\param Item Type of the items the data is assigned to (Graph::Node,
alpar@379
    49
  ///Graph::Edge, Graph::UEdge)
alpar@379
    50
  template<class Graph, class Item>
alpar@379
    51
  class Elevator
alpar@379
    52
  {
alpar@379
    53
  public:
alpar@379
    54
alpar@379
    55
    typedef Item Key;
alpar@379
    56
    typedef int Value;
alpar@379
    57
alpar@379
    58
  private:
alpar@379
    59
alpar@381
    60
    typedef Item *Vit;
alpar@379
    61
    typedef typename ItemSetTraits<Graph,Item>::template Map<Vit>::Type VitMap;
alpar@379
    62
    typedef typename ItemSetTraits<Graph,Item>::template Map<int>::Type IntMap;
alpar@379
    63
alpar@379
    64
    const Graph &_g;
alpar@379
    65
    int _max_level;
alpar@379
    66
    int _item_num;
alpar@379
    67
    VitMap _where;
alpar@379
    68
    IntMap _level;
alpar@379
    69
    std::vector<Item> _items;
alpar@379
    70
    std::vector<Vit> _first;
alpar@379
    71
    std::vector<Vit> _last_active;
alpar@379
    72
alpar@379
    73
    int _highest_active;
alpar@379
    74
alpar@379
    75
    void copy(Item i, Vit p)
alpar@379
    76
    {
alpar@382
    77
      _where.set(*p=i,p);
alpar@379
    78
    }
alpar@379
    79
    void copy(Vit s, Vit p)
alpar@379
    80
    {
alpar@379
    81
      if(s!=p)
alpar@379
    82
        {
alpar@379
    83
          Item i=*s;
alpar@379
    84
          *p=i;
alpar@382
    85
          _where.set(i,p);
alpar@379
    86
        }
alpar@379
    87
    }
alpar@379
    88
    void swap(Vit i, Vit j)
alpar@379
    89
    {
alpar@379
    90
      Item ti=*i;
alpar@379
    91
      Vit ct = _where[ti];
alpar@382
    92
      _where.set(ti,_where[*i=*j]);
alpar@382
    93
      _where.set(*j,ct);
alpar@379
    94
      *j=ti;
alpar@379
    95
    }
alpar@379
    96
alpar@379
    97
  public:
alpar@379
    98
alpar@379
    99
    ///Constructor with given maximum level.
alpar@379
   100
alpar@379
   101
    ///Constructor with given maximum level.
alpar@379
   102
    ///
alpar@379
   103
    ///\param g The underlying graph
alpar@379
   104
    ///\param max_level Set the range of the possible labels to
alpar@379
   105
    ///[0...\c max_level]
alpar@379
   106
    Elevator(const Graph &g,int max_level) :
alpar@379
   107
      _g(g),
alpar@379
   108
      _max_level(max_level),
alpar@379
   109
      _item_num(_max_level),
alpar@379
   110
      _where(g),
alpar@379
   111
      _level(g,0),
alpar@379
   112
      _items(_max_level),
alpar@379
   113
      _first(_max_level+2),
alpar@379
   114
      _last_active(_max_level+2),
alpar@379
   115
      _highest_active(-1) {}
alpar@379
   116
    ///Constructor.
alpar@379
   117
alpar@379
   118
    ///Constructor.
alpar@379
   119
    ///
alpar@379
   120
    ///\param g The underlying graph
alpar@379
   121
    ///The range of the possible labels is [0...\c max_level],
alpar@379
   122
    ///where \c max_level is equal to the number of labeled items in the graph.
alpar@379
   123
    Elevator(const Graph &g) :
alpar@379
   124
      _g(g),
alpar@379
   125
      _max_level(countItems<Graph, Item>(g)),
alpar@379
   126
      _item_num(_max_level),
alpar@379
   127
      _where(g),
alpar@379
   128
      _level(g,0),
alpar@379
   129
      _items(_max_level),
alpar@379
   130
      _first(_max_level+2),
alpar@379
   131
      _last_active(_max_level+2),
alpar@379
   132
      _highest_active(-1)
alpar@379
   133
    {
alpar@379
   134
    }
alpar@379
   135
alpar@379
   136
    ///Activate item \c i.
alpar@379
   137
alpar@379
   138
    ///Activate item \c i.
alpar@379
   139
    ///\pre Item \c i shouldn't be active before.
alpar@379
   140
    void activate(Item i)
alpar@379
   141
    {
alpar@379
   142
      const int l=_level[i];
alpar@379
   143
      swap(_where[i],++_last_active[l]);
alpar@379
   144
      if(l>_highest_active) _highest_active=l;
alpar@379
   145
    }
alpar@379
   146
alpar@379
   147
    ///Deactivate item \c i.
alpar@379
   148
alpar@379
   149
    ///Deactivate item \c i.
alpar@379
   150
    ///\pre Item \c i must be active before.
alpar@379
   151
    void deactivate(Item i)
alpar@379
   152
    {
alpar@379
   153
      swap(_where[i],_last_active[_level[i]]--);
alpar@379
   154
      while(_highest_active>=0 &&
alpar@379
   155
            _last_active[_highest_active]<_first[_highest_active])
alpar@379
   156
        _highest_active--;
alpar@379
   157
    }
alpar@379
   158
alpar@379
   159
    ///Query whether item \c i is active
alpar@379
   160
    bool active(Item i) const { return _where[i]<=_last_active[_level[i]]; }
alpar@379
   161
alpar@379
   162
    ///Return the level of item \c i.
alpar@379
   163
    int operator[](Item i) const { return _level[i]; }
alpar@379
   164
alpar@379
   165
    ///Return the number of items on level \c l.
alpar@379
   166
    int onLevel(int l) const
alpar@379
   167
    {
alpar@379
   168
      return _first[l+1]-_first[l];
alpar@379
   169
    }
alpar@379
   170
    ///Return true if the level is empty.
alpar@379
   171
    bool emptyLevel(int l) const
alpar@379
   172
    {
alpar@379
   173
      return _first[l+1]-_first[l]==0;
alpar@379
   174
    }
alpar@379
   175
    ///Return the number of items above level \c l.
alpar@379
   176
    int aboveLevel(int l) const
alpar@379
   177
    {
alpar@379
   178
      return _first[_max_level+1]-_first[l+1];
alpar@379
   179
    }
alpar@379
   180
    ///Return the number of active items on level \c l.
alpar@379
   181
    int activesOnLevel(int l) const
alpar@379
   182
    {
alpar@379
   183
      return _last_active[l]-_first[l]+1;
alpar@379
   184
    }
alpar@379
   185
    ///Return true if there is not active item on level \c l.
alpar@379
   186
    bool activeFree(int l) const
alpar@379
   187
    {
alpar@379
   188
      return _last_active[l]<_first[l];
alpar@379
   189
    }
alpar@379
   190
    ///Return the maximum allowed level.
alpar@379
   191
    int maxLevel() const
alpar@379
   192
    {
alpar@379
   193
      return _max_level;
alpar@379
   194
    }
alpar@379
   195
alpar@379
   196
    ///\name Highest Active Item
alpar@379
   197
    ///Functions for working with the highest level
alpar@379
   198
    ///active item.
alpar@379
   199
alpar@379
   200
    ///@{
alpar@379
   201
alpar@379
   202
    ///Return a highest level active item.
alpar@379
   203
alpar@379
   204
    ///Return a highest level active item.
alpar@379
   205
    ///
alpar@379
   206
    ///\return the highest level active item or INVALID if there is no active
alpar@379
   207
    ///item.
alpar@379
   208
    Item highestActive() const
alpar@379
   209
    {
alpar@379
   210
      return _highest_active>=0?*_last_active[_highest_active]:INVALID;
alpar@379
   211
    }
alpar@379
   212
alpar@379
   213
    ///Return a highest active level.
alpar@379
   214
alpar@379
   215
    ///Return a highest active level.
alpar@379
   216
    ///
alpar@379
   217
    ///\return the level of the highest active item or -1 if there is no active
alpar@379
   218
    ///item.
alpar@379
   219
    int highestActiveLevel() const
alpar@379
   220
    {
alpar@379
   221
      return _highest_active;
alpar@379
   222
    }
alpar@379
   223
alpar@379
   224
    ///Lift the highest active item by one.
alpar@379
   225
alpar@379
   226
    ///Lift the item returned by highestActive() by one.
alpar@379
   227
    ///
alpar@379
   228
    void liftHighestActive()
alpar@379
   229
    {
alpar@382
   230
      Item it = *_last_active[_highest_active];
alpar@382
   231
      _level.set(it,_level[it]+1);
alpar@379
   232
      swap(_last_active[_highest_active]--,_last_active[_highest_active+1]);
alpar@379
   233
      --_first[++_highest_active];
alpar@379
   234
    }
alpar@379
   235
alpar@379
   236
    ///Lift the highest active item.
alpar@379
   237
alpar@379
   238
    ///Lift the item returned by highestActive() to level \c new_level.
alpar@379
   239
    ///
alpar@379
   240
    ///\warning \c new_level must be strictly higher
alpar@379
   241
    ///than the current level.
alpar@379
   242
    ///
alpar@379
   243
    void liftHighestActive(int new_level)
alpar@379
   244
    {
alpar@379
   245
      const Item li = *_last_active[_highest_active];
alpar@379
   246
alpar@379
   247
      copy(--_first[_highest_active+1],_last_active[_highest_active]--);
alpar@379
   248
      for(int l=_highest_active+1;l<new_level;l++)
alpar@379
   249
        {
alpar@379
   250
          copy(--_first[l+1],_first[l]);
alpar@379
   251
          --_last_active[l];
alpar@379
   252
        }
alpar@379
   253
      copy(li,_first[new_level]);
alpar@382
   254
      _level.set(li,new_level);
alpar@379
   255
      _highest_active=new_level;
alpar@379
   256
    }
alpar@379
   257
alpar@379
   258
    ///Lift the highest active item.
alpar@379
   259
alpar@379
   260
    ///Lift the item returned by highestActive() to the top level and
alpar@379
   261
    ///deactivates it.
alpar@379
   262
    ///
alpar@379
   263
    ///\warning \c new_level must be strictly higher
alpar@379
   264
    ///than the current level.
alpar@379
   265
    ///
alpar@379
   266
    void liftHighestActiveToTop()
alpar@379
   267
    {
alpar@379
   268
      const Item li = *_last_active[_highest_active];
alpar@379
   269
alpar@379
   270
      copy(--_first[_highest_active+1],_last_active[_highest_active]--);
alpar@379
   271
      for(int l=_highest_active+1;l<_max_level;l++)
alpar@379
   272
        {
alpar@379
   273
          copy(--_first[l+1],_first[l]);
alpar@379
   274
          --_last_active[l];
alpar@379
   275
        }
alpar@379
   276
      copy(li,_first[_max_level]);
alpar@379
   277
      --_last_active[_max_level];
alpar@382
   278
      _level.set(li,_max_level);
alpar@379
   279
alpar@379
   280
      while(_highest_active>=0 &&
alpar@379
   281
            _last_active[_highest_active]<_first[_highest_active])
alpar@379
   282
        _highest_active--;
alpar@379
   283
    }
alpar@379
   284
alpar@379
   285
    ///@}
alpar@379
   286
alpar@379
   287
    ///\name Active Item on Certain Level
alpar@379
   288
    ///Functions for working with the active items.
alpar@379
   289
alpar@379
   290
    ///@{
alpar@379
   291
alpar@379
   292
    ///Returns an active item on level \c l.
alpar@379
   293
alpar@379
   294
    ///Returns an active item on level \c l.
alpar@379
   295
    ///
alpar@379
   296
    ///Returns an active item on level \c l or \ref INVALID if there is no such
alpar@379
   297
    ///an item. (\c l must be from the range [0...\c max_level].
alpar@379
   298
    Item activeOn(int l) const
alpar@379
   299
    {
alpar@379
   300
      return _last_active[l]>=_first[l]?*_last_active[l]:INVALID;
alpar@379
   301
    }
alpar@379
   302
alpar@379
   303
    ///Lifts the active item returned by \c activeOn() member function.
alpar@379
   304
alpar@379
   305
    ///Lifts the active item returned by \c activeOn() member function
alpar@379
   306
    ///by one.
alpar@379
   307
    Item liftActiveOn(int level)
alpar@379
   308
    {
alpar@382
   309
      Item it =*_last_active[level];
alpar@382
   310
      _level.set(it,_level[it]+1);
alpar@379
   311
      swap(_last_active[level]--, --_first[level+1]);
alpar@379
   312
      if (level+1>_highest_active) ++_highest_active;
alpar@379
   313
    }
alpar@379
   314
alpar@379
   315
    ///Lifts the active item returned by \c activeOn() member function.
alpar@379
   316
alpar@379
   317
    ///Lifts the active item returned by \c activeOn() member function
alpar@379
   318
    ///to the given level.
alpar@379
   319
    void liftActiveOn(int level, int new_level)
alpar@379
   320
    {
alpar@379
   321
      const Item ai = *_last_active[level];
alpar@379
   322
alpar@379
   323
      copy(--_first[level+1], _last_active[level]--);
alpar@379
   324
      for(int l=level+1;l<new_level;l++)
alpar@379
   325
        {
alpar@379
   326
          copy(_last_active[l],_first[l]);
alpar@379
   327
          copy(--_first[l+1], _last_active[l]--);
alpar@379
   328
        }
alpar@379
   329
      copy(ai,_first[new_level]);
alpar@382
   330
      _level.set(ai,new_level);
alpar@379
   331
      if (new_level>_highest_active) _highest_active=new_level;
alpar@379
   332
    }
alpar@379
   333
alpar@379
   334
    ///Lifts the active item returned by \c activeOn() member function.
alpar@379
   335
alpar@379
   336
    ///Lifts the active item returned by \c activeOn() member function
alpar@379
   337
    ///to the top level.
alpar@379
   338
    void liftActiveToTop(int level)
alpar@379
   339
    {
alpar@379
   340
      const Item ai = *_last_active[level];
alpar@379
   341
alpar@379
   342
      copy(--_first[level+1],_last_active[level]--);
alpar@379
   343
      for(int l=level+1;l<_max_level;l++)
alpar@379
   344
        {
alpar@379
   345
          copy(_last_active[l],_first[l]);
alpar@379
   346
          copy(--_first[l+1], _last_active[l]--);
alpar@379
   347
        }
alpar@379
   348
      copy(ai,_first[_max_level]);
alpar@379
   349
      --_last_active[_max_level];
alpar@382
   350
      _level.set(ai,_max_level);
alpar@379
   351
alpar@379
   352
      if (_highest_active==level) {
alpar@379
   353
        while(_highest_active>=0 &&
alpar@379
   354
              _last_active[_highest_active]<_first[_highest_active])
alpar@379
   355
          _highest_active--;
alpar@379
   356
      }
alpar@379
   357
    }
alpar@379
   358
alpar@379
   359
    ///@}
alpar@379
   360
alpar@379
   361
    ///Lift an active item to a higher level.
alpar@379
   362
alpar@379
   363
    ///Lift an active item to a higher level.
alpar@379
   364
    ///\param i The item to be lifted. It must be active.
alpar@379
   365
    ///\param new_level The new level of \c i. It must be strictly higher
alpar@379
   366
    ///than the current level.
alpar@379
   367
    ///
alpar@379
   368
    void lift(Item i, int new_level)
alpar@379
   369
    {
alpar@379
   370
      const int lo = _level[i];
alpar@379
   371
      const Vit w = _where[i];
alpar@379
   372
alpar@379
   373
      copy(_last_active[lo],w);
alpar@379
   374
      copy(--_first[lo+1],_last_active[lo]--);
alpar@379
   375
      for(int l=lo+1;l<new_level;l++)
alpar@379
   376
        {
alpar@379
   377
          copy(_last_active[l],_first[l]);
alpar@379
   378
          copy(--_first[l+1],_last_active[l]--);
alpar@379
   379
        }
alpar@379
   380
      copy(i,_first[new_level]);
alpar@382
   381
      _level.set(i,new_level);
alpar@379
   382
      if(new_level>_highest_active) _highest_active=new_level;
alpar@379
   383
    }
alpar@379
   384
alpar@380
   385
    ///Move an inactive item to the top but one level (in a dirty way).
alpar@379
   386
alpar@380
   387
    ///This function moves an inactive item to the top but one level.
alpar@380
   388
    ///It makes the underlying datastructure corrupt, so use is only if
alpar@380
   389
    ///you really know what it is for.
alpar@380
   390
    ///\pre The item is on the top level.
alpar@380
   391
    void dirtyTopButOne(Item i) {
alpar@382
   392
      _level.set(i,_max_level - 1);
alpar@379
   393
    }
alpar@379
   394
alpar@380
   395
    ///Lift all items on and above a level to the top (and deactivate them).
alpar@379
   396
alpar@380
   397
    ///This function lifts all items on and above level \c l to \c
alpar@379
   398
    ///maxLevel(), and also deactivates them.
alpar@379
   399
    void liftToTop(int l)
alpar@379
   400
    {
alpar@379
   401
      const Vit f=_first[l];
alpar@379
   402
      const Vit tl=_first[_max_level];
alpar@379
   403
      for(Vit i=f;i!=tl;++i)
alpar@382
   404
        _level.set(*i,_max_level);
alpar@379
   405
      for(int i=l;i<=_max_level;i++)
alpar@379
   406
        {
alpar@379
   407
          _first[i]=f;
alpar@379
   408
          _last_active[i]=f-1;
alpar@379
   409
        }
alpar@379
   410
      for(_highest_active=l-1;
alpar@379
   411
          _highest_active>=0 &&
alpar@379
   412
            _last_active[_highest_active]<_first[_highest_active];
alpar@379
   413
          _highest_active--) ;
alpar@379
   414
    }
alpar@379
   415
alpar@379
   416
  private:
alpar@379
   417
    int _init_lev;
alpar@379
   418
    Vit _init_num;
alpar@379
   419
alpar@379
   420
  public:
alpar@379
   421
alpar@379
   422
    ///\name Initialization
alpar@379
   423
    ///Using this function you can initialize the levels of the item.
alpar@379
   424
    ///\n
alpar@379
   425
    ///This initializatios is started with calling \c initStart().
alpar@379
   426
    ///Then the
alpar@379
   427
    ///items should be listed levels by levels statring with the lowest one
alpar@379
   428
    ///(with level 0). This is done by using \c initAddItem()
alpar@379
   429
    ///and \c initNewLevel(). Finally \c initFinish() must be called.
alpar@379
   430
    ///The items not listed will be put on the highest level.
alpar@379
   431
    ///@{
alpar@379
   432
alpar@379
   433
    ///Start the initialization process.
alpar@379
   434
alpar@379
   435
    void initStart()
alpar@379
   436
    {
alpar@379
   437
      _init_lev=0;
alpar@381
   438
      _init_num=&_items[0];
alpar@381
   439
      _first[0]=&_items[0];
alpar@381
   440
      _last_active[0]=&_items[0]-1;
alpar@381
   441
      Vit n=&_items[0];
alpar@379
   442
      for(typename ItemSetTraits<Graph,Item>::ItemIt i(_g);i!=INVALID;++i)
alpar@379
   443
        {
alpar@379
   444
          *n=i;
alpar@382
   445
          _where.set(i,n);
alpar@382
   446
          _level.set(i,_max_level);
alpar@379
   447
          ++n;
alpar@379
   448
        }
alpar@379
   449
    }
alpar@379
   450
alpar@379
   451
    ///Add an item to the current level.
alpar@379
   452
alpar@379
   453
    void initAddItem(Item i)
alpar@379
   454
    {
alpar@382
   455
      swap(_where[i],_init_num);
alpar@382
   456
      _level.set(i,_init_lev);
alpar@379
   457
      ++_init_num;
alpar@379
   458
    }
alpar@379
   459
alpar@379
   460
    ///Start a new level.
alpar@379
   461
alpar@379
   462
    ///Start a new level.
alpar@379
   463
    ///It shouldn't be used before the items on level 0 are listed.
alpar@379
   464
    void initNewLevel()
alpar@379
   465
    {
alpar@379
   466
      _init_lev++;
alpar@379
   467
      _first[_init_lev]=_init_num;
alpar@379
   468
      _last_active[_init_lev]=_init_num-1;
alpar@379
   469
    }
alpar@379
   470
alpar@379
   471
    ///Finalize the initialization process.
alpar@379
   472
alpar@379
   473
    void initFinish()
alpar@379
   474
    {
alpar@379
   475
      for(_init_lev++;_init_lev<=_max_level;_init_lev++)
alpar@379
   476
        {
alpar@379
   477
          _first[_init_lev]=_init_num;
alpar@379
   478
          _last_active[_init_lev]=_init_num-1;
alpar@379
   479
        }
alpar@381
   480
      _first[_max_level+1]=&_items[0]+_item_num;
alpar@381
   481
      _last_active[_max_level+1]=&_items[0]+_item_num-1;
alpar@379
   482
      _highest_active = -1;
alpar@379
   483
    }
alpar@379
   484
alpar@379
   485
    ///@}
alpar@379
   486
alpar@379
   487
  };
alpar@379
   488
alpar@379
   489
  ///Class for handling "labels" in push-relabel type algorithms.
alpar@379
   490
alpar@379
   491
  ///A class for handling "labels" in push-relabel type algorithms.
alpar@379
   492
  ///
alpar@379
   493
  ///\ingroup auxdat
alpar@379
   494
  ///Using this class you can assign "labels" (nonnegative integer numbers)
alpar@379
   495
  ///to the edges or nodes of a graph, manipulate and query them through
alpar@379
   496
  ///operations typically arising in "push-relabel" type algorithms.
alpar@379
   497
  ///
alpar@379
   498
  ///Each item is either \em active or not, and you can also choose a
alpar@379
   499
  ///highest level active item.
alpar@379
   500
  ///
alpar@379
   501
  ///\sa Elevator
alpar@379
   502
  ///
alpar@379
   503
  ///\param Graph the underlying graph type
alpar@379
   504
  ///\param Item Type of the items the data is assigned to (Graph::Node,
alpar@379
   505
  ///Graph::Edge, Graph::UEdge)
alpar@379
   506
  template <class Graph, class Item>
alpar@379
   507
  class LinkedElevator {
alpar@379
   508
  public:
alpar@379
   509
alpar@379
   510
    typedef Item Key;
alpar@379
   511
    typedef int Value;
alpar@379
   512
alpar@379
   513
  private:
alpar@379
   514
alpar@379
   515
    typedef typename ItemSetTraits<Graph,Item>::
alpar@379
   516
    template Map<Item>::Type ItemMap;
alpar@379
   517
    typedef typename ItemSetTraits<Graph,Item>::
alpar@379
   518
    template Map<int>::Type IntMap;
alpar@379
   519
    typedef typename ItemSetTraits<Graph,Item>::
alpar@379
   520
    template Map<bool>::Type BoolMap;
alpar@379
   521
alpar@379
   522
    const Graph &_graph;
alpar@379
   523
    int _max_level;
alpar@379
   524
    int _item_num;
alpar@379
   525
    std::vector<Item> _first, _last;
alpar@379
   526
    ItemMap _prev, _next;
alpar@379
   527
    int _highest_active;
alpar@379
   528
    IntMap _level;
alpar@379
   529
    BoolMap _active;
alpar@379
   530
alpar@379
   531
  public:
alpar@379
   532
    ///Constructor with given maximum level.
alpar@379
   533
alpar@379
   534
    ///Constructor with given maximum level.
alpar@379
   535
    ///
alpar@379
   536
    ///\param g The underlying graph
alpar@379
   537
    ///\param max_level Set the range of the possible labels to
alpar@379
   538
    ///[0...\c max_level]
alpar@379
   539
    LinkedElevator(const Graph& graph, int max_level)
alpar@379
   540
      : _graph(graph), _max_level(max_level), _item_num(_max_level),
alpar@379
   541
        _first(_max_level + 1), _last(_max_level + 1),
alpar@379
   542
        _prev(graph), _next(graph),
alpar@379
   543
        _highest_active(-1), _level(graph), _active(graph) {}
alpar@379
   544
alpar@379
   545
    ///Constructor.
alpar@379
   546
alpar@379
   547
    ///Constructor.
alpar@379
   548
    ///
alpar@379
   549
    ///\param g The underlying graph
alpar@379
   550
    ///The range of the possible labels is [0...\c max_level],
alpar@379
   551
    ///where \c max_level is equal to the number of labeled items in the graph.
alpar@379
   552
    LinkedElevator(const Graph& graph)
alpar@379
   553
      : _graph(graph), _max_level(countItems<Graph, Item>(graph)),
alpar@379
   554
        _item_num(_max_level),
alpar@379
   555
        _first(_max_level + 1), _last(_max_level + 1),
alpar@379
   556
        _prev(graph, INVALID), _next(graph, INVALID),
alpar@379
   557
        _highest_active(-1), _level(graph), _active(graph) {}
alpar@379
   558
alpar@379
   559
alpar@379
   560
    ///Activate item \c i.
alpar@379
   561
alpar@379
   562
    ///Activate item \c i.
alpar@379
   563
    ///\pre Item \c i shouldn't be active before.
alpar@379
   564
    void activate(Item i) {
alpar@379
   565
      _active.set(i, true);
alpar@379
   566
alpar@379
   567
      int level = _level[i];
alpar@379
   568
      if (level > _highest_active) {
alpar@379
   569
        _highest_active = level;
alpar@379
   570
      }
alpar@379
   571
alpar@379
   572
      if (_prev[i] == INVALID || _active[_prev[i]]) return;
alpar@379
   573
      //unlace
alpar@379
   574
      _next.set(_prev[i], _next[i]);
alpar@379
   575
      if (_next[i] != INVALID) {
alpar@379
   576
        _prev.set(_next[i], _prev[i]);
alpar@379
   577
      } else {
alpar@379
   578
        _last[level] = _prev[i];
alpar@379
   579
      }
alpar@379
   580
      //lace
alpar@379
   581
      _next.set(i, _first[level]);
alpar@379
   582
      _prev.set(_first[level], i);
alpar@379
   583
      _prev.set(i, INVALID);
alpar@379
   584
      _first[level] = i;
alpar@379
   585
alpar@379
   586
    }
alpar@379
   587
alpar@379
   588
    ///Deactivate item \c i.
alpar@379
   589
alpar@379
   590
    ///Deactivate item \c i.
alpar@379
   591
    ///\pre Item \c i must be active before.
alpar@379
   592
    void deactivate(Item i) {
alpar@379
   593
      _active.set(i, false);
alpar@379
   594
      int level = _level[i];
alpar@379
   595
alpar@379
   596
      if (_next[i] == INVALID || !_active[_next[i]])
alpar@379
   597
        goto find_highest_level;
alpar@379
   598
alpar@379
   599
      //unlace
alpar@379
   600
      _prev.set(_next[i], _prev[i]);
alpar@379
   601
      if (_prev[i] != INVALID) {
alpar@379
   602
        _next.set(_prev[i], _next[i]);
alpar@379
   603
      } else {
alpar@379
   604
        _first[_level[i]] = _next[i];
alpar@379
   605
      }
alpar@379
   606
      //lace
alpar@379
   607
      _prev.set(i, _last[level]);
alpar@379
   608
      _next.set(_last[level], i);
alpar@379
   609
      _next.set(i, INVALID);
alpar@379
   610
      _last[level] = i;
alpar@379
   611
alpar@379
   612
    find_highest_level:
alpar@379
   613
      if (level == _highest_active) {
alpar@379
   614
        while (_highest_active >= 0 && activeFree(_highest_active))
alpar@379
   615
          --_highest_active;
alpar@379
   616
      }
alpar@379
   617
    }
alpar@379
   618
alpar@379
   619
    ///Query whether item \c i is active
alpar@379
   620
    bool active(Item i) const { return _active[i]; }
alpar@379
   621
alpar@379
   622
    ///Return the level of item \c i.
alpar@379
   623
    int operator[](Item i) const { return _level[i]; }
alpar@379
   624
alpar@379
   625
    ///Return the number of items on level \c l.
alpar@379
   626
    int onLevel(int l) const {
alpar@379
   627
      int num = 0;
alpar@379
   628
      Item n = _first[l];
alpar@379
   629
      while (n != INVALID) {
alpar@379
   630
        ++num;
alpar@379
   631
        n = _next[n];
alpar@379
   632
      }
alpar@379
   633
      return num;
alpar@379
   634
    }
alpar@379
   635
alpar@379
   636
    ///Return true if the level is empty.
alpar@379
   637
    bool emptyLevel(int l) const {
alpar@379
   638
      return _first[l] == INVALID;
alpar@379
   639
    }
alpar@379
   640
alpar@379
   641
    ///Return the number of items above level \c l.
alpar@379
   642
    int aboveLevel(int l) const {
alpar@379
   643
      int num = 0;
alpar@379
   644
      for (int level = l + 1; level < _max_level; ++level)
alpar@379
   645
        num += onLevel(level);
alpar@379
   646
      return num;
alpar@379
   647
    }
alpar@379
   648
alpar@379
   649
    ///Return the number of active items on level \c l.
alpar@379
   650
    int activesOnLevel(int l) const {
alpar@379
   651
      int num = 0;
alpar@379
   652
      Item n = _first[l];
alpar@379
   653
      while (n != INVALID && _active[n]) {
alpar@379
   654
        ++num;
alpar@379
   655
        n = _next[n];
alpar@379
   656
      }
alpar@379
   657
      return num;
alpar@379
   658
    }
alpar@379
   659
alpar@379
   660
    ///Return true if there is not active item on level \c l.
alpar@379
   661
    bool activeFree(int l) const {
alpar@379
   662
      return _first[l] == INVALID || !_active[_first[l]];
alpar@379
   663
    }
alpar@379
   664
alpar@379
   665
    ///Return the maximum allowed level.
alpar@379
   666
    int maxLevel() const {
alpar@379
   667
      return _max_level;
alpar@379
   668
    }
alpar@379
   669
alpar@379
   670
    ///\name Highest Active Item
alpar@379
   671
    ///Functions for working with the highest level
alpar@379
   672
    ///active item.
alpar@379
   673
alpar@379
   674
    ///@{
alpar@379
   675
alpar@379
   676
    ///Return a highest level active item.
alpar@379
   677
alpar@379
   678
    ///Return a highest level active item.
alpar@379
   679
    ///
alpar@379
   680
    ///\return the highest level active item or INVALID if there is no
alpar@379
   681
    ///active item.
alpar@379
   682
    Item highestActive() const {
alpar@379
   683
      return _highest_active >= 0 ? _first[_highest_active] : INVALID;
alpar@379
   684
    }
alpar@379
   685
alpar@379
   686
    ///Return a highest active level.
alpar@379
   687
alpar@379
   688
    ///Return a highest active level.
alpar@379
   689
    ///
alpar@379
   690
    ///\return the level of the highest active item or -1 if there is
alpar@379
   691
    ///no active item.
alpar@379
   692
    int highestActiveLevel() const {
alpar@379
   693
      return _highest_active;
alpar@379
   694
    }
alpar@379
   695
alpar@379
   696
    ///Lift the highest active item by one.
alpar@379
   697
alpar@379
   698
    ///Lift the item returned by highestActive() by one.
alpar@379
   699
    ///
alpar@379
   700
    void liftHighestActive() {
alpar@379
   701
      Item i = _first[_highest_active];
alpar@379
   702
      if (_next[i] != INVALID) {
alpar@379
   703
        _prev.set(_next[i], INVALID);
alpar@379
   704
        _first[_highest_active] = _next[i];
alpar@379
   705
      } else {
alpar@379
   706
        _first[_highest_active] = INVALID;
alpar@379
   707
        _last[_highest_active] = INVALID;
alpar@379
   708
      }
alpar@379
   709
      _level.set(i, ++_highest_active);
alpar@379
   710
      if (_first[_highest_active] == INVALID) {
alpar@379
   711
        _first[_highest_active] = i;
alpar@379
   712
        _last[_highest_active] = i;
alpar@379
   713
        _prev.set(i, INVALID);
alpar@379
   714
        _next.set(i, INVALID);
alpar@379
   715
      } else {
alpar@379
   716
        _prev.set(_first[_highest_active], i);
alpar@379
   717
        _next.set(i, _first[_highest_active]);
alpar@379
   718
        _first[_highest_active] = i;
alpar@379
   719
      }
alpar@379
   720
    }
alpar@379
   721
alpar@379
   722
    ///Lift the highest active item.
alpar@379
   723
alpar@379
   724
    ///Lift the item returned by highestActive() to level \c new_level.
alpar@379
   725
    ///
alpar@379
   726
    ///\warning \c new_level must be strictly higher
alpar@379
   727
    ///than the current level.
alpar@379
   728
    ///
alpar@379
   729
    void liftHighestActive(int new_level) {
alpar@379
   730
      Item i = _first[_highest_active];
alpar@379
   731
      if (_next[i] != INVALID) {
alpar@379
   732
        _prev.set(_next[i], INVALID);
alpar@379
   733
        _first[_highest_active] = _next[i];
alpar@379
   734
      } else {
alpar@379
   735
        _first[_highest_active] = INVALID;
alpar@379
   736
        _last[_highest_active] = INVALID;
alpar@379
   737
      }
alpar@379
   738
      _level.set(i, _highest_active = new_level);
alpar@379
   739
      if (_first[_highest_active] == INVALID) {
alpar@379
   740
        _first[_highest_active] = _last[_highest_active] = i;
alpar@379
   741
        _prev.set(i, INVALID);
alpar@379
   742
        _next.set(i, INVALID);
alpar@379
   743
      } else {
alpar@379
   744
        _prev.set(_first[_highest_active], i);
alpar@379
   745
        _next.set(i, _first[_highest_active]);
alpar@379
   746
        _first[_highest_active] = i;
alpar@379
   747
      }
alpar@379
   748
    }
alpar@379
   749
alpar@379
   750
    ///Lift the highest active to top.
alpar@379
   751
alpar@379
   752
    ///Lift the item returned by highestActive() to the top level and
alpar@380
   753
    ///deactivates the item.
alpar@379
   754
    ///
alpar@379
   755
    void liftHighestActiveToTop() {
alpar@379
   756
      Item i = _first[_highest_active];
alpar@379
   757
      _level.set(i, _max_level);
alpar@379
   758
      if (_next[i] != INVALID) {
alpar@379
   759
        _prev.set(_next[i], INVALID);
alpar@379
   760
        _first[_highest_active] = _next[i];
alpar@379
   761
      } else {
alpar@379
   762
        _first[_highest_active] = INVALID;
alpar@379
   763
        _last[_highest_active] = INVALID;
alpar@379
   764
      }
alpar@379
   765
      while (_highest_active >= 0 && activeFree(_highest_active))
alpar@379
   766
        --_highest_active;
alpar@379
   767
    }
alpar@379
   768
alpar@379
   769
    ///@}
alpar@379
   770
alpar@379
   771
    ///\name Active Item on Certain Level
alpar@379
   772
    ///Functions for working with the active items.
alpar@379
   773
alpar@379
   774
    ///@{
alpar@379
   775
alpar@379
   776
    ///Returns an active item on level \c l.
alpar@379
   777
alpar@379
   778
    ///Returns an active item on level \c l.
alpar@379
   779
    ///
alpar@379
   780
    ///Returns an active item on level \c l or \ref INVALID if there is no such
alpar@379
   781
    ///an item. (\c l must be from the range [0...\c max_level].
alpar@379
   782
    Item activeOn(int l) const
alpar@379
   783
    {
alpar@379
   784
      return _active[_first[l]] ? _first[l] : INVALID;
alpar@379
   785
    }
alpar@379
   786
alpar@379
   787
    ///Lifts the active item returned by \c activeOn() member function.
alpar@379
   788
alpar@379
   789
    ///Lifts the active item returned by \c activeOn() member function
alpar@379
   790
    ///by one.
alpar@379
   791
    Item liftActiveOn(int l)
alpar@379
   792
    {
alpar@379
   793
      Item i = _first[l];
alpar@379
   794
      if (_next[i] != INVALID) {
alpar@379
   795
        _prev.set(_next[i], INVALID);
alpar@379
   796
        _first[l] = _next[i];
alpar@379
   797
      } else {
alpar@379
   798
        _first[l] = INVALID;
alpar@379
   799
        _last[l] = INVALID;
alpar@379
   800
      }
alpar@379
   801
      _level.set(i, ++l);
alpar@379
   802
      if (_first[l] == INVALID) {
alpar@379
   803
        _first[l] = _last[l] = i;
alpar@379
   804
        _prev.set(i, INVALID);
alpar@379
   805
        _next.set(i, INVALID);
alpar@379
   806
      } else {
alpar@379
   807
        _prev.set(_first[l], i);
alpar@379
   808
        _next.set(i, _first[l]);
alpar@379
   809
        _first[l] = i;
alpar@379
   810
      }
alpar@379
   811
      if (_highest_active < l) {
alpar@379
   812
        _highest_active = l;
alpar@379
   813
      }
alpar@379
   814
    }
alpar@379
   815
alpar@379
   816
    /// \brief Lifts the active item returned by \c activeOn() member function.
alpar@379
   817
    ///
alpar@379
   818
    /// Lifts the active item returned by \c activeOn() member function
alpar@379
   819
    /// to the given level.
alpar@379
   820
    void liftActiveOn(int l, int new_level)
alpar@379
   821
    {
alpar@379
   822
      Item i = _first[l];
alpar@379
   823
      if (_next[i] != INVALID) {
alpar@379
   824
        _prev.set(_next[i], INVALID);
alpar@379
   825
        _first[l] = _next[i];
alpar@379
   826
      } else {
alpar@379
   827
        _first[l] = INVALID;
alpar@379
   828
        _last[l] = INVALID;
alpar@379
   829
      }
alpar@379
   830
      _level.set(i, l = new_level);
alpar@379
   831
      if (_first[l] == INVALID) {
alpar@379
   832
        _first[l] = _last[l] = i;
alpar@379
   833
        _prev.set(i, INVALID);
alpar@379
   834
        _next.set(i, INVALID);
alpar@379
   835
      } else {
alpar@379
   836
        _prev.set(_first[l], i);
alpar@379
   837
        _next.set(i, _first[l]);
alpar@379
   838
        _first[l] = i;
alpar@379
   839
      }
alpar@379
   840
      if (_highest_active < l) {
alpar@379
   841
        _highest_active = l;
alpar@379
   842
      }
alpar@379
   843
    }
alpar@379
   844
alpar@379
   845
    ///Lifts the active item returned by \c activeOn() member function.
alpar@379
   846
alpar@379
   847
    ///Lifts the active item returned by \c activeOn() member function
alpar@379
   848
    ///to the top level.
alpar@379
   849
    void liftActiveToTop(int l)
alpar@379
   850
    {
alpar@379
   851
      Item i = _first[l];
alpar@379
   852
      if (_next[i] != INVALID) {
alpar@379
   853
        _prev.set(_next[i], INVALID);
alpar@379
   854
        _first[l] = _next[i];
alpar@379
   855
      } else {
alpar@379
   856
        _first[l] = INVALID;
alpar@379
   857
        _last[l] = INVALID;
alpar@379
   858
      }
alpar@379
   859
      _level.set(i, _max_level);
alpar@379
   860
      if (l == _highest_active) {
alpar@379
   861
        while (_highest_active >= 0 && activeFree(_highest_active))
alpar@379
   862
          --_highest_active;
alpar@379
   863
      }
alpar@379
   864
    }
alpar@379
   865
alpar@379
   866
    ///@}
alpar@379
   867
alpar@379
   868
    /// \brief Lift an active item to a higher level.
alpar@379
   869
    ///
alpar@379
   870
    /// Lift an active item to a higher level.
alpar@379
   871
    /// \param i The item to be lifted. It must be active.
alpar@379
   872
    /// \param new_level The new level of \c i. It must be strictly higher
alpar@379
   873
    /// than the current level.
alpar@379
   874
    ///
alpar@379
   875
    void lift(Item i, int new_level) {
alpar@379
   876
      if (_next[i] != INVALID) {
alpar@379
   877
        _prev.set(_next[i], _prev[i]);
alpar@379
   878
      } else {
alpar@379
   879
        _last[new_level] = _prev[i];
alpar@379
   880
      }
alpar@379
   881
      if (_prev[i] != INVALID) {
alpar@379
   882
        _next.set(_prev[i], _next[i]);
alpar@379
   883
      } else {
alpar@379
   884
        _first[new_level] = _next[i];
alpar@379
   885
      }
alpar@379
   886
      _level.set(i, new_level);
alpar@379
   887
      if (_first[new_level] == INVALID) {
alpar@379
   888
        _first[new_level] = _last[new_level] = i;
alpar@379
   889
        _prev.set(i, INVALID);
alpar@379
   890
        _next.set(i, INVALID);
alpar@379
   891
      } else {
alpar@379
   892
        _prev.set(_first[new_level], i);
alpar@379
   893
        _next.set(i, _first[new_level]);
alpar@379
   894
        _first[new_level] = i;
alpar@379
   895
      }
alpar@379
   896
      if (_highest_active < new_level) {
alpar@379
   897
        _highest_active = new_level;
alpar@379
   898
      }
alpar@379
   899
    }
alpar@379
   900
alpar@380
   901
    ///Move an inactive item to the top but one level (in a dirty way).
alpar@379
   902
alpar@380
   903
    ///This function moves an inactive item to the top but one level.
alpar@380
   904
    ///It makes the underlying datastructure corrupt, so use is only if
alpar@380
   905
    ///you really know what it is for.
alpar@380
   906
    ///\pre The item is on the top level.
alpar@380
   907
    void dirtyTopButOne(Item i) {
alpar@379
   908
      _level.set(i, _max_level - 1);
alpar@379
   909
    }
alpar@379
   910
alpar@380
   911
    ///Lift all items on and above a level to the top (and deactivate them).
alpar@379
   912
alpar@380
   913
    ///This function lifts all items on and above level \c l to \c
alpar@379
   914
    ///maxLevel(), and also deactivates them.
alpar@379
   915
    void liftToTop(int l)  {
alpar@379
   916
      for (int i = l + 1; _first[i] != INVALID; ++i) {
alpar@379
   917
        Item n = _first[i];
alpar@379
   918
        while (n != INVALID) {
alpar@379
   919
          _level.set(n, _max_level);
alpar@379
   920
          n = _next[n];
alpar@379
   921
        }
alpar@379
   922
        _first[i] = INVALID;
alpar@379
   923
        _last[i] = INVALID;
alpar@379
   924
      }
alpar@379
   925
      if (_highest_active > l - 1) {
alpar@379
   926
        _highest_active = l - 1;
alpar@379
   927
        while (_highest_active >= 0 && activeFree(_highest_active))
alpar@379
   928
          --_highest_active;
alpar@379
   929
      }
alpar@379
   930
    }
alpar@379
   931
alpar@379
   932
  private:
alpar@379
   933
alpar@379
   934
    int _init_level;
alpar@379
   935
alpar@379
   936
  public:
alpar@379
   937
alpar@379
   938
    ///\name Initialization
alpar@379
   939
    ///Using this function you can initialize the levels of the item.
alpar@379
   940
    ///\n
alpar@379
   941
    ///This initializatios is started with calling \c initStart().
alpar@379
   942
    ///Then the
alpar@379
   943
    ///items should be listed levels by levels statring with the lowest one
alpar@379
   944
    ///(with level 0). This is done by using \c initAddItem()
alpar@379
   945
    ///and \c initNewLevel(). Finally \c initFinish() must be called.
alpar@379
   946
    ///The items not listed will be put on the highest level.
alpar@379
   947
    ///@{
alpar@379
   948
alpar@379
   949
    ///Start the initialization process.
alpar@379
   950
alpar@379
   951
    void initStart() {
alpar@379
   952
alpar@379
   953
      for (int i = 0; i <= _max_level; ++i) {
alpar@379
   954
        _first[i] = _last[i] = INVALID;
alpar@379
   955
      }
alpar@379
   956
      _init_level = 0;
alpar@379
   957
      for(typename ItemSetTraits<Graph,Item>::ItemIt i(_graph);
alpar@379
   958
          i != INVALID; ++i) {
alpar@379
   959
        _level.set(i, _max_level);
alpar@379
   960
        _active.set(i, false);
alpar@379
   961
      }
alpar@379
   962
    }
alpar@379
   963
alpar@379
   964
    ///Add an item to the current level.
alpar@379
   965
alpar@379
   966
    void initAddItem(Item i) {
alpar@379
   967
      _level.set(i, _init_level);
alpar@379
   968
      if (_last[_init_level] == INVALID) {
alpar@379
   969
        _first[_init_level] = i;
alpar@379
   970
        _last[_init_level] = i;
alpar@379
   971
        _prev.set(i, INVALID);
alpar@379
   972
        _next.set(i, INVALID);
alpar@379
   973
      } else {
alpar@379
   974
        _prev.set(i, _last[_init_level]);
alpar@379
   975
        _next.set(i, INVALID);
alpar@379
   976
        _next.set(_last[_init_level], i);
alpar@379
   977
        _last[_init_level] = i;
alpar@379
   978
      }
alpar@379
   979
    }
alpar@379
   980
alpar@379
   981
    ///Start a new level.
alpar@379
   982
alpar@379
   983
    ///Start a new level.
alpar@379
   984
    ///It shouldn't be used before the items on level 0 are listed.
alpar@379
   985
    void initNewLevel() {
alpar@379
   986
      ++_init_level;
alpar@379
   987
    }
alpar@379
   988
alpar@379
   989
    ///Finalize the initialization process.
alpar@379
   990
alpar@379
   991
    void initFinish() {
alpar@379
   992
      _highest_active = -1;
alpar@379
   993
    }
alpar@379
   994
alpar@379
   995
    ///@}
alpar@379
   996
alpar@379
   997
  };
alpar@379
   998
alpar@379
   999
alpar@379
  1000
} //END OF NAMESPACE LEMON
alpar@379
  1001
alpar@379
  1002
#endif
alpar@379
  1003