File: named_vertices_hash_test.cpp

package info (click to toggle)
boost1.55 1.55.0%2Bdfsg-3
  • links: PTS, VCS
  • area: main
  • in suites: jessie, jessie-kfreebsd
  • size: 487,824 kB
  • ctags: 673,349
  • sloc: cpp: 2,098,430; xml: 106,036; ansic: 46,744; python: 32,427; sh: 11,864; cs: 2,121; asm: 1,640; makefile: 984; perl: 714; yacc: 456; php: 132; fortran: 43; sql: 13; csh: 6
file content (158 lines) | stat: -rw-r--r-- 4,538 bytes parent folder | download | duplicates (10)
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
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
// Copyright (C) 2007-2008 The Trustees of Indiana University.

// 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)

#include <boost/graph/use_mpi.hpp>
#include <boost/config.hpp>
#include <boost/throw_exception.hpp>
#include <boost/mpl/print.hpp>
#include <boost/graph/distributed/adjacency_list.hpp>
#include <boost/graph/distributed/mpi_process_group.hpp>
#include <boost/graph/iteration_macros.hpp>
#include <boost/test/minimal.hpp>
#include <string>
#include <iostream>

#ifdef BOOST_NO_EXCEPTIONS
void
boost::throw_exception(std::exception const& ex)
{
    std::cout << ex.what() << std::endl;
    abort();
}
#endif

using namespace boost;
using boost::graph::distributed::mpi_process_group;

/// City structure to be attached to each vertex
struct City {
  City() {}

  City(const std::string& name, int population = -1)
    : name(name), population(population) { }
  
  template<typename Archiver>
  void serialize(Archiver& ar, const unsigned int /*version*/)
  {
    ar & name & population;
  }

  std::string name;
  int population;
};

/// Our distribution function
template<typename T>
struct named_vertices_hashed_distribution
{
  template<typename ProcessGroup>
  named_vertices_hashed_distribution(const ProcessGroup& pg, 
        std::size_t /*num_vertices*/ = 0)
    : n(num_processes(pg)) { }

  int operator()(const T& value) const 
  {
    return hasher(value) % n;
  }

  std::size_t n;
  boost::hash<T> hasher;
};

typedef named_vertices_hashed_distribution<std::string> hasher_type;

namespace boost { namespace graph {

/// Use the City name as a key for indexing cities in a graph
template<>
struct internal_vertex_name<City>
{
  typedef multi_index::member<City, std::string, &City::name> type;
};

/// Allow the graph to build cities given only their names (filling in
/// the defaults for fields).
template<>
struct internal_vertex_constructor<City>
{
  typedef vertex_from_name<City> type;
};

//   namespace distributed
//   {
//     /// Use the City name as the source for the distribution hasher
//     ///
//     /// This is currently needed in addition to the specification of this
//     /// hasher functor as the 3rd template parameter to the distributedS 
//     /// template.
//     template<>
//     struct internal_vertex_name_distribution<City>
//     {
//       typedef named_vertices_hashed_distribution<std::string> type;
//     };
//   }

} } // end namespace boost::graph

/// Our road map, where each of the vertices are cities
typedef boost::adjacency_list<vecS, 
                       distributedS<mpi_process_group, vecS, hasher_type>, 
                       bidirectionalS, City> RoadMap;
typedef graph_traits<RoadMap>::vertex_descriptor Vertex;

int test_main(int argc, char** argv)
{
  boost::mpi::environment env(argc, argv);

  mpi_process_group pg;
  RoadMap map; // (pg, hasher_type(pg));

  int rank = process_id(pg);
  bool i_am_root = rank == 0;

  /// Create vertices for Bloomington, Indianapolis, Chicago. Everyone will
  /// try to do this, but only one of each vertex will be added.
  Vertex bloomington = add_vertex(City("Bloomington", 69291), map);
  Vertex chicago = add_vertex(City("Chicago", 9500000), map);
  Vertex indianapolis = add_vertex(City("Indianapolis", 791926), map);

  BGL_FORALL_VERTICES(city, map, RoadMap)
    std::cout << rank << ": " << map[city].name << ", population " 
              << map[city].population << std::endl;

  BOOST_CHECK(*find_vertex("Bloomington", map) == bloomington);
  BOOST_CHECK(*find_vertex("Indianapolis", map) == indianapolis);
  BOOST_CHECK(*find_vertex("Chicago", map) == chicago);

  if (i_am_root) {
    add_edge(bloomington, "Indianapolis", map);
    add_edge("Indianapolis", chicago, map);
    add_edge("Indianapolis", "Cincinnati", map);
  }

  synchronize(map);

  {
    property_map<RoadMap, std::string City::*>::type
      city_name = get(&City::name, map);

    BGL_FORALL_EDGES(road, map, RoadMap)
      std::cout << rank << ": " << get(city_name, source(road, map)) << " -> " 
                << get(city_name, target(road, map)) << std::endl;

    synchronize(map);
  }

  // Make sure the vertex for "Cincinnati" was created implicitly
  Vertex cincinnati = *find_vertex("Cincinnati", map);
  if (get(get(vertex_owner, map), cincinnati) 
        == process_id(map.process_group()))
    BOOST_CHECK(map[cincinnati].population == -1);

  synchronize(map);

  return 0;
}