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