src/hugo/kruskal.h
changeset 874 2195bc090dfe
parent 812 182d3a4d7ddb
child 881 a9f19f38970b
equal deleted inserted replaced
1:b33fc1b92420 2:c3f61cb0ce14
    19 ///\file
    19 ///\file
    20 ///\brief Kruskal's algorithm to compute a minimum cost tree
    20 ///\brief Kruskal's algorithm to compute a minimum cost tree
    21 ///
    21 ///
    22 ///Kruskal's algorithm to compute a minimum cost tree.
    22 ///Kruskal's algorithm to compute a minimum cost tree.
    23 
    23 
       
    24 ///\weakgroup spantree
    24 namespace hugo {
    25 namespace hugo {
    25 
    26 
    26   /// \addtogroup spantree
    27   /// \addtogroup spantree
    27   /// @{
    28   /// @{
    28 
    29 
    32   /// \param G The graph the algorithm runs on. The algorithm considers the
    33   /// \param G The graph the algorithm runs on. The algorithm considers the
    33   /// graph to be undirected, the direction of the edges are not used.
    34   /// graph to be undirected, the direction of the edges are not used.
    34   ///
    35   ///
    35   /// \param in This object is used to describe the edge costs. It must
    36   /// \param in This object is used to describe the edge costs. It must
    36   /// be an STL compatible 'Forward Container'
    37   /// be an STL compatible 'Forward Container'
    37   /// with <tt>std::pair<Graph::Edge,X></tt> as its <tt>value_type</tt>,
    38   /// with <tt>std::pair<GR::Edge,X></tt> as its <tt>value_type</tt>,
    38   /// where X is the type of the costs. It must contain every edge in
    39   /// where X is the type of the costs. It must contain every edge in
    39   /// cost-ascending order.
    40   /// cost-ascending order.
    40   ///\par
    41   ///\par
    41   /// For the sake of simplicity, there is a helper class KruskalMapInput,
    42   /// For the sake of simplicity, there is a helper class KruskalMapInput,
    42   /// which converts a
    43   /// which converts a
    50   /// edge will be set to \c true if it belongs to the tree, otherwise it will
    51   /// edge will be set to \c true if it belongs to the tree, otherwise it will
    51   /// be set to \c false. The value of each edge will be set exactly once.
    52   /// be set to \c false. The value of each edge will be set exactly once.
    52   ///
    53   ///
    53   /// \return The cost of the found tree.
    54   /// \return The cost of the found tree.
    54 
    55 
    55   template <typename Graph, typename InputEdgeOrder, typename OutBoolMap>
    56   template <class GR, class IN, class OUT>
    56   typename InputEdgeOrder::value_type::second_type
    57   typename IN::value_type::second_type
    57   kruskal(Graph const& G, InputEdgeOrder const& in, 
    58   kruskal(GR const& G, IN const& in, 
    58 		 OutBoolMap& out)
    59 		 OUT& out)
    59   {
    60   {
    60     typedef typename InputEdgeOrder::value_type::second_type EdgeCost;
    61     typedef typename IN::value_type::second_type EdgeCost;
    61     typedef typename Graph::template NodeMap<int> NodeIntMap;
    62     typedef typename GR::template NodeMap<int> NodeIntMap;
    62     typedef typename Graph::Node Node;
    63     typedef typename GR::Node Node;
    63 
    64 
    64     NodeIntMap comp(G, -1);
    65     NodeIntMap comp(G, -1);
    65     UnionFind<Node,NodeIntMap> uf(comp); 
    66     UnionFind<Node,NodeIntMap> uf(comp); 
    66       
    67       
    67     EdgeCost tot_cost = 0;
    68     EdgeCost tot_cost = 0;
    68     for (typename InputEdgeOrder::const_iterator p = in.begin(); 
    69     for (typename IN::const_iterator p = in.begin(); 
    69 	 p!=in.end(); ++p ) {
    70 	 p!=in.end(); ++p ) {
    70       if ( uf.join(G.head((*p).first),
    71       if ( uf.join(G.head((*p).first),
    71 		   G.tail((*p).first)) ) {
    72 		   G.tail((*p).first)) ) {
    72 	out.set((*p).first, true);
    73 	out.set((*p).first, true);
    73 	tot_cost += (*p).second;
    74 	tot_cost += (*p).second;
    81 
    82 
    82   /* A work-around for running Kruskal with const-reference bool maps... */
    83   /* A work-around for running Kruskal with const-reference bool maps... */
    83 
    84 
    84   ///\bug What is this? Or why doesn't it work?
    85   ///\bug What is this? Or why doesn't it work?
    85   ///
    86   ///
    86   template<typename Map>
    87   template<class Map>
    87   class NonConstMapWr {
    88   class NonConstMapWr {
    88     const Map &m;
    89     const Map &m;
    89   public:
    90   public:
    90     typedef typename Map::ValueType ValueType;
    91     typedef typename Map::ValueType ValueType;
    91 
    92 
    92     NonConstMapWr(const Map &_m) : m(_m) {}
    93     NonConstMapWr(const Map &_m) : m(_m) {}
    93 
    94 
    94     template<typename KeyType>
    95     template<class KeyType>
    95     void set(KeyType const& k, ValueType const &v) const { m.set(k,v); }
    96     void set(KeyType const& k, ValueType const &v) const { m.set(k,v); }
    96   };
    97   };
    97 
    98 
    98   template <typename Graph, typename InputEdgeOrder, typename OutBoolMap>
    99   template <class GR, class IN, class OUT>
    99   inline
   100   inline
   100   typename InputEdgeOrder::ValueType
   101   typename IN::ValueType
   101   kruskal(Graph const& G, InputEdgeOrder const& edges, 
   102   kruskal(GR const& G, IN const& edges, 
   102 	  OutBoolMap const& out_map)
   103 	  OUT const& out_map)
   103   {
   104   {
   104     NonConstMapWr<OutBoolMap> map_wr(out_map);
   105     NonConstMapWr<OUT> map_wr(out_map);
   105     return kruskal(G, edges, map_wr);
   106     return kruskal(G, edges, map_wr);
   106   }  
   107   }  
   107 
   108 
   108   /* ** ** Input-objects ** ** */
   109   /* ** ** Input-objects ** ** */
   109 
   110 
   113   ///
   114   ///
   114   /// In most cases you possibly want to use the \ref kruskalEdgeMap() instead.
   115   /// In most cases you possibly want to use the \ref kruskalEdgeMap() instead.
   115   ///
   116   ///
   116   /// \sa makeKruskalMapInput()
   117   /// \sa makeKruskalMapInput()
   117   ///
   118   ///
   118   ///\param Graph The type of the graph the algorithm runs on.
   119   ///\param GR The type of the graph the algorithm runs on.
   119   ///\param Map An edge map containing the cost of the edges.
   120   ///\param Map An edge map containing the cost of the edges.
   120   ///\par
   121   ///\par
   121   ///The cost type can be any type satisfying
   122   ///The cost type can be any type satisfying
   122   ///the STL 'LessThan comparable'
   123   ///the STL 'LessThan comparable'
   123   ///concept if it also has an operator+() implemented. (It is necessary for
   124   ///concept if it also has an operator+() implemented. (It is necessary for
   124   ///computing the total cost of the tree).
   125   ///computing the total cost of the tree).
   125   ///
   126   ///
   126   template<typename Graph, typename Map>
   127   template<class GR, class Map>
   127   class KruskalMapInput
   128   class KruskalMapInput
   128     : public std::vector< std::pair<typename Graph::Edge,
   129     : public std::vector< std::pair<typename GR::Edge,
   129 				    typename Map::ValueType> > {
   130 				    typename Map::ValueType> > {
   130     
   131     
   131   public:
   132   public:
   132     typedef std::vector< std::pair<typename Graph::Edge,
   133     typedef std::vector< std::pair<typename GR::Edge,
   133 				   typename Map::ValueType> > Parent;
   134 				   typename Map::ValueType> > Parent;
   134     typedef typename Parent::value_type value_type;
   135     typedef typename Parent::value_type value_type;
   135 
   136 
   136   private:
   137   private:
   137     class comparePair {
   138     class comparePair {
   146 
   147 
   147     void sort() {
   148     void sort() {
   148       std::sort(this->begin(), this->end(), comparePair());
   149       std::sort(this->begin(), this->end(), comparePair());
   149     }
   150     }
   150 
   151 
   151     KruskalMapInput(Graph const& G, Map const& m) {
   152     KruskalMapInput(GR const& G, Map const& m) {
   152       typedef typename Graph::EdgeIt EdgeIt;
   153       typedef typename GR::EdgeIt EdgeIt;
   153       
   154       
   154       this->clear();
   155       this->clear();
   155       for(EdgeIt e(G);e!=INVALID;++e) push_back(make_pair(e, m[e]));
   156       for(EdgeIt e(G);e!=INVALID;++e) push_back(make_pair(e, m[e]));
   156       sort();
   157       sort();
   157     }
   158     }
   174   ///concept if it also has an operator+() implemented. (It is necessary for
   175   ///concept if it also has an operator+() implemented. (It is necessary for
   175   ///computing the total cost of the tree).
   176   ///computing the total cost of the tree).
   176   ///
   177   ///
   177   ///\return An appropriate input source for \ref kruskal().
   178   ///\return An appropriate input source for \ref kruskal().
   178   ///
   179   ///
   179   template<typename Graph, typename Map>
   180   template<class GR, class Map>
   180   inline
   181   inline
   181   KruskalMapInput<Graph,Map> makeKruskalMapInput(const Graph &G,const Map &m)
   182   KruskalMapInput<GR,Map> makeKruskalMapInput(const GR &G,const Map &m)
   182   {
   183   {
   183     return KruskalMapInput<Graph,Map>(G,m);
   184     return KruskalMapInput<GR,Map>(G,m);
   184   }
   185   }
   185   
   186   
   186   
   187   
   187   /* ** ** Output-objects: simple writable bool maps** ** */
   188   /* ** ** Output-objects: simple writable bool maps** ** */
   188   
   189   
   192   /// the value "true".
   193   /// the value "true".
   193   /// \warning Not a regular property map, as it doesn't know its KeyType
   194   /// \warning Not a regular property map, as it doesn't know its KeyType
   194   /// \bug Missing documentation.
   195   /// \bug Missing documentation.
   195   /// \todo This class may be of wider usage, therefore it could move to
   196   /// \todo This class may be of wider usage, therefore it could move to
   196   /// <tt>maps.h</tt>
   197   /// <tt>maps.h</tt>
   197   template<typename Iterator>
   198   template<class Iterator>
   198   class SequenceOutput {
   199   class SequenceOutput {
   199     mutable Iterator it;
   200     mutable Iterator it;
   200 
   201 
   201   public:
   202   public:
   202     typedef bool ValueType;
   203     typedef bool ValueType;
   205 
   206 
   206     template<typename KeyType>
   207     template<typename KeyType>
   207     void set(KeyType const& k, bool v) const { if(v) {*it=k; ++it;} }
   208     void set(KeyType const& k, bool v) const { if(v) {*it=k; ++it;} }
   208   };
   209   };
   209 
   210 
   210   template<typename Iterator>
   211   template<class Iterator>
   211   inline
   212   inline
   212   SequenceOutput<Iterator>
   213   SequenceOutput<Iterator>
   213   makeSequenceOutput(Iterator it) {
   214   makeSequenceOutput(Iterator it) {
   214     return SequenceOutput<Iterator>(it);
   215     return SequenceOutput<Iterator>(it);
   215   }
   216   }
   238   /// be set to \c false. The value of each edge will be set exactly once.
   239   /// be set to \c false. The value of each edge will be set exactly once.
   239   ///
   240   ///
   240   /// \return The cost of the found tree.
   241   /// \return The cost of the found tree.
   241 
   242 
   242 
   243 
   243   template <typename Graph, typename EdgeCostMap, typename RetEdgeBoolMap>
   244   template <class GR, class IN, class RET>
   244   inline
   245   inline
   245   typename EdgeCostMap::ValueType
   246   typename IN::ValueType
   246   kruskalEdgeMap(Graph const& G,
   247   kruskalEdgeMap(GR const& G,
   247 		 EdgeCostMap const& in,
   248 		 IN const& in,
   248 		 RetEdgeBoolMap &out) {
   249 		 RET &out) {
   249     return kruskal(G,
   250     return kruskal(G,
   250 		   KruskalMapInput<Graph,EdgeCostMap>(G,in),
   251 		   KruskalMapInput<GR,IN>(G,in),
   251 		   out);
   252 		   out);
   252   }
   253   }
   253 
   254 
   254   /// \brief Wrapper function to kruskal().
   255   /// \brief Wrapper function to kruskal().
   255   /// Input is from an edge map, output is an STL Sequence.
   256   /// Input is from an edge map, output is an STL Sequence.
   264   ///STL 'LessThan Comparable'
   265   ///STL 'LessThan Comparable'
   265   ///concept if it also has an operator+() implemented. (It is necessary for
   266   ///concept if it also has an operator+() implemented. (It is necessary for
   266   ///computing the total cost of the tree).
   267   ///computing the total cost of the tree).
   267   ///
   268   ///
   268   /// \retval out This must be an iteraror of an STL Container with
   269   /// \retval out This must be an iteraror of an STL Container with
   269   /// <tt>Graph::Edge</tt> as its <tt>value_type</tt>.
   270   /// <tt>GR::Edge</tt> as its <tt>value_type</tt>.
   270   /// The algorithm copies the elements of the found tree into this sequence.
   271   /// The algorithm copies the elements of the found tree into this sequence.
   271   /// For example, if we know that the spanning tree of the graph \c G has
   272   /// For example, if we know that the spanning tree of the graph \c G has
   272   /// say 53 edges then
   273   /// say 53 edges then
   273   /// we can put its edges into a vector \c tree with a code like this.
   274   /// we can put its edges into a STL vector \c tree with a code like this.
   274   /// \code
   275   /// \code
   275   /// std::vector<Edge> tree(53);
   276   /// std::vector<Edge> tree(53);
   276   /// kruskalEdgeMap_IteratorOut(G,cost,tree.begin());
   277   /// kruskalEdgeMap_IteratorOut(G,cost,tree.begin());
   277   /// \endcode
   278   /// \endcode
   278   /// Or if we don't know in advance the size of the tree, we can write this.
   279   /// Or if we don't know in advance the size of the tree, we can write this.
   282   /// \endcode
   283   /// \endcode
   283   ///
   284   ///
   284   /// \return The cost of the found tree.
   285   /// \return The cost of the found tree.
   285   ///
   286   ///
   286   /// \bug its name does not follow the coding style.
   287   /// \bug its name does not follow the coding style.
   287   template <typename Graph, typename EdgeCostMap, typename RetIterator>
   288   template <class GR, class IN, class RET>
   288   inline
   289   inline
   289   typename EdgeCostMap::ValueType
   290   typename IN::ValueType
   290   kruskalEdgeMap_IteratorOut(const Graph& G,
   291   kruskalEdgeMap_IteratorOut(const GR& G,
   291 			     const EdgeCostMap& in,
   292 			     const IN& in,
   292 			     RetIterator out)
   293 			     RET out)
   293   {
   294   {
   294     SequenceOutput<RetIterator> _out(out);
   295     SequenceOutput<RET> _out(out);
   295     return kruskal(G,
   296     return kruskal(G,
   296 		   KruskalMapInput<Graph, EdgeCostMap>(G, in),
   297 		   KruskalMapInput<GR,IN>(G, in),
   297 		   _out);
   298 		   _out);
   298   }
   299   }
   299 
   300 
   300   /// @}
   301   /// @}
   301 
   302