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