/* * This file is part of MAMMULT: Metrics And Models for Multilayer Networks * * 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 . */ /** * * NiBiLaB model (Nicosia, Bianconi, Latora, Barthelemy) of multiplex * linear preferential attachment * * Nodes arrive sequentially on the first layer, but their replicas on * the second layer arrive at uniformly distributed times. * */ #include #include #include #include #include typedef struct{ int size; int N; int *val; } int_array_t; typedef struct{ int K; int N; int size; int *i; int *j; int *degrees; int *arrived; double *cumul; int_array_t *times; } ij_net_t; typedef struct{ double a; double b; double c; double d; } coupling_t; typedef struct{ int N; double x_min; double *distr; double gamma; } distr_t; int init_network(ij_net_t *G, int m0){ int n; for(n=0; ni[n] = n; G->j[n] = n+1 % m0; G->degrees[n] = 2; G->arrived[n] = n; } G->K = m0; G->N = m0; return n; } void dump_network(ij_net_t *G){ int i; for(i=0; i< G->K; i ++){ printf("%d %d\n",G->i[i], G->j[i]); } } void dump_network_to_file(ij_net_t *G, char *fname){ FILE *f; int i; f = fopen(fname, "w+"); for(i=0; i< G->K; i ++){ fprintf(f, "%d %d\n",G->i[i], G->j[i]); } fclose(f); } double f1(double v1, double v2, coupling_t *matr){ return v1 * matr->a + v2 * matr->b; } double f2(double v1, double v2, coupling_t *matr){ return v1 * matr->c + v2 * matr->d; } void compute_cumul(ij_net_t *G1, ij_net_t *G2, coupling_t *matr){ int i; double val; G1->cumul[0] = f1(G1->degrees[ G1->arrived[0] ], G2->degrees[ G1->arrived[0] ], matr) ; G2->cumul[0] = f2(G1->degrees[ G2->arrived[0] ], G2->degrees[ G2->arrived[0] ], matr) ; for(i=1; iN; i ++){ val = f1(G1->degrees[ G1->arrived[i] ], G2->degrees[ G1->arrived[i] ],matr) ; G1->cumul[i] = G1->cumul[i-1] + val; } for(i=1; iN; i ++){ val = f2(G1->degrees[ G2->arrived[i] ], G2->degrees[ G2->arrived[i] ], matr) ; G2->cumul[i] = G2->cumul[i-1] + val; } } void dump_cumul(ij_net_t *G){ int i; for (i=0; iN; i ++){ printf("%d %2.6f\n", G->times[i], G->cumul[i]); } } int select_neigh_cumul(ij_net_t *G){ double r; int j; r = (rand() * 1.0 / RAND_MAX) * G->cumul[ G->N-1 ]; //printf(" r: %f ", r); j = 0; /* Change with a binary search ???!?!?!?! */ while (r > G->cumul[j]){ j ++; } return G->arrived[j]; } int already_neighbour(ij_net_t *G, int j, int d, int offset){ int i; for(i=G-> K + offset; i< G->K + offset + j; i ++){ if (G->j[i] == d) return 1; } return 0; } void sample_edges(ij_net_t *G, int n, int m, int offset){ int j; int d; //printf("----"); for(j=0; ji[G->K + offset + j] = n; d = select_neigh_cumul(G); while(already_neighbour(G, j, d, offset)){ d = select_neigh_cumul(G); } //printf(" link %d--%d\n", n, d); G->j[G->K + offset + j] = d; G->degrees[d] += 1; } //printf("\n"); } void create_distr(double *v, double gamma, int x_min, int x_max){ int n, i; double sum, new_sum; n = x_max-x_min + 1; sum = 0; for(i=0; i v[i]) i++; return i; } int sample_power_law(distr_t *d){ double xi, q, val; int k; while(1){ xi = rand()* 1.0 / RAND_MAX; k = find_degree(d->distr, d->N, xi); val = rand()*1.0/RAND_MAX; q = d->x_min + xi * d->N; q = q / (floor(q) + 1); q = pow(q, d->gamma); if (val <= q){ return k; } } } int grow_multi_net_delay(ij_net_t *G1, ij_net_t *G2, int N, int m, int m0, coupling_t *matr){ int i, j; int d; int i2; i2 = m0; for(i=m0; iarrived[i] = i; sample_edges(G1, G1->arrived[i], m, 0); G1->degrees[G1->arrived[i]] += m; for (j=0; j < G2->times[i].N; j++){ G2->arrived[i2] = G2->times[i].val[j]; //printf("%d\n", G2->arrived[i2]); sample_edges(G2, G2->arrived[i2], m, m *j); G2->degrees[G2->arrived[i2]] += m; i2 += 1; } G1->N += 1; G1->K += m; G2->N += G2->times[i].N; G2->K += m * G2->times[i].N; } return 0; } void init_structure(ij_net_t *G, int N){ int i; G->i = malloc(G->size * sizeof(int)); G->j = malloc(G->size * sizeof(int)); G->degrees = malloc(N * sizeof(int)); G->arrived = malloc(N * sizeof(int)); G->cumul = malloc(N * sizeof(double)); G->times = malloc(N * sizeof(int_array_t)); for (i=0; itimes[i].size = 5; G->times[i].N = 0; G->times[i].val = malloc(5 * sizeof(int)); } memset(G->degrees, 0, N*sizeof(int)); G->N = 0; } void add_node_to_time(ij_net_t *G, int node, int t){ if (G->times[t].size == G->times[t].N){ G->times[t].size += 5; G->times[t].val = realloc(G->times[t].val, G->times[t].size); } G->times[t].val[G->times[t].N] = node; G->times[t].N += 1; } void init_times_delta(ij_net_t *G, int N){ int i; for (i=0; itimes[i].N; j++){ printf(" %d", G->times[i].val[j]); } printf("\n"); } } int main(int argc, char *argv[]){ ij_net_t G1, G2; int N, m, m0, k_max; coupling_t matr; double gamma; distr_t delay_distr; char str[256]; if (argc < 9){ printf("Usage: %s \n", argv[0]); exit(1); } srand(time(NULL)); /* Diagonal coupling */ matr.a = atof(argv[5]); matr.b = atof(argv[6]); matr.c = atof(argv[7]); matr.d = atof(argv[8]); N = atoi(argv[1]); m = atoi(argv[2]); m0 = atoi(argv[3]); G1.size = (N+m0) * m; G2.size = (N+m0) * m; init_structure(&G1, N); init_structure(&G2, N); G1.K = init_network(&G1, m0); G2.K = init_network(&G2, m0); init_times_random(&G2, N); //dump_times(&G2, N); fprintf(stderr, "Init finished!\n"); grow_multi_net_delay(&G1, &G2, N, m, m0, &matr); //printf("### G1\n"); sprintf(str, "%s_layer1.txt", argv[4]); dump_network_to_file(&G1, str); //printf("### G2\n"); sprintf(str, "%s_layer2.txt", argv[4]); dump_network_to_file(&G2, str); /* dump_network_to_file(S, S_num, argv[4]); */ /* printf("Network dumped!\n"); */ /* k_max = degree_distr(S, S_num, &distr); */ /* printf("k_max is: %d\n", k_max); */ /* dump_distr_to_file(distr, k_max, argv[5]); */ }