00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00018 #ifndef __defined_libdai_weightedgraph_h
00019 #define __defined_libdai_weightedgraph_h
00020
00021
00022 #include <vector>
00023 #include <map>
00024 #include <iostream>
00025 #include <set>
00026 #include <limits>
00027 #include <climits>
00028 #include <dai/util.h>
00029 #include <dai/exceptions.h>
00030 #include <dai/graph.h>
00031
00032 #include <boost/graph/adjacency_list.hpp>
00033 #include <boost/graph/prim_minimum_spanning_tree.hpp>
00034 #include <boost/graph/kruskal_min_spanning_tree.hpp>
00035
00036
00037 namespace dai {
00038
00039
00041 class DEdge {
00042 public:
00044 size_t first;
00045
00047 size_t second;
00048
00050 DEdge() : first(0), second(0) {}
00051
00053 DEdge( size_t m1, size_t m2 ) : first(m1), second(m2) {}
00054
00056 bool operator==( const DEdge &x ) const { return ((first == x.first) && (second == x.second)); }
00057
00059 bool operator<( const DEdge &x ) const {
00060 return( (first < x.first) || ((first == x.first) && (second < x.second)) );
00061 }
00062
00064 friend std::ostream & operator << (std::ostream & os, const DEdge & e) {
00065 os << "(" << e.first << "->" << e.second << ")";
00066 return os;
00067 }
00068 };
00069
00070
00072 class UEdge {
00073 public:
00075 size_t first;
00076
00078 size_t second;
00079
00081 UEdge() : first(0), second(0) {}
00082
00084 UEdge( size_t m1, size_t m2 ) : first(m1), second(m2) {}
00085
00087 UEdge( const DEdge &e ) : first(e.first), second(e.second) {}
00088
00090 bool operator==( const UEdge &x ) {
00091 return ((first == x.first) && (second == x.second)) || ((first == x.second) && (second == x.first));
00092 }
00093
00095 bool operator<( const UEdge &x ) const {
00096 size_t s = std::min( first, second );
00097 size_t l = std::max( first, second );
00098 size_t xs = std::min( x.first, x.second );
00099 size_t xl = std::max( x.first, x.second );
00100 return( (s < xs) || ((s == xs) && (l < xl)) );
00101 }
00102
00104 friend std::ostream & operator << (std::ostream & os, const UEdge & e) {
00105 if( e.first < e.second )
00106 os << "{" << e.first << "--" << e.second << "}";
00107 else
00108 os << "{" << e.second << "--" << e.first << "}";
00109 return os;
00110 }
00111 };
00112
00113
00115 class GraphEL : public std::set<UEdge> {
00116 public:
00118 GraphEL() {}
00119
00121 template <class InputIterator>
00122 GraphEL( InputIterator begin, InputIterator end ) {
00123 insert( begin, end );
00124 }
00125
00127 GraphEL( const GraphAL& G ) {
00128 for( size_t n1 = 0; n1 < G.nrNodes(); n1++ )
00129 foreach( const Neighbor n2, G.nb(n1) )
00130 if( n1 < n2 )
00131 insert( UEdge( n1, n2 ) );
00132 }
00133 };
00134
00135
00137 template<class T> class WeightedGraph : public std::map<UEdge, T> {};
00138
00139
00141
00145 class RootedTree : public std::vector<DEdge> {
00146 public:
00148 RootedTree() {}
00149
00151
00153 RootedTree( const GraphEL &T, size_t Root );
00154 };
00155
00156
00158
00163 template<typename T> RootedTree MinSpanningTree( const WeightedGraph<T> &G, bool usePrim ) {
00164 RootedTree result;
00165 if( G.size() > 0 ) {
00166 using namespace boost;
00167 using namespace std;
00168 typedef adjacency_list< vecS, vecS, undirectedS, no_property, property<edge_weight_t, double> > boostGraph;
00169
00170 set<size_t> nodes;
00171 vector<UEdge> edges;
00172 vector<double> weights;
00173 edges.reserve( G.size() );
00174 weights.reserve( G.size() );
00175 for( typename WeightedGraph<T>::const_iterator e = G.begin(); e != G.end(); e++ ) {
00176 weights.push_back( e->second );
00177 edges.push_back( e->first );
00178 nodes.insert( e->first.first );
00179 nodes.insert( e->first.second );
00180 }
00181
00182 size_t N = nodes.size();
00183 for( set<size_t>::const_iterator it = nodes.begin(); it != nodes.end(); it++ )
00184 if( *it >= N )
00185 DAI_THROWE(RUNTIME_ERROR,"Vertices must be in range [0..N) where N is the number of vertices.");
00186
00187 boostGraph g( edges.begin(), edges.end(), weights.begin(), nodes.size() );
00188 size_t root = *(nodes.begin());
00189 GraphEL tree;
00190 if( usePrim ) {
00191
00192 vector< graph_traits< boostGraph >::vertex_descriptor > p(N);
00193 prim_minimum_spanning_tree( g, &(p[0]) );
00194
00195
00196 for( size_t i = 0; i != p.size(); i++ ) {
00197 if( p[i] != i )
00198 tree.insert( UEdge( p[i], i ) );
00199 }
00200 } else {
00201
00202 vector< graph_traits< boostGraph >::edge_descriptor > t;
00203 t.reserve( N - 1 );
00204 kruskal_minimum_spanning_tree( g, std::back_inserter(t) );
00205
00206
00207 for( size_t i = 0; i != t.size(); i++ ) {
00208 size_t v1 = source( t[i], g );
00209 size_t v2 = target( t[i], g );
00210 if( v1 != v2 )
00211 tree.insert( UEdge( v1, v2 ) );
00212 }
00213 }
00214
00215
00216 result = RootedTree( tree, root );
00217 }
00218 return result;
00219 }
00220
00221
00223
00228 template<typename T> RootedTree MaxSpanningTree( const WeightedGraph<T> &G, bool usePrim ) {
00229 if( G.size() == 0 )
00230 return RootedTree();
00231 else {
00232 T maxweight = G.begin()->second;
00233 for( typename WeightedGraph<T>::const_iterator it = G.begin(); it != G.end(); it++ )
00234 if( it->second > maxweight )
00235 maxweight = it->second;
00236
00237 WeightedGraph<T> gr( G );
00238
00239
00240 for( typename WeightedGraph<T>::iterator it = gr.begin(); it != gr.end(); it++ )
00241 it->second = maxweight - it->second;
00242 return MinSpanningTree( gr, usePrim );
00243 }
00244 }
00245
00246
00247 }
00248
00249
00250 #endif