clustering_coefficient.hpp 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. // (C) Copyright 2007-2009 Andrew Sutton
  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_CLUSTERING_COEFFICIENT_HPP
  7. #define BOOST_GRAPH_CLUSTERING_COEFFICIENT_HPP
  8. #include <boost/next_prior.hpp>
  9. #include <boost/graph/graph_traits.hpp>
  10. #include <boost/graph/graph_concepts.hpp>
  11. #include <boost/graph/lookup_edge.hpp>
  12. #include <boost/concept/assert.hpp>
  13. namespace boost
  14. {
  15. namespace detail
  16. {
  17. template <class Graph>
  18. inline typename graph_traits<Graph>::degree_size_type
  19. possible_edges(const Graph& g, std::size_t k, directed_tag)
  20. {
  21. BOOST_CONCEPT_ASSERT(( GraphConcept<Graph> ));
  22. typedef typename graph_traits<Graph>::degree_size_type T;
  23. return T(k) * (T(k) - 1);
  24. }
  25. template <class Graph>
  26. inline typename graph_traits<Graph>::degree_size_type
  27. possible_edges(const Graph& g, size_t k, undirected_tag)
  28. {
  29. // dirty little trick...
  30. return possible_edges(g, k, directed_tag()) / 2;
  31. }
  32. // This template matches directedS and bidirectionalS.
  33. template <class Graph>
  34. inline typename graph_traits<Graph>::degree_size_type
  35. count_edges(const Graph& g,
  36. typename graph_traits<Graph>::vertex_descriptor u,
  37. typename graph_traits<Graph>::vertex_descriptor v,
  38. directed_tag)
  39. {
  40. BOOST_CONCEPT_ASSERT(( AdjacencyMatrixConcept<Graph> ));
  41. return (lookup_edge(u, v, g).second ? 1 : 0) +
  42. (lookup_edge(v, u, g).second ? 1 : 0);
  43. }
  44. // This template matches undirectedS
  45. template <class Graph>
  46. inline typename graph_traits<Graph>::degree_size_type
  47. count_edges(const Graph& g,
  48. typename graph_traits<Graph>::vertex_descriptor u,
  49. typename graph_traits<Graph>::vertex_descriptor v,
  50. undirected_tag)
  51. {
  52. BOOST_CONCEPT_ASSERT(( AdjacencyMatrixConcept<Graph> ));
  53. return lookup_edge(u, v, g).second ? 1 : 0;
  54. }
  55. }
  56. template <typename Graph, typename Vertex>
  57. inline typename graph_traits<Graph>::degree_size_type
  58. num_paths_through_vertex(const Graph& g, Vertex v)
  59. {
  60. BOOST_CONCEPT_ASSERT(( AdjacencyGraphConcept<Graph> ));
  61. typedef typename graph_traits<Graph>::directed_category Directed;
  62. typedef typename graph_traits<Graph>::adjacency_iterator AdjacencyIterator;
  63. // TODO: There should actually be a set of neighborhood functions
  64. // for things like this (num_neighbors() would be great).
  65. AdjacencyIterator i, end;
  66. boost::tie(i, end) = adjacent_vertices(v, g);
  67. std::size_t k = std::distance(i, end);
  68. return detail::possible_edges(g, k, Directed());
  69. }
  70. template <typename Graph, typename Vertex>
  71. inline typename graph_traits<Graph>::degree_size_type
  72. num_triangles_on_vertex(const Graph& g, Vertex v)
  73. {
  74. BOOST_CONCEPT_ASSERT(( IncidenceGraphConcept<Graph> ));
  75. BOOST_CONCEPT_ASSERT(( AdjacencyGraphConcept<Graph> ));
  76. typedef typename graph_traits<Graph>::degree_size_type Degree;
  77. typedef typename graph_traits<Graph>::directed_category Directed;
  78. typedef typename graph_traits<Graph>::adjacency_iterator AdjacencyIterator;
  79. // TODO: I might be able to reduce the requirement from adjacency graph
  80. // to incidence graph by using out edges.
  81. Degree count(0);
  82. AdjacencyIterator i, j, end;
  83. for(boost::tie(i, end) = adjacent_vertices(v, g); i != end; ++i) {
  84. for(j = boost::next(i); j != end; ++j) {
  85. count += detail::count_edges(g, *i, *j, Directed());
  86. }
  87. }
  88. return count;
  89. } /* namespace detail */
  90. template <typename T, typename Graph, typename Vertex>
  91. inline T
  92. clustering_coefficient(const Graph& g, Vertex v)
  93. {
  94. T zero(0);
  95. T routes = T(num_paths_through_vertex(g, v));
  96. return (routes > zero) ?
  97. T(num_triangles_on_vertex(g, v)) / routes : zero;
  98. }
  99. template <typename Graph, typename Vertex>
  100. inline double
  101. clustering_coefficient(const Graph& g, Vertex v)
  102. { return clustering_coefficient<double>(g, v); }
  103. template <typename Graph, typename ClusteringMap>
  104. inline typename property_traits<ClusteringMap>::value_type
  105. all_clustering_coefficients(const Graph& g, ClusteringMap cm)
  106. {
  107. BOOST_CONCEPT_ASSERT(( VertexListGraphConcept<Graph> ));
  108. typedef typename graph_traits<Graph>::vertex_descriptor Vertex;
  109. typedef typename graph_traits<Graph>::vertex_iterator VertexIterator;
  110. BOOST_CONCEPT_ASSERT(( WritablePropertyMapConcept<ClusteringMap,Vertex> ));
  111. typedef typename property_traits<ClusteringMap>::value_type Coefficient;
  112. Coefficient sum(0);
  113. VertexIterator i, end;
  114. for(boost::tie(i, end) = vertices(g); i != end; ++i) {
  115. Coefficient cc = clustering_coefficient<Coefficient>(g, *i);
  116. put(cm, *i, cc);
  117. sum += cc;
  118. }
  119. return sum / Coefficient(num_vertices(g));
  120. }
  121. template <typename Graph, typename ClusteringMap>
  122. inline typename property_traits<ClusteringMap>::value_type
  123. mean_clustering_coefficient(const Graph& g, ClusteringMap cm)
  124. {
  125. BOOST_CONCEPT_ASSERT(( VertexListGraphConcept<Graph> ));
  126. typedef typename graph_traits<Graph>::vertex_descriptor Vertex;
  127. typedef typename graph_traits<Graph>::vertex_iterator VertexIterator;
  128. BOOST_CONCEPT_ASSERT(( ReadablePropertyMapConcept<ClusteringMap,Vertex> ));
  129. typedef typename property_traits<ClusteringMap>::value_type Coefficient;
  130. Coefficient cc(0);
  131. VertexIterator i, end;
  132. for(boost::tie(i, end) = vertices(g); i != end; ++i) {
  133. cc += get(cm, *i);
  134. }
  135. return cc / Coefficient(num_vertices(g));
  136. }
  137. } /* namespace boost */
  138. #endif