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