geodesic_distance.hpp 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211
  1. // (C) Copyright Andrew Sutton 2007
  2. //
  3. // Use, modification and distribution are subject to the
  4. // Boost Software License, Version 1.0 (See accompanying file
  5. // LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
  6. #ifndef BOOST_GRAPH_GEODESIC_DISTANCE_HPP
  7. #define BOOST_GRAPH_GEODESIC_DISTANCE_HPP
  8. #include <boost/graph/detail/geodesic.hpp>
  9. #include <boost/graph/exterior_property.hpp>
  10. #include <boost/concept/assert.hpp>
  11. namespace boost
  12. {
  13. template <typename Graph,
  14. typename DistanceType,
  15. typename ResultType,
  16. typename Divides = std::divides<ResultType> >
  17. struct mean_geodesic_measure
  18. : public geodesic_measure<Graph, DistanceType, ResultType>
  19. {
  20. typedef geodesic_measure<Graph, DistanceType, ResultType> base_type;
  21. typedef typename base_type::distance_type distance_type;
  22. typedef typename base_type::result_type result_type;
  23. result_type operator ()(distance_type d, const Graph& g)
  24. {
  25. BOOST_CONCEPT_ASSERT(( VertexListGraphConcept<Graph> ));
  26. BOOST_CONCEPT_ASSERT(( NumericValueConcept<DistanceType> ));
  27. BOOST_CONCEPT_ASSERT(( NumericValueConcept<ResultType> ));
  28. BOOST_CONCEPT_ASSERT(( AdaptableBinaryFunctionConcept<Divides,ResultType,ResultType,ResultType> ));
  29. return (d == base_type::infinite_distance())
  30. ? base_type::infinite_result()
  31. : div(result_type(d), result_type(num_vertices(g) - 1));
  32. }
  33. Divides div;
  34. };
  35. template <typename Graph, typename DistanceMap>
  36. inline mean_geodesic_measure<Graph, typename property_traits<DistanceMap>::value_type, double>
  37. measure_mean_geodesic(const Graph&, DistanceMap)
  38. {
  39. return mean_geodesic_measure<Graph, typename property_traits<DistanceMap>::value_type, double>();
  40. }
  41. template <typename T, typename Graph, typename DistanceMap>
  42. inline mean_geodesic_measure<Graph, typename property_traits<DistanceMap>::value_type, T>
  43. measure_mean_geodesic(const Graph&, DistanceMap)
  44. {
  45. return mean_geodesic_measure<Graph, typename property_traits<DistanceMap>::value_type, T>();
  46. }
  47. // This is a little different because it's expected that the result type
  48. // should (must?) be the same as the distance type. There's a type of
  49. // transitivity in this thinking... If the average of distances has type
  50. // X then the average of x's should also be type X. Is there a case where this
  51. // is not true?
  52. //
  53. // This type is a little under-genericized... It needs generic parameters
  54. // for addition and division.
  55. template <typename Graph, typename DistanceType>
  56. struct mean_graph_distance_measure
  57. : public geodesic_measure<Graph, DistanceType, DistanceType>
  58. {
  59. typedef geodesic_measure<Graph, DistanceType, DistanceType> base_type;
  60. typedef typename base_type::distance_type distance_type;
  61. typedef typename base_type::result_type result_type;
  62. inline result_type operator ()(distance_type d, const Graph& g)
  63. {
  64. BOOST_CONCEPT_ASSERT(( VertexListGraphConcept<Graph> ));
  65. BOOST_CONCEPT_ASSERT(( NumericValueConcept<DistanceType> ));
  66. if(d == base_type::infinite_distance()) {
  67. return base_type::infinite_result();
  68. }
  69. else {
  70. return d / result_type(num_vertices(g));
  71. }
  72. }
  73. };
  74. template <typename Graph, typename DistanceMap>
  75. inline mean_graph_distance_measure<Graph, typename property_traits<DistanceMap>::value_type>
  76. measure_graph_mean_geodesic(const Graph&, DistanceMap)
  77. {
  78. typedef typename property_traits<DistanceMap>::value_type T;
  79. return mean_graph_distance_measure<Graph, T>();
  80. }
  81. template <typename Graph,
  82. typename DistanceMap,
  83. typename Measure,
  84. typename Combinator>
  85. inline typename Measure::result_type
  86. mean_geodesic(const Graph& g,
  87. DistanceMap dist,
  88. Measure measure,
  89. Combinator combine)
  90. {
  91. BOOST_CONCEPT_ASSERT(( DistanceMeasureConcept<Measure,Graph> ));
  92. typedef typename Measure::distance_type Distance;
  93. Distance n = detail::combine_distances(g, dist, combine, Distance(0));
  94. return measure(n, g);
  95. }
  96. template <typename Graph,
  97. typename DistanceMap,
  98. typename Measure>
  99. inline typename Measure::result_type
  100. mean_geodesic(const Graph& g, DistanceMap dist, Measure measure)
  101. {
  102. BOOST_CONCEPT_ASSERT(( DistanceMeasureConcept<Measure,Graph> ));
  103. typedef typename Measure::distance_type Distance;
  104. return mean_geodesic(g, dist, measure, std::plus<Distance>());
  105. }
  106. template <typename Graph, typename DistanceMap>
  107. inline double
  108. mean_geodesic(const Graph& g, DistanceMap dist)
  109. { return mean_geodesic(g, dist, measure_mean_geodesic(g, dist)); }
  110. template <typename T, typename Graph, typename DistanceMap>
  111. inline T
  112. mean_geodesic(const Graph& g, DistanceMap dist)
  113. { return mean_geodesic(g, dist, measure_mean_geodesic<T>(g, dist)); }
  114. template <typename Graph,
  115. typename DistanceMatrixMap,
  116. typename GeodesicMap,
  117. typename Measure>
  118. inline typename property_traits<GeodesicMap>::value_type
  119. all_mean_geodesics(const Graph& g,
  120. DistanceMatrixMap dist,
  121. GeodesicMap geo,
  122. Measure measure)
  123. {
  124. BOOST_CONCEPT_ASSERT(( VertexListGraphConcept<Graph> ));
  125. typedef typename graph_traits<Graph>::vertex_descriptor Vertex;
  126. typedef typename graph_traits<Graph>::vertex_iterator VertexIterator;
  127. BOOST_CONCEPT_ASSERT(( ReadablePropertyMapConcept<DistanceMatrixMap,Vertex> ));
  128. typedef typename property_traits<DistanceMatrixMap>::value_type DistanceMap;
  129. BOOST_CONCEPT_ASSERT(( DistanceMeasureConcept<Measure,Graph> ));
  130. typedef typename Measure::result_type Result;
  131. BOOST_CONCEPT_ASSERT(( WritablePropertyMapConcept<GeodesicMap,Vertex> ));
  132. BOOST_CONCEPT_ASSERT(( NumericValueConcept<Result> ));
  133. // NOTE: We could compute the mean geodesic here by performing additional
  134. // computations (i.e., adding and dividing). However, I don't really feel
  135. // like fully genericizing the entire operation yet so I'm not going to.
  136. Result inf = numeric_values<Result>::infinity();
  137. Result sum = numeric_values<Result>::zero();
  138. VertexIterator i, end;
  139. for(boost::tie(i, end) = vertices(g); i != end; ++i) {
  140. DistanceMap dm = get(dist, *i);
  141. Result r = mean_geodesic(g, dm, measure);
  142. put(geo, *i, r);
  143. // compute the sum along with geodesics
  144. if(r == inf) {
  145. sum = inf;
  146. }
  147. else if(sum != inf) {
  148. sum += r;
  149. }
  150. }
  151. // return the average of averages.
  152. return sum / Result(num_vertices(g));
  153. }
  154. template <typename Graph, typename DistanceMatrixMap, typename GeodesicMap>
  155. inline typename property_traits<GeodesicMap>::value_type
  156. all_mean_geodesics(const Graph& g, DistanceMatrixMap dist, GeodesicMap geo)
  157. {
  158. BOOST_CONCEPT_ASSERT(( GraphConcept<Graph> ));
  159. typedef typename graph_traits<Graph>::vertex_descriptor Vertex;
  160. BOOST_CONCEPT_ASSERT(( ReadablePropertyMapConcept<DistanceMatrixMap,Vertex> ));
  161. typedef typename property_traits<DistanceMatrixMap>::value_type DistanceMap;
  162. BOOST_CONCEPT_ASSERT(( WritablePropertyMapConcept<GeodesicMap,Vertex> ));
  163. typedef typename property_traits<GeodesicMap>::value_type Result;
  164. return all_mean_geodesics(g, dist, geo, measure_mean_geodesic<Result>(g, DistanceMap()));
  165. }
  166. template <typename Graph, typename GeodesicMap, typename Measure>
  167. inline typename Measure::result_type
  168. small_world_distance(const Graph& g, GeodesicMap geo, Measure measure)
  169. {
  170. BOOST_CONCEPT_ASSERT(( DistanceMeasureConcept<Measure,Graph> ));
  171. typedef typename Measure::result_type Result;
  172. Result sum = detail::combine_distances(g, geo, std::plus<Result>(), Result(0));
  173. return measure(sum, g);
  174. }
  175. template <typename Graph, typename GeodesicMap>
  176. inline typename property_traits<GeodesicMap>::value_type
  177. small_world_distance(const Graph& g, GeodesicMap geo)
  178. { return small_world_distance(g, geo, measure_graph_mean_geodesic(g, geo)); }
  179. }
  180. #endif