bundled_properties.cpp 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236
  1. // Boost Graph library
  2. // Copyright Douglas Gregor 2004. Use, modification and
  3. // distribution is subject to the Boost Software License, Version
  4. // 1.0. (See accompanying file LICENSE_1_0.txt or copy at
  5. // http://www.boost.org/LICENSE_1_0.txt)
  6. #include <boost/test/minimal.hpp>
  7. #include <boost/graph/adjacency_list.hpp>
  8. #include <boost/graph/adjacency_matrix.hpp>
  9. #include <boost/graph/filtered_graph.hpp>
  10. #include <boost/graph/subgraph.hpp>
  11. #include <string>
  12. #include <vector>
  13. #include <boost/graph/adjacency_list_io.hpp>
  14. #include <sstream>
  15. #include <boost/graph/iteration_macros.hpp>
  16. #include <algorithm>
  17. #include <iterator>
  18. using namespace std;
  19. using namespace boost;
  20. struct City
  21. {
  22. City() {}
  23. City(const std::string& name, int pop, int zipcode) : name(name), population(pop)
  24. {
  25. zipcodes.push_back(zipcode);
  26. }
  27. string name;
  28. int population;
  29. vector<int> zipcodes;
  30. };
  31. std::ostream& operator<<(std::ostream& out, const City& city)
  32. {
  33. out << city.name << ' ' << city.population << ' ';
  34. copy(city.zipcodes.begin(), city.zipcodes.end(),
  35. ostream_iterator<int>(out, " "));
  36. out << -1;
  37. return out;
  38. }
  39. std::istream& operator>>(std::istream& in, City& city)
  40. {
  41. if (in >> city.name >> city.population) {
  42. int zip;
  43. city.zipcodes.clear();
  44. while (in >> zip && zip != -1)
  45. city.zipcodes.push_back(zip);
  46. }
  47. return in;
  48. }
  49. bool operator==(const City& c1, const City& c2)
  50. {
  51. return (c1.name == c2.name && c1.population == c2.population
  52. && c1.zipcodes == c2.zipcodes);
  53. }
  54. struct Highway
  55. {
  56. Highway() {}
  57. Highway(const string& name, double miles, int speed_limit = 65, int lanes = 4, bool divided = true)
  58. : name(name), miles(miles), speed_limit(speed_limit), lanes(lanes), divided(divided) {}
  59. string name;
  60. double miles;
  61. int speed_limit;
  62. int lanes;
  63. bool divided;
  64. };
  65. std::ostream& operator<<(std::ostream& out, const Highway& highway)
  66. {
  67. return out << highway.name << ' ' << highway.miles << ' ' << highway.miles
  68. << ' ' << highway.speed_limit << ' ' << highway.lanes
  69. << ' ' << highway.divided;
  70. }
  71. std::istream& operator>>(std::istream& in, Highway& highway)
  72. {
  73. return in >> highway.name >> highway.miles >> highway.miles
  74. >> highway.speed_limit >> highway.lanes
  75. >> highway.divided;
  76. }
  77. bool operator==(const Highway& h1, const Highway& h2)
  78. {
  79. return (h1.name == h2.name && h1.miles == h2.miles
  80. && h1.speed_limit == h2.speed_limit && h1.lanes == h2.lanes
  81. && h1.divided == h2.divided);
  82. }
  83. template<bool> struct truth {};
  84. template<typename Map, typename VertexIterator, typename Bundle>
  85. typename boost::graph_traits<Map>::vertex_descriptor
  86. do_add_vertex(Map& map, VertexIterator, const Bundle& bundle, truth<true>)
  87. {
  88. return add_vertex(bundle, map);
  89. }
  90. template<typename Map, typename VertexIterator, typename Bundle>
  91. typename boost::graph_traits<Map>::vertex_descriptor
  92. do_add_vertex(Map& map, VertexIterator& vi, const Bundle& bundle, truth<false>)
  93. {
  94. get(boost::vertex_bundle, map)[*vi] = bundle;
  95. return *vi++;
  96. }
  97. template<class EL, class VL, class D, class VP, class EP, class GP>
  98. void test_io(adjacency_list<EL,VL,D,VP,EP,GP>& map, int)
  99. {
  100. typedef adjacency_list<EL,VL,D,VP,EP,GP> Map;
  101. ostringstream out;
  102. cout << write(map);
  103. out << write(map);
  104. istringstream in(out.str());
  105. adjacency_list<EL,VL,D,VP,EP,GP> map2;
  106. in >> read(map2);
  107. typename graph_traits<adjacency_list<EL,VL,D,VP,EP,GP> >::vertex_iterator
  108. v2 = vertices(map2).first;
  109. BGL_FORALL_VERTICES_T(v, map, Map) {
  110. BOOST_CHECK(map[v] == map2[*v2]);
  111. typename graph_traits<adjacency_list<EL,VL,D,VP,EP,GP> >::out_edge_iterator
  112. e2 = out_edges(*v2, map2).first;
  113. BGL_FORALL_OUTEDGES_T(v, e, map, Map) {
  114. BOOST_CHECK(map[e] == map[*e2]);
  115. ++e2;
  116. }
  117. ++v2;
  118. }
  119. }
  120. template<typename Map>
  121. void test_io(const Map&, long)
  122. {
  123. // Nothing to test
  124. }
  125. template<typename Map, bool CanAddVertex>
  126. void test_bundled_properties(Map*, truth<CanAddVertex> can_add_vertex)
  127. {
  128. typedef typename boost::graph_traits<Map>::vertex_iterator vertex_iterator;
  129. typedef typename boost::graph_traits<Map>::vertex_descriptor vertex_descriptor;
  130. typedef typename boost::graph_traits<Map>::edge_descriptor edge_descriptor;
  131. Map map(CanAddVertex? 2 : 3);
  132. vertex_iterator vi = vertices(map).first;
  133. vertex_descriptor v = *vi;
  134. map[v].name = "Troy";
  135. map[v].population = 49170;
  136. map[v].zipcodes.push_back(12180);
  137. ++vi;
  138. vertex_descriptor u = *vi++;
  139. map[u].name = "Albany";
  140. map[u].population = 95658;
  141. map[u].zipcodes.push_back(12201);
  142. // Try adding a vertex with a property value
  143. vertex_descriptor bloomington = do_add_vertex(map, vi, City("Bloomington", 39000, 47401),
  144. can_add_vertex);
  145. BOOST_CHECK(get(boost::vertex_bundle, map)[bloomington].zipcodes[0] == 47401);
  146. edge_descriptor e = add_edge(v, u, map).first;
  147. map[e].name = "I-87";
  148. map[e].miles = 10;
  149. map[e].speed_limit = 65;
  150. map[e].lanes = 4;
  151. map[e].divided = true;
  152. edge_descriptor our_trip = add_edge(v, bloomington, Highway("Long", 1000), map).first;
  153. BOOST_CHECK(get(boost::edge_bundle, map, our_trip).miles == 1000);
  154. BOOST_CHECK(get(get(&City::name, map), v) == "Troy");
  155. BOOST_CHECK(get(get(&Highway::name, map), e) == "I-87");
  156. BOOST_CHECK(get(&City::name, map, u) == "Albany");
  157. BOOST_CHECK(get(&Highway::name, map, e) == "I-87");
  158. put(&City::population, map, v, 49168);
  159. BOOST_CHECK(get(&City::population, map)[v] == 49168);
  160. boost::filtered_graph<Map, boost::keep_all> fmap(map, boost::keep_all());
  161. BOOST_CHECK(get(boost::edge_bundle, map, our_trip).miles == 1000);
  162. BOOST_CHECK(get(get(&City::name, fmap), v) == "Troy");
  163. BOOST_CHECK(get(get(&Highway::name, fmap), e) == "I-87");
  164. BOOST_CHECK(get(&City::name, fmap, u) == "Albany");
  165. BOOST_CHECK(get(&Highway::name, fmap, e) == "I-87");
  166. put(&City::population, fmap, v, 49169);
  167. BOOST_CHECK(get(&City::population, fmap)[v] == 49169);
  168. test_io(map, 0);
  169. }
  170. void test_subgraph_bundled_properties()
  171. {
  172. typedef boost::subgraph<
  173. boost::adjacency_list<boost::vecS, boost::vecS,
  174. boost::bidirectionalS, City,
  175. boost::property<boost::edge_index_t, int,
  176. Highway> > > SubMap;
  177. typedef boost::graph_traits<SubMap>::vertex_descriptor Vertex;
  178. typedef boost::graph_traits<SubMap>::vertex_iterator vertex_iterator;
  179. SubMap map(3);
  180. vertex_iterator vi = vertices(map).first;
  181. Vertex troy = *vi++;
  182. map[troy].name = "Troy";
  183. map[*vi++].name = "Bloomington";
  184. map[*vi++].name = "Endicott";
  185. SubMap& g1 = map.create_subgraph();
  186. Vertex troy1 = add_vertex(*vertices(map).first, g1);
  187. BOOST_CHECK(map[troy1].name == g1[troy1].name);
  188. }
  189. int test_main(int, char*[])
  190. {
  191. typedef boost::adjacency_list<
  192. boost::listS, boost::vecS, boost::bidirectionalS,
  193. City, Highway> Map1;
  194. typedef boost::adjacency_matrix<boost::directedS,
  195. City, Highway> Map2;
  196. test_bundled_properties(static_cast<Map1*>(0), truth<true>());
  197. test_bundled_properties(static_cast<Map2*>(0), truth<false>());
  198. test_subgraph_bundled_properties();
  199. return 0;
  200. }