src/hugo/kruskal.h
author deba
Wed, 08 Sep 2004 12:06:45 +0000
changeset 822 88226d9fe821
parent 810 e9fbc747ca47
child 824 157115b5814a
permissions -rw-r--r--
The MapFactories have been removed from the code because
if we use macros then they increases only the complexity.

The pair iterators of the maps are separeted from the maps.

Some macros and comments has been changed.
alpar@810
     1
// -*- c++ -*- //
alpar@810
     2
#ifndef HUGO_KRUSKAL_H
alpar@810
     3
#define HUGO_KRUSKAL_H
alpar@810
     4
alpar@810
     5
#include <algorithm>
alpar@810
     6
#include <hugo/unionfind.h>
alpar@810
     7
alpar@810
     8
/**
alpar@810
     9
@defgroup spantree Minimum Cost Spanning Tree Algorithms
alpar@810
    10
@ingroup galgs
alpar@810
    11
\brief This group containes the algorithms for finding a minimum cost spanning
alpar@810
    12
tree in a graph
alpar@810
    13
alpar@810
    14
This group containes the algorithms for finding a minimum cost spanning
alpar@810
    15
tree in a graph
alpar@810
    16
*/
alpar@810
    17
alpar@810
    18
///\ingroup spantree
alpar@810
    19
///\file
alpar@810
    20
///\brief Kruskal's algorithm to compute a minimum cost tree
alpar@810
    21
///
alpar@810
    22
///Kruskal's algorithm to compute a minimum cost tree.
alpar@810
    23
alpar@810
    24
namespace hugo {
alpar@810
    25
alpar@810
    26
  /// \addtogroup spantree
alpar@810
    27
  /// @{
alpar@810
    28
alpar@810
    29
  /// Kruskal's algorithm to find a minimum cost tree of a graph.
alpar@810
    30
alpar@810
    31
  /// This function runs Kruskal's algorithm to find a minimum cost tree.
alpar@810
    32
  /// \param G The graph the algorithm runs on. The algorithm considers the
alpar@810
    33
  /// graph to be undirected, the direction of the edges are not used.
alpar@810
    34
  ///
alpar@810
    35
  /// \param in This object is used to describe the edge costs. It must
alpar@810
    36
  /// be an STL compatible 'Forward Container'
alpar@810
    37
  /// with <tt>std::pair<Graph::Edge,X></tt> as its <tt>value_type</tt>,
alpar@810
    38
  /// where X is the type of the costs. It must contain every edge in
alpar@810
    39
  /// cost-ascending order.
alpar@810
    40
  ///\par
alpar@810
    41
  /// For the sake of simplicity, there is a helper class KruskalMapInput,
alpar@810
    42
  /// which converts a
alpar@810
    43
  /// simple edge map to an input of this form. Alternatively, you can use
alpar@810
    44
  /// the function \ref kruskalEdgeMap to compute the minimum cost tree if
alpar@810
    45
  /// the edge costs are given by an edge map.
alpar@810
    46
  ///
alpar@810
    47
  /// \retval out This must be a writable \c bool edge map.
alpar@810
    48
  /// After running the algorithm
alpar@810
    49
  /// this will contain the found minimum cost spanning tree: the value of an
alpar@810
    50
  /// edge will be set to \c true if it belongs to the tree, otherwise it will
alpar@810
    51
  /// be set to \c false. The value of each edge will be set exactly once.
alpar@810
    52
  ///
alpar@810
    53
  /// \return The cost of the found tree.
alpar@810
    54
alpar@810
    55
  template <typename Graph, typename InputEdgeOrder, typename OutBoolMap>
alpar@810
    56
  typename InputEdgeOrder::value_type::second_type
alpar@810
    57
  kruskal(Graph const& G, InputEdgeOrder const& in, 
alpar@810
    58
		 OutBoolMap& out)
alpar@810
    59
  {
alpar@810
    60
    typedef typename InputEdgeOrder::value_type::second_type EdgeCost;
alpar@810
    61
    typedef typename Graph::template NodeMap<int> NodeIntMap;
alpar@810
    62
    typedef typename Graph::Node Node;
alpar@810
    63
alpar@810
    64
    NodeIntMap comp(G, -1);
alpar@810
    65
    UnionFind<Node,NodeIntMap> uf(comp); 
alpar@810
    66
      
alpar@810
    67
    EdgeCost tot_cost = 0;
alpar@810
    68
    for (typename InputEdgeOrder::const_iterator p = in.begin(); 
alpar@810
    69
	 p!=in.end(); ++p ) {
alpar@810
    70
      if ( uf.join(G.head((*p).first),
alpar@810
    71
		   G.tail((*p).first)) ) {
alpar@810
    72
	out.set((*p).first, true);
alpar@810
    73
	tot_cost += (*p).second;
alpar@810
    74
      }
alpar@810
    75
      else {
alpar@810
    76
	out.set((*p).first, false);
alpar@810
    77
      }
alpar@810
    78
    }
alpar@810
    79
    return tot_cost;
alpar@810
    80
  }
alpar@810
    81
alpar@810
    82
  /* A work-around for running Kruskal with const-reference bool maps... */
alpar@810
    83
alpar@812
    84
  ///\bug What is this? Or why doesn't it work?
alpar@810
    85
  ///
alpar@810
    86
  template<typename Map>
alpar@810
    87
  class NonConstMapWr {
alpar@810
    88
    const Map &m;
alpar@810
    89
  public:
alpar@810
    90
    typedef typename Map::ValueType ValueType;
alpar@810
    91
alpar@810
    92
    NonConstMapWr(const Map &_m) : m(_m) {}
alpar@810
    93
alpar@810
    94
    template<typename KeyType>
alpar@810
    95
    void set(KeyType const& k, ValueType const &v) const { m.set(k,v); }
alpar@810
    96
  };
alpar@810
    97
alpar@810
    98
  template <typename Graph, typename InputEdgeOrder, typename OutBoolMap>
alpar@810
    99
  inline
alpar@810
   100
  typename InputEdgeOrder::ValueType
alpar@810
   101
  kruskal(Graph const& G, InputEdgeOrder const& edges, 
alpar@810
   102
	  OutBoolMap const& out_map)
alpar@810
   103
  {
alpar@810
   104
    NonConstMapWr<OutBoolMap> map_wr(out_map);
alpar@810
   105
    return kruskal(G, edges, map_wr);
alpar@810
   106
  }  
alpar@810
   107
alpar@810
   108
  /* ** ** Input-objects ** ** */
alpar@810
   109
alpar@810
   110
  /// Kruskal input source.
alpar@810
   111
alpar@810
   112
  /// Kruskal input source.
alpar@810
   113
  ///
alpar@810
   114
  /// In most cases you possibly want to use the \ref kruskalEdgeMap() instead.
alpar@810
   115
  ///
alpar@810
   116
  /// \sa makeKruskalMapInput()
alpar@810
   117
  ///
alpar@810
   118
  ///\param Graph The type of the graph the algorithm runs on.
alpar@810
   119
  ///\param Map An edge map containing the cost of the edges.
alpar@810
   120
  ///\par
alpar@810
   121
  ///The cost type can be any type satisfying
alpar@810
   122
  ///the STL 'LessThan comparable'
alpar@810
   123
  ///concept if it also has an operator+() implemented. (It is necessary for
alpar@810
   124
  ///computing the total cost of the tree).
alpar@810
   125
  ///
alpar@810
   126
  template<typename Graph, typename Map>
alpar@810
   127
  class KruskalMapInput
alpar@810
   128
    : public std::vector< std::pair<typename Graph::Edge,
alpar@810
   129
				    typename Map::ValueType> > {
alpar@810
   130
    
alpar@810
   131
  public:
alpar@810
   132
    typedef std::vector< std::pair<typename Graph::Edge,
alpar@810
   133
				   typename Map::ValueType> > Parent;
alpar@810
   134
    typedef typename Parent::value_type value_type;
alpar@810
   135
alpar@810
   136
  private:
alpar@810
   137
    class comparePair {
alpar@810
   138
    public:
alpar@810
   139
      bool operator()(const value_type& a,
alpar@810
   140
		      const value_type& b) {
alpar@810
   141
	return a.second < b.second;
alpar@810
   142
      }
alpar@810
   143
    };
alpar@810
   144
alpar@810
   145
  public:
alpar@810
   146
alpar@810
   147
    void sort() {
alpar@810
   148
      std::sort(this->begin(), this->end(), comparePair());
alpar@810
   149
    }
alpar@810
   150
alpar@810
   151
    KruskalMapInput(Graph const& G, Map const& m) {
alpar@810
   152
      typedef typename Graph::EdgeIt EdgeIt;
alpar@810
   153
      
alpar@810
   154
      this->clear();
alpar@810
   155
      for(EdgeIt e(G);e!=INVALID;++e) push_back(make_pair(e, m[e]));
alpar@810
   156
      sort();
alpar@810
   157
    }
alpar@810
   158
  };
alpar@810
   159
alpar@810
   160
  /// Creates a KruskalMapInput object for \ref kruskal()
alpar@810
   161
alpar@810
   162
  /// It makes is easier to use 
alpar@810
   163
  /// \ref KruskalMapInput by making it unnecessary 
alpar@810
   164
  /// to explicitly give the type of the parameters.
alpar@810
   165
  ///
alpar@810
   166
  /// In most cases you possibly
alpar@810
   167
  /// want to use the function kruskalEdgeMap() instead.
alpar@810
   168
  ///
alpar@810
   169
  ///\param G The type of the graph the algorithm runs on.
alpar@810
   170
  ///\param m An edge map containing the cost of the edges.
alpar@810
   171
  ///\par
alpar@810
   172
  ///The cost type can be any type satisfying the
alpar@810
   173
  ///STL 'LessThan Comparable'
alpar@810
   174
  ///concept if it also has an operator+() implemented. (It is necessary for
alpar@810
   175
  ///computing the total cost of the tree).
alpar@810
   176
  ///
alpar@810
   177
  ///\return An appropriate input source for \ref kruskal().
alpar@810
   178
  ///
alpar@810
   179
  template<typename Graph, typename Map>
alpar@810
   180
  inline
alpar@810
   181
  KruskalMapInput<Graph,Map> makeKruskalMapInput(const Graph &G,const Map &m)
alpar@810
   182
  {
alpar@810
   183
    return KruskalMapInput<Graph,Map>(G,m);
alpar@810
   184
  }
alpar@810
   185
  
alpar@810
   186
  
alpar@810
   187
  /* ** ** Output-objects: simple writable bool maps** ** */
alpar@810
   188
  
alpar@810
   189
  /// A writable bool-map that makes a sequence of "true" keys
alpar@810
   190
alpar@810
   191
  /// A writable bool-map that creates a sequence out of keys that receives
alpar@810
   192
  /// the value "true".
alpar@810
   193
  /// \warning Not a regular property map, as it doesn't know its KeyType
alpar@810
   194
  /// \bug Missing documentation.
alpar@810
   195
  /// \todo This class may be of wider usage, therefore it could move to
alpar@810
   196
  /// <tt>maps.h</tt>
alpar@810
   197
  template<typename Iterator>
alpar@810
   198
  class SequenceOutput {
alpar@810
   199
    mutable Iterator it;
alpar@810
   200
alpar@810
   201
  public:
alpar@810
   202
    typedef bool ValueType;
alpar@810
   203
alpar@810
   204
    SequenceOutput(Iterator const &_it) : it(_it) {}
alpar@810
   205
alpar@810
   206
    template<typename KeyType>
alpar@810
   207
    void set(KeyType const& k, bool v) const { if(v) {*it=k; ++it;} }
alpar@810
   208
  };
alpar@810
   209
alpar@810
   210
  template<typename Iterator>
alpar@810
   211
  inline
alpar@810
   212
  SequenceOutput<Iterator>
alpar@810
   213
  makeSequenceOutput(Iterator it) {
alpar@810
   214
    return SequenceOutput<Iterator>(it);
alpar@810
   215
  }
alpar@810
   216
alpar@810
   217
  /* ** ** Wrapper funtions ** ** */
alpar@810
   218
alpar@810
   219
alpar@810
   220
  /// \brief Wrapper function to kruskal().
alpar@810
   221
  /// Input is from an edge map, output is a plain bool map.
alpar@810
   222
  ///
alpar@810
   223
  /// Wrapper function to kruskal().
alpar@810
   224
  /// Input is from an edge map, output is a plain bool map.
alpar@810
   225
  ///
alpar@810
   226
  ///\param G The type of the graph the algorithm runs on.
alpar@810
   227
  ///\param in An edge map containing the cost of the edges.
alpar@810
   228
  ///\par
alpar@810
   229
  ///The cost type can be any type satisfying the
alpar@810
   230
  ///STL 'LessThan Comparable'
alpar@810
   231
  ///concept if it also has an operator+() implemented. (It is necessary for
alpar@810
   232
  ///computing the total cost of the tree).
alpar@810
   233
  ///
alpar@810
   234
  /// \retval out This must be a writable \c bool edge map.
alpar@810
   235
  /// After running the algorithm
alpar@810
   236
  /// this will contain the found minimum cost spanning tree: the value of an
alpar@810
   237
  /// edge will be set to \c true if it belongs to the tree, otherwise it will
alpar@810
   238
  /// be set to \c false. The value of each edge will be set exactly once.
alpar@810
   239
  ///
alpar@810
   240
  /// \return The cost of the found tree.
alpar@810
   241
alpar@810
   242
alpar@810
   243
  template <typename Graph, typename EdgeCostMap, typename RetEdgeBoolMap>
alpar@810
   244
  inline
alpar@810
   245
  typename EdgeCostMap::ValueType
alpar@810
   246
  kruskalEdgeMap(Graph const& G,
alpar@810
   247
		 EdgeCostMap const& in,
alpar@810
   248
		 RetEdgeBoolMap &out) {
alpar@810
   249
    return kruskal(G,
alpar@810
   250
		   KruskalMapInput<Graph,EdgeCostMap>(G,in),
alpar@810
   251
		   out);
alpar@810
   252
  }
alpar@810
   253
alpar@810
   254
  /// \brief Wrapper function to kruskal().
alpar@810
   255
  /// Input is from an edge map, output is an STL Sequence.
alpar@810
   256
  ///
alpar@810
   257
  /// Wrapper function to kruskal().
alpar@810
   258
  /// Input is from an edge map, output is an STL Sequence.
alpar@810
   259
  ///
alpar@810
   260
  ///\param G The type of the graph the algorithm runs on.
alpar@810
   261
  ///\param in An edge map containing the cost of the edges.
alpar@810
   262
  ///\par
alpar@810
   263
  ///The cost type can be any type satisfying the
alpar@810
   264
  ///STL 'LessThan Comparable'
alpar@810
   265
  ///concept if it also has an operator+() implemented. (It is necessary for
alpar@810
   266
  ///computing the total cost of the tree).
alpar@810
   267
  ///
alpar@810
   268
  /// \retval out This must be an iteraror of an STL Container with
alpar@810
   269
  /// <tt>Graph::Edge</tt> as its <tt>value_type</tt>.
alpar@810
   270
  /// The algorithm copies the elements of the found tree into this sequence.
alpar@810
   271
  /// For example, if we know that the spanning tree of the graph \c G has
alpar@810
   272
  /// say 53 edges then
alpar@810
   273
  /// we can put its edges into a vector \c tree with a code like this.
alpar@810
   274
  /// \code
alpar@810
   275
  /// std::vector<Edge> tree(53);
alpar@810
   276
  /// kruskalEdgeMap_IteratorOut(G,cost,tree.begin());
alpar@810
   277
  /// \endcode
alpar@810
   278
  /// Or if we don't know in advance the size of the tree, we can write this.
alpar@810
   279
  /// \code
alpar@810
   280
  /// std::vector<Edge> tree;
alpar@810
   281
  /// kruskalEdgeMap_IteratorOut(G,cost,std::back_inserter(tree));
alpar@810
   282
  /// \endcode
alpar@810
   283
  ///
alpar@810
   284
  /// \return The cost of the found tree.
alpar@810
   285
  ///
alpar@810
   286
  /// \bug its name does not follow the coding style.
alpar@810
   287
  template <typename Graph, typename EdgeCostMap, typename RetIterator>
alpar@810
   288
  inline
alpar@810
   289
  typename EdgeCostMap::ValueType
alpar@810
   290
  kruskalEdgeMap_IteratorOut(const Graph& G,
alpar@810
   291
			     const EdgeCostMap& in,
alpar@810
   292
			     RetIterator out)
alpar@810
   293
  {
alpar@810
   294
    SequenceOutput<RetIterator> _out(out);
alpar@810
   295
    return kruskal(G,
alpar@810
   296
		   KruskalMapInput<Graph, EdgeCostMap>(G, in),
alpar@810
   297
		   _out);
alpar@810
   298
  }
alpar@810
   299
alpar@810
   300
  /// @}
alpar@810
   301
alpar@810
   302
} //namespace hugo
alpar@810
   303
alpar@810
   304
#endif //HUGO_KRUSKAL_H