1// Copyright 2002 Rensselaer Polytechnic Institute
2
3// Use, modification and distribution is subject to the Boost Software
4// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
5// http://www.boost.org/LICENSE_1_0.txt)
6
7// Authors: Lauren Foutz
8// Scott Hill
9#include <boost/graph/floyd_warshall_shortest.hpp>
10#include <map>
11#include <algorithm>
12#include <iostream>
13#include <boost/random/linear_congruential.hpp>
14#include <boost/graph/graph_utility.hpp>
15#include <boost/graph/properties.hpp>
16#include <boost/graph/bellman_ford_shortest_paths.hpp>
17#include <boost/graph/random.hpp>
18#include <boost/graph/adjacency_list.hpp>
19#include <boost/graph/adjacency_matrix.hpp>
20#include <boost/core/lightweight_test.hpp>
21#include <algorithm>
22using namespace boost;
23
24template < typename T > inline const T& my_min(const T& x, const T& y)
25{
26 return x < y ? x : y;
27}
28
29template < typename Graph > bool acceptance_test(Graph& g, int vec, int e)
30{
31 boost::minstd_rand ran(vec);
32
33 {
34 typename boost::property_map< Graph, boost::vertex_name_t >::type index
35 = boost::get(boost::vertex_name, g);
36 typename boost::graph_traits< Graph >::vertex_iterator firstv, lastv,
37 firstv2, lastv2;
38 int x = 0;
39 for (boost::tie(firstv, lastv) = boost::vertices(g); firstv != lastv;
40 firstv++)
41 {
42 boost::put(index, *firstv, x);
43 x++;
44 }
45
46 for (int i = 0; i < e; i++)
47 {
48 boost::add_edge(index[ran() % vec], index[ran() % vec], g);
49 }
50
51 typename boost::graph_traits< Graph >::edge_iterator first, last;
52 typename boost::property_map< Graph, boost::edge_weight_t >::type
53 local_edge_map
54 = boost::get(boost::edge_weight, g);
55 for (boost::tie(first, last) = boost::edges(g); first != last; first++)
56 {
57 if (ran() % vec != 0)
58 {
59 boost::put(local_edge_map, *first, ran() % 100);
60 }
61 else
62 {
63 boost::put(local_edge_map, *first, 0 - (ran() % 100));
64 }
65 }
66
67 int int_inf = std::numeric_limits< int >::max
68 BOOST_PREVENT_MACRO_SUBSTITUTION();
69 typedef
70 typename boost::graph_traits< Graph >::vertex_descriptor vertex_des;
71 std::map< vertex_des, int > matrixRow;
72 std::map< vertex_des, std::map< vertex_des, int > > matrix;
73 typedef typename boost::property_map< Graph,
74 boost::vertex_distance_t >::type distance_type;
75 distance_type distance_row = boost::get(boost::vertex_distance, g);
76 for (boost::tie(firstv, lastv) = boost::vertices(g); firstv != lastv;
77 firstv++)
78 {
79 boost::put(distance_row, *firstv, int_inf);
80 matrixRow[*firstv] = int_inf;
81 }
82 for (boost::tie(firstv, lastv) = boost::vertices(g); firstv != lastv;
83 firstv++)
84 {
85 matrix[*firstv] = matrixRow;
86 }
87 for (boost::tie(firstv, lastv) = boost::vertices(g); firstv != lastv;
88 firstv++)
89 {
90 matrix[*firstv][*firstv] = 0;
91 }
92 std::map< vertex_des, std::map< vertex_des, int > > matrix3(matrix);
93 std::map< vertex_des, std::map< vertex_des, int > > matrix4(matrix);
94 for (boost::tie(first, last) = boost::edges(g); first != last; first++)
95 {
96 if (matrix[boost::source(*first, g)][boost::target(*first, g)]
97 != int_inf)
98 {
99 matrix[boost::source(*first, g)][boost::target(*first, g)]
100 = my_min(boost::get(local_edge_map, *first),
101 matrix[boost::source(*first, g)]
102 [boost::target(*first, g)]);
103 }
104 else
105 {
106 matrix[boost::source(*first, g)][boost::target(*first, g)]
107 = boost::get(local_edge_map, *first);
108 }
109 }
110 bool is_undirected = boost::is_same<
111 typename boost::graph_traits< Graph >::directed_category,
112 boost::undirected_tag >::value;
113 if (is_undirected)
114 {
115 for (boost::tie(first, last) = boost::edges(g); first != last;
116 first++)
117 {
118 if (matrix[boost::target(*first, g)][boost::source(*first, g)]
119 != int_inf)
120 {
121 matrix[boost::target(*first, g)][boost::source(*first, g)]
122 = my_min(boost::get(local_edge_map, *first),
123 matrix[boost::target(*first, g)]
124 [boost::source(*first, g)]);
125 }
126 else
127 {
128 matrix[boost::target(*first, g)][boost::source(*first, g)]
129 = boost::get(local_edge_map, *first);
130 }
131 }
132 }
133
134 bool bellman, floyd1, floyd2, floyd3;
135 floyd1 = boost::floyd_warshall_initialized_all_pairs_shortest_paths(g,
136 matrix,
137 weight_map(boost::get(boost::edge_weight, g))
138 .distance_inf(int_inf)
139 .distance_zero(0));
140
141 floyd2 = boost::floyd_warshall_all_pairs_shortest_paths(g, matrix3,
142 weight_map(local_edge_map).distance_inf(int_inf).distance_zero(0));
143
144 floyd3 = boost::floyd_warshall_all_pairs_shortest_paths(g, matrix4);
145
146 boost::dummy_property_map dummy_map;
147 std::map< vertex_des, std::map< vertex_des, int > > matrix2;
148 for (boost::tie(firstv, lastv) = vertices(g); firstv != lastv; firstv++)
149 {
150 boost::put(distance_row, *firstv, 0);
151 bellman = boost::bellman_ford_shortest_paths(g, vec,
152 weight_map(boost::get(boost::edge_weight, g))
153 .distance_map(boost::get(boost::vertex_distance, g))
154 .predecessor_map(dummy_map));
155 distance_row = boost::get(boost::vertex_distance, g);
156 for (boost::tie(firstv2, lastv2) = vertices(g); firstv2 != lastv2;
157 firstv2++)
158 {
159 matrix2[*firstv][*firstv2] = boost::get(distance_row, *firstv2);
160 boost::put(distance_row, *firstv2, int_inf);
161 }
162 if (bellman == false)
163 {
164 break;
165 }
166 }
167
168 if (bellman != floyd1 || bellman != floyd2 || bellman != floyd3)
169 {
170 std::cout << "A negative cycle was detected in one algorithm but "
171 "not the others. "
172 << std::endl;
173 return false;
174 }
175 else if (bellman == false && floyd1 == false && floyd2 == false
176 && floyd3 == false)
177 {
178 return true;
179 }
180 else
181 {
182 typename boost::graph_traits< Graph >::vertex_iterator first1,
183 first2, last1, last2;
184 for (boost::tie(first1, last1) = boost::vertices(g);
185 first1 != last1; first1++)
186 {
187 for (boost::tie(first2, last2) = boost::vertices(g);
188 first2 != last2; first2++)
189 {
190 if (matrix2[*first1][*first2] != matrix[*first1][*first2])
191 {
192 std::cout
193 << "Algorithms do not match at matrix point "
194 << index[*first1] << " " << index[*first2]
195 << " Bellman results: " << matrix2[*first1][*first2]
196 << " floyd 1 results " << matrix[*first1][*first2]
197 << std::endl;
198 return false;
199 }
200 if (matrix2[*first1][*first2] != matrix3[*first1][*first2])
201 {
202 std::cout
203 << "Algorithms do not match at matrix point "
204 << index[*first1] << " " << index[*first2]
205 << " Bellman results: " << matrix2[*first1][*first2]
206 << " floyd 2 results " << matrix3[*first1][*first2]
207 << std::endl;
208 return false;
209 }
210 if (matrix2[*first1][*first2] != matrix4[*first1][*first2])
211 {
212 std::cout
213 << "Algorithms do not match at matrix point "
214 << index[*first1] << " " << index[*first2]
215 << " Bellman results: " << matrix2[*first1][*first2]
216 << " floyd 3 results " << matrix4[*first1][*first2]
217 << std::endl;
218 return false;
219 }
220 }
221 }
222 }
223 }
224 return true;
225}
226
227template < typename Graph > bool acceptance_test2(Graph& g, int vec, int e)
228{
229 boost::minstd_rand ran(vec);
230
231 {
232
233 typename boost::property_map< Graph, boost::vertex_name_t >::type index
234 = boost::get(boost::vertex_name, g);
235 typename boost::graph_traits< Graph >::vertex_iterator firstv, lastv,
236 firstv2, lastv2;
237 int x = 0;
238 for (boost::tie(firstv, lastv) = boost::vertices(g); firstv != lastv;
239 firstv++)
240 {
241 boost::put(index, *firstv, x);
242 x++;
243 }
244
245 boost::generate_random_graph(g, vec, e, ran, true);
246
247 typename boost::graph_traits< Graph >::edge_iterator first, last;
248 typename boost::property_map< Graph, boost::edge_weight_t >::type
249 local_edge_map
250 = boost::get(boost::edge_weight, g);
251 for (boost::tie(first, last) = boost::edges(g); first != last; first++)
252 {
253 if (ran() % vec != 0)
254 {
255 boost::put(local_edge_map, *first, ran() % 100);
256 }
257 else
258 {
259 boost::put(local_edge_map, *first, 0 - (ran() % 100));
260 }
261 }
262
263 int int_inf = std::numeric_limits< int >::max
264 BOOST_PREVENT_MACRO_SUBSTITUTION();
265 typedef
266 typename boost::graph_traits< Graph >::vertex_descriptor vertex_des;
267 std::map< vertex_des, int > matrixRow;
268 std::map< vertex_des, std::map< vertex_des, int > > matrix;
269 typedef typename boost::property_map< Graph,
270 boost::vertex_distance_t >::type distance_type;
271 distance_type distance_row = boost::get(boost::vertex_distance, g);
272 for (boost::tie(firstv, lastv) = boost::vertices(g); firstv != lastv;
273 firstv++)
274 {
275 boost::put(distance_row, *firstv, int_inf);
276 matrixRow[*firstv] = int_inf;
277 }
278 for (boost::tie(firstv, lastv) = boost::vertices(g); firstv != lastv;
279 firstv++)
280 {
281 matrix[*firstv] = matrixRow;
282 }
283 for (boost::tie(firstv, lastv) = boost::vertices(g); firstv != lastv;
284 firstv++)
285 {
286 matrix[*firstv][*firstv] = 0;
287 }
288 std::map< vertex_des, std::map< vertex_des, int > > matrix3(matrix);
289 std::map< vertex_des, std::map< vertex_des, int > > matrix4(matrix);
290 for (boost::tie(first, last) = boost::edges(g); first != last; first++)
291 {
292 if (matrix[boost::source(*first, g)][boost::target(*first, g)]
293 != int_inf)
294 {
295 matrix[boost::source(*first, g)][boost::target(*first, g)]
296 = my_min(boost::get(local_edge_map, *first),
297 matrix[boost::source(*first, g)]
298 [boost::target(*first, g)]);
299 }
300 else
301 {
302 matrix[boost::source(*first, g)][boost::target(*first, g)]
303 = boost::get(local_edge_map, *first);
304 }
305 }
306 bool is_undirected = boost::is_same<
307 typename boost::graph_traits< Graph >::directed_category,
308 boost::undirected_tag >::value;
309 if (is_undirected)
310 {
311 for (boost::tie(first, last) = boost::edges(g); first != last;
312 first++)
313 {
314 if (matrix[boost::target(*first, g)][boost::source(*first, g)]
315 != int_inf)
316 {
317 matrix[boost::target(*first, g)][boost::source(*first, g)]
318 = my_min(boost::get(local_edge_map, *first),
319 matrix[boost::target(*first, g)]
320 [boost::source(*first, g)]);
321 }
322 else
323 {
324 matrix[boost::target(*first, g)][boost::source(*first, g)]
325 = boost::get(local_edge_map, *first);
326 }
327 }
328 }
329
330 bool bellman, floyd1, floyd2, floyd3;
331 floyd1 = boost::floyd_warshall_initialized_all_pairs_shortest_paths(g,
332 matrix,
333 weight_map(boost::get(boost::edge_weight, g))
334 .distance_inf(int_inf)
335 .distance_zero(0));
336
337 floyd2 = boost::floyd_warshall_all_pairs_shortest_paths(g, matrix3,
338 weight_map(local_edge_map).distance_inf(int_inf).distance_zero(0));
339
340 floyd3 = boost::floyd_warshall_all_pairs_shortest_paths(g, matrix4);
341
342 boost::dummy_property_map dummy_map;
343 std::map< vertex_des, std::map< vertex_des, int > > matrix2;
344 for (boost::tie(firstv, lastv) = vertices(g); firstv != lastv; firstv++)
345 {
346 boost::put(distance_row, *firstv, 0);
347 bellman = boost::bellman_ford_shortest_paths(g, vec,
348 weight_map(boost::get(boost::edge_weight, g))
349 .distance_map(boost::get(boost::vertex_distance, g))
350 .predecessor_map(dummy_map));
351 distance_row = boost::get(boost::vertex_distance, g);
352 for (boost::tie(firstv2, lastv2) = vertices(g); firstv2 != lastv2;
353 firstv2++)
354 {
355 matrix2[*firstv][*firstv2] = boost::get(distance_row, *firstv2);
356 boost::put(distance_row, *firstv2, int_inf);
357 }
358 if (bellman == false)
359 {
360 break;
361 }
362 }
363
364 if (bellman != floyd1 || bellman != floyd2 || bellman != floyd3)
365 {
366 std::cout << "A negative cycle was detected in one algorithm but "
367 "not the others. "
368 << std::endl;
369 return false;
370 }
371 else if (bellman == false && floyd1 == false && floyd2 == false
372 && floyd3 == false)
373 {
374 return true;
375 }
376 else
377 {
378 typename boost::graph_traits< Graph >::vertex_iterator first1,
379 first2, last1, last2;
380 for (boost::tie(first1, last1) = boost::vertices(g);
381 first1 != last1; first1++)
382 {
383 for (boost::tie(first2, last2) = boost::vertices(g);
384 first2 != last2; first2++)
385 {
386 if (matrix2[*first1][*first2] != matrix[*first1][*first2])
387 {
388 std::cout
389 << "Algorithms do not match at matrix point "
390 << index[*first1] << " " << index[*first2]
391 << " Bellman results: " << matrix2[*first1][*first2]
392 << " floyd 1 results " << matrix[*first1][*first2]
393 << std::endl;
394 return false;
395 }
396 if (matrix2[*first1][*first2] != matrix3[*first1][*first2])
397 {
398 std::cout
399 << "Algorithms do not match at matrix point "
400 << index[*first1] << " " << index[*first2]
401 << " Bellman results: " << matrix2[*first1][*first2]
402 << " floyd 2 results " << matrix3[*first1][*first2]
403 << std::endl;
404 return false;
405 }
406 if (matrix2[*first1][*first2] != matrix4[*first1][*first2])
407 {
408 std::cout
409 << "Algorithms do not match at matrix point "
410 << index[*first1] << " " << index[*first2]
411 << " Bellman results: " << matrix2[*first1][*first2]
412 << " floyd 3 results " << matrix4[*first1][*first2]
413 << std::endl;
414 return false;
415 }
416 }
417 }
418 }
419 }
420 return true;
421}
422
423int main(int, char*[])
424{
425 typedef boost::adjacency_list< boost::listS, boost::listS, boost::directedS,
426 boost::property< boost::vertex_distance_t, int,
427 boost::property< boost::vertex_name_t, int > >,
428 boost::property< boost::edge_weight_t, int > >
429 Digraph;
430 Digraph adjlist_digraph;
431 BOOST_TEST(acceptance_test2(adjlist_digraph, 100, 2000));
432
433 typedef boost::adjacency_matrix< boost::undirectedS,
434 boost::property< boost::vertex_distance_t, int,
435 boost::property< boost::vertex_name_t, int > >,
436 boost::property< boost::edge_weight_t, int > >
437 Graph;
438 Graph matrix_graph(100);
439 BOOST_TEST(acceptance_test(matrix_graph, 100, 2000));
440
441 return boost::report_errors();
442}
443

source code of boost/libs/graph/test/floyd_warshall_test.cpp