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 union {
00045 size_t first;
00047 size_t n1;
00048 };
00049
00051 union {
00052 size_t second;
00054 size_t n2;
00055 };
00056
00058 DEdge() : first(0), second(0) {}
00059
00061 DEdge( size_t m1, size_t m2 ) : first(m1), second(m2) {}
00062
00064 bool operator==( const DEdge &x ) const { return ((first == x.first) && (second == x.second)); }
00065
00067 bool operator<( const DEdge &x ) const {
00068 return( (first < x.first) || ((first == x.first) && (second < x.second)) );
00069 }
00070
00072 friend std::ostream & operator << (std::ostream & os, const DEdge & e) {
00073 os << "(" << e.first << "->" << e.second << ")";
00074 return os;
00075 }
00076 };
00077
00078
00080 class UEdge {
00081 public:
00083 union {
00084 size_t first;
00086 size_t n1;
00087 };
00088
00090 union {
00091 size_t second;
00093 size_t n2;
00094 };
00095
00097 UEdge() : first(0), second(0) {}
00098
00100 UEdge( size_t m1, size_t m2 ) : first(m1), second(m2) {}
00101
00103 UEdge( const DEdge &e ) : first(e.first), second(e.second) {}
00104
00106 bool operator==( const UEdge &x ) {
00107 return ((first == x.first) && (second == x.second)) || ((first == x.second) && (second == x.first));
00108 }
00109
00111 bool operator<( const UEdge &x ) const {
00112 size_t s = std::min( first, second );
00113 size_t l = std::max( first, second );
00114 size_t xs = std::min( x.first, x.second );
00115 size_t xl = std::max( x.first, x.second );
00116 return( (s < xs) || ((s == xs) && (l < xl)) );
00117 }
00118
00120 friend std::ostream & operator << (std::ostream & os, const UEdge & e) {
00121 if( e.first < e.second )
00122 os << "{" << e.first << "--" << e.second << "}";
00123 else
00124 os << "{" << e.second << "--" << e.first << "}";
00125 return os;
00126 }
00127 };
00128
00129
00131 class GraphEL : public std::set<UEdge> {
00132 public:
00134 GraphEL() {}
00135
00137 template <class InputIterator>
00138 GraphEL( InputIterator begin, InputIterator end ) {
00139 insert( begin, end );
00140 }
00141
00143 GraphEL( const GraphAL& G ) {
00144 for( size_t n1 = 0; n1 < G.nrNodes(); n1++ )
00145 foreach( const GraphAL::Neighbor n2, G.nb(n1) )
00146 if( n1 < n2 )
00147 insert( UEdge( n1, n2 ) );
00148 }
00149 };
00150
00151
00153 template<class T> class WeightedGraph : public std::map<UEdge, T> {};
00154
00155
00157
00161 class RootedTree : public std::vector<DEdge> {
00162 public:
00164 RootedTree() {}
00165
00167
00169 RootedTree( const GraphEL &T, size_t Root );
00170 };
00171
00172
00174
00179 template<typename T> RootedTree MinSpanningTree( const WeightedGraph<T> &G, bool usePrim ) {
00180 RootedTree result;
00181 if( G.size() > 0 ) {
00182 using namespace boost;
00183 using namespace std;
00184 typedef adjacency_list< vecS, vecS, undirectedS, no_property, property<edge_weight_t, double> > boostGraph;
00185
00186 set<size_t> nodes;
00187 vector<UEdge> edges;
00188 vector<double> weights;
00189 edges.reserve( G.size() );
00190 weights.reserve( G.size() );
00191 for( typename WeightedGraph<T>::const_iterator e = G.begin(); e != G.end(); e++ ) {
00192 weights.push_back( e->second );
00193 edges.push_back( e->first );
00194 nodes.insert( e->first.first );
00195 nodes.insert( e->first.second );
00196 }
00197
00198 size_t N = nodes.size();
00199 for( set<size_t>::const_iterator it = nodes.begin(); it != nodes.end(); it++ )
00200 if( *it >= N )
00201 DAI_THROWE(RUNTIME_ERROR,"Vertices must be in range [0..N) where N is the number of vertices.");
00202
00203 boostGraph g( edges.begin(), edges.end(), weights.begin(), nodes.size() );
00204 size_t root = *(nodes.begin());
00205 GraphEL tree;
00206 if( usePrim ) {
00207
00208 vector< graph_traits< boostGraph >::vertex_descriptor > p(N);
00209 prim_minimum_spanning_tree( g, &(p[0]) );
00210
00211
00212 for( size_t i = 0; i != p.size(); i++ ) {
00213 if( p[i] != i )
00214 tree.insert( UEdge( p[i], i ) );
00215 }
00216 } else {
00217
00218 vector< graph_traits< boostGraph >::edge_descriptor > t;
00219 t.reserve( N - 1 );
00220 kruskal_minimum_spanning_tree( g, std::back_inserter(t) );
00221
00222
00223 for( size_t i = 0; i != t.size(); i++ ) {
00224 size_t v1 = source( t[i], g );
00225 size_t v2 = target( t[i], g );
00226 if( v1 != v2 )
00227 tree.insert( UEdge( v1, v2 ) );
00228 }
00229 }
00230
00231
00232 result = RootedTree( tree, root );
00233 }
00234 return result;
00235 }
00236
00237
00239
00244 template<typename T> RootedTree MaxSpanningTree( const WeightedGraph<T> &G, bool usePrim ) {
00245 if( G.size() == 0 )
00246 return RootedTree();
00247 else {
00248 T maxweight = G.begin()->second;
00249 for( typename WeightedGraph<T>::const_iterator it = G.begin(); it != G.end(); it++ )
00250 if( it->second > maxweight )
00251 maxweight = it->second;
00252
00253 WeightedGraph<T> gr( G );
00254
00255
00256 for( typename WeightedGraph<T>::iterator it = gr.begin(); it != gr.end(); it++ )
00257 it->second = maxweight - it->second;
00258 return MinSpanningTree( gr, usePrim );
00259 }
00260 }
00261
00262
00264
00269 template<typename T> RootedTree MinSpanningTree( const WeightedGraph<T> &G ) {
00270 return MinSpanningTree( G, true );
00271 }
00272
00273
00275
00280 template<typename T> RootedTree MaxSpanningTree( const WeightedGraph<T> &G ) {
00281 return MaxSpanningTree( G, true );
00282 }
00283
00284
00286
00293 GraphEL RandomDRegularGraph( size_t N, size_t d );
00294
00295
00296 }
00297
00298
00299 #endif