/* make_random_paths.cpp source file * * Copyright 2004 Cromwell D. Enage. Covered by the Boost Software License, * Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) */ /* * Defines the Boost Unit Test Framework. */ #include #include #include /* * Defines the std::list class template and its iterators. */ #include /* * Defines the std::map class template. */ #include /* * Defines the boost::mt19937 class, to be used as a random-number-generating * engine. */ #include /* * Defines the boost::uniform_int class template, to be used as a random-number * distribution. */ #include /* * Defines the boost::variate_generator class template, to be used as the * front-end random-number generator. */ #include /* * Defines the boost::random_number_generator class template, to be used as the * front-end random-index generator. */ #include /* * Defines the boost::property_map and boost::associative_property_map class * templates and the boost::get and boost::put function templates. */ #include /* * Defines the boost::is_adjacent function template. */ #include /* * Defines the boost::graph_traits class template. */ #include /* * Defines the vertex and edge property tags. */ #include /* * Defines the boost::directedS, boost::undirectedS, and boost::bidirectionalS * selector tags. */ #include /* * Defines the boost::adjacency_list class template and its associated * non-member function templates. */ #include /* * Defines the boost::adjacency_matrix class template and its associated * non-member function templates. */ #include /* * Defines the boost::dijkstra_random_paths function template. */ #include /* * Defines the boost::ddnw_random_paths function template. */ #include /* * Defines the boost::loop_erased_random_paths function template. */ #include using boost::unit_test_framework::test_suite; using namespace boost; template bool contains_no_edges(Graph& g) { typename graph_traits::edge_iterator ei, eend; tie(ei, eend) = edges(g); return ei == eend; } template void init_graph(Graph& g) { add_edge(vertex(0, g), vertex(7, g), g); add_edge(vertex(1, g), vertex(2, g), g); add_edge(vertex(2, g), vertex(10, g), g); add_edge(vertex(2, g), vertex(5, g), g); add_edge(vertex(3, g), vertex(10, g), g); add_edge(vertex(3, g), vertex(0, g), g); add_edge(vertex(4, g), vertex(5, g), g); add_edge(vertex(4, g), vertex(0, g), g); add_edge(vertex(5, g), vertex(14, g), g); add_edge(vertex(6, g), vertex(3, g), g); add_edge(vertex(7, g), vertex(17, g), g); add_edge(vertex(7, g), vertex(11, g), g); add_edge(vertex(8, g), vertex(17, g), g); add_edge(vertex(8, g), vertex(1, g), g); add_edge(vertex(9, g), vertex(11, g), g); add_edge(vertex(9, g), vertex(1, g), g); add_edge(vertex(10, g), vertex(19, g), g); add_edge(vertex(10, g), vertex(15, g), g); add_edge(vertex(10, g), vertex(8, g), g); add_edge(vertex(11, g), vertex(19, g), g); add_edge(vertex(11, g), vertex(15, g), g); add_edge(vertex(11, g), vertex(4, g), g); add_edge(vertex(12, g), vertex(19, g), g); add_edge(vertex(12, g), vertex(8, g), g); add_edge(vertex(12, g), vertex(4, g), g); add_edge(vertex(13, g), vertex(15, g), g); add_edge(vertex(13, g), vertex(8, g), g); add_edge(vertex(13, g), vertex(4, g), g); add_edge(vertex(14, g), vertex(22, g), g); add_edge(vertex(14, g), vertex(12, g), g); add_edge(vertex(15, g), vertex(22, g), g); add_edge(vertex(15, g), vertex(6, g), g); add_edge(vertex(16, g), vertex(12, g), g); add_edge(vertex(16, g), vertex(6, g), g); add_edge(vertex(17, g), vertex(20, g), g); add_edge(vertex(18, g), vertex(9, g), g); add_edge(vertex(19, g), vertex(23, g), g); add_edge(vertex(19, g), vertex(18, g), g); add_edge(vertex(20, g), vertex(23, g), g); add_edge(vertex(20, g), vertex(13, g), g); add_edge(vertex(21, g), vertex(18, g), g); add_edge(vertex(21, g), vertex(13, g), g); add_edge(vertex(22, g), vertex(21, g), g); add_edge(vertex(23, g), vertex(16, g), g); } template void dijkstra_random_paths_test() { typedef typename graph_traits::vertex_descriptor Vertex; typedef typename graph_traits::vertex_iterator VertexIterator; typedef std::map VertexMap; typedef associative_property_map PredecessorMap; typedef typename property_map::type VertexIndexMap; typedef std::list Path; typedef typename Path::iterator PathIterator; typedef uniform_int RNGDistribution; typedef variate_generator RandomNumberGenerator; Graph g(24); VertexIterator source_itr, source_end, target_itr, target_end; Vertex v; VertexMap v_map; PredecessorMap pred_map(v_map); VertexIndexMap index_map = get(vertex_index_t(), g); Path path; PathIterator pi, pi_next; RNGEngine rng_engine; RNGDistribution rng_distribution(0, 16384); RandomNumberGenerator random_weight(rng_engine, rng_distribution); init_graph(g); for (tie(source_itr, source_end) = vertices(g); source_itr != source_end; ++source_itr) { dijkstra_random_paths( g, *source_itr, random_weight, predecessor_map(pred_map)); for (tie(target_itr, target_end) = vertices(g); target_itr != target_end; ++target_itr) { if (source_itr != target_itr) { for (v = *target_itr; v != get(pred_map, v); v = get(pred_map, v)) { path.push_front(v); } path.push_front(v); BOOST_CHECK_MESSAGE( v == *source_itr, "No path from " << get(index_map, *source_itr) << " to " << get(index_map, *target_itr)); pi_next = path.begin(); for (pi = pi_next; ++pi_next != path.end(); pi = pi_next) { BOOST_CHECK_MESSAGE( (is_adjacent(g, *pi, *pi_next)), "Path edge " << get(index_map, *pi) << "-" << get(index_map, *pi_next) << " not part of graph."); } path.clear(); } } } } template void ddnw_random_paths_test() { typedef typename graph_traits::vertex_descriptor InputVertex; typedef typename graph_traits::vertex_iterator InputVertexIterator; typedef std::map OutputVertexMap; typedef associative_property_map OutputPredecessorMap; typedef typename property_map::type VertexIndexMap; typedef std::list Path; typedef typename Path::iterator PathIterator; typedef uniform_int RNGDistribution; typedef variate_generator RandomNumberGenerator; InputGraph g(24); UtilGraph dag(24); InputVertexIterator source_itr, source_end, target_itr, target_end; InputVertex v; OutputVertexMap out_v_map; OutputPredecessorMap out_pred_map(out_v_map); VertexIndexMap index_map = get(vertex_index_t(), g); Path path; PathIterator pi, pi_next; RNGEngine rng_engine; RNGDistribution rng_distribution(0, 16384); RandomNumberGenerator random_weight(rng_engine, rng_distribution); init_graph(g); for (tie(source_itr, source_end) = vertices(g); source_itr != source_end; ++source_itr) { BOOST_CHECK_MESSAGE( num_vertices(dag) == num_vertices(g), "Utility graph doesn't have the same vertex count as input graph."); BOOST_CHECK_MESSAGE( contains_no_edges(dag), "Utility graph contains an edge."); try { ddnw_random_paths( g, *source_itr, random_weight, dag, predecessor_map(out_pred_map), vertex_index_map(get(vertex_index_t(), dag))); } catch (not_a_dag&) { BOOST_ERROR("ddnw_random_paths did not make utility graph a dag."); continue; } for (tie(target_itr, target_end) = vertices(g); target_itr != target_end; ++target_itr) { if (source_itr != target_itr) { for (v = *target_itr; v != get(out_pred_map, v); v = get(out_pred_map, v)) { path.push_front(v); } path.push_front(v); BOOST_CHECK_MESSAGE( v == *source_itr, "No path from " << get(index_map, *source_itr) << " to " << get(index_map, *target_itr)); pi_next = path.begin(); for (pi = pi_next; ++pi_next != path.end(); pi = pi_next) { BOOST_CHECK_MESSAGE( (is_adjacent(g, *pi, *pi_next)), "Path edge " << get(index_map, *pi) << "-" << get(index_map, *pi_next) << " not part of graph."); } path.clear(); } } } } template void loop_erased_random_paths_test() { typedef typename graph_traits::vertex_descriptor Vertex; typedef typename graph_traits::vertex_iterator VertexIterator; typedef std::map VertexMap; typedef associative_property_map PredecessorMap; typedef typename property_map::type VertexIndexMap; typedef std::list Path; typedef typename Path::iterator PathIterator; typedef random_number_generator RandomIndexGenerator; Graph g(24); Graph u_g(24); VertexIterator source_itr, source_end, target_itr, target_end; Vertex v; VertexMap v_map; PredecessorMap pred_map(v_map); VertexIndexMap index_map = get(vertex_index_t(), g); Path path; PathIterator pi, pi_next; RNGEngine rng_engine; RandomIndexGenerator rig(rng_engine); init_graph(g); for (tie(source_itr, source_end) = vertices(g); source_itr != source_end; ++source_itr) { BOOST_CHECK_MESSAGE( num_vertices(u_g) == num_vertices(g), "Utility graph doesn't have the same vertex count as input graph."); BOOST_CHECK_MESSAGE( contains_no_edges(u_g), "Utility graph contains an edge."); #if defined(BOOST_MSVC) && BOOST_MSVC <= 1300 // According to example code using dijkstra_shortest_paths, // VC++ has trouble with the named parameters mechanism. while (!loop_erased_random_paths(g, *source_itr, rig, pred_map, u_g)); #else while (!loop_erased_random_paths( g, *source_itr, rig, u_g, predecessor_map(pred_map), vertex_index_map(get(vertex_index_t(), u_g)))); #endif for (tie(target_itr, target_end) = vertices(g); target_itr != target_end; ++target_itr) { if (source_itr != target_itr) { for (v = *target_itr; v != get(pred_map, v); v = get(pred_map, v)) { path.push_front(v); } path.push_front(v); BOOST_CHECK_MESSAGE( v == *source_itr, "No path from " << get(index_map, *source_itr) << " to " << get(index_map, *target_itr)); pi_next = path.begin(); for (pi = pi_next; ++pi_next != path.end(); pi = pi_next) { BOOST_CHECK_MESSAGE( (is_adjacent(g, *pi, *pi_next)), "Path edge " << get(index_map, *pi) << "-" << get(index_map, *pi_next) << " not part of graph."); } path.clear(); } } } } template void test() { BOOST_MESSAGE( "Testing dijkstra_random_paths function template on undirected graph."); dijkstra_random_paths_test(); BOOST_MESSAGE( "Testing ddnw_random_paths function template on undirected graph."); ddnw_random_paths_test(); BOOST_MESSAGE( "Testing loop_erased_random_paths function template on " << "undirected graph."); loop_erased_random_paths_test(); BOOST_MESSAGE( "Testing dijkstra_random_paths function template on directed graph."); dijkstra_random_paths_test(); BOOST_MESSAGE( "Testing ddnw_random_paths function template on directed graph."); ddnw_random_paths_test(); BOOST_MESSAGE( "Testing loop_erased_random_paths function template on " << "directed graph."); loop_erased_random_paths_test(); } template void vec_adjacency_list_test() { typedef adjacency_list,no_property> UndirectedGraph; typedef adjacency_list,no_property> DirectedGraph; typedef adjacency_list,no_property> BidirectionalGraph; test(); BOOST_MESSAGE( "Testing dijkstra_random_paths function template on bidigraph."); dijkstra_random_paths_test(); BOOST_MESSAGE( "Testing ddnw_random_paths function template on bidigraph."); ddnw_random_paths_test(); BOOST_MESSAGE( "Testing loop_erased_random_paths function template on " << "bidigraph."); loop_erased_random_paths_test(); } template void adjacency_matrix_test() { typedef adjacency_matrix< undirectedS,no_property,property,no_property> UndirectedGraph; typedef adjacency_matrix< directedS,no_property,property,no_property> DirectedGraph; test(); } void vec_adjacency_list_vecS_test_case() { BOOST_MESSAGE("vec_adjacency_list_test vecS"); vec_adjacency_list_test(); } void vec_adjacency_list_listS_test_case() { BOOST_MESSAGE("vec_adjacency_list_test listS"); vec_adjacency_list_test(); } void vec_adjacency_list_setS_test_case() { BOOST_MESSAGE("vec_adjacency_list_test setS"); vec_adjacency_list_test(); } void vec_adjacency_list_multisetS_test_case() { BOOST_MESSAGE("vec_adjacency_list_test multisetS"); vec_adjacency_list_test(); } void adjacency_matrix_test_case() { BOOST_MESSAGE("adjacency_matrix_test"); adjacency_matrix_test(); } test_suite* init_unit_test_suite(int argc, char** argv) { test_suite* test = BOOST_TEST_SUITE("make_random_paths unit test"); test->add(BOOST_TEST_CASE(&vec_adjacency_list_vecS_test_case)); test->add(BOOST_TEST_CASE(&vec_adjacency_list_listS_test_case)); test->add(BOOST_TEST_CASE(&vec_adjacency_list_setS_test_case)); test->add(BOOST_TEST_CASE(&vec_adjacency_list_multisetS_test_case)); test->add(BOOST_TEST_CASE(&adjacency_matrix_test_case)); return test; }