/** * 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 computes the betweenness of all the nodes of a graph, * using Brandes' algorithm, and counting all the shortest paths * originating from a set of nodes (potentially the whole set of * vertices). * * References: * U. Brandes. "A Faster Algorithm for Betweenness * Centrality". J. Math. Sociol. 25 (2001), 163-177. * */ #include #include #include #include #include "utils.h" void usage(char *argv[]){ printf("********************************************************************\n" "** **\n" "** -*- betweenness -*- **\n" "** **\n" "** Compute the betweenness of all the nodes and edges of a **\n" "** network due to the shortest paths originating from a set **\n" "** of initial nodes. The set can be either a sequence of **\n" "** nodes (if the second argument is 'SEQ') or a random sample **\n" "** from the set of all the nodes (if it is 'RND'). **\n" "** **\n" "** The input file is an edge-list (use '-' to read from STDIN). **\n" "** **\n" "** With 'SEQ': **\n" "** If is not specified, computes the betweenness **\n" "** using shortest paths from *all* the nodes (WARNING: This can **\n" "** be slow for large graphs!). If is not specified, **\n" "** use shortest paths from all the nodes between **\n" "** and the node with the largest label. **\n" "** **\n" "** With 'RND': **\n" "** Compute the betweenness based on the shortest paths from **\n" "** nodes sampled uniformly at random. **\n" "** **\n" "** When called with just , use all the nodes. **\n" "** **\n" "** The betweenness of all the nodes is printed on standard **\n" "** output (STDOUT), while the edge betweenness is printed on **\n" "** standard error (STDERR) **\n" "** **\n" "********************************************************************\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" " (c) Vincenzo Nicosia 2009-2017 (v.nicosia@qmul.ac.uk)\n\n"); printf("Usage: %s [SEQ []]\n" , argv[0]); printf("Usage: %s [RND ]\n" , argv[0]); } /* * Add a node the a list of predecessors */ void add_predecessor(unsigned int **pred, unsigned int k){ (*pred)[0] += 1; *pred = realloc(*pred, ((*pred)[0] + 1) * sizeof(unsigned int)); (*pred)[ (*pred)[0] ] = k; } /* * * Compute node and edge betweenness, based on shortest paths * originating on the "num" nodes specified in "nlist". "edge_bet" * should be an appropriately allocated (and initialised to zero!!!!) * vector of length equal to J_slap, and will contain the values of * edge betweenness. * */ double* compute_bet_dependency(unsigned int N, unsigned int *J_slap, unsigned int *r_slap, unsigned int *nlist, unsigned int num, double *edge_bet){ int i, j, k, w, idx, cur_node, m; unsigned int *marked, **preds, *dist, *nj; double *delta, *cB, val; unsigned int d; unsigned int n, nd, ndp; unsigned int edge_pos; dist = malloc(N * sizeof(unsigned int)); marked = malloc(N * sizeof(unsigned int)); preds = malloc(N * sizeof(unsigned int *)); nj = malloc(N * sizeof(unsigned int)); delta = malloc(N * sizeof(double)); cB = malloc(N * sizeof(double)); for (i=0; i 0){ for(i = n; i< n+nd; i ++){ cur_node = marked[i]; for (k=r_slap[cur_node]; k=1; k--){ w = marked[k]; for (idx=1; idx <= preds[w][0]; idx ++ ){ i = preds[w][idx]; val = 1.0 * nj[i] / nj[w] * (1 + delta[w]); delta[i] += val; /* Now we should update the betweenness of the edge (i,w) in the appropriate position of the vector edge_bet*/ find_neigh_in_Jslap(J_slap, r_slap, N, i, w, &edge_pos); edge_bet[edge_pos] += val; find_neigh_in_Jslap(J_slap, r_slap, N, w, i, &edge_pos); edge_bet[edge_pos] += val; } cB[w] += delta[w]; } } free(dist); free(marked); for (i=0; i 3){ if(!my_strcasecmp(argv[2], "SEQ")){ n_start = atoi(argv[3]); if (n_start > N-1) n_start = 0; if (argc > 4){ n_end = atoi(argv[4]); } else{ n_end = N-1; } num = n_end - n_start + 1; } else if (!my_strcasecmp(argv[2], "RND")){ num = atoi(argv[3]); n_start = 0; n_end = num-1; if (num > N || num < 1) num = N; shuffle_vector(nlist, N); } } sort_neighbours(J_slap, r_slap, N); edge_bet = malloc(K * sizeof(double)); memset(edge_bet, 0, K * sizeof(double)); cB = compute_bet_dependency(N, J_slap, r_slap, nlist+n_start, num, edge_bet); dump_cB(cB, N); dump_edge_bet(J_slap, r_slap, N, edge_bet, stderr); free(cB); free(J_slap); free(r_slap); free(edge_bet); free(nlist); }