/*
* 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 .
*/
/**
*
* Tune the inter-layer degree correlation function \bar{q}(k) of a
* two-layer multiplex, in order to make it as similar as possible to
* a power law with exponent $\mu$, where $\mu$ is given as input
*
* This version of the program is (or, better, "shoud be") able to
* tune also the value of the pre-factor "a"
*
*/
#include
#include
#include
#include
#include
#include "rank_utils.h"
inline double compute_delta(double q, double k, double mu, double a){
return fabs(log(q) - mu * log(k) - log(a));
//return fabs (q - a*pow(k,mu));
}
void tune_qnn_adaptive(double *R1, double *R2, int N, int *pairing, double eps,
double beta, double mu_target){
double act_mu, test_mu, F, F_new, F_old;
double delta1_old, delta2_old, delta1_new, delta2_new;
double val, prob;
double mu, a, err, dummy_a;
int *new_pairing;
int p1, p2, tmp_val;
int tot;
char swap = 0;
new_pairing = malloc(N * sizeof(int));
copy_pairing(pairing, new_pairing, N);
a = 1.0;
F = 10000;
fit_current_trend(R1, R2, N, pairing, &mu, &a, &err);
fprintf(stderr, "Initial mu: %g a: %g corr: %g\n", mu, a, err);
//fprintf("%f %f %f %f %f\n", eps, beta, mu_target, act_mu, F);
tot = 0;
while (F > eps){
/* sample two positions of "pairing" and shuffle them in "new_pairing" */
p1 = rand() % N;
p2 = rand() % N;
while (p2 == p1){
p2 = rand() % N;
}
tmp_val = new_pairing[p1];
new_pairing[p1] = new_pairing[p2];
new_pairing[p2] = tmp_val;
delta1_old = compute_delta(R2[pairing[p1]], R1[p1], mu_target, a);
delta2_old = compute_delta(R2[pairing[p2]], R1[p2], mu_target, a);
delta1_new = compute_delta(R2[new_pairing[p1]], R1[p1], mu_target, a);
delta2_new = compute_delta(R2[new_pairing[p2]], R1[p2], mu_target, a);
//F_new = log(delta1_new * delta2_new);
//F_old = log(delta1_old * delta2_old);
F_new = delta1_new + delta2_new;
F_old = delta1_old + delta2_old;
if (F_new <= F_old){/* Accept this swap with probability 1 */
tmp_val = pairing[p1];
pairing[p1] = pairing[p2];
pairing[p2] = tmp_val;
//act_mu = test_mu;
swap = 1;
}
else{/* Accept the swap with a certain probability */
val = 1.0 * rand() / RAND_MAX;
//prob = pow(fabs(F - F_new)/(F+F_new), beta);
prob = exp(-(F_new - F_old)/beta);
//fprintf(stderr, "-- %g %g %g -> %f \n", F_new, F_old, F_new - F_old, prob);
if (val < prob){ /* Accept the swap */
tmp_val = pairing[p1];
pairing[p1] = pairing[p2];
pairing[p2] = tmp_val;
//act_mu = test_mu;
swap = 1;
}
else{ /* Rollback the swap */
tmp_val = new_pairing[p1];
new_pairing[p1] = new_pairing[p2];
new_pairing[p2] = tmp_val;
swap = 0;
}
}
///F = fabs(act_mu - mu_target);
///if (tot % 200 == 0){
//fprintf(stderr, "%d %g\n", tot, act_mu);
//fprintf(stderr, "%d: %f %f ---- %f %f ---- %f %f ---- %d \n",
//tot, delta1_old, delta2_old, delta1_new, delta2_new, F_old, F_new, swap);
///}
tot += 1;
if (tot %200 == 0){
fit_current_trend(R1, R2, N, pairing, &mu, &a, &err);
fprintf(stderr, "mu: %g a: %g corr: %g\n", mu, a, err);
//a = a - 0.01 *(a - exp(a));
a = exp(a);
}
fit_current_trend(R1, R2, N, pairing, &mu, &dummy_a, &err);
F = fabs(mu - mu_target);
}
fit_current_trend(R1, R2, N, pairing, &mu, &a, &err);
fprintf(stderr, "Final mu: %g a: %g corr: %g\n", mu, a, err);
}
void dump_qnn(double *R1, double *R2, int N, int *pairing){
int i;
int *qnn, *num;
qnn = malloc(N * sizeof(int));
num = malloc(N * sizeof(int));
for (i=0; i0){
printf("%d %f\n", i, 1.0*qnn[i]/num[i]);
}
}
free(num);
free(qnn);
}
void dump_degs(double *R1, double *R2, int N, int *pairing){
int i;
for(i=0; i [RND|NAT|INV]\n", argv[0]);
exit(1);
}
mu_target = atof(argv[3]);
eps = atof(argv[4]);
beta = atof(argv[5]);
load_ranking(argv[1], &N1, &R1);
load_ranking(argv[2], &N2, &R2);
if (N1 != N2){
printf("Error!!!! The two files must have the same number of lines!!!! Exiting...\n");
exit(1);
}
pairing = malloc(N1 * sizeof(int));
select_pairing(pairing, N1, argc, argv, 6);
tune_qnn_adaptive(R1, R2, N1, pairing, eps, beta, mu_target);
dump_pairing(pairing, N1);
//dump_qnn(R1, R2, N1, pairing);
//dump_degs(R1, R2, N1, pairing);
}