File: test_graph_topology.cpp

package info (click to toggle)
boost1.90 1.90.0-1
  • links: PTS, VCS
  • area: main
  • in suites:
  • size: 593,120 kB
  • sloc: cpp: 4,190,908; xml: 196,648; python: 34,618; ansic: 23,145; asm: 5,468; sh: 3,774; makefile: 1,161; perl: 1,020; sql: 728; ruby: 676; yacc: 478; java: 77; lisp: 24; csh: 6
file content (130 lines) | stat: -rw-r--r-- 4,603 bytes parent folder | download | duplicates (5)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
// Copyright (C) 2007 Trustees of Indiana University

// Authors: Douglas Gregor
//          Andrew Lumsdaine

// Use, modification and distribution is subject to 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)

// A test of the communicator that passes data around a ring and
// verifies that the same data makes it all the way. Should test all
// of the various kinds of data that can be sent (primitive types, POD
// types, serializable objects, etc.)
#include <boost/mpi/graph_communicator.hpp>
#include <boost/mpi/communicator.hpp>
#include <boost/mpi/environment.hpp>
#include <boost/graph/adjacency_list.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/graph/erdos_renyi_generator.hpp>
#include <boost/random/linear_congruential.hpp>
#include <boost/graph/iteration_macros.hpp>
#include <boost/graph/isomorphism.hpp>
#include <algorithm> // for shuffle
#include <boost/serialization/vector.hpp>
#include <boost/mpi/collectives/broadcast.hpp>
#include <boost/config.hpp>

#include "mpi_test_utils.hpp"

#include <random>

using boost::mpi::communicator;
using boost::mpi::graph_communicator;
using namespace boost;

int main()
{
  boost::function_requires< IncidenceGraphConcept<graph_communicator> >();
  boost::function_requires< AdjacencyGraphConcept<graph_communicator> >();
  boost::function_requires< VertexListGraphConcept<graph_communicator> >();
  boost::function_requires< EdgeListGraphConcept<graph_communicator> >();
  int failed = 0;
  double prob = 0.1;

  boost::mpi::environment env;
  communicator world;

  // Random number generator
  minstd_rand gen;

  // Build a random graph with as many vertices as there are processes
  typedef adjacency_list<listS, vecS, bidirectionalS> Graph;
  sorted_erdos_renyi_iterator<minstd_rand, Graph>
    first(gen, world.size(), prob), last;
  Graph graph(first, last, world.size());

  // Display the original graph
  if (world.rank() == 0) {
    std::cout << "Original, random graph:\n";
    BGL_FORALL_VERTICES(v, graph, Graph) {
      BGL_FORALL_OUTEDGES(v, e, graph, Graph) {
        std::cout << source(e, graph) << " -> " << target(e, graph) 
                  << std::endl;
      }
    }
  }

  // Create an arbitrary mapping from vertices to integers
  typedef property_map<Graph, vertex_index_t>::type GraphVertexIndexMap;
  std::vector<int> graph_alt_index_vec(num_vertices(graph));
  iterator_property_map<int*, GraphVertexIndexMap> 
    graph_alt_index(&graph_alt_index_vec[0], get(vertex_index, graph));

  // Rank 0 will populate the alternative index vector
  if (world.rank() == 0) {
    int index = 0;
    BGL_FORALL_VERTICES(v, graph, Graph)
      put(graph_alt_index, v, index++);

    {
      std::random_device rd;
      std::mt19937 gen(rd());
      std::shuffle(graph_alt_index_vec.begin(), graph_alt_index_vec.end(), gen);
    }
  }
  broadcast(world, graph_alt_index_vec, 0);

  // Display the original graph with the remapping
  if (world.rank() == 0) {
    std::cout << "Original, random graph with remapped vertex numbers:\n";
    BGL_FORALL_VERTICES(v, graph, Graph) {
      BGL_FORALL_OUTEDGES(v, e, graph, Graph) {
        std::cout << get(graph_alt_index, source(e, graph)) << " -> " 
                  << get(graph_alt_index, target(e, graph)) << std::endl;
      }
    }
  }

  // Create a communicator with a topology equivalent to the graph
  graph_communicator graph_comm(world, graph, graph_alt_index, false);

  // The communicator's topology should have the same number of
  // vertices and edges and the original graph
  BOOST_MPI_CHECK((int)num_vertices(graph) == num_vertices(graph_comm), failed);
  BOOST_MPI_CHECK((int)num_edges(graph) == num_edges(graph_comm), failed);

  // Display the communicator graph
  if (graph_comm.rank() == 0) {
    std::cout << "Communicator graph:\n";
    BGL_FORALL_VERTICES(v, graph_comm, graph_communicator) {
      BGL_FORALL_OUTEDGES(v, e, graph_comm, graph_communicator) {
        std::cout << source(e, graph_comm) << " -> " << target(e, graph_comm) 
                  << std::endl;
      }
    }

    std::cout << "Communicator graph via edges():\n";
    BGL_FORALL_EDGES(e, graph_comm, graph_communicator)
      std::cout << source(e, graph_comm) << " -> " << target(e, graph_comm) 
                << std::endl;
  }
  (graph_comm.barrier)();

  // Verify the isomorphism
  if (graph_comm.rank() == 0)
    std::cout << "Verifying isomorphism..." << std::endl;
  BOOST_MPI_CHECK(verify_isomorphism(graph, graph_comm, graph_alt_index), failed);
  
  return failed;
}