geodesic_distance.hpp 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217
  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, typename DistanceType, typename ResultType,
  14. typename Divides = std::divides< ResultType > >
  15. struct mean_geodesic_measure
  16. : public geodesic_measure< Graph, DistanceType, ResultType >
  17. {
  18. typedef geodesic_measure< Graph, DistanceType, ResultType > base_type;
  19. typedef typename base_type::distance_type distance_type;
  20. typedef typename base_type::result_type result_type;
  21. result_type operator()(distance_type d, const Graph& g)
  22. {
  23. BOOST_CONCEPT_ASSERT((VertexListGraphConcept< Graph >));
  24. BOOST_CONCEPT_ASSERT((NumericValueConcept< DistanceType >));
  25. BOOST_CONCEPT_ASSERT((NumericValueConcept< ResultType >));
  26. // NOTE: Disabled until this concept assert is fixed in Boost.ConceptCheck.
  27. // BOOST_CONCEPT_ASSERT((AdaptableBinaryFunctionConcept< Divides,
  28. // 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,
  37. typename property_traits< DistanceMap >::value_type, double >
  38. measure_mean_geodesic(const Graph&, DistanceMap)
  39. {
  40. return mean_geodesic_measure< Graph,
  41. typename property_traits< DistanceMap >::value_type, double >();
  42. }
  43. template < typename T, typename Graph, typename DistanceMap >
  44. inline mean_geodesic_measure< Graph,
  45. typename property_traits< DistanceMap >::value_type, T >
  46. measure_mean_geodesic(const Graph&, DistanceMap)
  47. {
  48. return mean_geodesic_measure< Graph,
  49. typename property_traits< DistanceMap >::value_type, T >();
  50. }
  51. // This is a little different because it's expected that the result type
  52. // should (must?) be the same as the distance type. There's a type of
  53. // transitivity in this thinking... If the average of distances has type
  54. // X then the average of x's should also be type X. Is there a case where this
  55. // is not true?
  56. //
  57. // This type is a little under-genericized... It needs generic parameters
  58. // for addition and division.
  59. template < typename Graph, typename DistanceType >
  60. struct mean_graph_distance_measure
  61. : public geodesic_measure< Graph, DistanceType, DistanceType >
  62. {
  63. typedef geodesic_measure< Graph, DistanceType, DistanceType > base_type;
  64. typedef typename base_type::distance_type distance_type;
  65. typedef typename base_type::result_type result_type;
  66. inline result_type operator()(distance_type d, const Graph& g)
  67. {
  68. BOOST_CONCEPT_ASSERT((VertexListGraphConcept< Graph >));
  69. BOOST_CONCEPT_ASSERT((NumericValueConcept< DistanceType >));
  70. if (d == base_type::infinite_distance())
  71. {
  72. return base_type::infinite_result();
  73. }
  74. else
  75. {
  76. return d / result_type(num_vertices(g));
  77. }
  78. }
  79. };
  80. template < typename Graph, typename DistanceMap >
  81. inline mean_graph_distance_measure< Graph,
  82. typename property_traits< DistanceMap >::value_type >
  83. measure_graph_mean_geodesic(const Graph&, DistanceMap)
  84. {
  85. typedef typename property_traits< DistanceMap >::value_type T;
  86. return mean_graph_distance_measure< Graph, T >();
  87. }
  88. template < typename Graph, typename DistanceMap, typename Measure,
  89. typename Combinator >
  90. inline typename Measure::result_type mean_geodesic(
  91. const Graph& g, DistanceMap dist, Measure measure, Combinator combine)
  92. {
  93. BOOST_CONCEPT_ASSERT((DistanceMeasureConcept< Measure, Graph >));
  94. typedef typename Measure::distance_type Distance;
  95. Distance n = detail::combine_distances(g, dist, combine, Distance(0));
  96. return measure(n, g);
  97. }
  98. template < typename Graph, typename DistanceMap, typename Measure >
  99. inline typename Measure::result_type mean_geodesic(
  100. 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 mean_geodesic(const Graph& g, DistanceMap dist)
  108. {
  109. return mean_geodesic(g, dist, measure_mean_geodesic(g, dist));
  110. }
  111. template < typename T, typename Graph, typename DistanceMap >
  112. inline T mean_geodesic(const Graph& g, DistanceMap dist)
  113. {
  114. return mean_geodesic(g, dist, measure_mean_geodesic< T >(g, dist));
  115. }
  116. template < typename Graph, typename DistanceMatrixMap, typename GeodesicMap,
  117. typename Measure >
  118. inline typename property_traits< GeodesicMap >::value_type all_mean_geodesics(
  119. const Graph& g, DistanceMatrixMap dist, GeodesicMap geo, Measure measure)
  120. {
  121. BOOST_CONCEPT_ASSERT((VertexListGraphConcept< Graph >));
  122. typedef typename graph_traits< Graph >::vertex_descriptor Vertex;
  123. typedef typename graph_traits< Graph >::vertex_iterator VertexIterator;
  124. BOOST_CONCEPT_ASSERT(
  125. (ReadablePropertyMapConcept< DistanceMatrixMap, Vertex >));
  126. typedef
  127. typename property_traits< DistanceMatrixMap >::value_type DistanceMap;
  128. BOOST_CONCEPT_ASSERT((DistanceMeasureConcept< Measure, Graph >));
  129. typedef typename Measure::result_type Result;
  130. BOOST_CONCEPT_ASSERT((WritablePropertyMapConcept< GeodesicMap, Vertex >));
  131. BOOST_CONCEPT_ASSERT((NumericValueConcept< Result >));
  132. // NOTE: We could compute the mean geodesic here by performing additional
  133. // computations (i.e., adding and dividing). However, I don't really feel
  134. // like fully genericizing the entire operation yet so I'm not going to.
  135. Result inf = numeric_values< Result >::infinity();
  136. Result sum = numeric_values< Result >::zero();
  137. VertexIterator i, end;
  138. for (boost::tie(i, end) = vertices(g); i != end; ++i)
  139. {
  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. {
  146. sum = inf;
  147. }
  148. else if (sum != inf)
  149. {
  150. sum += r;
  151. }
  152. }
  153. // return the average of averages.
  154. return sum / Result(num_vertices(g));
  155. }
  156. template < typename Graph, typename DistanceMatrixMap, typename GeodesicMap >
  157. inline typename property_traits< GeodesicMap >::value_type all_mean_geodesics(
  158. const Graph& g, DistanceMatrixMap dist, GeodesicMap geo)
  159. {
  160. BOOST_CONCEPT_ASSERT((GraphConcept< Graph >));
  161. typedef typename graph_traits< Graph >::vertex_descriptor Vertex;
  162. BOOST_CONCEPT_ASSERT(
  163. (ReadablePropertyMapConcept< DistanceMatrixMap, Vertex >));
  164. typedef
  165. typename property_traits< DistanceMatrixMap >::value_type DistanceMap;
  166. BOOST_CONCEPT_ASSERT((WritablePropertyMapConcept< GeodesicMap, Vertex >));
  167. typedef typename property_traits< GeodesicMap >::value_type Result;
  168. return all_mean_geodesics(
  169. g, dist, geo, measure_mean_geodesic< Result >(g, DistanceMap()));
  170. }
  171. template < typename Graph, typename GeodesicMap, typename Measure >
  172. inline typename Measure::result_type small_world_distance(
  173. const Graph& g, GeodesicMap geo, Measure measure)
  174. {
  175. BOOST_CONCEPT_ASSERT((DistanceMeasureConcept< Measure, Graph >));
  176. typedef typename Measure::result_type Result;
  177. Result sum
  178. = detail::combine_distances(g, geo, std::plus< Result >(), Result(0));
  179. return measure(sum, g);
  180. }
  181. template < typename Graph, typename GeodesicMap >
  182. inline typename property_traits< GeodesicMap >::value_type small_world_distance(
  183. const Graph& g, GeodesicMap geo)
  184. {
  185. return small_world_distance(g, geo, measure_graph_mean_geodesic(g, geo));
  186. }
  187. }
  188. #endif