1 //=======================================================================
2 // Copyright 2001 University of Notre Dame.
3 // Author: Andrew Janiszewski, Jeremy G. Siek
5 // Distributed under the Boost Software License, Version 1.0. (See
6 // accompanying file LICENSE_1_0.txt or copy at
7 // http://www.boost.org/LICENSE_1_0.txt)
8 //=======================================================================
10 #include <boost/test/minimal.hpp>
11 #include <boost/graph/adjacency_list.hpp>
12 #include <boost/graph/random.hpp>
13 #include <boost/graph/graph_utility.hpp>
14 #include <boost/graph/graph_archetypes.hpp>
15 #include <boost/graph/breadth_first_search.hpp>
17 #include <boost/random/mersenne_twister.hpp>
19 #ifdef BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP
20 using namespace boost
;
23 template <typename DistanceMap
, typename ParentMap
,
24 typename Graph
, typename ColorMap
>
25 class bfs_testing_visitor
27 typedef typename
boost::graph_traits
<Graph
>::vertex_descriptor Vertex
;
28 typedef typename
boost::graph_traits
<Graph
>::edge_descriptor Edge
;
29 typedef typename
boost::color_traits
<
30 typename
boost::property_traits
<ColorMap
>::value_type
34 bfs_testing_visitor(Vertex s
, DistanceMap d
, ParentMap p
, ColorMap c
)
35 : current_distance(0), distance(d
), parent(p
), color(c
), src(s
) { }
37 void initialize_vertex(const Vertex
& u
, const Graph
& ) const {
38 BOOST_CHECK(get(color
, u
) == Color::white());
40 void examine_vertex(const Vertex
& u
, const Graph
& ) const {
42 // Ensure that the distances monotonically increase.
43 BOOST_CHECK( distance
[u
] == current_distance
44 || distance
[u
] == current_distance
+ 1 );
45 if (distance
[u
] == current_distance
+ 1) // new level
48 void discover_vertex(const Vertex
& u
, const Graph
& ) const {
49 BOOST_CHECK( get(color
, u
) == Color::gray() );
53 BOOST_CHECK( parent
[u
] == current_vertex
);
54 BOOST_CHECK( distance
[u
] == current_distance
+ 1 );
55 BOOST_CHECK( distance
[u
] == distance
[parent
[u
]] + 1 );
58 void examine_edge(const Edge
& e
, const Graph
& g
) const {
59 BOOST_CHECK( source(e
, g
) == current_vertex
);
61 void tree_edge(const Edge
& e
, const Graph
& g
) const {
62 BOOST_CHECK( get(color
, target(e
, g
)) == Color::white() );
63 Vertex u
= source(e
, g
), v
= target(e
, g
);
64 BOOST_CHECK( distance
[u
] == current_distance
);
66 distance
[v
] = distance
[u
] + 1;
68 void non_tree_edge(const Edge
& e
, const Graph
& g
) const {
69 BOOST_CHECK( color
[target(e
, g
)] != Color::white() );
71 if (boost::is_directed(g
))
73 BOOST_CHECK(distance
[target(e
, g
)] <= distance
[source(e
, g
)] + 1);
75 // cross edge (or going backwards on a tree edge)
76 BOOST_CHECK(distance
[target(e
, g
)] == distance
[source(e
, g
)]
77 || distance
[target(e
, g
)] == distance
[source(e
, g
)] + 1
78 || distance
[target(e
, g
)] == distance
[source(e
, g
)] - 1
83 void gray_target(const Edge
& e
, const Graph
& g
) const {
84 BOOST_CHECK( color
[target(e
, g
)] == Color::gray() );
87 void black_target(const Edge
& e
, const Graph
& g
) const {
88 BOOST_CHECK( color
[target(e
, g
)] == Color::black() );
90 // All vertices adjacent to a black vertex must already be discovered
91 typename
boost::graph_traits
<Graph
>::adjacency_iterator ai
, ai_end
;
92 for (boost::tie(ai
, ai_end
) = adjacent_vertices(target(e
, g
), g
);
94 BOOST_CHECK( color
[*ai
] != Color::white() );
96 void finish_vertex(const Vertex
& u
, const Graph
& ) const {
97 BOOST_CHECK( color
[u
] == Color::black() );
101 mutable Vertex current_vertex
;
102 mutable typename
boost::property_traits
<DistanceMap
>::value_type
104 DistanceMap distance
;
111 template <class Graph
>
114 typedef boost::graph_traits
<Graph
> Traits
;
115 typedef typename
Traits::vertices_size_type
117 static void go(vertices_size_type max_V
) {
118 typedef typename
Traits::vertex_descriptor vertex_descriptor
;
119 typedef boost::color_traits
<boost::default_color_type
> Color
;
121 vertices_size_type i
;
122 typename
Traits::edges_size_type j
;
123 typename
Traits::vertex_iterator ui
, ui_end
;
127 for (i
= 0; i
< max_V
; ++i
)
128 for (j
= 0; j
< i
*i
; ++j
) {
130 boost::generate_random_graph(g
, i
, j
, gen
);
132 // declare the "start" variable
133 vertex_descriptor start
= boost::random_vertex(g
, gen
);
136 std::vector
<int> distance(i
, (std::numeric_limits
<int>::max
)());
138 std::vector
<vertex_descriptor
> parent(i
);
139 for (boost::tie(ui
, ui_end
) = vertices(g
); ui
!= ui_end
; ++ui
)
141 std::vector
<boost::default_color_type
> color(i
);
143 // Get vertex index map
144 typedef typename
boost::property_map
<Graph
, boost::vertex_index_t
>::const_type idx_type
;
145 idx_type idx
= get(boost::vertex_index
, g
);
147 // Make property maps from vectors
149 boost::iterator_property_map
<std::vector
<int>::iterator
, idx_type
>
151 distance_pm_type
distance_pm(distance
.begin(), idx
);
153 boost::iterator_property_map
<typename
std::vector
<vertex_descriptor
>::iterator
, idx_type
>
155 parent_pm_type
parent_pm(parent
.begin(), idx
);
157 boost::iterator_property_map
<std::vector
<boost::default_color_type
>::iterator
, idx_type
>
159 color_pm_type
color_pm(color
.begin(), idx
);
161 // Create the testing visitor.
162 bfs_testing_visitor
<distance_pm_type
, parent_pm_type
, Graph
,
164 vis(start
, distance_pm
, parent_pm
, color_pm
);
166 boost::breadth_first_search(g
, start
,
168 color_map(color_pm
));
170 // All white vertices should be unreachable from the source.
171 for (boost::tie(ui
, ui_end
) = vertices(g
); ui
!= ui_end
; ++ui
)
172 if (color
[*ui
] == Color::white()) {
173 std::vector
<boost::default_color_type
> color2(i
, Color::white());
174 BOOST_CHECK(!boost::is_reachable(start
, *ui
, g
, color_pm_type(color2
.begin(), idx
)));
177 // The shortest path to a child should be one longer than
178 // shortest path to the parent.
179 for (boost::tie(ui
, ui_end
) = vertices(g
); ui
!= ui_end
; ++ui
)
180 if (parent
[*ui
] != *ui
) // *ui not the root of the bfs tree
181 BOOST_CHECK(distance
[*ui
] == distance
[parent
[*ui
]] + 1);
187 int test_main(int argc
, char* argv
[])
189 using namespace boost
;
192 max_V
= atoi(argv
[1]);
194 bfs_test
< adjacency_list
<vecS
, vecS
, directedS
> >::go(max_V
);
195 bfs_test
< adjacency_list
<vecS
, vecS
, undirectedS
> >::go(max_V
);