One more step towards Undir -> U conversion...
3 * This file is a part of LEMON, a generic C++ optimization library
5 * Copyright (C) 2003-2006
6 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
7 * (Egervary Research Group on Combinatorial Optimization, EGRES).
9 * Permission to use, modify and distribute this software is granted
10 * provided that this copyright notice appears in all copies. For
11 * precise terms see the accompanying LICENSE file.
13 * This software is provided "AS IS" with no warranty of any kind,
14 * express or implied, and with no claim as to its suitability for any
19 #ifndef LEMON_FREDMAN_TARJAN_H
20 #define LEMON_FREDMAN_TARJAN_H
24 ///\brief FredmanTarjan algorithm to compute minimum spanning forest.
29 #include <lemon/list_graph.h>
30 #include <lemon/smart_graph.h>
31 #include <lemon/fib_heap.h>
32 #include <lemon/radix_sort.h>
33 #include <lemon/invalid.h>
34 #include <lemon/error.h>
35 #include <lemon/maps.h>
36 #include <lemon/traits.h>
37 #include <lemon/graph_utils.h>
39 #include <lemon/concept/ugraph.h>
43 ///Default traits class of FredmanTarjan class.
45 ///Default traits class of FredmanTarjan class.
46 ///\param GR Graph type.
47 ///\param LM Type of cost map.
48 template<class GR, class LM>
49 struct FredmanTarjanDefaultTraits{
50 ///The graph type the algorithm runs on.
52 ///The type of the map that stores the edge costs.
54 ///The type of the map that stores the edge costs.
55 ///It must meet the \ref concept::ReadMap "ReadMap" concept.
57 //The type of the cost of the edges.
58 typedef typename LM::Value Value;
59 ///The type of the map that stores whether an edge is in the
60 ///spanning tree or not.
62 ///The type of the map that stores whether an edge is in the
63 ///spanning tree or not.
64 ///It must meet the \ref concept::ReadWriteMap "ReadWriteMap" concept.
65 ///By default it is a BoolEdgeMap.
66 typedef typename UGraph::template UEdgeMap<bool> TreeMap;
67 ///Instantiates a TreeMap.
69 ///This function instantiates a \ref TreeMap.
70 ///\param _graph is the graph, to which
71 ///we would like to define the \ref TreeMap
72 static TreeMap *createTreeMap(const GR &_graph){
73 return new TreeMap(_graph);
77 ///%FredmanTarjan algorithm class to find a minimum spanning tree.
80 ///This class provides an efficient implementation of %FredmanTarjan algorithm
81 ///whitch is sometimes a bit quicker than the Prim algorithm on larger graphs.
82 ///Due to the structure of the algorithm, it has less controll functions than
85 ///The running time is O(e*B(e,n)) where e is the number of edges, n is the
86 ///number of nodes in the graph and B(e,n) is min { i | log^(i) n <= e/n}
87 ///( log^(i+1) n = log(log^(i)) n )
89 ///The edge costs are passed to the algorithm using a
90 ///\ref concept::ReadMap "ReadMap",
91 ///so it is easy to change it to any kind of cost.
93 ///The type of the cost is determined by the
94 ///\ref concept::ReadMap::Value "Value" of the cost map.
96 ///\param GR The graph type the algorithm runs on. The default value
97 ///is \ref ListUGraph. The value of GR is not used directly by
98 ///FredmanTarjan, it is only passed to \ref FredmanTarjanDefaultTraits.
100 ///\param LM This read-only UEdgeMap determines the costs of the
101 ///edges. It is read once for each edge, so the map may involve in
102 ///relatively time consuming process to compute the edge cost if
103 ///it is necessary. The default map type is \ref
104 ///concept::UGraph::UEdgeMap "UGraph::UEdgeMap<int>". The value
105 ///of LM is not used directly by FredmanTarjan, it is only passed to \ref
106 ///FredmanTarjanDefaultTraits.
108 ///\param TR Traits class to set
109 ///various data types used by the algorithm. The default traits
110 ///class is \ref FredmanTarjanDefaultTraits
111 ///"FredmanTarjanDefaultTraits<GR,LM>". See \ref
112 ///FredmanTarjanDefaultTraits for the documentation of a FredmanTarjan traits
115 ///\author Balazs Attila Mihaly
118 template <typename GR,
122 template <typename GR=ListUGraph,
123 typename LM=typename GR::template UEdgeMap<int>,
124 typename TR=FredmanTarjanDefaultTraits<GR,LM> >
126 class FredmanTarjan {
129 * \brief \ref Exception for uninitialized parameters.
131 * This error represents problems in the initialization
132 * of the parameters of the algorithms.
134 class UninitializedParameter : public lemon::UninitializedParameter {
136 virtual const char* exceptionName() const {
137 return "lemon::FredmanTarjan::UninitializedParameter";
143 ///The type of the underlying graph.
144 typedef typename TR::UGraph UGraph;
146 typedef typename UGraph::Node Node;
148 typedef typename UGraph::NodeIt NodeIt;
150 typedef typename UGraph::UEdge UEdge;
152 typedef typename UGraph::UEdgeIt UEdgeIt;
154 typedef typename UGraph::IncEdgeIt IncEdgeIt;
156 ///The type of the cost of the edges.
157 typedef typename TR::CostMap::Value Value;
158 ///The type of the map that stores the edge costs.
159 typedef typename TR::CostMap CostMap;
160 ///Edges of the spanning tree.
161 typedef typename TR::TreeMap TreeMap;
163 ///Pointer to the underlying graph.
165 ///Pointer to the cost map
167 ///Pointer to the map of tree edges.
169 ///Indicates if \ref _tree is locally allocated (\c true) or not.
172 ///Creates the maps if necessary.
177 _tree=Traits::createTreeMap(*graph);
183 typedef FredmanTarjan Create;
185 ///\name Named template parameters
190 struct DefTreeMapTraits : public Traits {
192 static TreeMap *createTreeMap(const UGraph &) {
193 throw UninitializedParameter();
196 ///\ref named-templ-param "Named parameter" for setting TreeMap
198 ///\ref named-templ-param "Named parameter" for setting TreeMap
202 : public FredmanTarjan< UGraph, CostMap, DefTreeMapTraits<TM> > {
203 typedef FredmanTarjan< UGraph, CostMap, DefTreeMapTraits<TM> > Create;
215 template<class SrcGraph,class OrigMap,class Heap,class ProcessedMap,class PredMap>
216 void processNextTree(const SrcGraph& graph,const OrigMap& orig,Heap &heap,
217 ProcessedMap& processed,PredMap& pred,int& tree_counter,const int limit){
218 std::vector<typename SrcGraph::Node> tree_nodes;
219 int tree_index=tree_counter;
221 while(!heap.empty() && !stop){
222 typename SrcGraph::Node v=heap.top();
224 if(processed[v]!=-1){
225 heap.state(v,Heap::PRE_HEAP);
226 tree_index=processed[v];
227 _tree->set(orig[pred[v]],true);
231 tree_nodes.push_back(v);
232 for(typename SrcGraph::IncEdgeIt e(graph,v);e!=INVALID;++e){
233 typename SrcGraph::Node w=graph.oppositeNode(v,e);
234 switch(heap.state(w)){
236 if(heap.size()>=limit){
240 heap.push(w,(*cost)[orig[e]]);
245 if ((*cost)[orig[e]]<heap[w]){
246 heap.decrease(w,(*cost)[orig[e]]);
250 case Heap::POST_HEAP:
255 for(int i=1;i<(int)tree_nodes.size();++i){
256 _tree->set(orig[pred[tree_nodes[i]]],true);
257 processed.set(tree_nodes[i],tree_index);
258 heap.state(tree_nodes[i], Heap::PRE_HEAP);
260 processed.set(tree_nodes[0],tree_index);
261 heap.state(tree_nodes[0],Heap::PRE_HEAP);
262 while (!heap.empty()) {
263 typename SrcGraph::Node v=heap.top();
265 heap.state(v,Heap::PRE_HEAP);
267 if(!stop)++tree_counter;
270 template<class SrcGraph,class OrigMap,class ProcessedMap>
271 void createTrees(const SrcGraph& graph,const OrigMap& orig, ProcessedMap& processed,
272 int edgenum,int& tree_counter){
273 typedef typename SrcGraph::Node Node;
274 typedef typename SrcGraph::UEdge UEdge;
275 typedef typename SrcGraph::NodeIt NodeIt;
276 typedef typename SrcGraph::template NodeMap<int> HeapCrossRef;
277 typedef typename SrcGraph::template NodeMap<UEdge> PredMap;
278 HeapCrossRef crossref(graph,-1);
279 FibHeap<Node,Value,HeapCrossRef> heap(crossref);
280 PredMap pred(graph,INVALID);
281 int rate=2*edgenum/countNodes(graph);
282 int limit=(rate>std::numeric_limits<int>::digits)?std::numeric_limits<int>::max():(1<<rate);
283 for(NodeIt i(graph);i!=INVALID;++i){
284 if(processed[i]==-1){
285 heap.push(i, Value());
286 processNextTree(graph,orig,heap,processed,pred,tree_counter,limit);
291 template<class SrcGraph,class DestGraph,class SrcOrigMap,class DestOrigMap,class ProcessedMap>
292 void collect(const SrcGraph& srcgraph,const SrcOrigMap& srcorig,DestGraph& destgraph,
293 DestOrigMap& destorig,const ProcessedMap& processed,const int tree_counter){
294 typedef typename SrcGraph::Node Node;
295 typedef typename DestGraph::Node DNode;
296 typedef typename SrcGraph::UEdge UEdge;
297 typedef typename DestGraph::UEdge DUEdge;
298 typedef typename SrcGraph::Edge Edge;
299 typedef typename SrcGraph::EdgeIt EdgeIt;
300 std::vector<Edge> edges;
301 std::vector<DNode> nodes(tree_counter, INVALID);
302 for(EdgeIt i(srcgraph);i!=INVALID;++i){
303 if(processed[srcgraph.source(i)]<processed[srcgraph.target(i)]){
305 if(nodes[processed[srcgraph.source(i)]]==INVALID) {
306 nodes[processed[srcgraph.source(i)]]=destgraph.addNode();
308 if(nodes[processed[srcgraph.target(i)]]==INVALID) {
309 nodes[processed[srcgraph.target(i)]]=destgraph.addNode();
314 radixSort(edges.begin(),edges.end(),mapFunctor(composeMap(processed,sourceMap(srcgraph))));
315 counterSort(edges.begin(),edges.end(),mapFunctor(composeMap(processed,targetMap(srcgraph))));
316 for(int i=0;i!=(int)edges.size();++i){
317 int srcproc=processed[srcgraph.source(edges[i])];
318 int trgproc=processed[srcgraph.target(edges[i])];
319 Value minval=(*cost)[srcorig[edges[i]]];
320 UEdge minpos=edges[i];
321 while (i+1!=(int)edges.size() && srcproc==processed[srcgraph.source(edges[i+1])] &&
322 trgproc==processed[srcgraph.target(edges[i+1])]) {
323 if (minval>(*cost)[srcorig[edges[i+1]]]) {
324 minval=(*cost)[srcorig[edges[i+1]]];
329 destorig[destgraph.addEdge(nodes[srcproc],nodes[trgproc])]=srcorig[minpos];
333 template<class SrcGraph,class OrigMap>
334 void phase(const SrcGraph& graph,const OrigMap& orig,int edgenum){
335 int tree_counter = 0;
336 typename SrcGraph::template NodeMap<int> processed(graph,-1);
337 SmartUGraph destgraph;
338 SmartUGraph::UEdgeMap<typename OrigMap::Value> destorig(destgraph);
339 createTrees(graph,orig,processed,edgenum,tree_counter);
340 collect(graph,orig,destgraph,destorig,processed,tree_counter);
341 if (countNodes(destgraph)>1) {
342 phase(destgraph,destorig,edgenum);
350 ///\param _graph the graph the algorithm will run on.
351 ///\param _cost the cost map used by the algorithm.
352 FredmanTarjan(const UGraph& _graph, const CostMap& _cost) :
353 graph(&_graph), cost(&_cost),
354 _tree(0), local_tree(false)
356 checkConcept<concept::UGraph, UGraph>();
361 if(local_tree) delete _tree;
364 ///Sets the cost map.
366 ///Sets the cost map.
367 ///\return <tt> (*this) </tt>
368 FredmanTarjan &costMap(const CostMap &m){
373 ///Sets the map storing the tree edges.
375 ///Sets the map storing the tree edges.
376 ///If you don't use this function before calling \ref run(),
377 ///it will allocate one. The destuctor deallocates this
378 ///automatically allocated map, of course.
379 ///By default this is a BoolEdgeMap.
380 ///\return <tt> (*this) </tt>
381 FredmanTarjan &treeMap(TreeMap &m){
391 ///\name Execution control
392 ///The simplest way to execute the algorithm is to use
393 ///one of the member functions called \c run(...).
397 ///Initializes the internal data structures.
399 ///Initializes the internal data structures.
403 for(typename Graph::UEdgeIt i(*graph);i!=INVALID;++i){
408 ///Executes the algorithm.
410 ///Executes the algorithm.
412 ///\pre init() must be called and at least one node should be added
413 ///with addSource() before using this function.
415 ///This method runs the %FredmanTarjan algorithm from the node(s)
416 ///in order to compute the
417 ///minimum spanning tree.
419 phase(*graph,identityMap<UEdge>(),countEdges(*graph));
422 ///Runs %FredmanTarjan algorithm.
424 ///This method runs the %FredmanTarjan algorithm
425 ///in order to compute the minimum spanning forest.
427 ///\note ft.run() is just a shortcut of the following code.
439 ///\name Query Functions
440 ///The result of the %FredmanTarjan algorithm can be obtained using these
442 ///Before the use of these functions,
443 ///either run() or start() must be called.
447 ///Returns a reference to the tree edges map.
449 ///Returns a reference to the TreeEdgeMap of the edges of the
450 ///minimum spanning tree. The value of the map is \c true only if the
451 ///edge is in the minimum spanning tree.
453 ///\pre \ref run() or \ref start() must be called before using this
455 const TreeMap &treeMap() const { return *_tree;}
457 ///Sets the tree edges map.
459 ///Sets the TreeMap of the edges of the minimum spanning tree.
460 ///The map values belonging to the edges of the minimum
461 ///spanning tree are set to \c tree_edge_value or \c true by default
462 ///while the edge values not belonging to the minimum spanning tree are
464 ///\c tree_default_value or \c false by default.
466 ///\pre \ref run() or \ref start() must be called before using this
469 template<class TreeMap>
472 const typename TreeMap::Value& tree_edge_value=true,
473 const typename TreeMap::Value& tree_default_value=false) const {
474 for(typename UGraph::UEdgeIt i(*graph);i!=INVALID;++i){
475 (*_tree)[i]?tree.set(i,tree_edge_value):tree.set(i,tree_default_value);
479 ///\brief Checks if an edge is in the spanning tree or not.
481 ///Checks if an edge is in the spanning tree or not.
482 ///\param e is the edge that will be checked
483 ///\return \c true if e is in the spanning tree, \c false otherwise
490 /// \ingroup spantree
492 /// \brief Function type interface for FredmanTarjan algorithm.
494 /// Function type interface for FredmanTarjan algorithm.
495 /// \param graph the UGraph that the algorithm runs on
496 /// \param cost the CostMap of the edges
497 /// \retval tree the EdgeMap that contains whether an edge is in the
498 /// spanning tree or not
501 template<class Graph,class CostMap,class TreeMap>
502 void fredmanTarjan(const Graph& graph, const CostMap& cost,TreeMap& tree){
503 typename FredmanTarjan<Graph,CostMap>::template DefTreeMap<TreeMap>::
504 Create ft(graph,cost);
509 } //END OF NAMESPACE LEMON