/**
* This program is free software: you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see
* .
*
* (c) Vincenzo Nicosia 2009-2017 --
*
* This file is part of NetBunch, a package for complex network
* analysis and modelling. For more information please visit:
*
* http://www.complex-networks.net/
*
* If you use this software, please add a reference to
*
* V. Latora, V. Nicosia, G. Russo
* "Complex Networks: Principles, Methods and Applications"
* Cambridge University Press (2017)
* ISBN: 9781107103184
*
***********************************************************************
*
* This program finds the communities in a graph using the greedy
* modularity optimisation algorithm proposed by Clauset, Newman, and
* Moore.
*
* References:
*
* [1] A. Clauset, M. E. J. Newman, and C. Moore. "Finding community
* structure in very large networks". Phys. Rev. E 70 (2004),
* 066111.
*
*/
#include
#include
#include
#include
#include
#include "utils.h"
#include "cnm_bst_pq.h"
#include "dset.h"
void usage(char *argv[]){
printf("********************************************************************\n"
"** **\n"
"** -*- cnm -*- **\n"
"** **\n"
"** Find the communities of the input graph 'graph_in' using **\n"
"** the greedy modularity optimisation algorithm proposed by **\n"
"** Clauset, Newman, and Moore. **\n"
"** **\n"
"** The input file 'graph_in' is an edge-list. **\n"
"** If 'graph_in' is equal to '-' (dash), read the file from **\n"
"** the standard input (STDIN). **\n"
"** **\n"
"** The program prints on STDOUT the partition corresponding **\n"
"** to the largest value of modularity, in the format: **\n"
"** **\n"
"** node_1 comm_1 **\n"
"** node_2 comm_2 **\n"
"** node_3 comm_3 **\n"
"** ..... **\n"
"** **\n"
"** where 'comm_1' is the community to which 'node_1' belongs. **\n"
"** **\n"
"** The program prints on STDERR the number of communities and **\n"
"** the value of modularity obtained at each step, in the **\n"
"** format: **\n"
"** **\n"
"** ## nc: NUM_COMM Q_max: Q_MAX **\n"
"** nc_1 Q_1 **\n"
"** nc_2 Q_2 **\n"
"** nc_3 Q_3 **\n"
"** ... **\n"
"** **\n"
"** where 'nc_1', 'nc_2', 'nc_3', etc. is the number of **\n"
"** communities at the 1st, 2nd, 3rd step etc., and 'Q_1', **\n"
"** 'Q_2', 'Q_3', etc. are the value of the modularity **\n"
"** function of the corresponding node partition. The first **\n"
"** output line reports the number of communities NUM_COMM **\n"
"** and corresponding value of modularity Q_MAX of the best **\n"
"** partition found. **\n"
"** **\n"
"********************************************************************\n"
" This is Free Software - You can use and distribute it under \n"
" the terms of the GNU General Public License, version 3 or later\n\n"
" Please visit http://www.complex-networks.net for more information\n\n"
" (c) Vincenzo Nicosia 2009-2017 (v.nicosia@qmul.ac.uk)\n"
"********************************************************************\n\n"
);
printf("Usage: %s \n", argv[0]);
exit(1);
}
/* shuffle a vector in-place */
void shuffle_vector_ptr(unsigned int **v, unsigned int N){
int i, pos;
void *tmp;
for(i=N-1; i>=0; i--){
pos = rand() % N;
if (pos != i){
tmp = v[i];
v[i] = v[pos];
v[pos] = tmp;
}
}
}
/* initialise BST-related functions */
void set_bst_funs(ilfunc_t *f){
f->alloc = cnm_bst_alloc;
f->dealloc = cnm_bst_dealloc;
f->compare = cnm_bst_compare;
f->print = cnm_bst_print;
}
/* Initialise priority-queue-related functions */
void set_pq_funs(gen_pqueue_func_t *f){
f->compare = cnm_pq_compare;
f->alloc_vector = cnm_pq_alloc_vector;
f->dealloc_vector = cnm_pq_dealloc_vector;
f->alloc_key = cnm_pq_alloc_key;
f->copy_key = cnm_pq_copy_key;
f->print_elem = cnm_pq_print_elem;
f->set_key = cnm_pq_set_key;
f->compare_to_key = cnm_pq_compare_to_key;
}
void init_bsts(unsigned int *J_slap, unsigned int *r_slap, unsigned int N,
bst_pq_t *b, bst_pq_t *H, gen_stack_t *node_cache){
unsigned int i, j, n, m, deg_i, deg_j;
//struct_key_t dQ;
double dQ;
//struct_neigh_t ith, jth;
unsigned int K;
node_t *node_ptr;
ilfunc_t bst_funs;
gen_pqueue_func_t pq_funs;
unsigned int *nodes;
set_bst_funs(&bst_funs);
set_pq_funs(&pq_funs);
K = r_slap[N]/2;
*H = bst_pq_create(&bst_funs, &pq_funs, MAX_QUEUE, N, node_cache);
nodes = malloc(N * sizeof(unsigned int));
for (i=0; iv, (b[i]->last + 1) * sizeof(node_t *));
num_neighs = b[i]->last + 1;
shuffle_vector_ptr((void*)neighs, num_neighs);
for(m=0; mv, (b[j]->last + 1) * sizeof(node_t *));
num_neighs = b[j]->last + 1;
shuffle_vector_ptr((void*)neighs, num_neighs);
for(m=0; mQ_max){
Q_max = Q;
N_max = N-l-1;
}
}
fprintf(stdout, "### nc: %d Q_max: %g\n", N_max, Q_max);
free(a);
free(neighs);
return comms;
}
void dump_communities(dset_t *comms, unsigned int N){
int i;
for(i=0; i