alpar@379: /* -*- mode: C++; indent-tabs-mode: nil; -*-
alpar@379:  *
alpar@379:  * This file is a part of LEMON, a generic C++ optimization library.
alpar@379:  *
alpar@379:  * Copyright (C) 2003-2008
alpar@379:  * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
alpar@379:  * (Egervary Research Group on Combinatorial Optimization, EGRES).
alpar@379:  *
alpar@379:  * Permission to use, modify and distribute this software is granted
alpar@379:  * provided that this copyright notice appears in all copies. For
alpar@379:  * precise terms see the accompanying LICENSE file.
alpar@379:  *
alpar@379:  * This software is provided "AS IS" with no warranty of any kind,
alpar@379:  * express or implied, and with no claim as to its suitability for any
alpar@379:  * purpose.
alpar@379:  *
alpar@379:  */
alpar@379: 
alpar@379: #ifndef LEMON_ELEVATOR_H
alpar@379: #define LEMON_ELEVATOR_H
alpar@379: 
alpar@379: ///\ingroup auxdat
alpar@379: ///\file
alpar@379: ///\brief Elevator class
alpar@379: ///
alpar@379: ///Elevator class implements an efficient data structure
alpar@379: ///for labeling items in push-relabel type algorithms.
alpar@379: ///
alpar@379: 
kpeter@383: #include <lemon/bits/traits.h>
kpeter@383: 
alpar@379: namespace lemon {
alpar@379: 
alpar@379:   ///Class for handling "labels" in push-relabel type algorithms.
alpar@379: 
alpar@379:   ///A class for handling "labels" in push-relabel type algorithms.
alpar@379:   ///
alpar@379:   ///\ingroup auxdat
alpar@379:   ///Using this class you can assign "labels" (nonnegative integer numbers)
alpar@379:   ///to the edges or nodes of a graph, manipulate and query them through
alpar@379:   ///operations typically arising in "push-relabel" type algorithms.
alpar@379:   ///
alpar@379:   ///Each item is either \em active or not, and you can also choose a
alpar@379:   ///highest level active item.
alpar@379:   ///
alpar@379:   ///\sa LinkedElevator
alpar@379:   ///
kpeter@383:   ///\param Graph Type of the underlying graph.
alpar@379:   ///\param Item Type of the items the data is assigned to (Graph::Node,
kpeter@383:   ///Graph::Arc, Graph::Edge).
alpar@379:   template<class Graph, class Item>
alpar@379:   class Elevator
alpar@379:   {
alpar@379:   public:
alpar@379: 
alpar@379:     typedef Item Key;
alpar@379:     typedef int Value;
alpar@379: 
alpar@379:   private:
alpar@379: 
alpar@381:     typedef Item *Vit;
alpar@379:     typedef typename ItemSetTraits<Graph,Item>::template Map<Vit>::Type VitMap;
alpar@379:     typedef typename ItemSetTraits<Graph,Item>::template Map<int>::Type IntMap;
alpar@379: 
alpar@379:     const Graph &_g;
alpar@379:     int _max_level;
alpar@379:     int _item_num;
alpar@379:     VitMap _where;
alpar@379:     IntMap _level;
alpar@379:     std::vector<Item> _items;
alpar@379:     std::vector<Vit> _first;
alpar@379:     std::vector<Vit> _last_active;
alpar@379: 
alpar@379:     int _highest_active;
alpar@379: 
alpar@379:     void copy(Item i, Vit p)
alpar@379:     {
alpar@382:       _where.set(*p=i,p);
alpar@379:     }
alpar@379:     void copy(Vit s, Vit p)
alpar@379:     {
alpar@379:       if(s!=p)
alpar@379:         {
alpar@379:           Item i=*s;
alpar@379:           *p=i;
alpar@382:           _where.set(i,p);
alpar@379:         }
alpar@379:     }
alpar@379:     void swap(Vit i, Vit j)
alpar@379:     {
alpar@379:       Item ti=*i;
alpar@379:       Vit ct = _where[ti];
alpar@382:       _where.set(ti,_where[*i=*j]);
alpar@382:       _where.set(*j,ct);
alpar@379:       *j=ti;
alpar@379:     }
alpar@379: 
alpar@379:   public:
alpar@379: 
alpar@379:     ///Constructor with given maximum level.
alpar@379: 
alpar@379:     ///Constructor with given maximum level.
alpar@379:     ///
kpeter@383:     ///\param graph The underlying graph.
kpeter@383:     ///\param max_level The maximum allowed level.
kpeter@383:     ///Set the range of the possible labels to <tt>[0..max_level]</tt>.
kpeter@383:     Elevator(const Graph &graph,int max_level) :
kpeter@383:       _g(graph),
alpar@379:       _max_level(max_level),
alpar@379:       _item_num(_max_level),
kpeter@383:       _where(graph),
kpeter@383:       _level(graph,0),
alpar@379:       _items(_max_level),
alpar@379:       _first(_max_level+2),
alpar@379:       _last_active(_max_level+2),
alpar@379:       _highest_active(-1) {}
alpar@379:     ///Constructor.
alpar@379: 
alpar@379:     ///Constructor.
alpar@379:     ///
kpeter@383:     ///\param graph The underlying graph.
kpeter@383:     ///Set the range of the possible labels to <tt>[0..max_level]</tt>,
alpar@379:     ///where \c max_level is equal to the number of labeled items in the graph.
kpeter@383:     Elevator(const Graph &graph) :
kpeter@383:       _g(graph),
kpeter@383:       _max_level(countItems<Graph, Item>(graph)),
alpar@379:       _item_num(_max_level),
kpeter@383:       _where(graph),
kpeter@383:       _level(graph,0),
alpar@379:       _items(_max_level),
alpar@379:       _first(_max_level+2),
alpar@379:       _last_active(_max_level+2),
alpar@379:       _highest_active(-1)
alpar@379:     {
alpar@379:     }
alpar@379: 
alpar@379:     ///Activate item \c i.
alpar@379: 
alpar@379:     ///Activate item \c i.
alpar@379:     ///\pre Item \c i shouldn't be active before.
alpar@379:     void activate(Item i)
alpar@379:     {
alpar@379:       const int l=_level[i];
alpar@379:       swap(_where[i],++_last_active[l]);
alpar@379:       if(l>_highest_active) _highest_active=l;
alpar@379:     }
alpar@379: 
alpar@379:     ///Deactivate item \c i.
alpar@379: 
alpar@379:     ///Deactivate item \c i.
alpar@379:     ///\pre Item \c i must be active before.
alpar@379:     void deactivate(Item i)
alpar@379:     {
alpar@379:       swap(_where[i],_last_active[_level[i]]--);
alpar@379:       while(_highest_active>=0 &&
alpar@379:             _last_active[_highest_active]<_first[_highest_active])
alpar@379:         _highest_active--;
alpar@379:     }
alpar@379: 
alpar@379:     ///Query whether item \c i is active
alpar@379:     bool active(Item i) const { return _where[i]<=_last_active[_level[i]]; }
alpar@379: 
alpar@379:     ///Return the level of item \c i.
alpar@379:     int operator[](Item i) const { return _level[i]; }
alpar@379: 
alpar@379:     ///Return the number of items on level \c l.
alpar@379:     int onLevel(int l) const
alpar@379:     {
alpar@379:       return _first[l+1]-_first[l];
alpar@379:     }
kpeter@383:     ///Return true if level \c l is empty.
alpar@379:     bool emptyLevel(int l) const
alpar@379:     {
alpar@379:       return _first[l+1]-_first[l]==0;
alpar@379:     }
alpar@379:     ///Return the number of items above level \c l.
alpar@379:     int aboveLevel(int l) const
alpar@379:     {
alpar@379:       return _first[_max_level+1]-_first[l+1];
alpar@379:     }
alpar@379:     ///Return the number of active items on level \c l.
alpar@379:     int activesOnLevel(int l) const
alpar@379:     {
alpar@379:       return _last_active[l]-_first[l]+1;
alpar@379:     }
kpeter@383:     ///Return true if there is no active item on level \c l.
alpar@379:     bool activeFree(int l) const
alpar@379:     {
alpar@379:       return _last_active[l]<_first[l];
alpar@379:     }
alpar@379:     ///Return the maximum allowed level.
alpar@379:     int maxLevel() const
alpar@379:     {
alpar@379:       return _max_level;
alpar@379:     }
alpar@379: 
alpar@379:     ///\name Highest Active Item
alpar@379:     ///Functions for working with the highest level
alpar@379:     ///active item.
alpar@379: 
alpar@379:     ///@{
alpar@379: 
alpar@379:     ///Return a highest level active item.
alpar@379: 
kpeter@383:     ///Return a highest level active item or INVALID if there is no active
alpar@379:     ///item.
alpar@379:     Item highestActive() const
alpar@379:     {
alpar@379:       return _highest_active>=0?*_last_active[_highest_active]:INVALID;
alpar@379:     }
alpar@379: 
kpeter@383:     ///Return the highest active level.
alpar@379: 
kpeter@383:     ///Return the level of the highest active item or -1 if there is no active
alpar@379:     ///item.
alpar@379:     int highestActiveLevel() const
alpar@379:     {
alpar@379:       return _highest_active;
alpar@379:     }
alpar@379: 
alpar@379:     ///Lift the highest active item by one.
alpar@379: 
alpar@379:     ///Lift the item returned by highestActive() by one.
alpar@379:     ///
alpar@379:     void liftHighestActive()
alpar@379:     {
alpar@382:       Item it = *_last_active[_highest_active];
alpar@382:       _level.set(it,_level[it]+1);
alpar@379:       swap(_last_active[_highest_active]--,_last_active[_highest_active+1]);
alpar@379:       --_first[++_highest_active];
alpar@379:     }
alpar@379: 
kpeter@383:     ///Lift the highest active item to the given level.
alpar@379: 
alpar@379:     ///Lift the item returned by highestActive() to level \c new_level.
alpar@379:     ///
alpar@379:     ///\warning \c new_level must be strictly higher
alpar@379:     ///than the current level.
alpar@379:     ///
alpar@379:     void liftHighestActive(int new_level)
alpar@379:     {
alpar@379:       const Item li = *_last_active[_highest_active];
alpar@379: 
alpar@379:       copy(--_first[_highest_active+1],_last_active[_highest_active]--);
alpar@379:       for(int l=_highest_active+1;l<new_level;l++)
alpar@379:         {
alpar@379:           copy(--_first[l+1],_first[l]);
alpar@379:           --_last_active[l];
alpar@379:         }
alpar@379:       copy(li,_first[new_level]);
alpar@382:       _level.set(li,new_level);
alpar@379:       _highest_active=new_level;
alpar@379:     }
alpar@379: 
kpeter@383:     ///Lift the highest active item to the top level.
alpar@379: 
alpar@379:     ///Lift the item returned by highestActive() to the top level and
kpeter@383:     ///deactivate it.
alpar@379:     void liftHighestActiveToTop()
alpar@379:     {
alpar@379:       const Item li = *_last_active[_highest_active];
alpar@379: 
alpar@379:       copy(--_first[_highest_active+1],_last_active[_highest_active]--);
alpar@379:       for(int l=_highest_active+1;l<_max_level;l++)
alpar@379:         {
alpar@379:           copy(--_first[l+1],_first[l]);
alpar@379:           --_last_active[l];
alpar@379:         }
alpar@379:       copy(li,_first[_max_level]);
alpar@379:       --_last_active[_max_level];
alpar@382:       _level.set(li,_max_level);
alpar@379: 
alpar@379:       while(_highest_active>=0 &&
alpar@379:             _last_active[_highest_active]<_first[_highest_active])
alpar@379:         _highest_active--;
alpar@379:     }
alpar@379: 
alpar@379:     ///@}
alpar@379: 
alpar@379:     ///\name Active Item on Certain Level
alpar@379:     ///Functions for working with the active items.
alpar@379: 
alpar@379:     ///@{
alpar@379: 
kpeter@383:     ///Return an active item on level \c l.
alpar@379: 
kpeter@383:     ///Return an active item on level \c l or \ref INVALID if there is no such
alpar@379:     ///an item. (\c l must be from the range [0...\c max_level].
alpar@379:     Item activeOn(int l) const
alpar@379:     {
alpar@379:       return _last_active[l]>=_first[l]?*_last_active[l]:INVALID;
alpar@379:     }
alpar@379: 
kpeter@383:     ///Lift the active item returned by \c activeOn(level) by one.
alpar@379: 
kpeter@383:     ///Lift the active item returned by \ref activeOn() "activeOn(level)"
alpar@379:     ///by one.
alpar@379:     Item liftActiveOn(int level)
alpar@379:     {
alpar@382:       Item it =*_last_active[level];
alpar@382:       _level.set(it,_level[it]+1);
alpar@379:       swap(_last_active[level]--, --_first[level+1]);
alpar@379:       if (level+1>_highest_active) ++_highest_active;
alpar@379:     }
alpar@379: 
kpeter@383:     ///Lift the active item returned by \c activeOn(level) to the given level.
alpar@379: 
kpeter@383:     ///Lift the active item returned by \ref activeOn() "activeOn(level)"
alpar@379:     ///to the given level.
alpar@379:     void liftActiveOn(int level, int new_level)
alpar@379:     {
alpar@379:       const Item ai = *_last_active[level];
alpar@379: 
alpar@379:       copy(--_first[level+1], _last_active[level]--);
alpar@379:       for(int l=level+1;l<new_level;l++)
alpar@379:         {
alpar@379:           copy(_last_active[l],_first[l]);
alpar@379:           copy(--_first[l+1], _last_active[l]--);
alpar@379:         }
alpar@379:       copy(ai,_first[new_level]);
alpar@382:       _level.set(ai,new_level);
alpar@379:       if (new_level>_highest_active) _highest_active=new_level;
alpar@379:     }
alpar@379: 
kpeter@383:     ///Lift the active item returned by \c activeOn(level) to the top level.
alpar@379: 
kpeter@383:     ///Lift the active item returned by \ref activeOn() "activeOn(level)"
kpeter@383:     ///to the top level and deactivate it.
alpar@379:     void liftActiveToTop(int level)
alpar@379:     {
alpar@379:       const Item ai = *_last_active[level];
alpar@379: 
alpar@379:       copy(--_first[level+1],_last_active[level]--);
alpar@379:       for(int l=level+1;l<_max_level;l++)
alpar@379:         {
alpar@379:           copy(_last_active[l],_first[l]);
alpar@379:           copy(--_first[l+1], _last_active[l]--);
alpar@379:         }
alpar@379:       copy(ai,_first[_max_level]);
alpar@379:       --_last_active[_max_level];
alpar@382:       _level.set(ai,_max_level);
alpar@379: 
alpar@379:       if (_highest_active==level) {
alpar@379:         while(_highest_active>=0 &&
alpar@379:               _last_active[_highest_active]<_first[_highest_active])
alpar@379:           _highest_active--;
alpar@379:       }
alpar@379:     }
alpar@379: 
alpar@379:     ///@}
alpar@379: 
alpar@379:     ///Lift an active item to a higher level.
alpar@379: 
alpar@379:     ///Lift an active item to a higher level.
alpar@379:     ///\param i The item to be lifted. It must be active.
alpar@379:     ///\param new_level The new level of \c i. It must be strictly higher
alpar@379:     ///than the current level.
alpar@379:     ///
alpar@379:     void lift(Item i, int new_level)
alpar@379:     {
alpar@379:       const int lo = _level[i];
alpar@379:       const Vit w = _where[i];
alpar@379: 
alpar@379:       copy(_last_active[lo],w);
alpar@379:       copy(--_first[lo+1],_last_active[lo]--);
alpar@379:       for(int l=lo+1;l<new_level;l++)
alpar@379:         {
alpar@379:           copy(_last_active[l],_first[l]);
alpar@379:           copy(--_first[l+1],_last_active[l]--);
alpar@379:         }
alpar@379:       copy(i,_first[new_level]);
alpar@382:       _level.set(i,new_level);
alpar@379:       if(new_level>_highest_active) _highest_active=new_level;
alpar@379:     }
alpar@379: 
alpar@380:     ///Move an inactive item to the top but one level (in a dirty way).
alpar@379: 
kpeter@383:     ///This function moves an inactive item from the top level to the top
kpeter@383:     ///but one level (in a dirty way).
kpeter@383:     ///\warning It makes the underlying datastructure corrupt, so use it
kpeter@383:     ///only if you really know what it is for.
alpar@380:     ///\pre The item is on the top level.
alpar@380:     void dirtyTopButOne(Item i) {
alpar@382:       _level.set(i,_max_level - 1);
alpar@379:     }
alpar@379: 
kpeter@383:     ///Lift all items on and above the given level to the top level.
alpar@379: 
kpeter@383:     ///This function lifts all items on and above level \c l to the top
kpeter@383:     ///level and deactivates them.
alpar@379:     void liftToTop(int l)
alpar@379:     {
alpar@379:       const Vit f=_first[l];
alpar@379:       const Vit tl=_first[_max_level];
alpar@379:       for(Vit i=f;i!=tl;++i)
alpar@382:         _level.set(*i,_max_level);
alpar@379:       for(int i=l;i<=_max_level;i++)
alpar@379:         {
alpar@379:           _first[i]=f;
alpar@379:           _last_active[i]=f-1;
alpar@379:         }
alpar@379:       for(_highest_active=l-1;
alpar@379:           _highest_active>=0 &&
alpar@379:             _last_active[_highest_active]<_first[_highest_active];
alpar@379:           _highest_active--) ;
alpar@379:     }
alpar@379: 
alpar@379:   private:
alpar@379:     int _init_lev;
alpar@379:     Vit _init_num;
alpar@379: 
alpar@379:   public:
alpar@379: 
alpar@379:     ///\name Initialization
kpeter@383:     ///Using these functions you can initialize the levels of the items.
alpar@379:     ///\n
kpeter@383:     ///The initialization must be started with calling \c initStart().
kpeter@383:     ///Then the items should be listed level by level starting with the
kpeter@383:     ///lowest one (level 0) using \c initAddItem() and \c initNewLevel().
kpeter@383:     ///Finally \c initFinish() must be called.
kpeter@383:     ///The items not listed are put on the highest level.
alpar@379:     ///@{
alpar@379: 
alpar@379:     ///Start the initialization process.
alpar@379:     void initStart()
alpar@379:     {
alpar@379:       _init_lev=0;
alpar@381:       _init_num=&_items[0];
alpar@381:       _first[0]=&_items[0];
alpar@381:       _last_active[0]=&_items[0]-1;
alpar@381:       Vit n=&_items[0];
alpar@379:       for(typename ItemSetTraits<Graph,Item>::ItemIt i(_g);i!=INVALID;++i)
alpar@379:         {
alpar@379:           *n=i;
alpar@382:           _where.set(i,n);
alpar@382:           _level.set(i,_max_level);
alpar@379:           ++n;
alpar@379:         }
alpar@379:     }
alpar@379: 
alpar@379:     ///Add an item to the current level.
alpar@379:     void initAddItem(Item i)
alpar@379:     {
alpar@382:       swap(_where[i],_init_num);
alpar@382:       _level.set(i,_init_lev);
alpar@379:       ++_init_num;
alpar@379:     }
alpar@379: 
alpar@379:     ///Start a new level.
alpar@379: 
alpar@379:     ///Start a new level.
alpar@379:     ///It shouldn't be used before the items on level 0 are listed.
alpar@379:     void initNewLevel()
alpar@379:     {
alpar@379:       _init_lev++;
alpar@379:       _first[_init_lev]=_init_num;
alpar@379:       _last_active[_init_lev]=_init_num-1;
alpar@379:     }
alpar@379: 
alpar@379:     ///Finalize the initialization process.
alpar@379:     void initFinish()
alpar@379:     {
alpar@379:       for(_init_lev++;_init_lev<=_max_level;_init_lev++)
alpar@379:         {
alpar@379:           _first[_init_lev]=_init_num;
alpar@379:           _last_active[_init_lev]=_init_num-1;
alpar@379:         }
alpar@381:       _first[_max_level+1]=&_items[0]+_item_num;
alpar@381:       _last_active[_max_level+1]=&_items[0]+_item_num-1;
alpar@379:       _highest_active = -1;
alpar@379:     }
alpar@379: 
alpar@379:     ///@}
alpar@379: 
alpar@379:   };
alpar@379: 
alpar@379:   ///Class for handling "labels" in push-relabel type algorithms.
alpar@379: 
alpar@379:   ///A class for handling "labels" in push-relabel type algorithms.
alpar@379:   ///
alpar@379:   ///\ingroup auxdat
alpar@379:   ///Using this class you can assign "labels" (nonnegative integer numbers)
alpar@379:   ///to the edges or nodes of a graph, manipulate and query them through
alpar@379:   ///operations typically arising in "push-relabel" type algorithms.
alpar@379:   ///
alpar@379:   ///Each item is either \em active or not, and you can also choose a
alpar@379:   ///highest level active item.
alpar@379:   ///
alpar@379:   ///\sa Elevator
alpar@379:   ///
kpeter@383:   ///\param Graph Type of the underlying graph.
alpar@379:   ///\param Item Type of the items the data is assigned to (Graph::Node,
kpeter@383:   ///Graph::Arc, Graph::Edge).
alpar@379:   template <class Graph, class Item>
alpar@379:   class LinkedElevator {
alpar@379:   public:
alpar@379: 
alpar@379:     typedef Item Key;
alpar@379:     typedef int Value;
alpar@379: 
alpar@379:   private:
alpar@379: 
alpar@379:     typedef typename ItemSetTraits<Graph,Item>::
alpar@379:     template Map<Item>::Type ItemMap;
alpar@379:     typedef typename ItemSetTraits<Graph,Item>::
alpar@379:     template Map<int>::Type IntMap;
alpar@379:     typedef typename ItemSetTraits<Graph,Item>::
alpar@379:     template Map<bool>::Type BoolMap;
alpar@379: 
alpar@379:     const Graph &_graph;
alpar@379:     int _max_level;
alpar@379:     int _item_num;
alpar@379:     std::vector<Item> _first, _last;
alpar@379:     ItemMap _prev, _next;
alpar@379:     int _highest_active;
alpar@379:     IntMap _level;
alpar@379:     BoolMap _active;
alpar@379: 
alpar@379:   public:
alpar@379:     ///Constructor with given maximum level.
alpar@379: 
alpar@379:     ///Constructor with given maximum level.
alpar@379:     ///
kpeter@383:     ///\param graph The underlying graph.
kpeter@383:     ///\param max_level The maximum allowed level.
kpeter@383:     ///Set the range of the possible labels to <tt>[0..max_level]</tt>.
alpar@379:     LinkedElevator(const Graph& graph, int max_level)
alpar@379:       : _graph(graph), _max_level(max_level), _item_num(_max_level),
alpar@379:         _first(_max_level + 1), _last(_max_level + 1),
alpar@379:         _prev(graph), _next(graph),
alpar@379:         _highest_active(-1), _level(graph), _active(graph) {}
alpar@379: 
alpar@379:     ///Constructor.
alpar@379: 
alpar@379:     ///Constructor.
alpar@379:     ///
kpeter@383:     ///\param graph The underlying graph.
kpeter@383:     ///Set the range of the possible labels to <tt>[0..max_level]</tt>,
alpar@379:     ///where \c max_level is equal to the number of labeled items in the graph.
alpar@379:     LinkedElevator(const Graph& graph)
alpar@379:       : _graph(graph), _max_level(countItems<Graph, Item>(graph)),
alpar@379:         _item_num(_max_level),
alpar@379:         _first(_max_level + 1), _last(_max_level + 1),
alpar@379:         _prev(graph, INVALID), _next(graph, INVALID),
alpar@379:         _highest_active(-1), _level(graph), _active(graph) {}
alpar@379: 
alpar@379: 
alpar@379:     ///Activate item \c i.
alpar@379: 
alpar@379:     ///Activate item \c i.
alpar@379:     ///\pre Item \c i shouldn't be active before.
alpar@379:     void activate(Item i) {
alpar@379:       _active.set(i, true);
alpar@379: 
alpar@379:       int level = _level[i];
alpar@379:       if (level > _highest_active) {
alpar@379:         _highest_active = level;
alpar@379:       }
alpar@379: 
alpar@379:       if (_prev[i] == INVALID || _active[_prev[i]]) return;
alpar@379:       //unlace
alpar@379:       _next.set(_prev[i], _next[i]);
alpar@379:       if (_next[i] != INVALID) {
alpar@379:         _prev.set(_next[i], _prev[i]);
alpar@379:       } else {
alpar@379:         _last[level] = _prev[i];
alpar@379:       }
alpar@379:       //lace
alpar@379:       _next.set(i, _first[level]);
alpar@379:       _prev.set(_first[level], i);
alpar@379:       _prev.set(i, INVALID);
alpar@379:       _first[level] = i;
alpar@379: 
alpar@379:     }
alpar@379: 
alpar@379:     ///Deactivate item \c i.
alpar@379: 
alpar@379:     ///Deactivate item \c i.
alpar@379:     ///\pre Item \c i must be active before.
alpar@379:     void deactivate(Item i) {
alpar@379:       _active.set(i, false);
alpar@379:       int level = _level[i];
alpar@379: 
alpar@379:       if (_next[i] == INVALID || !_active[_next[i]])
alpar@379:         goto find_highest_level;
alpar@379: 
alpar@379:       //unlace
alpar@379:       _prev.set(_next[i], _prev[i]);
alpar@379:       if (_prev[i] != INVALID) {
alpar@379:         _next.set(_prev[i], _next[i]);
alpar@379:       } else {
alpar@379:         _first[_level[i]] = _next[i];
alpar@379:       }
alpar@379:       //lace
alpar@379:       _prev.set(i, _last[level]);
alpar@379:       _next.set(_last[level], i);
alpar@379:       _next.set(i, INVALID);
alpar@379:       _last[level] = i;
alpar@379: 
alpar@379:     find_highest_level:
alpar@379:       if (level == _highest_active) {
alpar@379:         while (_highest_active >= 0 && activeFree(_highest_active))
alpar@379:           --_highest_active;
alpar@379:       }
alpar@379:     }
alpar@379: 
alpar@379:     ///Query whether item \c i is active
alpar@379:     bool active(Item i) const { return _active[i]; }
alpar@379: 
alpar@379:     ///Return the level of item \c i.
alpar@379:     int operator[](Item i) const { return _level[i]; }
alpar@379: 
alpar@379:     ///Return the number of items on level \c l.
alpar@379:     int onLevel(int l) const {
alpar@379:       int num = 0;
alpar@379:       Item n = _first[l];
alpar@379:       while (n != INVALID) {
alpar@379:         ++num;
alpar@379:         n = _next[n];
alpar@379:       }
alpar@379:       return num;
alpar@379:     }
alpar@379: 
alpar@379:     ///Return true if the level is empty.
alpar@379:     bool emptyLevel(int l) const {
alpar@379:       return _first[l] == INVALID;
alpar@379:     }
alpar@379: 
alpar@379:     ///Return the number of items above level \c l.
alpar@379:     int aboveLevel(int l) const {
alpar@379:       int num = 0;
alpar@379:       for (int level = l + 1; level < _max_level; ++level)
alpar@379:         num += onLevel(level);
alpar@379:       return num;
alpar@379:     }
alpar@379: 
alpar@379:     ///Return the number of active items on level \c l.
alpar@379:     int activesOnLevel(int l) const {
alpar@379:       int num = 0;
alpar@379:       Item n = _first[l];
alpar@379:       while (n != INVALID && _active[n]) {
alpar@379:         ++num;
alpar@379:         n = _next[n];
alpar@379:       }
alpar@379:       return num;
alpar@379:     }
alpar@379: 
kpeter@383:     ///Return true if there is no active item on level \c l.
alpar@379:     bool activeFree(int l) const {
alpar@379:       return _first[l] == INVALID || !_active[_first[l]];
alpar@379:     }
alpar@379: 
alpar@379:     ///Return the maximum allowed level.
alpar@379:     int maxLevel() const {
alpar@379:       return _max_level;
alpar@379:     }
alpar@379: 
alpar@379:     ///\name Highest Active Item
alpar@379:     ///Functions for working with the highest level
alpar@379:     ///active item.
alpar@379: 
alpar@379:     ///@{
alpar@379: 
alpar@379:     ///Return a highest level active item.
alpar@379: 
kpeter@383:     ///Return a highest level active item or INVALID if there is no active
kpeter@383:     ///item.
alpar@379:     Item highestActive() const {
alpar@379:       return _highest_active >= 0 ? _first[_highest_active] : INVALID;
alpar@379:     }
alpar@379: 
kpeter@383:     ///Return the highest active level.
alpar@379: 
kpeter@383:     ///Return the level of the highest active item or -1 if there is no active
kpeter@383:     ///item.
alpar@379:     int highestActiveLevel() const {
alpar@379:       return _highest_active;
alpar@379:     }
alpar@379: 
alpar@379:     ///Lift the highest active item by one.
alpar@379: 
alpar@379:     ///Lift the item returned by highestActive() by one.
alpar@379:     ///
alpar@379:     void liftHighestActive() {
alpar@379:       Item i = _first[_highest_active];
alpar@379:       if (_next[i] != INVALID) {
alpar@379:         _prev.set(_next[i], INVALID);
alpar@379:         _first[_highest_active] = _next[i];
alpar@379:       } else {
alpar@379:         _first[_highest_active] = INVALID;
alpar@379:         _last[_highest_active] = INVALID;
alpar@379:       }
alpar@379:       _level.set(i, ++_highest_active);
alpar@379:       if (_first[_highest_active] == INVALID) {
alpar@379:         _first[_highest_active] = i;
alpar@379:         _last[_highest_active] = i;
alpar@379:         _prev.set(i, INVALID);
alpar@379:         _next.set(i, INVALID);
alpar@379:       } else {
alpar@379:         _prev.set(_first[_highest_active], i);
alpar@379:         _next.set(i, _first[_highest_active]);
alpar@379:         _first[_highest_active] = i;
alpar@379:       }
alpar@379:     }
alpar@379: 
kpeter@383:     ///Lift the highest active item to the given level.
alpar@379: 
alpar@379:     ///Lift the item returned by highestActive() to level \c new_level.
alpar@379:     ///
alpar@379:     ///\warning \c new_level must be strictly higher
alpar@379:     ///than the current level.
alpar@379:     ///
alpar@379:     void liftHighestActive(int new_level) {
alpar@379:       Item i = _first[_highest_active];
alpar@379:       if (_next[i] != INVALID) {
alpar@379:         _prev.set(_next[i], INVALID);
alpar@379:         _first[_highest_active] = _next[i];
alpar@379:       } else {
alpar@379:         _first[_highest_active] = INVALID;
alpar@379:         _last[_highest_active] = INVALID;
alpar@379:       }
alpar@379:       _level.set(i, _highest_active = new_level);
alpar@379:       if (_first[_highest_active] == INVALID) {
alpar@379:         _first[_highest_active] = _last[_highest_active] = i;
alpar@379:         _prev.set(i, INVALID);
alpar@379:         _next.set(i, INVALID);
alpar@379:       } else {
alpar@379:         _prev.set(_first[_highest_active], i);
alpar@379:         _next.set(i, _first[_highest_active]);
alpar@379:         _first[_highest_active] = i;
alpar@379:       }
alpar@379:     }
alpar@379: 
kpeter@383:     ///Lift the highest active item to the top level.
alpar@379: 
alpar@379:     ///Lift the item returned by highestActive() to the top level and
kpeter@383:     ///deactivate it.
alpar@379:     void liftHighestActiveToTop() {
alpar@379:       Item i = _first[_highest_active];
alpar@379:       _level.set(i, _max_level);
alpar@379:       if (_next[i] != INVALID) {
alpar@379:         _prev.set(_next[i], INVALID);
alpar@379:         _first[_highest_active] = _next[i];
alpar@379:       } else {
alpar@379:         _first[_highest_active] = INVALID;
alpar@379:         _last[_highest_active] = INVALID;
alpar@379:       }
alpar@379:       while (_highest_active >= 0 && activeFree(_highest_active))
alpar@379:         --_highest_active;
alpar@379:     }
alpar@379: 
alpar@379:     ///@}
alpar@379: 
alpar@379:     ///\name Active Item on Certain Level
alpar@379:     ///Functions for working with the active items.
alpar@379: 
alpar@379:     ///@{
alpar@379: 
kpeter@383:     ///Return an active item on level \c l.
alpar@379: 
kpeter@383:     ///Return an active item on level \c l or \ref INVALID if there is no such
alpar@379:     ///an item. (\c l must be from the range [0...\c max_level].
alpar@379:     Item activeOn(int l) const
alpar@379:     {
alpar@379:       return _active[_first[l]] ? _first[l] : INVALID;
alpar@379:     }
alpar@379: 
kpeter@383:     ///Lift the active item returned by \c activeOn(l) by one.
alpar@379: 
kpeter@383:     ///Lift the active item returned by \ref activeOn() "activeOn(l)"
alpar@379:     ///by one.
alpar@379:     Item liftActiveOn(int l)
alpar@379:     {
alpar@379:       Item i = _first[l];
alpar@379:       if (_next[i] != INVALID) {
alpar@379:         _prev.set(_next[i], INVALID);
alpar@379:         _first[l] = _next[i];
alpar@379:       } else {
alpar@379:         _first[l] = INVALID;
alpar@379:         _last[l] = INVALID;
alpar@379:       }
alpar@379:       _level.set(i, ++l);
alpar@379:       if (_first[l] == INVALID) {
alpar@379:         _first[l] = _last[l] = i;
alpar@379:         _prev.set(i, INVALID);
alpar@379:         _next.set(i, INVALID);
alpar@379:       } else {
alpar@379:         _prev.set(_first[l], i);
alpar@379:         _next.set(i, _first[l]);
alpar@379:         _first[l] = i;
alpar@379:       }
alpar@379:       if (_highest_active < l) {
alpar@379:         _highest_active = l;
alpar@379:       }
alpar@379:     }
alpar@379: 
kpeter@383:     ///Lift the active item returned by \c activeOn(l) to the given level.
kpeter@383: 
kpeter@383:     ///Lift the active item returned by \ref activeOn() "activeOn(l)"
kpeter@383:     ///to the given level.
alpar@379:     void liftActiveOn(int l, int new_level)
alpar@379:     {
alpar@379:       Item i = _first[l];
alpar@379:       if (_next[i] != INVALID) {
alpar@379:         _prev.set(_next[i], INVALID);
alpar@379:         _first[l] = _next[i];
alpar@379:       } else {
alpar@379:         _first[l] = INVALID;
alpar@379:         _last[l] = INVALID;
alpar@379:       }
alpar@379:       _level.set(i, l = new_level);
alpar@379:       if (_first[l] == INVALID) {
alpar@379:         _first[l] = _last[l] = i;
alpar@379:         _prev.set(i, INVALID);
alpar@379:         _next.set(i, INVALID);
alpar@379:       } else {
alpar@379:         _prev.set(_first[l], i);
alpar@379:         _next.set(i, _first[l]);
alpar@379:         _first[l] = i;
alpar@379:       }
alpar@379:       if (_highest_active < l) {
alpar@379:         _highest_active = l;
alpar@379:       }
alpar@379:     }
alpar@379: 
kpeter@383:     ///Lift the active item returned by \c activeOn(l) to the top level.
alpar@379: 
kpeter@383:     ///Lift the active item returned by \ref activeOn() "activeOn(l)"
kpeter@383:     ///to the top level and deactivate it.
alpar@379:     void liftActiveToTop(int l)
alpar@379:     {
alpar@379:       Item i = _first[l];
alpar@379:       if (_next[i] != INVALID) {
alpar@379:         _prev.set(_next[i], INVALID);
alpar@379:         _first[l] = _next[i];
alpar@379:       } else {
alpar@379:         _first[l] = INVALID;
alpar@379:         _last[l] = INVALID;
alpar@379:       }
alpar@379:       _level.set(i, _max_level);
alpar@379:       if (l == _highest_active) {
alpar@379:         while (_highest_active >= 0 && activeFree(_highest_active))
alpar@379:           --_highest_active;
alpar@379:       }
alpar@379:     }
alpar@379: 
alpar@379:     ///@}
alpar@379: 
alpar@379:     /// \brief Lift an active item to a higher level.
alpar@379:     ///
alpar@379:     /// Lift an active item to a higher level.
alpar@379:     /// \param i The item to be lifted. It must be active.
alpar@379:     /// \param new_level The new level of \c i. It must be strictly higher
alpar@379:     /// than the current level.
alpar@379:     ///
alpar@379:     void lift(Item i, int new_level) {
alpar@379:       if (_next[i] != INVALID) {
alpar@379:         _prev.set(_next[i], _prev[i]);
alpar@379:       } else {
alpar@379:         _last[new_level] = _prev[i];
alpar@379:       }
alpar@379:       if (_prev[i] != INVALID) {
alpar@379:         _next.set(_prev[i], _next[i]);
alpar@379:       } else {
alpar@379:         _first[new_level] = _next[i];
alpar@379:       }
alpar@379:       _level.set(i, new_level);
alpar@379:       if (_first[new_level] == INVALID) {
alpar@379:         _first[new_level] = _last[new_level] = i;
alpar@379:         _prev.set(i, INVALID);
alpar@379:         _next.set(i, INVALID);
alpar@379:       } else {
alpar@379:         _prev.set(_first[new_level], i);
alpar@379:         _next.set(i, _first[new_level]);
alpar@379:         _first[new_level] = i;
alpar@379:       }
alpar@379:       if (_highest_active < new_level) {
alpar@379:         _highest_active = new_level;
alpar@379:       }
alpar@379:     }
alpar@379: 
alpar@380:     ///Move an inactive item to the top but one level (in a dirty way).
alpar@379: 
kpeter@383:     ///This function moves an inactive item from the top level to the top
kpeter@383:     ///but one level (in a dirty way).
kpeter@383:     ///\warning It makes the underlying datastructure corrupt, so use it
kpeter@383:     ///only if you really know what it is for.
alpar@380:     ///\pre The item is on the top level.
alpar@380:     void dirtyTopButOne(Item i) {
alpar@379:       _level.set(i, _max_level - 1);
alpar@379:     }
alpar@379: 
kpeter@383:     ///Lift all items on and above the given level to the top level.
alpar@379: 
kpeter@383:     ///This function lifts all items on and above level \c l to the top
kpeter@383:     ///level and deactivates them.
alpar@379:     void liftToTop(int l)  {
alpar@379:       for (int i = l + 1; _first[i] != INVALID; ++i) {
alpar@379:         Item n = _first[i];
alpar@379:         while (n != INVALID) {
alpar@379:           _level.set(n, _max_level);
alpar@379:           n = _next[n];
alpar@379:         }
alpar@379:         _first[i] = INVALID;
alpar@379:         _last[i] = INVALID;
alpar@379:       }
alpar@379:       if (_highest_active > l - 1) {
alpar@379:         _highest_active = l - 1;
alpar@379:         while (_highest_active >= 0 && activeFree(_highest_active))
alpar@379:           --_highest_active;
alpar@379:       }
alpar@379:     }
alpar@379: 
alpar@379:   private:
alpar@379: 
alpar@379:     int _init_level;
alpar@379: 
alpar@379:   public:
alpar@379: 
alpar@379:     ///\name Initialization
kpeter@383:     ///Using these functions you can initialize the levels of the items.
alpar@379:     ///\n
kpeter@383:     ///The initialization must be started with calling \c initStart().
kpeter@383:     ///Then the items should be listed level by level starting with the
kpeter@383:     ///lowest one (level 0) using \c initAddItem() and \c initNewLevel().
kpeter@383:     ///Finally \c initFinish() must be called.
kpeter@383:     ///The items not listed are put on the highest level.
alpar@379:     ///@{
alpar@379: 
alpar@379:     ///Start the initialization process.
alpar@379:     void initStart() {
alpar@379: 
alpar@379:       for (int i = 0; i <= _max_level; ++i) {
alpar@379:         _first[i] = _last[i] = INVALID;
alpar@379:       }
alpar@379:       _init_level = 0;
alpar@379:       for(typename ItemSetTraits<Graph,Item>::ItemIt i(_graph);
alpar@379:           i != INVALID; ++i) {
alpar@379:         _level.set(i, _max_level);
alpar@379:         _active.set(i, false);
alpar@379:       }
alpar@379:     }
alpar@379: 
alpar@379:     ///Add an item to the current level.
alpar@379:     void initAddItem(Item i) {
alpar@379:       _level.set(i, _init_level);
alpar@379:       if (_last[_init_level] == INVALID) {
alpar@379:         _first[_init_level] = i;
alpar@379:         _last[_init_level] = i;
alpar@379:         _prev.set(i, INVALID);
alpar@379:         _next.set(i, INVALID);
alpar@379:       } else {
alpar@379:         _prev.set(i, _last[_init_level]);
alpar@379:         _next.set(i, INVALID);
alpar@379:         _next.set(_last[_init_level], i);
alpar@379:         _last[_init_level] = i;
alpar@379:       }
alpar@379:     }
alpar@379: 
alpar@379:     ///Start a new level.
alpar@379: 
alpar@379:     ///Start a new level.
alpar@379:     ///It shouldn't be used before the items on level 0 are listed.
alpar@379:     void initNewLevel() {
alpar@379:       ++_init_level;
alpar@379:     }
alpar@379: 
alpar@379:     ///Finalize the initialization process.
alpar@379:     void initFinish() {
alpar@379:       _highest_active = -1;
alpar@379:     }
alpar@379: 
alpar@379:     ///@}
alpar@379: 
alpar@379:   };
alpar@379: 
alpar@379: 
alpar@379: } //END OF NAMESPACE LEMON
alpar@379: 
alpar@379: #endif
alpar@379: