Mercurial > repos > petr-novak > repeatrxplorer
diff louvain/community.cpp @ 0:1d1b9e1b2e2f draft
Uploaded
author | petr-novak |
---|---|
date | Thu, 19 Dec 2019 10:24:45 -0500 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/louvain/community.cpp Thu Dec 19 10:24:45 2019 -0500 @@ -0,0 +1,341 @@ +// File: community.h +// -- community detection source file +//----------------------------------------------------------------------------- +// Community detection +// Based on the article "Fast unfolding of community hierarchies in large networks" +// Copyright (C) 2008 V. Blondel, J.-L. Guillaume, R. Lambiotte, E. Lefebvre +// +// This program must not be distributed without agreement of the above mentionned authors. +//----------------------------------------------------------------------------- +// Author : E. Lefebvre, adapted by J.-L. Guillaume +// Email : jean-loup.guillaume@lip6.fr +// Location : Paris, France +// Time : February 2008 +//----------------------------------------------------------------------------- +// see readme.txt for more details + +#include "community.h" + +using namespace std; + +Community::Community(char * filename, char * filename_w, int type, int nbp, double minm) { + g = Graph(filename, filename_w, type); + size = g.nb_nodes; + + neigh_weight.resize(size,-1); + neigh_pos.resize(size); + neigh_last=0; + + n2c.resize(size); + in.resize(size); + tot.resize(size); + + for (int i=0 ; i<size ; i++) { + n2c[i] = i; + tot[i] = g.weighted_degree(i); + in[i] = g.nb_selfloops(i); + } + + nb_pass = nbp; + min_modularity = minm; +} + +Community::Community(Graph gc, int nbp, double minm) { + g = gc; + size = g.nb_nodes; + + neigh_weight.resize(size,-1); + neigh_pos.resize(size); + neigh_last=0; + + n2c.resize(size); + in.resize(size); + tot.resize(size); + + for (int i=0 ; i<size ; i++) { + n2c[i] = i; + in[i] = g.nb_selfloops(i); + tot[i] = g.weighted_degree(i); + } + + nb_pass = nbp; + min_modularity = minm; +} + +void +Community::init_partition(char * filename) { + ifstream finput; + finput.open(filename,fstream::in); + + // read partition + while (!finput.eof()) { + unsigned int node, comm; + finput >> node >> comm; + + if (finput) { + int old_comm = n2c[node]; + neigh_comm(node); + + remove(node, old_comm, neigh_weight[old_comm]); + + unsigned int i=0; + for ( i=0 ; i<neigh_last ; i++) { + unsigned int best_comm = neigh_pos[i]; + float best_nblinks = neigh_weight[neigh_pos[i]]; + if (best_comm==comm) { + insert(node, best_comm, best_nblinks); + break; + } + } + if (i==neigh_last) + insert(node, comm, 0); + } + } + finput.close(); +} + +// inline void +// Community::remove(int node, int comm, double dnodecomm) { +// assert(node>=0 && node<size); + +// tot[comm] -= g.weighted_degree(node); +// in[comm] -= 2*dnodecomm + g.nb_selfloops(node); +// n2c[node] = -1; +// } + +// inline void +// Community::insert(int node, int comm, double dnodecomm) { +// assert(node>=0 && node<size); + +// tot[comm] += g.weighted_degree(node); +// in[comm] += 2*dnodecomm + g.nb_selfloops(node); +// n2c[node]=comm; +// } + +void +Community::display() { + for (int i=0 ; i<size ; i++) + cerr << " " << i << "/" << n2c[i] << "/" << in[i] << "/" << tot[i] ; + cerr << endl; +} + + +double +Community::modularity() { + double q = 0.; + double m2 = (double)g.total_weight; + + for (int i=0 ; i<size ; i++) { + if (tot[i]>0) + q += (double)in[i]/m2 - ((double)tot[i]/m2)*((double)tot[i]/m2); + } + + return q; +} + +void +Community::neigh_comm(unsigned int node) { + for (unsigned int i=0 ; i<neigh_last ; i++) + neigh_weight[neigh_pos[i]]=-1; + neigh_last=0; + + pair<vector<unsigned int>::iterator, vector<float>::iterator> p = g.neighbors(node); + + unsigned int deg = g.nb_neighbors(node); + + neigh_pos[0]=n2c[node]; + neigh_weight[neigh_pos[0]]=0; + neigh_last=1; + + for (unsigned int i=0 ; i<deg ; i++) { + unsigned int neigh = *(p.first+i); + unsigned int neigh_comm = n2c[neigh]; + double neigh_w = (g.weights.size()==0)?1.:*(p.second+i); + + if (neigh!=node) { + if (neigh_weight[neigh_comm]==-1) { + neigh_weight[neigh_comm]=0.; + neigh_pos[neigh_last++]=neigh_comm; + } + neigh_weight[neigh_comm]+=neigh_w; + } + } +} + +void +Community::partition2graph() { + vector<int> renumber(size, -1); + for (int node=0 ; node<size ; node++) { + renumber[n2c[node]]++; + } + + int final=0; + for (int i=0 ; i<size ; i++) + if (renumber[i]!=-1) + renumber[i]=final++; + + + for (int i=0 ; i<size ; i++) { + pair<vector<unsigned int>::iterator, vector<float>::iterator> p = g.neighbors(i); + + int deg = g.nb_neighbors(i); + for (int j=0 ; j<deg ; j++) { + int neigh = *(p.first+j); + cout << renumber[n2c[i]] << " " << renumber[n2c[neigh]] << endl; + } + } +} + +void +Community::display_partition() { + vector<int> renumber(size, -1); + for (int node=0 ; node<size ; node++) { + renumber[n2c[node]]++; + } + + int final=0; + for (int i=0 ; i<size ; i++) + if (renumber[i]!=-1) + renumber[i]=final++; + + for (int i=0 ; i<size ; i++) + cout << i << " " << renumber[n2c[i]] << endl; +} + + +Graph +Community::partition2graph_binary() { + // Renumber communities + vector<int> renumber(size, -1); + for (int node=0 ; node<size ; node++) { + renumber[n2c[node]]++; + } + + int final=0; + for (int i=0 ; i<size ; i++) + if (renumber[i]!=-1) + renumber[i]=final++; + + // Compute communities + vector<vector<int> > comm_nodes(final); + for (int node=0 ; node<size ; node++) { + comm_nodes[renumber[n2c[node]]].push_back(node); + } + + // Compute weighted graph + Graph g2; + g2.nb_nodes = comm_nodes.size(); + g2.degrees.resize(comm_nodes.size()); + + int comm_deg = comm_nodes.size(); + for (int comm=0 ; comm<comm_deg ; comm++) { + map<int,float> m; + map<int,float>::iterator it; + + int comm_size = comm_nodes[comm].size(); + for (int node=0 ; node<comm_size ; node++) { + pair<vector<unsigned int>::iterator, vector<float>::iterator> p = g.neighbors(comm_nodes[comm][node]); + int deg = g.nb_neighbors(comm_nodes[comm][node]); + for (int i=0 ; i<deg ; i++) { + int neigh = *(p.first+i); + int neigh_comm = renumber[n2c[neigh]]; + double neigh_weight = (g.weights.size()==0)?1.:*(p.second+i); + + it = m.find(neigh_comm); + if (it==m.end()) + m.insert(make_pair(neigh_comm, neigh_weight)); + else + it->second+=neigh_weight; + } + } + g2.degrees[comm]=(comm==0)?m.size():g2.degrees[comm-1]+m.size(); + g2.nb_links+=m.size(); + + + for (it = m.begin() ; it!=m.end() ; it++) { + g2.total_weight += it->second; + g2.links.push_back(it->first); + g2.weights.push_back(it->second); + } + } + + return g2; +} + + +bool +Community::one_level() { + bool improvement=false ; + int nb_moves; + int nb_pass_done = 0; + double new_mod = modularity(); + double cur_mod = new_mod; + + vector<int> random_order(size); + for (int i=0 ; i<size ; i++) + random_order[i]=i; + for (int i=0 ; i<size-1 ; i++) { + int rand_pos = rand()%(size-i)+i; + int tmp = random_order[i]; + random_order[i] = random_order[rand_pos]; + random_order[rand_pos] = tmp; + } + + // repeat while + // there is an improvement of modularity + // or there is an improvement of modularity greater than a given epsilon + // or a predefined number of pass have been done + do { + cur_mod = new_mod; + nb_moves = 0; + nb_pass_done++; + + // for each node: remove the node from its community and insert it in the best community + for (int node_tmp=0 ; node_tmp<size ; node_tmp++) { +// int node = node_tmp; + int node = random_order[node_tmp]; + int node_comm = n2c[node]; + double w_degree = g.weighted_degree(node); + + // computation of all neighboring communities of current node + neigh_comm(node); + // remove node from its current community + remove(node, node_comm, neigh_weight[node_comm]); + + // compute the nearest community for node + // default choice for future insertion is the former community + int best_comm = node_comm; + double best_nblinks = 0.; + double best_increase = 0.; + for (unsigned int i=0 ; i<neigh_last ; i++) { + double increase = modularity_gain(node, neigh_pos[i], neigh_weight[neigh_pos[i]], w_degree); + if (increase>best_increase) { + best_comm = neigh_pos[i]; + best_nblinks = neigh_weight[neigh_pos[i]]; + best_increase = increase; + } + } + + // insert node in the nearest community + insert(node, best_comm, best_nblinks); + + if (best_comm!=node_comm) + nb_moves++; + } + + double total_tot=0; + double total_in=0; + for (unsigned int i=0 ; i<tot.size() ;i++) { + total_tot+=tot[i]; + total_in+=in[i]; + } + + new_mod = modularity(); + if (nb_moves>0) + improvement=true; + + } while (nb_moves>0 && new_mod-cur_mod>min_modularity); + + return improvement; +} +