/** * 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 * *********************************************************************** * * Implementation of a data structure to maintain a cumulative * distribution and sample values from it. Used in all the models of * growing graphs based on some kind of preferential attachment. * */ #include #include #include "cum_distr.h" cum_distr_t* cum_distr_init(unsigned int N){ cum_distr_t* d = NULL; d = malloc(sizeof(cum_distr_t)); d->N = N; d->num = 0; d->sum = 0; d->v = malloc((d->N) * sizeof(idval_t)); return d; } int cum_distr_add(cum_distr_t *d, unsigned int id, long double val){ idval_t *tmp; if (d->num == d->N){ //fprintf(stderr, "+++++++++ REALLOC ++++++++++\n"); d->N += 10; tmp = realloc(d->v, d->N * sizeof(idval_t)); if (!tmp){ d->N -= 10; fprintf(stderr, "#### Error!!! Unable to add more values to the cumulative distribution!!!\n"); return -1; } else{ d->v = tmp; } } d->sum += val; d->v[d->num].id = id; d->v[d->num].value = d->sum; d->num += 1; //fprintf(stderr, ">>>>>> update >>>>>> d->num: %d\n", d->num); return 0; } /* sample an id from the cumulative distribution, by means of binary search */ unsigned int cum_distr_sample(cum_distr_t *d){ long double val; unsigned int high, low, cur; val = d->sum * rand() / RAND_MAX; cur = d->num / 2; low = 0; high = d->num - 1; while (low < high){ if (d->v[cur].value < val){ low = cur+1; } else if(d->v[cur].value >= val){ high = cur; } cur = (high + low) / 2; } return d->v[cur].id; } void cum_distr_dump(cum_distr_t *d){ unsigned int i; for(i=0; i< d->num; i++){ fprintf(stderr, "(%d, %g)\n", d->v[i].id, (double)(d->v[i].value)); } } void cum_distr_destroy(cum_distr_t *d){ free(d->v); free(d); }