2 * lemon/fredman_tarjan.h - Part of LEMON, a generic C++ optimization library
4 * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
5 * (Egervary Research Group on Combinatorial Optimization, EGRES).
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.
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
17 #ifndef LEMON_FREDMAN_TARJAN_H
18 #define LEMON_FREDMAN_TARJAN_H
22 ///\brief FredmanTarjan algorithm to compute minimum spanning forest.
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>
37 #include <lemon/concept/ugraph.h>
41 ///Default traits class of FredmanTarjan class.
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.
50 ///The type of the map that stores the edge costs.
52 ///The type of the map that stores the edge costs.
53 ///It must meet the \ref concept::ReadMap "ReadMap" concept.
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.
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.
67 ///This function instantiates a \ref TreeMap.
68 ///\param _graph 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);
75 ///%FredmanTarjan algorithm class to find a minimum spanning tree.
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
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 )
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.
91 ///The type of the cost is determined by the
92 ///\ref concept::ReadMap::Value "Value" of the cost map.
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.
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.
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
113 ///\author Balazs Attila Mihaly
116 template <typename GR,
120 template <typename GR=ListUGraph,
121 typename LM=typename GR::template UEdgeMap<int>,
122 typename TR=FredmanTarjanDefaultTraits<GR,LM> >
124 class FredmanTarjan {
127 * \brief \ref Exception for uninitialized parameters.
129 * This error represents problems in the initialization
130 * of the parameters of the algorithms.
132 class UninitializedParameter : public lemon::UninitializedParameter {
134 virtual const char* exceptionName() const {
135 return "lemon::FredmanTarjan::UninitializedParameter";
141 ///The type of the underlying graph.
142 typedef typename TR::UGraph UGraph;
144 typedef typename UGraph::Node Node;
146 typedef typename UGraph::NodeIt NodeIt;
148 typedef typename UGraph::UEdge UEdge;
150 typedef typename UGraph::UEdgeIt UEdgeIt;
152 typedef typename UGraph::IncEdgeIt IncEdgeIt;
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;
161 ///Pointer to the underlying graph.
163 ///Pointer to the cost map
165 ///Pointer to the map of tree edges.
167 ///Indicates if \ref _tree is locally allocated (\c true) or not.
170 ///Creates the maps if necessary.
175 _tree=Traits::createTreeMap(*graph);
181 typedef FredmanTarjan Create;
183 ///\name Named template parameters
188 struct DefTreeMapTraits : public Traits {
190 static TreeMap *createTreeMap(const UGraph &) {
191 throw UninitializedParameter();
194 ///\ref named-templ-param "Named parameter" for setting TreeMap
196 ///\ref named-templ-param "Named parameter" for setting TreeMap
200 : public FredmanTarjan< UGraph, CostMap, DefTreeMapTraits<TM> > {
201 typedef FredmanTarjan< UGraph, CostMap, DefTreeMapTraits<TM> > Create;
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;
219 while(!heap.empty() && !stop){
220 typename SrcGraph::Node v=heap.top();
222 if(processed[v]!=-1){
223 heap.state(v,Heap::PRE_HEAP);
224 tree_index=processed[v];
225 _tree->set(orig[pred[v]],true);
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)){
234 if(heap.size()>=limit){
238 heap.push(w,(*cost)[orig[e]]);
243 if ((*cost)[orig[e]]<heap[w]){
244 heap.decrease(w,(*cost)[orig[e]]);
248 case Heap::POST_HEAP:
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);
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();
263 heap.state(v,Heap::PRE_HEAP);
265 if(!stop)++tree_counter;
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);
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)]){
303 if(nodes[processed[srcgraph.source(i)]]==INVALID) {
304 nodes[processed[srcgraph.source(i)]]=destgraph.addNode();
306 if(nodes[processed[srcgraph.target(i)]]==INVALID) {
307 nodes[processed[srcgraph.target(i)]]=destgraph.addNode();
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]]];
327 destorig[destgraph.addEdge(nodes[srcproc],nodes[trgproc])]=srcorig[minpos];
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);
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)
354 checkConcept<concept::UGraph, UGraph>();
359 if(local_tree) delete _tree;
362 ///Sets the cost map.
364 ///Sets the cost map.
365 ///\return <tt> (*this) </tt>
366 FredmanTarjan &costMap(const CostMap &m){
371 ///Sets the map storing the tree edges.
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){
389 ///\name Execution control
390 ///The simplest way to execute the algorithm is to use
391 ///one of the member functions called \c run(...).
395 ///Initializes the internal data structures.
397 ///Initializes the internal data structures.
401 for(typename Graph::UEdgeIt i(*graph);i!=INVALID;++i){
406 ///Executes the algorithm.
408 ///Executes the algorithm.
410 ///\pre init() must be called and at least one node should be added
411 ///with addSource() before using this function.
413 ///This method runs the %FredmanTarjan algorithm from the node(s)
414 ///in order to compute the
415 ///minimum spanning tree.
417 phase(*graph,identityMap<UEdge>(),countEdges(*graph));
420 ///Runs %FredmanTarjan algorithm.
422 ///This method runs the %FredmanTarjan algorithm
423 ///in order to compute the minimum spanning forest.
425 ///\note ft.run() is just a shortcut of the following code.
437 ///\name Query Functions
438 ///The result of the %FredmanTarjan algorithm can be obtained using these
440 ///Before the use of these functions,
441 ///either run() or start() must be called.
445 ///Returns a reference to the tree edges map.
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.
451 ///\pre \ref run() or \ref start() must be called before using this
453 const TreeMap &treeMap() const { return *_tree;}
455 ///Sets the tree edges map.
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
462 ///\param tree_default_value or \c false by default.
464 ///\pre \ref run() or \ref start() must be called before using this
467 template<class TreeMap>
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);
477 ///\brief Checks if an edge is in the spanning tree or not.
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
488 /// \ingroup spantree
490 /// \brief Function type interface for FredmanTarjan algorithm.
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
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);
507 } //END OF NAMESPACE LEMON