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