1 | //
|
---|
2 | //=======================================================================
|
---|
3 | // Copyright 1997, 1998, 1999, 2000 University of Notre Dame.
|
---|
4 | // Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek
|
---|
5 | //
|
---|
6 | // Distributed under the Boost Software License, Version 1.0. (See
|
---|
7 | // accompanying file LICENSE_1_0.txt or copy at
|
---|
8 | // http://www.boost.org/LICENSE_1_0.txt)
|
---|
9 | //=======================================================================
|
---|
10 | //
|
---|
11 | #ifndef BOOST_GRAPH_UTILITY_HPP
|
---|
12 | #define BOOST_GRAPH_UTILITY_HPP
|
---|
13 |
|
---|
14 | #include <stdlib.h>
|
---|
15 | #include <iostream>
|
---|
16 | #include <algorithm>
|
---|
17 | #include <assert.h>
|
---|
18 | #include <boost/config.hpp>
|
---|
19 | #include <boost/tuple/tuple.hpp>
|
---|
20 | #ifndef BOOST_NO_SLIST
|
---|
21 | # include <slist> // shouldn't have to include this... -JGS
|
---|
22 | #endif
|
---|
23 | #include <boost/graph/graph_traits.hpp>
|
---|
24 | #include <boost/graph/properties.hpp>
|
---|
25 | #include <boost/pending/container_traits.hpp>
|
---|
26 | #include <boost/graph/depth_first_search.hpp>
|
---|
27 | // iota moved to detail/algorithm.hpp
|
---|
28 | #include <boost/detail/algorithm.hpp>
|
---|
29 |
|
---|
30 | namespace boost {
|
---|
31 |
|
---|
32 | // Provide an undirected graph interface alternative to the
|
---|
33 | // the source() and target() edge functions.
|
---|
34 | template <class UndirectedGraph>
|
---|
35 | inline
|
---|
36 | std::pair<typename graph_traits<UndirectedGraph>::vertex_descriptor,
|
---|
37 | typename graph_traits<UndirectedGraph>::vertex_descriptor>
|
---|
38 | incident(typename graph_traits<UndirectedGraph>::edge_descriptor e,
|
---|
39 | UndirectedGraph& g)
|
---|
40 | {
|
---|
41 | return std::make_pair(source(e,g), target(e,g));
|
---|
42 | }
|
---|
43 |
|
---|
44 | // Provide an undirected graph interface alternative
|
---|
45 | // to the out_edges() function.
|
---|
46 | template <class Graph>
|
---|
47 | inline
|
---|
48 | std::pair<typename graph_traits<Graph>::out_edge_iterator,
|
---|
49 | typename graph_traits<Graph>::out_edge_iterator>
|
---|
50 | incident_edges(typename graph_traits<Graph>::vertex_descriptor u,
|
---|
51 | Graph& g)
|
---|
52 | {
|
---|
53 | return out_edges(u, g);
|
---|
54 | }
|
---|
55 |
|
---|
56 | template <class Graph>
|
---|
57 | inline typename graph_traits<Graph>::vertex_descriptor
|
---|
58 | opposite(typename graph_traits<Graph>::edge_descriptor e,
|
---|
59 | typename graph_traits<Graph>::vertex_descriptor v,
|
---|
60 | const Graph& g)
|
---|
61 | {
|
---|
62 | typedef typename graph_traits<Graph>::vertex_descriptor vertex_descriptor;
|
---|
63 | if (v == source(e, g))
|
---|
64 | return target(e, g);
|
---|
65 | else if (v == target(e, g))
|
---|
66 | return source(e, g);
|
---|
67 | else
|
---|
68 | return vertex_descriptor();
|
---|
69 | }
|
---|
70 |
|
---|
71 | //===========================================================================
|
---|
72 | // Some handy predicates
|
---|
73 |
|
---|
74 | template <typename Vertex, typename Graph>
|
---|
75 | struct incident_from_predicate {
|
---|
76 | incident_from_predicate(Vertex u, const Graph& g)
|
---|
77 | : m_u(u), m_g(g) { }
|
---|
78 | template <class Edge>
|
---|
79 | bool operator()(const Edge& e) const {
|
---|
80 | return source(e, m_g) == m_u;
|
---|
81 | }
|
---|
82 | Vertex m_u;
|
---|
83 | const Graph& m_g;
|
---|
84 | };
|
---|
85 | template <typename Vertex, typename Graph>
|
---|
86 | inline incident_from_predicate<Vertex, Graph>
|
---|
87 | incident_from(Vertex u, const Graph& g) {
|
---|
88 | return incident_from_predicate<Vertex, Graph>(u, g);
|
---|
89 | }
|
---|
90 |
|
---|
91 | template <typename Vertex, typename Graph>
|
---|
92 | struct incident_to_predicate {
|
---|
93 | incident_to_predicate(Vertex u, const Graph& g)
|
---|
94 | : m_u(u), m_g(g) { }
|
---|
95 | template <class Edge>
|
---|
96 | bool operator()(const Edge& e) const {
|
---|
97 | return target(e, m_g) == m_u;
|
---|
98 | }
|
---|
99 | Vertex m_u;
|
---|
100 | const Graph& m_g;
|
---|
101 | };
|
---|
102 | template <typename Vertex, typename Graph>
|
---|
103 | inline incident_to_predicate<Vertex, Graph>
|
---|
104 | incident_to(Vertex u, const Graph& g) {
|
---|
105 | return incident_to_predicate<Vertex, Graph>(u, g);
|
---|
106 | }
|
---|
107 |
|
---|
108 | template <typename Vertex, typename Graph>
|
---|
109 | struct incident_on_predicate {
|
---|
110 | incident_on_predicate(Vertex u, const Graph& g)
|
---|
111 | : m_u(u), m_g(g) { }
|
---|
112 | template <class Edge>
|
---|
113 | bool operator()(const Edge& e) const {
|
---|
114 | return source(e, m_g) == m_u || target(e, m_g) == m_u;
|
---|
115 | }
|
---|
116 | Vertex m_u;
|
---|
117 | const Graph& m_g;
|
---|
118 | };
|
---|
119 | template <typename Vertex, typename Graph>
|
---|
120 | inline incident_on_predicate<Vertex, Graph>
|
---|
121 | incident_on(Vertex u, const Graph& g) {
|
---|
122 | return incident_on_predicate<Vertex, Graph>(u, g);
|
---|
123 | }
|
---|
124 |
|
---|
125 | template <typename Vertex, typename Graph>
|
---|
126 | struct connects_predicate {
|
---|
127 | connects_predicate(Vertex u, Vertex v, const Graph& g)
|
---|
128 | : m_u(u), m_v(v), m_g(g) { }
|
---|
129 | template <class Edge>
|
---|
130 | bool operator()(const Edge& e) const {
|
---|
131 | if (is_directed(m_g))
|
---|
132 | return source(e, m_g) == m_u && target(e, m_g) == m_v;
|
---|
133 | else
|
---|
134 | return (source(e, m_g) == m_u && target(e, m_g) == m_v)
|
---|
135 | || (source(e, m_g) == m_v && target(e, m_g) == m_u);
|
---|
136 | }
|
---|
137 | Vertex m_u, m_v;
|
---|
138 | const Graph& m_g;
|
---|
139 | };
|
---|
140 | template <typename Vertex, typename Graph>
|
---|
141 | inline connects_predicate<Vertex, Graph>
|
---|
142 | connects(Vertex u, Vertex v, const Graph& g) {
|
---|
143 | return connects_predicate<Vertex, Graph>(u, v, g);
|
---|
144 | }
|
---|
145 |
|
---|
146 |
|
---|
147 | // Need to convert all of these printing functions to take an ostream object
|
---|
148 | // -JGS
|
---|
149 |
|
---|
150 | template <class IncidenceGraph, class Name>
|
---|
151 | void print_in_edges(const IncidenceGraph& G, Name name)
|
---|
152 | {
|
---|
153 | typename graph_traits<IncidenceGraph>::vertex_iterator ui,ui_end;
|
---|
154 | for (tie(ui,ui_end) = vertices(G); ui != ui_end; ++ui) {
|
---|
155 | std::cout << get(name,*ui) << " <-- ";
|
---|
156 | typename graph_traits<IncidenceGraph>
|
---|
157 | ::in_edge_iterator ei, ei_end;
|
---|
158 | for(tie(ei,ei_end) = in_edges(*ui,G); ei != ei_end; ++ei)
|
---|
159 | std::cout << get(name,source(*ei,G)) << " ";
|
---|
160 | std::cout << std::endl;
|
---|
161 | }
|
---|
162 | }
|
---|
163 |
|
---|
164 | template <class IncidenceGraph, class Name>
|
---|
165 | void print_graph_dispatch(const IncidenceGraph& G, Name name, directed_tag)
|
---|
166 | {
|
---|
167 | typename graph_traits<IncidenceGraph>::vertex_iterator ui,ui_end;
|
---|
168 | for (tie(ui,ui_end) = vertices(G); ui != ui_end; ++ui) {
|
---|
169 | std::cout << get(name,*ui) << " --> ";
|
---|
170 | typename graph_traits<IncidenceGraph>
|
---|
171 | ::out_edge_iterator ei, ei_end;
|
---|
172 | for(tie(ei,ei_end) = out_edges(*ui,G); ei != ei_end; ++ei)
|
---|
173 | std::cout << get(name,target(*ei,G)) << " ";
|
---|
174 | std::cout << std::endl;
|
---|
175 | }
|
---|
176 | }
|
---|
177 | template <class IncidenceGraph, class Name>
|
---|
178 | void print_graph_dispatch(const IncidenceGraph& G, Name name, undirected_tag)
|
---|
179 | {
|
---|
180 | typename graph_traits<IncidenceGraph>::vertex_iterator ui,ui_end;
|
---|
181 | for (tie(ui,ui_end) = vertices(G); ui != ui_end; ++ui) {
|
---|
182 | std::cout << get(name,*ui) << " <--> ";
|
---|
183 | typename graph_traits<IncidenceGraph>
|
---|
184 | ::out_edge_iterator ei, ei_end;
|
---|
185 | for(tie(ei,ei_end) = out_edges(*ui,G); ei != ei_end; ++ei)
|
---|
186 | std::cout << get(name,target(*ei,G)) << " ";
|
---|
187 | std::cout << std::endl;
|
---|
188 | }
|
---|
189 | }
|
---|
190 | template <class IncidenceGraph, class Name>
|
---|
191 | void print_graph(const IncidenceGraph& G, Name name)
|
---|
192 | {
|
---|
193 | typedef typename graph_traits<IncidenceGraph>
|
---|
194 | ::directed_category Cat;
|
---|
195 | print_graph_dispatch(G, name, Cat());
|
---|
196 | }
|
---|
197 | template <class IncidenceGraph>
|
---|
198 | void print_graph(const IncidenceGraph& G) {
|
---|
199 | print_graph(G, get(vertex_index, G));
|
---|
200 | }
|
---|
201 |
|
---|
202 | template <class EdgeListGraph, class Name>
|
---|
203 | void print_edges(const EdgeListGraph& G, Name name)
|
---|
204 | {
|
---|
205 | typename graph_traits<EdgeListGraph>::edge_iterator ei, ei_end;
|
---|
206 | for (tie(ei, ei_end) = edges(G); ei != ei_end; ++ei)
|
---|
207 | std::cout << "(" << get(name, source(*ei, G))
|
---|
208 | << "," << get(name, target(*ei, G)) << ") ";
|
---|
209 | std::cout << std::endl;
|
---|
210 | }
|
---|
211 |
|
---|
212 | template <class EdgeListGraph, class VertexName, class EdgeName>
|
---|
213 | void print_edges2(const EdgeListGraph& G, VertexName vname, EdgeName ename)
|
---|
214 | {
|
---|
215 | typename graph_traits<EdgeListGraph>::edge_iterator ei, ei_end;
|
---|
216 | for (tie(ei, ei_end) = edges(G); ei != ei_end; ++ei)
|
---|
217 | std::cout << get(ename, *ei) << "(" << get(vname, source(*ei, G))
|
---|
218 | << "," << get(vname, target(*ei, G)) << ") ";
|
---|
219 | std::cout << std::endl;
|
---|
220 | }
|
---|
221 |
|
---|
222 | template <class VertexListGraph, class Name>
|
---|
223 | void print_vertices(const VertexListGraph& G, Name name)
|
---|
224 | {
|
---|
225 | typename graph_traits<VertexListGraph>::vertex_iterator vi,vi_end;
|
---|
226 | for (tie(vi,vi_end) = vertices(G); vi != vi_end; ++vi)
|
---|
227 | std::cout << get(name,*vi) << " ";
|
---|
228 | std::cout << std::endl;
|
---|
229 | }
|
---|
230 |
|
---|
231 | template <class Graph, class Vertex>
|
---|
232 | bool is_adj_dispatch(Graph& g, Vertex a, Vertex b, bidirectional_tag)
|
---|
233 | {
|
---|
234 | typedef typename graph_traits<Graph>::edge_descriptor
|
---|
235 | edge_descriptor;
|
---|
236 | typename graph_traits<Graph>::adjacency_iterator vi, viend,
|
---|
237 | adj_found;
|
---|
238 | tie(vi, viend) = adjacent_vertices(a, g);
|
---|
239 | adj_found = std::find(vi, viend, b);
|
---|
240 | if (adj_found == viend)
|
---|
241 | return false;
|
---|
242 |
|
---|
243 | typename graph_traits<Graph>::out_edge_iterator oi, oiend,
|
---|
244 | out_found;
|
---|
245 | tie(oi, oiend) = out_edges(a, g);
|
---|
246 | out_found = std::find_if(oi, oiend, incident_to(b, g));
|
---|
247 | if (out_found == oiend)
|
---|
248 | return false;
|
---|
249 |
|
---|
250 | typename graph_traits<Graph>::in_edge_iterator ii, iiend,
|
---|
251 | in_found;
|
---|
252 | tie(ii, iiend) = in_edges(b, g);
|
---|
253 | in_found = std::find_if(ii, iiend, incident_from(a, g));
|
---|
254 | if (in_found == iiend)
|
---|
255 | return false;
|
---|
256 |
|
---|
257 | return true;
|
---|
258 | }
|
---|
259 | template <class Graph, class Vertex>
|
---|
260 | bool is_adj_dispatch(Graph& g, Vertex a, Vertex b, directed_tag)
|
---|
261 | {
|
---|
262 | typedef typename graph_traits<Graph>::edge_descriptor
|
---|
263 | edge_descriptor;
|
---|
264 | typename graph_traits<Graph>::adjacency_iterator vi, viend, found;
|
---|
265 | tie(vi, viend) = adjacent_vertices(a, g);
|
---|
266 | #if defined(BOOST_MSVC) && BOOST_MSVC <= 1300 && defined(__SGI_STL_PORT)
|
---|
267 | // Getting internal compiler error with std::find()
|
---|
268 | found = viend;
|
---|
269 | for (; vi != viend; ++vi)
|
---|
270 | if (*vi == b) {
|
---|
271 | found = vi;
|
---|
272 | break;
|
---|
273 | }
|
---|
274 | #else
|
---|
275 | found = std::find(vi, viend, b);
|
---|
276 | #endif
|
---|
277 | if ( found == viend )
|
---|
278 | return false;
|
---|
279 |
|
---|
280 | typename graph_traits<Graph>::out_edge_iterator oi, oiend,
|
---|
281 | out_found;
|
---|
282 | tie(oi, oiend) = out_edges(a, g);
|
---|
283 |
|
---|
284 | #if defined(BOOST_MSVC) && BOOST_MSVC <= 1300 && defined(__SGI_STL_PORT)
|
---|
285 | // Getting internal compiler error with std::find()
|
---|
286 | out_found = oiend;
|
---|
287 | for (; oi != oiend; ++oi)
|
---|
288 | if (target(*oi, g) == b) {
|
---|
289 | out_found = oi;
|
---|
290 | break;
|
---|
291 | }
|
---|
292 | #else
|
---|
293 | out_found = std::find_if(oi, oiend, incident_to(b, g));
|
---|
294 | #endif
|
---|
295 | if (out_found == oiend)
|
---|
296 | return false;
|
---|
297 | return true;
|
---|
298 | }
|
---|
299 | template <class Graph, class Vertex>
|
---|
300 | bool is_adj_dispatch(Graph& g, Vertex a, Vertex b, undirected_tag)
|
---|
301 | {
|
---|
302 | return is_adj_dispatch(g, a, b, directed_tag());
|
---|
303 | }
|
---|
304 |
|
---|
305 | template <class Graph, class Vertex>
|
---|
306 | bool is_adjacent(Graph& g, Vertex a, Vertex b) {
|
---|
307 | typedef typename graph_traits<Graph>::directed_category Cat;
|
---|
308 | return is_adj_dispatch(g, a, b, Cat());
|
---|
309 | }
|
---|
310 |
|
---|
311 | template <class Graph, class Edge>
|
---|
312 | bool in_edge_set(Graph& g, Edge e)
|
---|
313 | {
|
---|
314 | typename Graph::edge_iterator ei, ei_end, found;
|
---|
315 | tie(ei, ei_end) = edges(g);
|
---|
316 | found = std::find(ei, ei_end, e);
|
---|
317 | return found != ei_end;
|
---|
318 | }
|
---|
319 |
|
---|
320 | template <class Graph, class Vertex>
|
---|
321 | bool in_vertex_set(Graph& g, Vertex v)
|
---|
322 | {
|
---|
323 | typename Graph::vertex_iterator vi, vi_end, found;
|
---|
324 | tie(vi, vi_end) = vertices(g);
|
---|
325 | found = std::find(vi, vi_end, v);
|
---|
326 | return found != vi_end;
|
---|
327 | }
|
---|
328 |
|
---|
329 | template <class Graph, class Vertex>
|
---|
330 | bool in_edge_set(Graph& g, Vertex u, Vertex v)
|
---|
331 | {
|
---|
332 | typename Graph::edge_iterator ei, ei_end;
|
---|
333 | for (tie(ei,ei_end) = edges(g); ei != ei_end; ++ei)
|
---|
334 | if (source(*ei,g) == u && target(*ei,g) == v)
|
---|
335 | return true;
|
---|
336 | return false;
|
---|
337 | }
|
---|
338 |
|
---|
339 | // is x a descendant of y?
|
---|
340 | template <typename ParentMap>
|
---|
341 | inline bool is_descendant
|
---|
342 | (typename property_traits<ParentMap>::value_type x,
|
---|
343 | typename property_traits<ParentMap>::value_type y,
|
---|
344 | ParentMap parent)
|
---|
345 | {
|
---|
346 | if (get(parent, x) == x) // x is the root of the tree
|
---|
347 | return false;
|
---|
348 | else if (get(parent, x) == y)
|
---|
349 | return true;
|
---|
350 | else
|
---|
351 | return is_descendant(get(parent, x), y, parent);
|
---|
352 | }
|
---|
353 |
|
---|
354 | // is y reachable from x?
|
---|
355 | template <typename IncidenceGraph, typename VertexColorMap>
|
---|
356 | inline bool is_reachable
|
---|
357 | (typename graph_traits<IncidenceGraph>::vertex_descriptor x,
|
---|
358 | typename graph_traits<IncidenceGraph>::vertex_descriptor y,
|
---|
359 | const IncidenceGraph& g,
|
---|
360 | VertexColorMap color) // should start out white for every vertex
|
---|
361 | {
|
---|
362 | typedef typename property_traits<VertexColorMap>::value_type ColorValue;
|
---|
363 | dfs_visitor<> vis;
|
---|
364 | depth_first_visit(g, x, vis, color);
|
---|
365 | return get(color, y) != color_traits<ColorValue>::white();
|
---|
366 | }
|
---|
367 |
|
---|
368 | // Is the undirected graph connected?
|
---|
369 | // Is the directed graph strongly connected?
|
---|
370 | template <typename VertexListGraph, typename VertexColorMap>
|
---|
371 | inline bool is_connected(const VertexListGraph& g, VertexColorMap color)
|
---|
372 | {
|
---|
373 | typedef typename property_traits<VertexColorMap>::value_type ColorValue;
|
---|
374 | typedef color_traits<ColorValue> Color;
|
---|
375 | typename graph_traits<VertexListGraph>::vertex_iterator
|
---|
376 | ui, ui_end, vi, vi_end, ci, ci_end;
|
---|
377 | for (tie(ui, ui_end) = vertices(g); ui != ui_end; ++ui)
|
---|
378 | for (tie(vi, vi_end) = vertices(g); vi != vi_end; ++vi)
|
---|
379 | if (*ui != *vi) {
|
---|
380 | for (tie(ci, ci_end) = vertices(g); ci != ci_end; ++ci)
|
---|
381 | put(color, *ci, Color::white());
|
---|
382 | if (! is_reachable(*ui, *vi, color))
|
---|
383 | return false;
|
---|
384 | }
|
---|
385 | return true;
|
---|
386 | }
|
---|
387 |
|
---|
388 | template <typename Graph>
|
---|
389 | bool is_self_loop
|
---|
390 | (typename graph_traits<Graph>::edge_descriptor e,
|
---|
391 | const Graph& g)
|
---|
392 | {
|
---|
393 | return source(e, g) == target(e, g);
|
---|
394 | }
|
---|
395 |
|
---|
396 |
|
---|
397 | template <class T1, class T2>
|
---|
398 | std::pair<T1,T2>
|
---|
399 | make_list(const T1& t1, const T2& t2)
|
---|
400 | { return std::make_pair(t1, t2); }
|
---|
401 |
|
---|
402 | template <class T1, class T2, class T3>
|
---|
403 | std::pair<T1,std::pair<T2,T3> >
|
---|
404 | make_list(const T1& t1, const T2& t2, const T3& t3)
|
---|
405 | { return std::make_pair(t1, std::make_pair(t2, t3)); }
|
---|
406 |
|
---|
407 | template <class T1, class T2, class T3, class T4>
|
---|
408 | std::pair<T1,std::pair<T2,std::pair<T3,T4> > >
|
---|
409 | make_list(const T1& t1, const T2& t2, const T3& t3, const T4& t4)
|
---|
410 | { return std::make_pair(t1, std::make_pair(t2, std::make_pair(t3, t4))); }
|
---|
411 |
|
---|
412 | template <class T1, class T2, class T3, class T4, class T5>
|
---|
413 | std::pair<T1,std::pair<T2,std::pair<T3,std::pair<T4,T5> > > >
|
---|
414 | make_list(const T1& t1, const T2& t2, const T3& t3, const T4& t4, const T5& t5)
|
---|
415 | { return std::make_pair(t1, std::make_pair(t2, std::make_pair(t3, std::make_pair(t4, t5)))); }
|
---|
416 |
|
---|
417 | } /* namespace boost */
|
---|
418 |
|
---|
419 | #endif /* BOOST_GRAPH_UTILITY_HPP*/
|
---|