Commit 0b5d7f7d authored by Raghvendra Mall's avatar Raghvendra Mall

First message

parents
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
#!/bin/bash
CC=g++
CFLAGS= -ansi -O5 -Wall
LDFLAGS= -ansi -lm -Wall
EXEC=community convert hierarchy
OBJ1= graph_binary.o community.o
OBJ2= graph.o
all: $(EXEC)
community : $(OBJ1) main_community.o
$(CC) -o $@ $^ $(LDFLAGS)
convert : $(OBJ2) main_convert.o
$(CC) -o $@ $^ $(LDFLAGS)
hierarchy : main_hierarchy.o
$(CC) -o $@ $^ $(LDFLAGS)
##########################################
# Generic rules
##########################################
%.o: %.cpp %.h
$(CC) -o $@ -c $< $(CFLAGS)
%.o: %.cpp
$(CC) -o $@ -c $< $(CFLAGS)
clean:
rm -f *.o *~ $(EXEC)
// 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;
}
// File: community.h
// -- community detection header 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
#ifndef COMMUNITY_H
#define COMMUNITY_H
#include <stdlib.h>
#include <stdio.h>
#include <iostream>
#include <iomanip>
#include <fstream>
#include <vector>
#include <map>
#include "graph_binary.h"
using namespace std;
class Community {
public:
vector<double> neigh_weight;
vector<unsigned int> neigh_pos;
unsigned int neigh_last;
Graph g; // network to compute communities for
int size; // nummber of nodes in the network and size of all vectors
vector<int> n2c; // community to which each node belongs
vector<double> in,tot; // used to compute the modularity participation of each community
// number of pass for one level computation
// if -1, compute as many pass as needed to increase modularity
int nb_pass;
// a new pass is computed if the last one has generated an increase
// greater than min_modularity
// if 0. even a minor increase is enough to go for one more pass
double min_modularity;
// constructors:
// reads graph from file using graph constructor
// type defined the weighted/unweighted status of the graph file
Community (char *filename, char *filename_w, int type, int nb_pass, double min_modularity);
// copy graph
Community (Graph g, int nb_pass, double min_modularity);
// initiliazes the partition with something else than all nodes alone
void init_partition(char *filename_part);
// display the community of each node
void display();
// remove the node from its current community with which it has dnodecomm links
inline void remove(int node, int comm, double dnodecomm);
// insert the node in comm with which it shares dnodecomm links
inline void insert(int node, int comm, double dnodecomm);
// compute the gain of modularity if node where inserted in comm
// given that node has dnodecomm links to comm. The formula is:
// [(In(comm)+2d(node,comm))/2m - ((tot(comm)+deg(node))/2m)^2]-
// [In(comm)/2m - (tot(comm)/2m)^2 - (deg(node)/2m)^2]
// where In(comm) = number of half-links strictly inside comm
// Tot(comm) = number of half-links inside or outside comm (sum(degrees))
// d(node,com) = number of links from node to comm
// deg(node) = node degree
// m = number of links
inline double modularity_gain(int node, int comm, double dnodecomm, double w_degree);
// compute the set of neighboring communities of node
// for each community, gives the number of links from node to comm
void neigh_comm(unsigned int node);
// compute the modularity of the current partition
double modularity();
// displays the graph of communities as computed by one_level
void partition2graph();
// displays the current partition (with communities renumbered from 0 to k-1)
void display_partition();
// generates the binary graph of communities as computed by one_level
Graph partition2graph_binary();
// compute communities of the graph for one level
// return true if some nodes have been moved
bool one_level();
};
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;
}
inline double
Community::modularity_gain(int node, int comm, double dnodecomm, double w_degree) {
assert(node>=0 && node<size);
double totc = (double)tot[comm];
double degc = (double)w_degree;
double m2 = (double)g.total_weight;
double dnc = (double)dnodecomm;
return (dnc - totc*degc/m2);
}
#endif // COMMUNITY_H
// File: graph.cpp
// -- simple graph handling 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 "graph.h"
using namespace std;
Graph::Graph(char *filename, int type) {
ifstream finput;
finput.open(filename,fstream::in);
int nb_links=0;
while (!finput.eof()) {
unsigned int src, dest;
double weight=1.;
if (type==WEIGHTED) {
finput >> src >> dest >> weight;
} else {
finput >> src >> dest;
}
if (finput) {
if (links.size()<=max(src,dest)+1) {
links.resize(max(src,dest)+1);
}
links[src].push_back(make_pair(dest,weight));
if (src!=dest)
links[dest].push_back(make_pair(src,weight));
nb_links++;
}
}
finput.close();
}
void
Graph::renumber(int type) {
vector<int> linked(links.size(),-1);
vector<int> renum(links.size(),-1);
int nb=0;
for (unsigned int i=0 ; i<links.size() ; i++) {
for (unsigned int j=0 ; j<links[i].size() ; j++) {
linked[i]=1;
linked[links[i][j].first]=1;
}
}
for (unsigned int i=0 ; i<links.size() ; i++) {
if (linked[i]==1)
renum[i]=nb++;
}
for (unsigned int i=0 ; i<links.size() ; i++) {
if (linked[i]==1) {
for (unsigned int j=0 ; j<links[i].size() ; j++) {
links[i][j].first = renum[links[i][j].first];
}