clustering_coefficient.hpp 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  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 possible_edges(
  19. 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 possible_edges(
  27. 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 count_edges(
  35. const Graph& g, typename graph_traits< Graph >::vertex_descriptor u,
  36. typename graph_traits< Graph >::vertex_descriptor v, directed_tag)
  37. {
  38. BOOST_CONCEPT_ASSERT((AdjacencyMatrixConcept< Graph >));
  39. return (lookup_edge(u, v, g).second ? 1 : 0)
  40. + (lookup_edge(v, u, g).second ? 1 : 0);
  41. }
  42. // This template matches undirectedS
  43. template < class Graph >
  44. inline typename graph_traits< Graph >::degree_size_type count_edges(
  45. const Graph& g, typename graph_traits< Graph >::vertex_descriptor u,
  46. typename graph_traits< Graph >::vertex_descriptor v, undirected_tag)
  47. {
  48. BOOST_CONCEPT_ASSERT((AdjacencyMatrixConcept< Graph >));
  49. return lookup_edge(u, v, g).second ? 1 : 0;
  50. }
  51. }
  52. template < typename Graph, typename Vertex >
  53. inline typename graph_traits< Graph >::degree_size_type
  54. num_paths_through_vertex(const Graph& g, Vertex v)
  55. {
  56. BOOST_CONCEPT_ASSERT((AdjacencyGraphConcept< Graph >));
  57. typedef typename graph_traits< Graph >::directed_category Directed;
  58. typedef
  59. typename graph_traits< Graph >::adjacency_iterator AdjacencyIterator;
  60. // TODO: There should actually be a set of neighborhood functions
  61. // for things like this (num_neighbors() would be great).
  62. AdjacencyIterator i, end;
  63. boost::tie(i, end) = adjacent_vertices(v, g);
  64. std::size_t k = std::distance(i, end);
  65. return detail::possible_edges(g, k, Directed());
  66. }
  67. template < typename Graph, typename Vertex >
  68. inline typename graph_traits< Graph >::degree_size_type num_triangles_on_vertex(
  69. const Graph& g, Vertex v)
  70. {
  71. BOOST_CONCEPT_ASSERT((IncidenceGraphConcept< Graph >));
  72. BOOST_CONCEPT_ASSERT((AdjacencyGraphConcept< Graph >));
  73. typedef typename graph_traits< Graph >::degree_size_type Degree;
  74. typedef typename graph_traits< Graph >::directed_category Directed;
  75. typedef
  76. typename graph_traits< Graph >::adjacency_iterator AdjacencyIterator;
  77. // TODO: I might be able to reduce the requirement from adjacency graph
  78. // to incidence graph by using out edges.
  79. Degree count(0);
  80. AdjacencyIterator i, j, end;
  81. for (boost::tie(i, end) = adjacent_vertices(v, g); i != end; ++i)
  82. {
  83. for (j = boost::next(i); j != end; ++j)
  84. {
  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 clustering_coefficient(const Graph& g, Vertex v)
  92. {
  93. T zero(0);
  94. T routes = T(num_paths_through_vertex(g, v));
  95. return (routes > zero) ? T(num_triangles_on_vertex(g, v)) / routes : zero;
  96. }
  97. template < typename Graph, typename Vertex >
  98. inline double clustering_coefficient(const Graph& g, Vertex v)
  99. {
  100. return clustering_coefficient< double >(g, v);
  101. }
  102. template < typename Graph, typename ClusteringMap >
  103. inline typename property_traits< ClusteringMap >::value_type
  104. all_clustering_coefficients(const Graph& g, ClusteringMap cm)
  105. {
  106. BOOST_CONCEPT_ASSERT((VertexListGraphConcept< Graph >));
  107. typedef typename graph_traits< Graph >::vertex_descriptor Vertex;
  108. typedef typename graph_traits< Graph >::vertex_iterator VertexIterator;
  109. BOOST_CONCEPT_ASSERT((WritablePropertyMapConcept< ClusteringMap, Vertex >));
  110. typedef typename property_traits< ClusteringMap >::value_type Coefficient;
  111. Coefficient sum(0);
  112. VertexIterator i, end;
  113. for (boost::tie(i, end) = vertices(g); i != end; ++i)
  114. {
  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. {
  134. cc += get(cm, *i);
  135. }
  136. return cc / Coefficient(num_vertices(g));
  137. }
  138. } /* namespace boost */
  139. #endif