os/ossrv/stdcpp/tsrc/Boost_test/graph/src/isomorphism.cpp
author sl
Tue, 10 Jun 2014 14:32:02 +0200 (2014-06-10)
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
sl@0
     1
// Boost.Graph library isomorphism test
sl@0
     2
sl@0
     3
// Copyright (C) 2001-20044 Douglas Gregor (dgregor at cs dot indiana dot edu)
sl@0
     4
//
sl@0
     5
// Distributed under the Boost Software License, Version 1.0. (See
sl@0
     6
// accompanying file LICENSE_1_0.txt or copy at
sl@0
     7
// http://www.boost.org/LICENSE_1_0.txt)
sl@0
     8
sl@0
     9
// For more information, see http://www.boost.org
sl@0
    10
//
sl@0
    11
// Revision History:
sl@0
    12
//
sl@0
    13
// 29 Nov 2001    Jeremy Siek
sl@0
    14
//      Changed to use Boost.Random.
sl@0
    15
// 29 Nov 2001    Doug Gregor
sl@0
    16
//      Initial checkin.
sl@0
    17
/*
sl@0
    18
 * © Portions copyright (c) 2006-2007 Nokia Corporation.  All rights reserved.
sl@0
    19
*/
sl@0
    20
sl@0
    21
#include <iostream>
sl@0
    22
#include <fstream>
sl@0
    23
#include <map>
sl@0
    24
#include <algorithm>
sl@0
    25
#include <cstdlib>
sl@0
    26
#include <time.h> // clock used without std:: qualifier?
sl@0
    27
#include <boost/test/minimal.hpp>
sl@0
    28
#include <boost/graph/adjacency_list.hpp>
sl@0
    29
#include <boost/graph/isomorphism.hpp>
sl@0
    30
#include <boost/property_map.hpp>
sl@0
    31
#include <boost/random/variate_generator.hpp>
sl@0
    32
#include <boost/random/uniform_real.hpp>
sl@0
    33
#include <boost/random/uniform_int.hpp>
sl@0
    34
#include <boost/random/mersenne_twister.hpp>
sl@0
    35
#include <boost/lexical_cast.hpp>
sl@0
    36
#ifdef __SYMBIAN32__
sl@0
    37
#include "std_log_result.h"
sl@0
    38
#define LOG_FILENAME_LINE __FILE__, __LINE__
sl@0
    39
#endif
sl@0
    40
using namespace boost;
sl@0
    41
sl@0
    42
template <typename Generator>
sl@0
    43
struct random_functor {
sl@0
    44
  random_functor(Generator& g) : g(g) { }
sl@0
    45
  std::size_t operator()(std::size_t n) {
sl@0
    46
    boost::uniform_int<std::size_t> distrib(0, n-1);
sl@0
    47
    boost::variate_generator<boost::mt19937&, boost::uniform_int<std::size_t> >
sl@0
    48
      x(g, distrib);
sl@0
    49
    return x();
sl@0
    50
  }
sl@0
    51
  Generator& g;
sl@0
    52
};
sl@0
    53
sl@0
    54
template<typename Graph1, typename Graph2>
sl@0
    55
void randomly_permute_graph(const Graph1& g1, Graph2& g2)
sl@0
    56
{
sl@0
    57
  // Need a clean graph to start with
sl@0
    58
  BOOST_REQUIRE(num_vertices(g2) == 0);
sl@0
    59
  BOOST_REQUIRE(num_edges(g2) == 0);
sl@0
    60
sl@0
    61
  typedef typename graph_traits<Graph1>::vertex_descriptor vertex1;
sl@0
    62
  typedef typename graph_traits<Graph2>::vertex_descriptor vertex2;
sl@0
    63
  typedef typename graph_traits<Graph1>::edge_iterator edge_iterator;
sl@0
    64
sl@0
    65
  boost::mt19937 gen;
sl@0
    66
  random_functor<boost::mt19937> rand_fun(gen);
sl@0
    67
sl@0
    68
  // Decide new order
sl@0
    69
  std::vector<vertex1> orig_vertices;
sl@0
    70
  std::copy(vertices(g1).first, vertices(g1).second, std::back_inserter(orig_vertices));
sl@0
    71
  std::random_shuffle(orig_vertices.begin(), orig_vertices.end(), rand_fun);
sl@0
    72
  std::map<vertex1, vertex2> vertex_map;
sl@0
    73
sl@0
    74
  for (std::size_t i = 0; i < num_vertices(g1); ++i) {
sl@0
    75
    vertex_map[orig_vertices[i]] = add_vertex(g2);
sl@0
    76
  }
sl@0
    77
sl@0
    78
  for (edge_iterator e = edges(g1).first; e != edges(g1).second; ++e) {
sl@0
    79
    add_edge(vertex_map[source(*e, g1)], vertex_map[target(*e, g1)], g2);
sl@0
    80
  }
sl@0
    81
}
sl@0
    82
sl@0
    83
template<typename Graph>
sl@0
    84
void generate_random_digraph(Graph& g, double edge_probability)
sl@0
    85
{
sl@0
    86
  typedef typename graph_traits<Graph>::vertex_iterator vertex_iterator;
sl@0
    87
  boost::mt19937 random_gen;
sl@0
    88
  boost::uniform_real<double> distrib(0.0, 1.0);
sl@0
    89
  boost::variate_generator<boost::mt19937&, boost::uniform_real<double> >
sl@0
    90
    random_dist(random_gen, distrib);
sl@0
    91
sl@0
    92
  for (vertex_iterator u = vertices(g).first; u != vertices(g).second; ++u) {
sl@0
    93
    vertex_iterator v = u;
sl@0
    94
    ++v;
sl@0
    95
    for (; v != vertices(g).second; ++v) {
sl@0
    96
      if (random_dist() <= edge_probability)
sl@0
    97
        add_edge(*u, *v, g);
sl@0
    98
    }
sl@0
    99
  }
sl@0
   100
}
sl@0
   101
sl@0
   102
void test_isomorphism(int n, double edge_probability)
sl@0
   103
{
sl@0
   104
  typedef adjacency_list<vecS, vecS, bidirectionalS> graph1;
sl@0
   105
  typedef adjacency_list<listS, listS, bidirectionalS,
sl@0
   106
                         property<vertex_index_t, int> > graph2;
sl@0
   107
sl@0
   108
  graph1 g1(n);
sl@0
   109
  generate_random_digraph(g1, edge_probability);
sl@0
   110
  graph2 g2;
sl@0
   111
  randomly_permute_graph(g1, g2);
sl@0
   112
sl@0
   113
  int v_idx = 0;
sl@0
   114
  for (graph2::vertex_iterator v = vertices(g2).first;
sl@0
   115
       v != vertices(g2).second; ++v) {
sl@0
   116
    put(vertex_index_t(), g2, *v, v_idx++);
sl@0
   117
  }
sl@0
   118
sl@0
   119
  std::map<graph1::vertex_descriptor, graph2::vertex_descriptor> mapping;
sl@0
   120
sl@0
   121
  bool isomorphism_correct = true;
sl@0
   122
  clock_t start = clock();
sl@0
   123
  
sl@0
   124
  isomorphism_correct = isomorphism(g1, g2, isomorphism_map(make_assoc_property_map(mapping)));
sl@0
   125
 
sl@0
   126
  BOOST_CHECK(isomorphism_correct);
sl@0
   127
              
sl@0
   128
  clock_t end = clock();
sl@0
   129
sl@0
   130
  std::cout << "Elapsed time (clock cycles): " << (end - start) << std::endl;
sl@0
   131
sl@0
   132
  bool verify_correct = true;
sl@0
   133
  
sl@0
   134
  verify_correct = verify_isomorphism(g1, g2, make_assoc_property_map(mapping));
sl@0
   135
  
sl@0
   136
  BOOST_CHECK(verify_correct);
sl@0
   137
sl@0
   138
  if (!isomorphism_correct || !verify_correct) {
sl@0
   139
    // Output graph 1
sl@0
   140
    {
sl@0
   141
      std::ofstream out("isomorphism_failure.bg1");
sl@0
   142
      out << num_vertices(g1) << std::endl;
sl@0
   143
      for (graph1::edge_iterator e = edges(g1).first;
sl@0
   144
           e != edges(g1).second; ++e) {
sl@0
   145
        out << get(vertex_index_t(), g1, source(*e, g1)) << ' '
sl@0
   146
            << get(vertex_index_t(), g1, target(*e, g1)) << std::endl;
sl@0
   147
      }
sl@0
   148
    }
sl@0
   149
sl@0
   150
    // Output graph 2
sl@0
   151
    {
sl@0
   152
      std::ofstream out("isomorphism_failure.bg2");
sl@0
   153
      out << num_vertices(g2) << std::endl;
sl@0
   154
      for (graph2::edge_iterator e = edges(g2).first;
sl@0
   155
           e != edges(g2).second; ++e) {
sl@0
   156
        out << get(vertex_index_t(), g2, source(*e, g2)) << ' '
sl@0
   157
            << get(vertex_index_t(), g2, target(*e, g2)) << std::endl;
sl@0
   158
      }
sl@0
   159
    }
sl@0
   160
  }
sl@0
   161
}
sl@0
   162
sl@0
   163
int test_main(int argc, char* argv[])
sl@0
   164
{
sl@0
   165
  if (argc < 3) {
sl@0
   166
    test_isomorphism(30, 0.45);
sl@0
   167
#ifdef __SYMBIAN32__
sl@0
   168
    std_log(LOG_FILENAME_LINE,"[End Test Case ]");
sl@0
   169
sl@0
   170
	testResultXml("isomorphism");
sl@0
   171
	close_log_file();
sl@0
   172
#endif
sl@0
   173
    return 0;
sl@0
   174
  }
sl@0
   175
sl@0
   176
  int n = boost::lexical_cast<int>(argv[1]);
sl@0
   177
  double edge_prob = boost::lexical_cast<double>(argv[2]);
sl@0
   178
  test_isomorphism(n, edge_prob);
sl@0
   179
 
sl@0
   180
#ifdef __SYMBIAN32__
sl@0
   181
std_log(LOG_FILENAME_LINE,"[End Test Case ]");
sl@0
   182
sl@0
   183
	testResultXml("isomorphism");
sl@0
   184
	close_log_file();
sl@0
   185
#endif
sl@0
   186
  return 0;
sl@0
   187
}