lemon/elevator.h
author Peter Kovacs <kpeter@inf.elte.hu>
Fri, 03 Apr 2009 18:59:15 +0200
changeset 600 6ac5d9ae1d3d
parent 440 88ed40ad0d4f
child 550 c5fd2d996909
permissions -rw-r--r--
Support real types + numerical stability fix in NS (#254)

- Real types are supported by appropriate inicialization.
- A feature of the XTI spanning tree structure is removed to ensure
numerical stability (could cause problems using integer types).
The node potentials are updated always on the lower subtree,
in order to prevent overflow problems.
The former method isn't notably faster during to our tests.
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@503
    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@383
    49
  ///\param Graph Type of the underlying graph.
alpar@379
    50
  ///\param Item Type of the items the data is assigned to (Graph::Node,
kpeter@383
    51
  ///Graph::Arc, Graph::Edge).
alpar@379
    52
  template<class Graph, 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;
alpar@379
    63
    typedef typename ItemSetTraits<Graph,Item>::template Map<Vit>::Type VitMap;
alpar@379
    64
    typedef typename ItemSetTraits<Graph,Item>::template Map<int>::Type IntMap;
alpar@379
    65
alpar@379
    66
    const Graph &_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
    {
alpar@382
    79
      _where.set(*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;
alpar@382
    87
          _where.set(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];
alpar@382
    94
      _where.set(ti,_where[*i=*j]);
alpar@382
    95
      _where.set(*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@383
   108
    Elevator(const Graph &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@383
   125
    Elevator(const Graph &graph) :
kpeter@383
   126
      _g(graph),
kpeter@383
   127
      _max_level(countItems<Graph, 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];
alpar@382
   229
      _level.set(it,_level[it]+1);
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]);
alpar@382
   252
      _level.set(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];
alpar@382
   272
      _level.set(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];
alpar@382
   302
      _level.set(it,_level[it]+1);
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]);
alpar@382
   322
      _level.set(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];
alpar@382
   342
      _level.set(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]);
alpar@382
   373
      _level.set(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) {
alpar@382
   385
      _level.set(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)
alpar@382
   397
        _level.set(*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];
alpar@379
   433
      for(typename ItemSetTraits<Graph,Item>::ItemIt i(_g);i!=INVALID;++i)
alpar@379
   434
        {
alpar@379
   435
          *n=i;
alpar@382
   436
          _where.set(i,n);
alpar@382
   437
          _level.set(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);
alpar@382
   446
      _level.set(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@383
   492
  ///\param Graph Type of the underlying graph.
alpar@379
   493
  ///\param Item Type of the items the data is assigned to (Graph::Node,
kpeter@383
   494
  ///Graph::Arc, Graph::Edge).
alpar@379
   495
  template <class Graph, 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
alpar@379
   504
    typedef typename ItemSetTraits<Graph,Item>::
alpar@379
   505
    template Map<Item>::Type ItemMap;
alpar@379
   506
    typedef typename ItemSetTraits<Graph,Item>::
alpar@379
   507
    template Map<int>::Type IntMap;
alpar@379
   508
    typedef typename ItemSetTraits<Graph,Item>::
alpar@379
   509
    template Map<bool>::Type BoolMap;
alpar@379
   510
alpar@379
   511
    const Graph &_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>.
alpar@379
   528
    LinkedElevator(const Graph& 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.
alpar@379
   541
    LinkedElevator(const Graph& graph)
alpar@379
   542
      : _graph(graph), _max_level(countItems<Graph, 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) {
alpar@379
   554
      _active.set(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
alpar@379
   563
      _next.set(_prev[i], _next[i]);
alpar@379
   564
      if (_next[i] != INVALID) {
alpar@379
   565
        _prev.set(_next[i], _prev[i]);
alpar@379
   566
      } else {
alpar@379
   567
        _last[level] = _prev[i];
alpar@379
   568
      }
alpar@379
   569
      //lace
alpar@379
   570
      _next.set(i, _first[level]);
alpar@379
   571
      _prev.set(_first[level], i);
alpar@379
   572
      _prev.set(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) {
alpar@379
   582
      _active.set(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
alpar@379
   589
      _prev.set(_next[i], _prev[i]);
alpar@379
   590
      if (_prev[i] != INVALID) {
alpar@379
   591
        _next.set(_prev[i], _next[i]);
alpar@379
   592
      } else {
alpar@379
   593
        _first[_level[i]] = _next[i];
alpar@379
   594
      }
alpar@379
   595
      //lace
alpar@379
   596
      _prev.set(i, _last[level]);
alpar@379
   597
      _next.set(_last[level], i);
alpar@379
   598
      _next.set(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) {
alpar@379
   688
        _prev.set(_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
      }
alpar@379
   694
      _level.set(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;
alpar@379
   698
        _prev.set(i, INVALID);
alpar@379
   699
        _next.set(i, INVALID);
alpar@379
   700
      } else {
alpar@379
   701
        _prev.set(_first[_highest_active], i);
alpar@379
   702
        _next.set(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) {
alpar@379
   717
        _prev.set(_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
      }
alpar@379
   723
      _level.set(i, _highest_active = new_level);
alpar@379
   724
      if (_first[_highest_active] == INVALID) {
alpar@379
   725
        _first[_highest_active] = _last[_highest_active] = i;
alpar@379
   726
        _prev.set(i, INVALID);
alpar@379
   727
        _next.set(i, INVALID);
alpar@379
   728
      } else {
alpar@379
   729
        _prev.set(_first[_highest_active], i);
alpar@379
   730
        _next.set(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];
alpar@379
   741
      _level.set(i, _max_level);
alpar@379
   742
      if (_next[i] != INVALID) {
alpar@379
   743
        _prev.set(_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) {
alpar@379
   777
        _prev.set(_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
      }
alpar@379
   783
      _level.set(i, ++l);
alpar@379
   784
      if (_first[l] == INVALID) {
alpar@379
   785
        _first[l] = _last[l] = i;
alpar@379
   786
        _prev.set(i, INVALID);
alpar@379
   787
        _next.set(i, INVALID);
alpar@379
   788
      } else {
alpar@379
   789
        _prev.set(_first[l], i);
alpar@379
   790
        _next.set(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) {
alpar@379
   806
        _prev.set(_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
      }
alpar@379
   812
      _level.set(i, l = new_level);
alpar@379
   813
      if (_first[l] == INVALID) {
alpar@379
   814
        _first[l] = _last[l] = i;
alpar@379
   815
        _prev.set(i, INVALID);
alpar@379
   816
        _next.set(i, INVALID);
alpar@379
   817
      } else {
alpar@379
   818
        _prev.set(_first[l], i);
alpar@379
   819
        _next.set(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) {
alpar@379
   835
        _prev.set(_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
      }
alpar@379
   841
      _level.set(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) {
alpar@379
   859
        _prev.set(_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) {
alpar@379
   864
        _next.set(_prev[i], _next[i]);
alpar@379
   865
      } else {
alpar@379
   866
        _first[new_level] = _next[i];
alpar@379
   867
      }
alpar@379
   868
      _level.set(i, new_level);
alpar@379
   869
      if (_first[new_level] == INVALID) {
alpar@379
   870
        _first[new_level] = _last[new_level] = i;
alpar@379
   871
        _prev.set(i, INVALID);
alpar@379
   872
        _next.set(i, INVALID);
alpar@379
   873
      } else {
alpar@379
   874
        _prev.set(_first[new_level], i);
alpar@379
   875
        _next.set(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) {
alpar@379
   891
      _level.set(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) {
alpar@379
   902
          _level.set(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;
alpar@379
   938
      for(typename ItemSetTraits<Graph,Item>::ItemIt i(_graph);
alpar@379
   939
          i != INVALID; ++i) {
alpar@379
   940
        _level.set(i, _max_level);
alpar@379
   941
        _active.set(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) {
alpar@379
   947
      _level.set(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;
alpar@379
   951
        _prev.set(i, INVALID);
alpar@379
   952
        _next.set(i, INVALID);
alpar@379
   953
      } else {
alpar@379
   954
        _prev.set(i, _last[_init_level]);
alpar@379
   955
        _next.set(i, INVALID);
alpar@379
   956
        _next.set(_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