sl@0: // Boost.Graph library isomorphism test sl@0: sl@0: // Copyright (C) 2001-20044 Douglas Gregor (dgregor at cs dot indiana dot edu) sl@0: // sl@0: // Distributed under the Boost Software License, Version 1.0. (See sl@0: // accompanying file LICENSE_1_0.txt or copy at sl@0: // http://www.boost.org/LICENSE_1_0.txt) sl@0: sl@0: // For more information, see http://www.boost.org sl@0: // sl@0: // Revision History: sl@0: // sl@0: // 29 Nov 2001 Jeremy Siek sl@0: // Changed to use Boost.Random. sl@0: // 29 Nov 2001 Doug Gregor sl@0: // Initial checkin. sl@0: /* sl@0: * © Portions copyright (c) 2006-2007 Nokia Corporation. All rights reserved. sl@0: */ sl@0: sl@0: #include sl@0: #include sl@0: #include sl@0: #include sl@0: #include sl@0: #include // clock used without std:: qualifier? sl@0: #include sl@0: #include sl@0: #include sl@0: #include sl@0: #include sl@0: #include sl@0: #include sl@0: #include sl@0: #include sl@0: #ifdef __SYMBIAN32__ sl@0: #include "std_log_result.h" sl@0: #define LOG_FILENAME_LINE __FILE__, __LINE__ sl@0: #endif sl@0: using namespace boost; sl@0: sl@0: template sl@0: struct random_functor { sl@0: random_functor(Generator& g) : g(g) { } sl@0: std::size_t operator()(std::size_t n) { sl@0: boost::uniform_int distrib(0, n-1); sl@0: boost::variate_generator > sl@0: x(g, distrib); sl@0: return x(); sl@0: } sl@0: Generator& g; sl@0: }; sl@0: sl@0: template sl@0: void randomly_permute_graph(const Graph1& g1, Graph2& g2) sl@0: { sl@0: // Need a clean graph to start with sl@0: BOOST_REQUIRE(num_vertices(g2) == 0); sl@0: BOOST_REQUIRE(num_edges(g2) == 0); sl@0: sl@0: typedef typename graph_traits::vertex_descriptor vertex1; sl@0: typedef typename graph_traits::vertex_descriptor vertex2; sl@0: typedef typename graph_traits::edge_iterator edge_iterator; sl@0: sl@0: boost::mt19937 gen; sl@0: random_functor rand_fun(gen); sl@0: sl@0: // Decide new order sl@0: std::vector orig_vertices; sl@0: std::copy(vertices(g1).first, vertices(g1).second, std::back_inserter(orig_vertices)); sl@0: std::random_shuffle(orig_vertices.begin(), orig_vertices.end(), rand_fun); sl@0: std::map vertex_map; sl@0: sl@0: for (std::size_t i = 0; i < num_vertices(g1); ++i) { sl@0: vertex_map[orig_vertices[i]] = add_vertex(g2); sl@0: } sl@0: sl@0: for (edge_iterator e = edges(g1).first; e != edges(g1).second; ++e) { sl@0: add_edge(vertex_map[source(*e, g1)], vertex_map[target(*e, g1)], g2); sl@0: } sl@0: } sl@0: sl@0: template sl@0: void generate_random_digraph(Graph& g, double edge_probability) sl@0: { sl@0: typedef typename graph_traits::vertex_iterator vertex_iterator; sl@0: boost::mt19937 random_gen; sl@0: boost::uniform_real distrib(0.0, 1.0); sl@0: boost::variate_generator > sl@0: random_dist(random_gen, distrib); sl@0: sl@0: for (vertex_iterator u = vertices(g).first; u != vertices(g).second; ++u) { sl@0: vertex_iterator v = u; sl@0: ++v; sl@0: for (; v != vertices(g).second; ++v) { sl@0: if (random_dist() <= edge_probability) sl@0: add_edge(*u, *v, g); sl@0: } sl@0: } sl@0: } sl@0: sl@0: void test_isomorphism(int n, double edge_probability) sl@0: { sl@0: typedef adjacency_list graph1; sl@0: typedef adjacency_list > graph2; sl@0: sl@0: graph1 g1(n); sl@0: generate_random_digraph(g1, edge_probability); sl@0: graph2 g2; sl@0: randomly_permute_graph(g1, g2); sl@0: sl@0: int v_idx = 0; sl@0: for (graph2::vertex_iterator v = vertices(g2).first; sl@0: v != vertices(g2).second; ++v) { sl@0: put(vertex_index_t(), g2, *v, v_idx++); sl@0: } sl@0: sl@0: std::map mapping; sl@0: sl@0: bool isomorphism_correct = true; sl@0: clock_t start = clock(); sl@0: sl@0: isomorphism_correct = isomorphism(g1, g2, isomorphism_map(make_assoc_property_map(mapping))); sl@0: sl@0: BOOST_CHECK(isomorphism_correct); sl@0: sl@0: clock_t end = clock(); sl@0: sl@0: std::cout << "Elapsed time (clock cycles): " << (end - start) << std::endl; sl@0: sl@0: bool verify_correct = true; sl@0: sl@0: verify_correct = verify_isomorphism(g1, g2, make_assoc_property_map(mapping)); sl@0: sl@0: BOOST_CHECK(verify_correct); sl@0: sl@0: if (!isomorphism_correct || !verify_correct) { sl@0: // Output graph 1 sl@0: { sl@0: std::ofstream out("isomorphism_failure.bg1"); sl@0: out << num_vertices(g1) << std::endl; sl@0: for (graph1::edge_iterator e = edges(g1).first; sl@0: e != edges(g1).second; ++e) { sl@0: out << get(vertex_index_t(), g1, source(*e, g1)) << ' ' sl@0: << get(vertex_index_t(), g1, target(*e, g1)) << std::endl; sl@0: } sl@0: } sl@0: sl@0: // Output graph 2 sl@0: { sl@0: std::ofstream out("isomorphism_failure.bg2"); sl@0: out << num_vertices(g2) << std::endl; sl@0: for (graph2::edge_iterator e = edges(g2).first; sl@0: e != edges(g2).second; ++e) { sl@0: out << get(vertex_index_t(), g2, source(*e, g2)) << ' ' sl@0: << get(vertex_index_t(), g2, target(*e, g2)) << std::endl; sl@0: } sl@0: } sl@0: } sl@0: } sl@0: sl@0: int test_main(int argc, char* argv[]) sl@0: { sl@0: if (argc < 3) { sl@0: test_isomorphism(30, 0.45); sl@0: #ifdef __SYMBIAN32__ sl@0: std_log(LOG_FILENAME_LINE,"[End Test Case ]"); sl@0: sl@0: testResultXml("isomorphism"); sl@0: close_log_file(); sl@0: #endif sl@0: return 0; sl@0: } sl@0: sl@0: int n = boost::lexical_cast(argv[1]); sl@0: double edge_prob = boost::lexical_cast(argv[2]); sl@0: test_isomorphism(n, edge_prob); sl@0: sl@0: #ifdef __SYMBIAN32__ sl@0: std_log(LOG_FILENAME_LINE,"[End Test Case ]"); sl@0: sl@0: testResultXml("isomorphism"); sl@0: close_log_file(); sl@0: #endif sl@0: return 0; sl@0: }