lemon/fredman_tarjan.h
changeset 1924 9fdc893e2199
child 1946 17eb3eaad9f8
equal deleted inserted replaced
-1:000000000000 0:c943bc590917
       
     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