1 /* This file is part of libDAI - http://www.libdai.org/
3 * libDAI is licensed under the terms of the GNU General Public License version
4 * 2, or (at your option) any later version. libDAI is distributed without any
5 * warranty. See the file COPYING for more details.
7 * Copyright (C) 2006-2009 Joris Mooij [joris dot mooij at libdai dot org]
8 * Copyright (C) 2006-2007 Radboud University Nijmegen, The Netherlands
13 * \brief Defines some utility functions for (weighted) undirected graphs, trees and rooted trees.
14 * \todo Improve general support for graphs and trees.
18 #ifndef __defined_libdai_weightedgraph_h
19 #define __defined_libdai_weightedgraph_h
27 #include <climits> // Work-around for bug in boost graph library
29 #include <boost/graph/adjacency_list.hpp>
30 #include <boost/graph/prim_minimum_spanning_tree.hpp>
36 /// Represents a directed edge
39 /// First node index (source of edge)
42 /// Second node index (sink of edge)
45 /// Default constructor
48 /// Constructs a directed edge pointing from \a m1 to \a m2
49 DEdge( size_t m1
, size_t m2
) : n1(m1
), n2(m2
) {}
51 /// Tests for equality
52 bool operator==( const DEdge
&x
) const { return ((n1
== x
.n1
) && (n2
== x
.n2
)); }
54 /// Tests for inequality
55 bool operator!=( const DEdge
&x
) const { return !(*this == x
); }
57 /// Smaller-than operator (performs lexicographical comparison)
58 bool operator<( const DEdge
&x
) const {
59 return( (n1
< x
.n1
) || ((n1
== x
.n1
) && (n2
< x
.n2
)) );
62 /// Writes a directed edge to an output stream
63 friend std::ostream
& operator << (std::ostream
& os
, const DEdge
& e
) {
64 os
<< "(" << e
.n1
<< "," << e
.n2
<< ")";
70 /// Represents an undirected edge
78 /// Default constructor
81 /// Constructs an undirected edge between \a m1 and \a m2
82 UEdge( size_t m1
, size_t m2
) : n1(m1
), n2(m2
) {}
84 /// Construct from DEdge
85 UEdge( const DEdge
&e
) : n1(e
.n1
), n2(e
.n2
) {}
87 /// Tests for inequality (disregarding the ordering of the nodes)
88 bool operator==( const UEdge
&x
) {
89 return ((n1
== x
.n1
) && (n2
== x
.n2
)) || ((n1
== x
.n2
) && (n2
== x
.n1
));
92 /// Smaller-than operator
93 bool operator<( const UEdge
&x
) const {
94 size_t s
= n1
, l
= n2
;
97 size_t xs
= x
.n1
, xl
= x
.n2
;
100 return( (s
< xs
) || ((s
== xs
) && (l
< xl
)) );
103 /// Writes an undirected edge to an output stream
104 friend std::ostream
& operator << (std::ostream
& os
, const UEdge
& e
) {
106 os
<< "{" << e
.n1
<< "," << e
.n2
<< "}";
108 os
<< "{" << e
.n2
<< "," << e
.n1
<< "}";
114 /// Represents an undirected graph, implemented as a std::set of undirected edges
115 class Graph
: public std::set
<UEdge
> {
117 /// Default constructor
120 /// Construct from range of objects that can be cast to DEdge
121 template <class InputIterator
>
122 Graph( InputIterator begin
, InputIterator end
) {
123 insert( begin
, end
);
128 /// Represents an undirected weighted graph, with weights of type \a T, implemented as a std::map mapping undirected edges to weights
129 template<class T
> class WeightedGraph
: public std::map
<UEdge
, T
> {};
132 /// Represents a rooted tree, implemented as a vector of directed edges
133 /** By convention, the edges are stored such that they point away from
134 * the root and such that edges nearer to the root come before edges
135 * farther away from the root.
137 class RootedTree
: public std::vector
<DEdge
> {
139 /// Default constructor
142 /// Constructs a rooted tree from a tree and a root
143 /** \pre T has no cycles and contains node \a Root
145 RootedTree( const Graph
&T
, size_t Root
);
151 /** \deprecated Please use Graph instead
153 typedef std::vector
<UEdge
> UEdgeVec
;
156 /** \deprecated Please use RootedTree instead
158 typedef std::vector
<DEdge
> DEdgeVec
;
161 /// Constructs a rooted tree from a tree and a root
162 /** \pre T has no cycles and contains node \a Root
163 * \deprecated Please use RootedTree::RootedTree(const Graph &, size_t) instead
165 DEdgeVec
GrowRootedTree( const Graph
&T
, size_t Root
);
167 /// Uses Prim's algorithm to construct a minimal spanning tree from the (positively) weighted graph \a G.
168 /** Uses implementation in Boost Graph Library.
170 template<typename T
> RootedTree
MinSpanningTreePrims( const WeightedGraph
<T
> &G
) {
173 using namespace boost
;
175 typedef adjacency_list
< vecS
, vecS
, undirectedS
, property
<vertex_distance_t
, int>, property
<edge_weight_t
, double> > boostGraph
;
176 typedef pair
<size_t, size_t> E
;
180 vector
<double> weights
;
181 edges
.reserve( G
.size() );
182 weights
.reserve( G
.size() );
183 for( typename WeightedGraph
<T
>::const_iterator e
= G
.begin(); e
!= G
.end(); e
++ ) {
184 weights
.push_back( e
->second
);
185 edges
.push_back( E( e
->first
.n1
, e
->first
.n2
) );
186 nodes
.insert( e
->first
.n1
);
187 nodes
.insert( e
->first
.n2
);
190 boostGraph
g( edges
.begin(), edges
.end(), weights
.begin(), nodes
.size() );
191 vector
< graph_traits
< boostGraph
>::vertex_descriptor
> p( num_vertices(g
) );
192 prim_minimum_spanning_tree( g
, &(p
[0]) );
194 // Store tree edges in result
197 for( size_t i
= 0; i
!= p
.size(); i
++ )
199 tree
.insert( UEdge( p
[i
], i
) );
202 // Order them to obtain a rooted tree
203 result
= RootedTree( tree
, root
);
209 /// Use Prim's algorithm to construct a maximal spanning tree from the (positively) weighted graph \a G.
210 /** Uses implementation in Boost Graph Library.
212 template<typename T
> RootedTree
MaxSpanningTreePrims( const WeightedGraph
<T
> &G
) {
216 T maxweight
= G
.begin()->second
;
217 for( typename WeightedGraph
<T
>::const_iterator it
= G
.begin(); it
!= G
.end(); it
++ )
218 if( it
->second
> maxweight
)
219 maxweight
= it
->second
;
220 // make a copy of the graph
221 WeightedGraph
<T
> gr( G
);
222 // invoke MinSpanningTreePrims with negative weights
223 // (which have to be shifted to satisfy positivity criterion)
224 for( typename WeightedGraph
<T
>::iterator it
= gr
.begin(); it
!= gr
.end(); it
++ )
225 it
->second
= maxweight
- it
->second
;
226 return MinSpanningTreePrims( gr
);
231 /// Constructs a random undirected graph of \a N nodes, where each node has connectivity \a d
232 /** Algorithm 1 in [\ref StW99].
233 * Draws a random graph of size \a N and uniform degree \a d
234 * from an almost uniform probability distribution over these graphs
235 * (which becomes uniform in the limit that \a d is small and \a N goes
238 Graph
RandomDRegularGraph( size_t N
, size_t d
);
241 } // end of namespace dai