lemon/fredman_tarjan.h
author alpar
Thu, 02 Feb 2006 08:51:10 +0000
changeset 1940 e47d0614a489
child 1946 17eb3eaad9f8
permissions -rw-r--r--
- also works off-line
- icc-8.0 in (not) tested, as well.
     1 /* -*- C++ -*-
     2  * lemon/fredman_tarjan.h - Part of LEMON, a generic C++ optimization library
     3  *
     4  * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
     5  * (Egervary Research Group on Combinatorial Optimization, EGRES).
     6  *
     7  * Permission to use, modify and distribute this software is granted
     8  * provided that this copyright notice appears in all copies. For
     9  * precise terms see the accompanying LICENSE file.
    10  *
    11  * This software is provided "AS IS" with no warranty of any kind,
    12  * express or implied, and with no claim as to its suitability for any
    13  * purpose.
    14  *
    15  */
    16 
    17 #ifndef LEMON_FREDMAN_TARJAN_H
    18 #define LEMON_FREDMAN_TARJAN_H
    19 
    20 ///\ingroup spantree
    21 ///\file
    22 ///\brief FredmanTarjan algorithm to compute minimum spanning forest.
    23 
    24 #include <limits>
    25 #include <vector>
    26 
    27 #include <lemon/list_graph.h>
    28 #include <lemon/smart_graph.h>
    29 #include <lemon/fib_heap.h>
    30 #include <lemon/radix_sort.h>
    31 #include <lemon/invalid.h>
    32 #include <lemon/error.h>
    33 #include <lemon/maps.h>
    34 #include <lemon/traits.h>
    35 #include <lemon/graph_utils.h>
    36 
    37 #include <lemon/concept/ugraph.h>
    38 
    39 namespace lemon {
    40 
    41   ///Default traits class of FredmanTarjan class.
    42 
    43   ///Default traits class of FredmanTarjan class.
    44   ///\param GR Graph type.
    45   ///\param LM Type of cost map.
    46   template<class GR, class LM>
    47   struct FredmanTarjanDefaultTraits{
    48     ///The graph type the algorithm runs on. 
    49     typedef GR UGraph;
    50     ///The type of the map that stores the edge costs.
    51 
    52     ///The type of the map that stores the edge costs.
    53     ///It must meet the \ref concept::ReadMap "ReadMap" concept.
    54     typedef LM CostMap;
    55     //The type of the cost of the edges.
    56     typedef typename LM::Value Value;
    57     ///The type of the map that stores whether an edge is in the
    58     ///spanning tree or not.
    59 
    60     ///The type of the map that stores whether an edge is in the
    61     ///spanning tree or not.
    62     ///It must meet the \ref concept::ReadWriteMap "ReadWriteMap" concept.
    63     ///By default it is a BoolEdgeMap.
    64     typedef typename UGraph::template UEdgeMap<bool> TreeMap;
    65     ///Instantiates a TreeMap.
    66 
    67     ///This function instantiates a \ref TreeMap.
    68     ///\param g is the graph, to which
    69     ///we would like to define the \ref TreeMap
    70     static TreeMap *createTreeMap(const GR &_graph){
    71       return new TreeMap(_graph);
    72     }
    73   };
    74   
    75   ///%FredmanTarjan algorithm class to find a minimum spanning tree.
    76   
    77   /// \ingroup spantree
    78   ///This class provides an efficient implementation of %FredmanTarjan algorithm
    79   ///whitch is sometimes a bit quicker than the Prim algorithm on larger graphs.
    80   ///Due to the structure of the algorithm, it has less controll functions than
    81   ///Prim.
    82   ///
    83   ///The running time is O(e*B(e,n)) where e is the number of edges, n is the
    84   ///number of nodes in the graph and B(e,n) is min { i | log^(i) n <= e/n}
    85   ///( log^(i+1) n = log(log^(i)) n )
    86   ///
    87   ///The edge costs are passed to the algorithm using a
    88   ///\ref concept::ReadMap "ReadMap",
    89   ///so it is easy to change it to any kind of cost.
    90   ///
    91   ///The type of the cost is determined by the
    92   ///\ref concept::ReadMap::Value "Value" of the cost map.
    93   ///
    94   ///\param GR The graph type the algorithm runs on. The default value
    95   ///is \ref ListUGraph. The value of GR is not used directly by
    96   ///FredmanTarjan, it is only passed to \ref FredmanTarjanDefaultTraits.
    97   ///
    98   ///\param LM This read-only UEdgeMap determines the costs of the
    99   ///edges. It is read once for each edge, so the map may involve in
   100   ///relatively time consuming process to compute the edge cost if
   101   ///it is necessary. The default map type is \ref
   102   ///concept::UGraph::UEdgeMap "UGraph::UEdgeMap<int>". The value
   103   ///of LM is not used directly by FredmanTarjan, it is only passed to \ref
   104   ///FredmanTarjanDefaultTraits.
   105   ///
   106   ///\param TR Traits class to set
   107   ///various data types used by the algorithm.  The default traits
   108   ///class is \ref FredmanTarjanDefaultTraits
   109   ///"FredmanTarjanDefaultTraits<GR,LM>".  See \ref
   110   ///FredmanTarjanDefaultTraits for the documentation of a FredmanTarjan traits
   111   ///class.
   112   ///
   113   ///\author Balazs Attila Mihaly
   114 
   115 #ifdef DOXYGEN
   116   template <typename GR,
   117 	    typename LM,
   118 	    typename TR>
   119 #else
   120   template <typename GR=ListUGraph,
   121 	    typename LM=typename GR::template UEdgeMap<int>,
   122 	    typename TR=FredmanTarjanDefaultTraits<GR,LM> >
   123 #endif
   124   class FredmanTarjan {
   125   public:
   126     /**
   127      * \brief \ref Exception for uninitialized parameters.
   128      *
   129      * This error represents problems in the initialization
   130      * of the parameters of the algorithms.
   131      */
   132     class UninitializedParameter : public lemon::UninitializedParameter {
   133     public:
   134       virtual const char* exceptionName() const {
   135 	return "lemon::FredmanTarjan::UninitializedParameter";
   136       }
   137     };
   138 
   139     typedef GR Graph;
   140     typedef TR Traits;
   141     ///The type of the underlying graph.
   142     typedef typename TR::UGraph UGraph;
   143     ///\e
   144     typedef typename UGraph::Node Node;
   145     ///\e
   146     typedef typename UGraph::NodeIt NodeIt;
   147     ///\e
   148     typedef typename UGraph::UEdge UEdge;
   149     ///\e
   150     typedef typename UGraph::UEdgeIt UEdgeIt;
   151     ///\e
   152     typedef typename UGraph::IncEdgeIt IncEdgeIt;
   153     
   154     ///The type of the cost of the edges.
   155     typedef typename TR::CostMap::Value Value;
   156     ///The type of the map that stores the edge costs.
   157     typedef typename TR::CostMap CostMap;
   158     ///Edges of the spanning tree.
   159     typedef typename TR::TreeMap TreeMap;
   160   private:
   161     ///Pointer to the underlying graph.
   162     const UGraph *graph;
   163     ///Pointer to the cost map
   164     const CostMap *cost;
   165     ///Pointer to the map of tree edges.
   166     TreeMap *_tree;
   167     ///Indicates if \ref _tree is locally allocated (\c true) or not.
   168     bool local_tree;
   169 
   170     ///Creates the maps if necessary.
   171     
   172     void create_maps(){
   173       if(!_tree){
   174 	local_tree=true;
   175 	_tree=Traits::createTreeMap(*graph);
   176       }
   177     }
   178     
   179   public :
   180 
   181     typedef FredmanTarjan Create;
   182  
   183     ///\name Named template parameters
   184 
   185     ///@{
   186 
   187     template <class TM>
   188     struct DefTreeMapTraits : public Traits {
   189       typedef TM TreeMap;
   190       static TreeMap *createTreeMap(const UGraph &) {
   191 	throw UninitializedParameter();
   192       }
   193     };
   194     ///\ref named-templ-param "Named parameter" for setting TreeMap 
   195 
   196     ///\ref named-templ-param "Named parameter" for setting TreeMap
   197     ///
   198     template <class TM>
   199     struct DefTreeMap
   200       : public FredmanTarjan< UGraph, CostMap, DefTreeMapTraits<TM> > { 
   201       typedef FredmanTarjan< UGraph, CostMap, DefTreeMapTraits<TM> > Create;
   202     };
   203 
   204     ///@}
   205 
   206 
   207   protected:
   208 
   209     FredmanTarjan() {}
   210 
   211   private:
   212 
   213     template<class SrcGraph,class OrigMap,class Heap,class ProcessedMap,class PredMap>
   214     void processNextTree(const SrcGraph& graph,const OrigMap& orig,Heap &heap,
   215 	ProcessedMap& processed,PredMap& pred,int& tree_counter,const int limit){
   216       std::vector<typename SrcGraph::Node> tree_nodes;
   217       int tree_index=tree_counter;
   218       bool stop=false;
   219       while(!heap.empty() && !stop){
   220         typename SrcGraph::Node v=heap.top();
   221         heap.pop();
   222 	if(processed[v]!=-1){
   223 	  heap.state(v,Heap::PRE_HEAP);
   224 	  tree_index=processed[v];
   225 	  _tree->set(orig[pred[v]],true);
   226 	  stop=true;
   227 	  break;
   228         }
   229 	tree_nodes.push_back(v);
   230 	for(typename SrcGraph::IncEdgeIt e(graph,v);e!=INVALID;++e){
   231 	  typename SrcGraph::Node w=graph.oppositeNode(v,e);
   232 	  switch(heap.state(w)){
   233 	  case Heap::PRE_HEAP:
   234 	    if(heap.size()>=limit){
   235 	      stop=true;
   236 	    }
   237 	    else{
   238 	      heap.push(w,(*cost)[orig[e]]);
   239 	      pred.set(w,e);
   240 	    }
   241 	    break;
   242 	  case Heap::IN_HEAP:
   243 	    if ((*cost)[orig[e]]<heap[w]){
   244 	      heap.decrease(w,(*cost)[orig[e]]); 
   245 	      pred.set(w,e);
   246 	    }
   247 	    break;
   248 	  case Heap::POST_HEAP:
   249 	    break;
   250 	  }
   251 	}
   252       }
   253       for(int i=1;i<(int)tree_nodes.size();++i){
   254 	_tree->set(orig[pred[tree_nodes[i]]],true);
   255         processed.set(tree_nodes[i],tree_index);
   256         heap.state(tree_nodes[i], Heap::PRE_HEAP);
   257       }
   258       processed.set(tree_nodes[0],tree_index);
   259       heap.state(tree_nodes[0],Heap::PRE_HEAP);
   260       while (!heap.empty()) {
   261         typename SrcGraph::Node v=heap.top();
   262 	heap.pop();
   263         heap.state(v,Heap::PRE_HEAP);
   264       }
   265       if(!stop)++tree_counter;
   266     }
   267 
   268     template<class SrcGraph,class OrigMap,class ProcessedMap>
   269     void createTrees(const SrcGraph& graph,const OrigMap& orig, ProcessedMap& processed,
   270 	int edgenum,int& tree_counter){
   271       typedef typename SrcGraph::Node Node;
   272       typedef typename SrcGraph::UEdge UEdge;
   273       typedef typename SrcGraph::NodeIt NodeIt;
   274       typedef typename SrcGraph::template NodeMap<int> HeapCrossRef;
   275       typedef typename SrcGraph::template NodeMap<UEdge> PredMap;
   276       HeapCrossRef crossref(graph,-1);
   277       FibHeap<Node,Value,HeapCrossRef> heap(crossref);
   278       PredMap pred(graph,INVALID);
   279       int rate=2*edgenum/countNodes(graph);
   280       int limit=(rate>std::numeric_limits<int>::digits)?std::numeric_limits<int>::max():(1<<rate);
   281       for(NodeIt i(graph);i!=INVALID;++i){
   282 	if(processed[i]==-1){
   283 	  heap.push(i, Value());
   284 	  processNextTree(graph,orig,heap,processed,pred,tree_counter,limit);
   285 	}
   286       }
   287     }
   288 
   289     template<class SrcGraph,class DestGraph,class SrcOrigMap,class DestOrigMap,class ProcessedMap>
   290     void collect(const SrcGraph& srcgraph,const SrcOrigMap& srcorig,DestGraph& destgraph,
   291 	DestOrigMap& destorig,const ProcessedMap& processed,const int tree_counter){
   292       typedef typename SrcGraph::Node Node;
   293       typedef typename DestGraph::Node DNode;
   294       typedef typename SrcGraph::UEdge UEdge;
   295       typedef typename DestGraph::UEdge DUEdge;
   296       typedef typename SrcGraph::Edge Edge;
   297       typedef typename SrcGraph::EdgeIt EdgeIt;
   298       std::vector<Edge> edges;
   299       std::vector<DNode> nodes(tree_counter, INVALID);
   300       for(EdgeIt i(srcgraph);i!=INVALID;++i){
   301 	if(processed[srcgraph.source(i)]<processed[srcgraph.target(i)]){
   302 	  edges.push_back(i);
   303           if(nodes[processed[srcgraph.source(i)]]==INVALID) {
   304 	    nodes[processed[srcgraph.source(i)]]=destgraph.addNode();
   305 	  }
   306           if(nodes[processed[srcgraph.target(i)]]==INVALID) {
   307 	    nodes[processed[srcgraph.target(i)]]=destgraph.addNode();
   308 	  }
   309 	}
   310       }
   311       
   312       radixSort(edges.begin(),edges.end(),mapFunctor(composeMap(processed,sourceMap(srcgraph))));
   313       counterSort(edges.begin(),edges.end(),mapFunctor(composeMap(processed,targetMap(srcgraph))));
   314       for(int i=0;i!=(int)edges.size();++i){
   315 	int srcproc=processed[srcgraph.source(edges[i])];
   316 	int trgproc=processed[srcgraph.target(edges[i])];
   317         Value minval=(*cost)[srcorig[edges[i]]];
   318         UEdge minpos=edges[i];
   319 	while (i+1!=(int)edges.size() && srcproc==processed[srcgraph.source(edges[i+1])] &&
   320 	  trgproc==processed[srcgraph.target(edges[i+1])]) {
   321 	  if (minval>(*cost)[srcorig[edges[i+1]]]) {
   322             minval=(*cost)[srcorig[edges[i+1]]];
   323             minpos=edges[i+1];
   324 	  }
   325           ++i;
   326 	} 
   327 	destorig[destgraph.addEdge(nodes[srcproc],nodes[trgproc])]=srcorig[minpos];
   328       }
   329     }
   330 
   331     template<class SrcGraph,class OrigMap>
   332     void phase(const SrcGraph& graph,const OrigMap& orig,int edgenum){
   333       int tree_counter = 0;
   334       typename SrcGraph::template NodeMap<int> processed(graph,-1);
   335       SmartUGraph destgraph;
   336       SmartUGraph::UEdgeMap<typename OrigMap::Value> destorig(destgraph);
   337       createTrees(graph,orig,processed,edgenum,tree_counter);
   338       collect(graph,orig,destgraph,destorig,processed,tree_counter);
   339       if (countNodes(destgraph)>1) {
   340         phase(destgraph,destorig,edgenum);
   341       }
   342     }
   343 
   344   public:      
   345     
   346     ///Constructor.
   347     
   348     ///\param _graph the graph the algorithm will run on.
   349     ///\param _cost the cost map used by the algorithm.
   350     FredmanTarjan(const UGraph& _graph, const CostMap& _cost) :
   351       graph(&_graph), cost(&_cost),
   352       _tree(0), local_tree(false)
   353     {
   354       checkConcept<concept::UGraph, UGraph>();
   355     }
   356     
   357     ///Destructor.
   358     ~FredmanTarjan(){
   359       if(local_tree) delete _tree;
   360     }
   361 
   362     ///Sets the cost map.
   363 
   364     ///Sets the cost map.
   365     ///\return <tt> (*this) </tt>
   366     FredmanTarjan &costMap(const CostMap &m){
   367       cost = &m;
   368       return *this;
   369     }
   370 
   371     ///Sets the map storing the tree edges.
   372 
   373     ///Sets the map storing the tree edges.
   374     ///If you don't use this function before calling \ref run(),
   375     ///it will allocate one. The destuctor deallocates this
   376     ///automatically allocated map, of course.
   377     ///By default this is a BoolEdgeMap.
   378     ///\return <tt> (*this) </tt>
   379     FredmanTarjan &treeMap(TreeMap &m){
   380       if(local_tree) {
   381 	delete _tree;
   382 	local_tree=false;
   383       }
   384       _tree = &m;
   385       return *this;
   386     }
   387 
   388   public:
   389     ///\name Execution control
   390     ///The simplest way to execute the algorithm is to use
   391     ///one of the member functions called \c run(...).
   392 
   393     ///@{
   394 
   395     ///Initializes the internal data structures.
   396 
   397     ///Initializes the internal data structures.
   398     ///
   399     void init(){
   400       create_maps();
   401       for(typename Graph::UEdgeIt i(*graph);i!=INVALID;++i){
   402 	_tree->set(i,false);
   403       }
   404     }
   405 
   406     ///Executes the algorithm.
   407 
   408     ///Executes the algorithm.
   409     ///
   410     ///\pre init() must be called and at least one node should be added
   411     ///with addSource() before using this function.
   412     ///
   413     ///This method runs the %FredmanTarjan algorithm from the node(s)
   414     ///in order to compute the
   415     ///minimum spanning tree.
   416     void start(){
   417 	phase(*graph,identityMap<UEdge>(),countEdges(*graph));
   418     }
   419     
   420     ///Runs %FredmanTarjan algorithm.
   421     
   422     ///This method runs the %FredmanTarjan algorithm
   423     ///in order to compute the minimum spanning forest.
   424     ///
   425     ///\note ft.run() is just a shortcut of the following code.
   426     ///\code
   427     ///  ft.init();
   428     ///  ft.start();
   429     ///\endcode
   430     void run() {
   431       init();
   432       start();
   433     }
   434 
   435     ///@}
   436 
   437     ///\name Query Functions
   438     ///The result of the %FredmanTarjan algorithm can be obtained using these
   439     ///functions.\n
   440     ///Before the use of these functions,
   441     ///either run() or start() must be called.
   442     
   443     ///@{
   444 
   445     ///Returns a reference to the tree edges map.
   446 
   447     ///Returns a reference to the TreeEdgeMap of the edges of the
   448     ///minimum spanning tree. The value of the map is \c true only if the 
   449     ///edge is in the minimum spanning tree.
   450     ///
   451     ///\pre \ref run() or \ref start() must be called before using this 
   452     ///function.
   453     const TreeMap &treeMap() const { return *_tree;}
   454  
   455     ///Sets the tree edges map.
   456 
   457     ///Sets the TreeMap of the edges of the minimum spanning tree.
   458     ///The map values belonging to the edges of the minimum
   459     ///spanning tree are set to \param tree_edge_value or \c true by default 
   460     ///while the edge values not belonging to the minimum spanning tree are 
   461     ///set to
   462     ///\param tree_default_value or \c false by default.
   463     ///
   464     ///\pre \ref run() or \ref start() must be called before using this 
   465     ///function.
   466 
   467     template<class TreeMap>
   468     void treeEdges(
   469         TreeMap& tree,
   470         const typename TreeMap::Value& tree_edge_value=true,
   471         const typename TreeMap::Value& tree_default_value=false) const {
   472       for(typename UGraph::UEdgeIt i(*graph);i!=INVALID;++i){
   473 	(*_tree)[i]?tree.set(i,tree_edge_value):tree.set(i,tree_default_value);
   474       }
   475     }
   476 
   477     ///\brief Checks if an edge is in the spanning tree or not.
   478 
   479     ///Checks if an edge is in the spanning tree or not.
   480     ///\param e is the edge that will be checked
   481     ///\return \c true if e is in the spanning tree, \c false otherwise
   482     bool tree(UEdge e){
   483       return (*_tree)[e];
   484     }
   485     ///@}
   486   };
   487 
   488   /// \ingroup spantree
   489   ///
   490   /// \brief Function type interface for FredmanTarjan algorithm.
   491   ///
   492   /// Function type interface for FredmanTarjan algorithm.
   493   /// \param graph the UGraph that the algorithm runs on
   494   /// \param cost the CostMap of the edges
   495   /// \retval tree the EdgeMap that contains whether an edge is in the 
   496   /// spanning tree or not
   497   ///
   498   /// \sa Prim
   499   template<class Graph,class CostMap,class TreeMap>
   500   void fredmanTarjan(const Graph& graph, const CostMap& cost,TreeMap& tree){
   501     typename FredmanTarjan<Graph,CostMap>::template DefTreeMap<TreeMap>::
   502       Create ft(graph,cost);
   503     ft.treeMap(tree);
   504     ft.run();
   505   };
   506 
   507 } //END OF NAMESPACE LEMON
   508 
   509 #endif