Commit 1441551e authored by Tiago Peixoto's avatar Tiago Peixoto
Browse files

Improve performance of global/local_clustering()

parent 4d7eb88e
...@@ -18,10 +18,16 @@ ...@@ -18,10 +18,16 @@
#ifndef GRAPH_CLUSTERING_HH #ifndef GRAPH_CLUSTERING_HH
#define GRAPH_CLUSTERING_HH #define GRAPH_CLUSTERING_HH
#include "config.h"
#include "tr1_include.hh" #include "tr1_include.hh"
#include TR1_HEADER(unordered_set) #include TR1_HEADER(unordered_set)
#include <boost/mpl/if.hpp> #include <boost/mpl/if.hpp>
#ifdef HAVE_SPARSEHASH
#include <dense_hash_set>
#endif
#include <ext/numeric> #include <ext/numeric>
using __gnu_cxx::power; using __gnu_cxx::power;
...@@ -29,59 +35,53 @@ namespace graph_tool ...@@ -29,59 +35,53 @@ namespace graph_tool
{ {
using namespace boost; using namespace boost;
#ifdef HAVE_SPARSEHASH
using google::dense_hash_set;
#endif
// calculates the number of triangles to which v belongs // calculates the number of triangles to which v belongs
template <class Graph> template <class Graph>
pair<int,int> pair<int,int>
get_triangles(typename graph_traits<Graph>::vertex_descriptor v, const Graph &g) get_triangles(typename graph_traits<Graph>::vertex_descriptor v, const Graph &g)
{ {
tr1::unordered_set<typename graph_traits<Graph>::vertex_descriptor> typedef typename graph_traits<Graph>::vertex_descriptor vertex_t;
neighbour_set1, neighbour_set2, neighbour_set3;
#ifdef HAVE_SPARSEHASH
typedef dense_hash_set<vertex_t> set_t;
#else
typedef unordered_set<vertex_t> set_t;
#endif
set_t neighbour_set;
#ifdef HAVE_SPARSEHASH
neighbour_set.set_empty_key(numeric_limits<vertex_t>::max());
neighbour_set.resize(out_degree(v, g));
#endif
size_t triangles = 0, k = 0; size_t triangles = 0;
typename graph_traits<Graph>::adjacency_iterator n1_begin, n1_end, n1; typename graph_traits<Graph>::adjacency_iterator n, n_end;
tie(n1_begin, n1_end) = adjacent_vertices(v, g); for (tie(n, n_end) = adjacent_vertices(v, g); n != n_end; ++n)
for (n1 = n1_begin; n1 != n1_end; ++n1)
{ {
if (*n1 == v) // no self-loops if (*n == v) // no self-loops
continue; continue;
if (neighbour_set1.find(*n1) != neighbour_set1.end()) neighbour_set.insert(*n);
continue; }
else
neighbour_set1.insert(*n1);
typename graph_traits<Graph>::adjacency_iterator n2_begin, n2_end, n2; for (tie(n, n_end) = adjacent_vertices(v, g); n != n_end; ++n)
tie(n2_begin, n2_end) = adjacent_vertices(*n1, g); {
for (n2 = n2_begin; n2 != n2_end; ++n2) typename graph_traits<Graph>::adjacency_iterator n2, n2_end;
for (tie(n2, n2_end) = adjacent_vertices(*n, g); n2 != n2_end; ++n2)
{ {
if (*n2 == *n1) // no self-loops if (*n2 == *n) // no self-loops
continue; continue;
if (neighbour_set2.find(*n2) != neighbour_set2.end()) if (neighbour_set.find(*n2) != neighbour_set.end())
continue; ++triangles;
else
neighbour_set2.insert(*n2);
typename graph_traits<Graph>::adjacency_iterator
n3_begin, n3_end, n3;
tie(n3_begin, n3_end) = adjacent_vertices(*n2, g);
for (n3 = n3_begin; n3 != n3_end; ++n3)
{
if (*n3 == *n2) // no self-loops
continue;
if (neighbour_set3.find(*n3) != neighbour_set3.end())
continue;
else
neighbour_set3.insert(*n3);
if (*n3 == v) //found a triangle
triangles++;
}
neighbour_set3.clear();
} }
neighbour_set2.clear();
k++;
} }
neighbour_set1.clear();
size_t k = out_degree(v, g);
return make_pair(triangles/2,(k*(k-1))/2); return make_pair(triangles/2,(k*(k-1))/2);
} }
...@@ -113,8 +113,7 @@ struct get_global_clustering ...@@ -113,8 +113,7 @@ struct get_global_clustering
// "jackknife" variance // "jackknife" variance
c_err = 0.0; c_err = 0.0;
double cerr = 0.0;
double cerr = 0.0;
#pragma omp parallel for default(shared) private(i,temp) \ #pragma omp parallel for default(shared) private(i,temp) \
schedule(static) if (N > 100) reduction(+:cerr) schedule(static) if (N > 100) reduction(+:cerr)
...@@ -155,10 +154,7 @@ struct set_clustering_to_property ...@@ -155,10 +154,7 @@ struct set_clustering_to_property
double(triangles.first)/triangles.second : double(triangles.first)/triangles.second :
0.0; 0.0;
#pragma omp critical clust_map[v] = c_type(clustering);
{
clust_map[v] = c_type(clustering);
}
} }
} }
......
...@@ -134,7 +134,7 @@ def local_clustering(g, prop=None, undirected=True): ...@@ -134,7 +134,7 @@ def local_clustering(g, prop=None, undirected=True):
prop = g.new_vertex_property("double") prop = g.new_vertex_property("double")
if g.is_directed() and undirected: if g.is_directed() and undirected:
g = GraphView(g, directed=False) g = GraphView(g, directed=False)
_gt.extended_clustering(g._Graph__graph, [_prop("v", g, prop)]) _gt.local_clustering(g._Graph__graph, _prop("v", g, prop))
return prop return prop
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment