#include #include #include #include #include #include #include #include #include #include // These variables are required in the computation of the Complexity unsigned long long int length; unsigned long long int prime_layer; unsigned int *maximum_overlap; mpz_t *maximum_prime_product; unsigned long long int *Nlinks_aggregate; unsigned long long int *Nlinks_multiplex; char **fp_string; char **fp_string_aggregate; unsigned long long int *dimension_string; unsigned long long int *string_counter; unsigned long long int *string_counter_aggregate; double **omega; double *complexity_multiplex_reducibility; //Definition of the structures struct edge{ unsigned long long int node_i; unsigned long long int node_j; unsigned long long int key; unsigned int overlap_aggregate; mpz_t weight_link; }; struct layer{ struct edge *links_table; unsigned long long int max_node; unsigned long long int nlinks; int l1; int l2; }; struct tree { // datum must be the first field in struct tree const void *datum; struct tree *left, *right; }; typedef void freer(void *node); void usage(char *argv[]){ printf( "******************************************************************************\n" "** **\n" "** Reducibility algorithm for a multiplex system based on **\n" "** information complexity **\n" "** **\n" "**********+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*********\n" "** **\n" "** list containing the list of node IDs in the multiplex **\n" "** **\n" "** **\n" "** should be a list of the layer composing the **\n" "** multiplex network **\n" "** **\n" "** **\n" "** ---------- Optional Variables --------- **\n" "** **\n" "** represents the number of times the Kolmogorov **\n" "** complexity is averaged (default = 100) **\n" "** **\n" "** <#core> represents the number of cores used in the computation of **\n" "** the complexity (default: sequential computation, i.e. #core =1) **\n" "** **\n" "** <-v> be more verbose -- show misc extra info **\n" "** **\n" "** <-s> save optimal multiplex on files in current directory **\n" "** **\n" "** <-w> save all the multiplex aggregation on files in current directory **\n" "** **\n" "** OUTPUT: by default the algorithm returns the following info: **\n" "** partition of the multiplex --> Number of layers, KC multiplex, **\n" "** # links multiplex, KC aggregate, # links aggregate, complexity, q **\n" "** **\n" "******************************************************************************\n"); printf("Usage: %s (ITER = 100) (-p #core) (-v verbose) (-s save optimal multiplex on files) (-w save all the reduced multiplex on files) [fileout]\n\n" , argv[0]); } void chopN_string(char *, size_t); unsigned long long int *load_unique_nodes(char *, unsigned long long int *, unsigned long long int *,unsigned int ); struct layer *load_data(char *listoffiles, unsigned int *, unsigned long long int *, unsigned long long int ,unsigned int ); unsigned long long int load_edgelist(char *, struct edge **, unsigned long long int *, unsigned long long int ); int cmpfunc (const void *, const void *); void list_prime(unsigned long long int **,unsigned int ); void allocate_memory(struct layer *,unsigned int ); void reduce_multiplex(void **,struct layer *, unsigned int, unsigned int, unsigned long long int, unsigned long long int *, unsigned long long int *, unsigned long long int , int , double ***, int **, unsigned int ,unsigned int ,unsigned int , unsigned int ); void evaluate_KC(struct layer *, unsigned int ,unsigned long long int, unsigned long long int *, unsigned long long int *, unsigned long long int, unsigned int,unsigned int); struct layer *multiplex_into_binarytree(void **,struct layer *, unsigned int, unsigned long long int, unsigned long long int *, unsigned long long int *, unsigned long long int, unsigned long long int *, unsigned int ); unsigned long long int *particular_primes_sequence(struct layer *, unsigned int); unsigned long long int *shuffle_nodes(unsigned long long int, unsigned long long int *); struct layer *update_nodelabel(struct layer *, unsigned long long int *, unsigned int,unsigned long long int, unsigned long long int *); void free_structgmp_multiplex(struct layer *, struct layer *, unsigned int); void tdestroy(void *root); int delete_root(const void *node1, const void *node2); int compare_keys(const void *, const void *); int mpz_cmp_flag_to_01(int ); unsigned long long int print_file_bothfast_onstring(void **,unsigned long long int *, unsigned int, unsigned int); void print_elements_onstring_reducibility(const void *, const VISIT, const int); void print_elements_onstring_weighted_aggregate(const void *, const VISIT, const int); unsigned long long int dynamic_compress(char*, unsigned long long int); void aggregate(struct layer **,unsigned int, unsigned int, unsigned int, unsigned long long int,unsigned int); void recursive_print (struct layer *, unsigned int,unsigned int , unsigned int, unsigned int, int **,unsigned int,unsigned int); void free_structure(unsigned long long int *,unsigned long long int *,struct layer *, unsigned int); int * compute_sequence_layers(struct layer *, unsigned int,unsigned int ); void dump_multiplex_on_file(struct layer *multiplex,int *sequence_multiplex_toprint, unsigned int numberoflayers_maximum_reducibility, unsigned long long int *nodes_unique, unsigned long long int); void dump_all_multiplex_on_file(struct layer *multiplex,int *sequence_multiplex_toprint, unsigned int numberoflayers_maximum_reducibility, unsigned long long int *nodes_unique, unsigned long long int); int main(int argc, char *argv[]) { unsigned long long int *primeslist,*nodes_unique,length_unique, MAX_NODE,N; unsigned int M,i,j,k,ITER,parallel=1,verbose=0,partition_verbose=1,save_multiplex=0,save_multiplex_total=0; double maximum_reducibility=0; unsigned int index_maximum_reducibility,numberoflayers_maximum_reducibility; int counter; int *sequence_multiplex_toprint; struct layer *multiplex; unsigned long int randval,esc; void *root; char *str_par; FILE *f; ITER = 100; // RANDOM SEED srand(time(NULL)); // OR // f = fopen("/dev/urandom", "r"); // esc=fread(&randval, sizeof(randval),1, f); // fclose(f); // printf("%lu\n", randval); // srand(randval); if (argc <= 2){ usage(argv); exit(1); } if (argc > 3) { if (argv[3][0] !='-') { ITER = (unsigned int)atoi(argv[3]); fprintf(stderr,"Number of iterations: %u\n", ITER); } } //Checking for the parallel option for (i = 1; i < argc; i++) { if (argv[i][0] == '-' && argv[i][1] == 'p') { if (argc > i+1) parallel = (unsigned int)atoi(argv[i+1]); else { str_par=argv[i]; chopN_string(str_par, 2); parallel = (unsigned int)atoi(argv[i]); } fprintf(stderr,"Number of core inserted: %u\n",parallel); } if (argv[i][0] == '-' && argv[i][1] == 'v') { fprintf(stderr,"Verbose activated\n"); verbose = 1; } if (argv[i][0] == '-' && argv[i][1] == 's') { fprintf(stderr,"Save multiplex activated\n"); save_multiplex = 1; } if (argv[i][0] == '-' && argv[i][1] == 'w') { fprintf(stderr,"Write all multiplex on file activated\n"); save_multiplex_total = 1; } } if(verbose) fprintf(stderr,"Finding the number of nodes...\n"); nodes_unique=load_unique_nodes(argv[1],&length_unique, &MAX_NODE,verbose); multiplex=load_data(argv[2],&M,nodes_unique,length_unique,verbose); if(verbose) fprintf(stderr,"Computing the prime list...\n"); primeslist=(unsigned long long int *)malloc(M*sizeof(unsigned long long int)); list_prime(&primeslist,M); //**************************************************** //Number of M primes used in the script // for (i=0;i maximum_reducibility ) { maximum_reducibility=complexity_multiplex_reducibility[i]; index_maximum_reducibility = i; numberoflayers_maximum_reducibility=i+1; } //fprintf(stderr,"%d %lf\n",i+1,complexity_multiplex_reducibility[i]); } if (verbose == 1) fprintf(stderr,"\nM_optimal: %d\t\tMaximum quality function: %lf\n",numberoflayers_maximum_reducibility,maximum_reducibility); if( save_multiplex == 1) { sequence_multiplex_toprint=compute_sequence_layers(multiplex,index_maximum_reducibility,M); dump_multiplex_on_file(multiplex,sequence_multiplex_toprint,numberoflayers_maximum_reducibility,nodes_unique,length_unique); } if( save_multiplex_total == 1) { for (counter = M-2; counter>=0;counter--) { index_maximum_reducibility=counter; numberoflayers_maximum_reducibility=counter+1; sequence_multiplex_toprint=compute_sequence_layers(multiplex,index_maximum_reducibility,M); dump_all_multiplex_on_file(multiplex,sequence_multiplex_toprint,numberoflayers_maximum_reducibility,nodes_unique,length_unique); } } //Free process free_structure(primeslist,nodes_unique,multiplex,2*M-1); for (i = 0; i < (2*M-1); i++) { free(distance_matrix[i]); free(omega[i]); } free(distance_matrix); free(vectorprint); free(complexity_multiplex_reducibility); free(omega); } void chopN_string(char *str, size_t n) { assert(n != 0 && str != 0); size_t len = strlen(str); if (n > len) return; memmove(str, str+n, len - n + 1); } unsigned long long int *load_unique_nodes(char *filename, unsigned long long int *length_unique, unsigned long long int *MAX_NODE,unsigned int verbose) { FILE *fp; unsigned long long int *unique_nodes, size=10000, k=0; int scan=0; fp = fopen(filename,"r"); unique_nodes=(unsigned long long int *)malloc(size*sizeof(unsigned long long int)); while(scan!=EOF) { if(k==size) { size+=10000; unique_nodes=(unsigned long long int *)realloc(unique_nodes,size*sizeof(unsigned long long int)); } scan=fscanf(fp,"%llu",&(unique_nodes[k])); k++; } k=k-1; unique_nodes=(unsigned long long int *)realloc(unique_nodes,k*sizeof(unsigned long long int)); if(verbose) fprintf(stderr,"Number of unique nodes: %llu\n\n",k); fclose(fp); *MAX_NODE = unique_nodes[k-1]; *length_unique=k; return(unique_nodes); } struct layer *load_data(char *listoffiles, unsigned int *M, unsigned long long int *unique_nodes, unsigned long long int length_unique,unsigned int verbose) { FILE *fp,*singlefp; struct layer *array; char line[256]; char* token; unsigned long long int N,i,size; size = 10000; array = (struct layer *)malloc(size * sizeof(struct layer )); i=0; fp= fopen(listoffiles,"r"); while (1) { if (i == size) { size+=10000; array= (struct layer *)realloc(array,size*sizeof(struct layer)); } if (fgets(line,256, fp) == NULL) break; token = strtok(line,"\n"); N=unique_nodes[length_unique-1]; array[i].max_node=N; array[i].nlinks=load_edgelist(token,&(array[i].links_table),unique_nodes,length_unique); if(verbose) fprintf(stderr,"%s --> Number of links: %llu\n\n",token,array[i].nlinks); i++; } fclose(fp); *M=i; array= (struct layer *)realloc(array,(2*(*M)-1)*sizeof(struct layer)); if(verbose) fprintf(stderr,"Number of layers in the multiplex:%llu\n\n",i); return(array); } unsigned long long int load_edgelist(char *filename, struct edge **current, unsigned long long int *unique_nodes, unsigned long long int length_unique) { unsigned long long int temp1,temp2,counter_edges=0, size =1000,Nedges,auxiliary; unsigned long int scan=0; unsigned long long int *item; char buff[256]; char *ptr; FILE *fp; *(current)=(struct edge *) malloc(size * sizeof(struct edge )); unsigned long long int *p_a=&(unique_nodes[0]); unsigned long long int *p_b; unsigned long long int differenceInBytes; fp= fopen(filename,"r"); while(scan!=EOF) { if (counter_edges == size) { size+=1000; *(current)=(struct edge*)realloc(*(current),size*sizeof(struct edge )); } // PARSING DATA WITH NODES_UNIQUE -> Take the corresponding index -1 of that element scan=fscanf(fp, "%llu", &temp1); item = (unsigned long long int*) bsearch (&temp1, unique_nodes, length_unique, sizeof (unsigned long long int), cmpfunc); p_b=item; differenceInBytes = (p_b - p_a); temp1=differenceInBytes; scan=fscanf(fp, "%llu", &temp2); item = (unsigned long long int*) bsearch (&temp2, unique_nodes, length_unique, sizeof (unsigned long long int), cmpfunc); p_b=item; differenceInBytes = (p_b - p_a); temp2=differenceInBytes; //The link that we are going to add is formed by the nodes temp1 --- temp2 //In order to maintain the first element smaller than the second do this check if(temp1>temp2) { auxiliary=temp2; temp2=temp1; temp1=auxiliary; } (*current)[counter_edges].node_i = temp1; (*current)[counter_edges].node_j = temp2; //fprintf(stderr,"%u %u\n\n",temp1, temp2); counter_edges++; } Nedges=counter_edges-1; *(current)=(struct edge*)realloc(*(current),Nedges*sizeof(struct edge )); fclose(fp); return(Nedges); } int cmpfunc (const void * a, const void * b) { return ( *(long long int*)a - *(long long int*)b ); } void list_prime(unsigned long long int **listofprimes,unsigned int numberofprimes) { unsigned long long int i,s; mpz_t prime; mpz_init(prime); //Initialize prime and set its value to 0. mpz_set_ui(prime, 2); //Set the value of prime to be 2 (*listofprimes)[0]=2; for(i=1; i"); } evaluate_KC(multiplex,M,MAX_NODE,primeslist,nodes_unique,length_unique,ITER,parallel); //******************************************************************************** /*Creation of the duplex structure for evaluating the similarity for all the (M 2) couples of layers*/ duplex=(struct layer *)malloc(2*sizeof(struct layer)); *vectorprint=(int *)calloc ((2*M-1),sizeof(int)); for (i = 0; i< M-1; i++) { for (j = i+1; j< M; j++) { *root = NULL; duplex[0].nlinks=multiplex[i].nlinks; duplex[0].links_table=multiplex[i].links_table; duplex[0].max_node=multiplex[i].max_node; duplex[1].nlinks=multiplex[j].nlinks; duplex[1].links_table=multiplex[j].links_table; duplex[1].max_node=multiplex[j].max_node; sumKC=0; sumKCaggregate=0; nedges_intersection=0; cumulative_complexity=0.0; omp_set_num_threads(parallel); //Allocation for the parallel computing temporarystruct = (struct layer **) malloc (parallel*sizeof(struct layer *)); nthread_root = (void **) malloc (parallel*sizeof(void *)); Nlinks_aggregate= (unsigned long long int *)malloc(parallel*sizeof(unsigned long long int )); Nlinks_multiplex= (unsigned long long int *)malloc(parallel*sizeof(unsigned long long int )); dimension_string= (unsigned long long int *)malloc(parallel*sizeof(unsigned long long int )); string_counter= (unsigned long long int *)malloc(parallel*sizeof(unsigned long long int )); string_counter_aggregate= (unsigned long long int *)malloc(parallel*sizeof(unsigned long long int )); fp_string= (char **)malloc(parallel*sizeof(char *)); fp_string_aggregate= (char **)malloc(parallel*sizeof(char *)); maximum_overlap=(unsigned int *)malloc(parallel*sizeof(unsigned int )); maximum_prime_product=(mpz_t *)malloc(parallel*sizeof(mpz_t)); for (k=0;k max_KC_step) { max_KC_step = fraction; row=i; column=j; } //printf("\nlayer %u with %u -- number of total links multiplex: %u -- aggregate:%u\n",i,j,Nlinks_multiplex[nthread],Nlinks_aggregate[nthread]); free(temporarystruct); free(nthread_root); free(Nlinks_aggregate); free(Nlinks_multiplex); free(dimension_string); free(string_counter); free(string_counter_aggregate); free(fp_string); free(fp_string_aggregate); free(maximum_overlap); for (k=0;k= omega[row][column] && (*distance_matrix)[i][j] < min) { min =(*distance_matrix)[i][j] ; new_row=i; new_column=j; } } row=new_row; column=new_column; if (verbose) fprintf(stderr,"\n\nThe index with the minimum value %lf is %u %u\n",min,row, column); for (i=0; i<(2*M-1); i++) { for (j=0; j<(2*M-1); j++) { if(i == row || j == row || i == column || j == column || i==j ) (*distance_matrix)[i][j]=1000.0; //printf("%.4lf ", (*distance_matrix)[i][j]); } //printf("\n"); } //Aggregate the two layers yielding the maximum value of complexity and put such layer as M+1 in the multiplex structure aggregate(&multiplex,M+1,row,column,MAX_NODE,verbose); //l1 and l2 are the two layers that will be merged in this round multiplex[Mmod].l1=row; multiplex[Mmod].l2=column; //Vectorprint keeps track of the layers that are going to be merged (used for the printing procedure) (*vectorprint)[row]=1; (*vectorprint)[column]=1; if (verbose || partition_verbose) { for (i = 0; i < M; i++) { if ( (*vectorprint)[i] == 0) printf("%d, ", multiplex[i].l1); } for (i=Mmod; i >= M; i--) { printf("( %d %d ), ", multiplex[i].l1,multiplex[i].l2); } if (partition_verbose) printf("-->"); } layers_order=(unsigned int *)malloc((M-1)*sizeof(unsigned int )); //Layers_order contains the indexes of the layers composing the multiplex after the merging process j=0; for (i = 0; i = max_KC_step && (*distance_matrix)[i][j]!= 1000.0) { max_KC_step = (*distance_matrix)[i][j]; row=i; column=j; } } } // Find the layers i and j with small value of complexity and high value of overlap min=1000.0; for(i=0; i < Mmod-1;i++) for (j = i+1; j < Mmod; j++) { if( (*distance_matrix)[i][j] <= max_KC_step && omega[i][j] >= omega[row][column] && (*distance_matrix)[i][j] < min) { min=(*distance_matrix)[i][j]; flag_intern=1; new_row=i; new_column=j; } } row=new_row; column=new_column; // If the duplex with the properties searched before is not found, then we will // take the duplex having the smallest value of KC_D/ KC_A and maximum value available of omega function (overlap) if (flag_intern==0) { omegastar=0; for(i=0; i < Mmod-1;i++) for (j = i+1; j < Mmod; j++) { if( (*distance_matrix)[i][j] <= max_KC_step && omega[i][j] > omegastar) { new_row=i; new_column=j; omegastar=omega[i][j]; } } row=new_row; column=new_column; } if (verbose) fprintf(stderr,"\n\nThe index with the minimum value %lf is %u %u\n",min,row, column); for (i=0; i<(2*M-1); i++) { for (j=0; j<(2*M-1); j++) { if(i == row || j == row || i == column || j == column ) (*distance_matrix)[i][j]=1000.0; } } multiplex[Mmod].l1=row; multiplex[Mmod].l2=column; if (row < M) (*vectorprint)[row]=1; if (column < M) (*vectorprint)[column]=1; int *copy=(int *)calloc((2*M-1),sizeof(int)); for ( i = 0; i < 2*M-1; i++) { copy[i]=(*vectorprint)[i]; } //If the number of layers are greater than 2 continue, otherwise stop. You have done all the steps if ( M > 2) { aggregate(&multiplex,Mmod+1,row,column,MAX_NODE,verbose); //Layers order contains the indexes of the layers composing the multiplex after the merging process step=Mmod-M+1; layers_order=(unsigned int *)malloc((M-step)*sizeof(unsigned int )); j=0; for (i = 0; i < M; i++) { if ( copy[i] == 0) { if (verbose || partition_verbose) printf("%d, ", multiplex[i].l1); layers_order[j++]=multiplex[i].l1; copy[i]=1; } } for (i=Mmod; i >= M; i--) { if(copy[i]==0) { layers_order[j++]=i; if (verbose || partition_verbose) printf("( "); recursive_print(multiplex,i,i,M,Mmod,©,verbose,partition_verbose); if (verbose|| partition_verbose) printf("), "); } } free(copy); if (partition_verbose) printf("-->"); //Layers order contains the indexes of the layers composing the multiplex after the merging process //***********Evaluate the Kolmogorov Complexity of the multiplex with M-1 layers************ new_multiplex=(struct layer *)malloc((M - step)*sizeof(struct layer )); for (i = 0; i < M-step; i++) new_multiplex[i]=multiplex[layers_order[i]]; evaluate_KC(new_multiplex,M-step,MAX_NODE,primeslist,nodes_unique,length_unique,ITER,parallel); free(layers_order); free(new_multiplex); free(duplex); } if (Mmod+1 < 2*M-1) { reduce_multiplex(root,multiplex,M,Mmod+1,MAX_NODE,primeslist,nodes_unique,length_unique,1,distance_matrix,vectorprint,ITER,parallel,verbose,partition_verbose); } else { if(verbose) fprintf(stderr,"\nFinish!\n"); } } } void evaluate_KC(struct layer *multiplex, unsigned int M,unsigned long long int MAX_NODE, unsigned long long int *primeslist, unsigned long long int *nodes_unique, unsigned long long int length_unique, unsigned int ITER,unsigned int parallel) { unsigned long long int dimension_KC,dimension_KC_aggregate,k,nedges_intersection; unsigned int nthread; struct layer **temporarystruct; void **nthread_root; double sumKC,sumKCaggregate,complexity,numerator,denominator,cumulative_complexity; //***********Evaluate the Kolmogorov Complexity of the whole multiplex************ sumKC=0; sumKCaggregate=0; nedges_intersection=0; cumulative_complexity=0.0; omp_set_num_threads(parallel); //Allocation for the parallel computing temporarystruct = (struct layer **) malloc (parallel*sizeof(struct layer *)); nthread_root = (void **) malloc (parallel*sizeof(void *)); Nlinks_aggregate= (unsigned long long int *)malloc(parallel*sizeof(unsigned long long int )); Nlinks_multiplex= (unsigned long long int *)malloc(parallel*sizeof(unsigned long long int )); dimension_string= (unsigned long long int *)malloc(parallel*sizeof(unsigned long long int )); string_counter= (unsigned long long int *)malloc(parallel*sizeof(unsigned long long int )); string_counter_aggregate= (unsigned long long int *)malloc(parallel*sizeof(unsigned long long int )); fp_string= (char **)malloc(parallel*sizeof(char *)); fp_string_aggregate= (char **)malloc(parallel*sizeof(char *)); maximum_overlap=(unsigned int *)malloc(parallel*sizeof(unsigned int )); maximum_prime_product=(mpz_t *)malloc(parallel*sizeof(mpz_t)); for (k=0;k nodej) { temporarystruct[distr1[k]].links_table[i].node_i = temporarystruct[distr1[k]].links_table[i].node_j; temporarystruct[distr1[k]].links_table[i].node_j = nodei; nodei=temporarystruct[distr1[k]].links_table[i].node_i; nodej=temporarystruct[distr1[k]].links_table[i].node_j; } Nlinks_multiplex[nthread]++; temporarystruct[distr1[k]].links_table[i].key= MAX_NODE * (nodei) + (nodej); update=tfind (& temporarystruct[distr1[k]].links_table[i], root, compare_keys); // If the element does not belong to the tree, then update is egual to NULL and the element will be // inserted with the function tsearch if( update== NULL) { Nlinks_aggregate[nthread]++; mpz_set_ui(temporarystruct[distr1[k]].links_table[i].weight_link, primeslist[k]); temporarystruct[distr1[k]].links_table[i].overlap_aggregate++; (void) tsearch(& temporarystruct[distr1[k]].links_table[i], root, compare_keys); } else { //If the element already exists in the tree then// //update the prime weight of the link considered// (*length_nedges_intersection)++; update=*(struct edge **)update; (*update).overlap_aggregate++; mpz_mul_ui((*update).weight_link,(*update).weight_link,primeslist[k]); if (mpz_cmp_flag_to_01(mpz_cmp((*update).weight_link,maximum_prime_product[nthread]))) { //gmp_printf("changing %Zd in %Zd\n",maximum_prime_product[nthread],(*update).weight_link); mpz_set(maximum_prime_product[nthread],(*update).weight_link); } } } } //fprintf(stderr,"%d ", length_nedges_intersection ); free(distr1); free(shuffle); return(temporarystruct); } unsigned long long int *particular_primes_sequence(struct layer *multiplex, unsigned int M) { unsigned long long int *distr1,*distr2,*temp,i,j; distr1=(unsigned long long int*)malloc(M*sizeof(unsigned long long int)); distr2=(unsigned long long int*)malloc(M*sizeof(unsigned long long int)); temp=(unsigned long long int*)malloc(M*sizeof(unsigned long long int)); for(i=0;i0;i--) { j=rand()%(i+1); temp = distr[i]; distr[i]=distr[j]; distr[j]=temp; } //for(i=0;ikey < e2->key) return -1; else if (e1->key == e2->key) return 0; else return 1; } int mpz_cmp_flag_to_01(int mpz_cmp_flag){ if(mpz_cmp_flag <= 0) return 0; else return 1; } unsigned long long int print_file_bothfast_onstring(void **root,unsigned long long int *dimension_aggregate, unsigned int flag, unsigned int thread_number) { unsigned long long int dimension=0; //If flag is zero, then the aggregate will be unweighted --> Used for computing the distance among layers dimension_string[thread_number]=100000; fp_string[thread_number]= (char *) malloc (dimension_string[thread_number] * sizeof(char)); fp_string_aggregate[thread_number]= (char *)malloc (dimension_string[thread_number] * sizeof(char)); string_counter[thread_number]=0; string_counter_aggregate[thread_number]=0; //Printing the weighted multiplex on string if (flag == 0) twalk(root,print_elements_onstring_reducibility); else twalk(root,print_elements_onstring_weighted_aggregate); dimension = dynamic_compress(fp_string[thread_number],string_counter[thread_number]+1); *dimension_aggregate = dynamic_compress(fp_string_aggregate[thread_number],string_counter_aggregate[thread_number]+1); free(fp_string[thread_number]); free(fp_string_aggregate[thread_number]); return(dimension); } void print_elements_onstring_reducibility(const void *nodep, const VISIT which, const int depth) { struct edge *e = *((struct edge **) nodep); switch (which) { case leaf: case postorder: length++; //unsigned int thread_number = 0; unsigned int thread_number= omp_get_thread_num(); if( (string_counter[thread_number] > (dimension_string[thread_number] - 5000) && string_counter[thread_number] < dimension_string[thread_number]) || (string_counter_aggregate[thread_number] > (dimension_string[thread_number] - 5000) && string_counter_aggregate[thread_number] < dimension_string[thread_number] )) { dimension_string[thread_number]+=100000; fp_string[thread_number]= (char *)realloc (fp_string[thread_number],dimension_string[thread_number] * sizeof(char)); fp_string_aggregate[thread_number]= (char *)realloc (fp_string_aggregate[thread_number],dimension_string[thread_number] * sizeof(char)); } string_counter[thread_number] += gmp_sprintf(fp_string[thread_number]+string_counter[thread_number],"%llu %llu %Zd\n", e->node_i, e->node_j,e->weight_link); if(e->overlap_aggregate>1) { //string_counter_aggregate[thread_number] += gmp_sprintf(fp_string_aggregate[thread_number]+string_counter_aggregate[thread_number],"%u %u %u\n", e->node_i, e->node_j,e->overlap_aggregate); //string_counter_aggregate[thread_number] += gmp_sprintf(fp_string_aggregate[thread_number]+string_counter_aggregate[thread_number],"%u %u %u\n", e->node_i, e->node_j,(unsigned int)pow(prime_layer,(double)e->overlap_aggregate)); string_counter_aggregate[thread_number] += gmp_sprintf(fp_string_aggregate[thread_number]+string_counter_aggregate[thread_number],"%llu %llu %u\n", e->node_i, e->node_j,2); //gmp_printf("%Ld %Ld %.0lf\n", e->node_i, e->node_j,pow(prime_layer,(double)e->overlap_aggregate)); } else { if(e->overlap_aggregate==1) { //string_counter_aggregate[thread_number] += gmp_sprintf(fp_string_aggregate[thread_number]+string_counter_aggregate[thread_number],"%u %u %u\n", e->node_i, e->node_j,1); //string_counter_aggregate[thread_number] += gmp_sprintf(fp_string_aggregate[thread_number]+string_counter_aggregate[thread_number],"%u %u %u\n", e->node_i, e->node_j,prime_layer); string_counter_aggregate[thread_number] += gmp_sprintf(fp_string_aggregate[thread_number]+string_counter_aggregate[thread_number],"%llu %llu %u\n", e->node_i, e->node_j,2); //gmp_printf("%Ld %Ld %d\n", e->node_i, e->node_j,prime_layer); } } break; default: break; } } void print_elements_onstring_weighted_aggregate(const void *nodep, const VISIT which, const int depth) { struct edge *e = *((struct edge **) nodep); switch (which) { case leaf: case postorder: length++; //unsigned int thread_number = 0; unsigned int thread_number= omp_get_thread_num(); mpz_t temporary_mpz; if( (string_counter[thread_number] > (dimension_string[thread_number] - 5000) && string_counter[thread_number] < dimension_string[thread_number]) || (string_counter_aggregate[thread_number] > (dimension_string[thread_number] - 5000) && string_counter_aggregate[thread_number] < dimension_string[thread_number] )) { dimension_string[thread_number]+=100000; fp_string[thread_number]= (char *)realloc (fp_string[thread_number],dimension_string[thread_number] * sizeof(char)); fp_string_aggregate[thread_number]= (char *)realloc (fp_string_aggregate[thread_number],dimension_string[thread_number] * sizeof(char)); } string_counter[thread_number] += gmp_sprintf(fp_string[thread_number]+string_counter[thread_number],"%llu %llu %Zd\n", e->node_i, e->node_j,e->weight_link); //gmp_printf("%u %u %Zd\n", e->node_i, e->node_j,e->weight_link); mpz_init(temporary_mpz); mpz_set(temporary_mpz,maximum_prime_product[thread_number]); //mpz_ui_pow_ui(temporary_mpz,prime_layer,maximum_overlap[thread_number]); //gmp_printf("%u %u %Zd\n", e->node_i, e->node_j,temporary_mpz); string_counter_aggregate[thread_number] += gmp_sprintf(fp_string_aggregate[thread_number]+string_counter_aggregate[thread_number],"%llu %llu %Zd\n", e->node_i, e->node_j,temporary_mpz); //string_counter_aggregate[thread_number] += gmp_sprintf(fp_string_aggregate[thread_number]+string_counter_aggregate[thread_number],"%u %u %u\n", e->node_i, e->node_j,e->overlap_aggregate); //string_counter_aggregate[thread_number] += gmp_sprintf(fp_string_aggregate[thread_number]+string_counter_aggregate[thread_number],"%u %u %u\n", e->node_i, e->node_j,2); //gmp_printf("%Ld %Ld %.0lf\n", e->node_i, e->node_j,pow(prime_layer,(double)e->overlap_aggregate)); mpz_clear(temporary_mpz); break; default: break; } } unsigned long long int dynamic_compress(char* str, unsigned long long int size) { char *temporary_dyn; unsigned long long int dimension; temporary_dyn= (char *)malloc(size*sizeof(char)); // deflate // zlib struct z_stream defstream; defstream.zalloc = Z_NULL; defstream.zfree = Z_NULL; defstream.opaque = Z_NULL; defstream.avail_in = (uInt)strlen(str)+1; // size of input, string + terminator defstream.next_in = (Bytef *)str; // input char array //printf("Size of the output:%d\n", size); defstream.avail_out = (uInt)size; // size of output defstream.next_out = (Bytef *)temporary_dyn; // output char array deflateInit(&defstream, Z_DEFAULT_COMPRESSION); deflate(&defstream, Z_FINISH); deflateEnd(&defstream); // This is one way of getting the size of the output //printf("Deflated size is: %lu\n", (char *) defstream.next_out - temporary_dyn); dimension= (char *) defstream.next_out - temporary_dyn; free(temporary_dyn); return(dimension); } void aggregate(struct layer **multiplex,unsigned int Nlayers, unsigned int row, unsigned int column, unsigned long long int MAX_NODE,unsigned int verbose) { void *root=NULL; unsigned int *layer_to_collapse,k; unsigned long long int num_links=0,max_nodelayer=0,size=1000,a,b,i; struct edge *update,**new_link; layer_to_collapse = (unsigned int *)malloc(2*sizeof(unsigned int)); layer_to_collapse[0]=row; layer_to_collapse[1]=column; new_link = &(*multiplex)[Nlayers-1].links_table; *new_link = (struct edge *) malloc(size * sizeof(struct edge )); if (verbose) { fprintf(stderr,"%u---Link: %llu\n",layer_to_collapse[0],(*multiplex)[layer_to_collapse[0]].nlinks); fprintf(stderr,"%u---Link: %llu\n",layer_to_collapse[1],(*multiplex)[layer_to_collapse[1]].nlinks); } //fprintf(fp_partition,"%Ld %Ld 1 2\n",layer_to_collapse[0],layer_to_collapse[1]); for (k=0;k<2;k++) { for (i = 0; i < (*multiplex)[layer_to_collapse[k]].nlinks; i++) { a=(*multiplex)[layer_to_collapse[k]].links_table[i].node_i; b=(*multiplex)[layer_to_collapse[k]].links_table[i].node_j; (*multiplex)[layer_to_collapse[k]].links_table[i].key= a*MAX_NODE+b; //printf("link: %Ld %Ld\n",a,b); update=tfind (& (*multiplex)[layer_to_collapse[k]].links_table[i], &root, compare_keys); // If the element does not belong to the tree, then update is egual to NULL and the element will be // inserted with the function tsearch if( update == NULL) { //Find the max node between the two layers to aggregate if(max_nodelayer < b ) max_nodelayer = b; //Unweighted union of the two layers (void) tsearch(& (*multiplex)[layer_to_collapse[k]].links_table[i], &root, compare_keys); (*new_link)[num_links].node_i= a; (*new_link)[num_links].node_j= b; (*new_link)[num_links].key= MAX_NODE * (a) + (b); (*new_link)[num_links].overlap_aggregate=0; mpz_init((*new_link)[num_links].weight_link); //mpz_set_ui((*new_link)[num_links].weight_link, size); //printf("unione: %Ld %Ld\n",(*new_link)[num_links].node_i,(*new_link)[num_links].node_i); num_links++; if(num_links == size) { size+=1000; (*new_link)=(struct edge *)realloc((*new_link),size*sizeof(struct edge)); } } } } (*multiplex)[Nlayers-1].links_table=*new_link; (*multiplex)[Nlayers-1].nlinks=num_links; if (verbose) fprintf(stderr,"Number of links aggregate:%llu\n\n", num_links); (*multiplex)[Nlayers-1].max_node=max_nodelayer; free(layer_to_collapse); tdestroy(root); } void recursive_print (struct layer *multiplex, unsigned int i,unsigned int iprev, unsigned int M, unsigned int Mmod, int **copy,unsigned int verbose,unsigned int partition_verbose) { unsigned int j,k,flag=0; //printf("eccome con %d %d ",multiplex[i].l1,multiplex[i].l2); if(i!= iprev) { (*copy)[iprev]=i; } if ((*copy)[i]==0) { if(multiplex[i].l1 < M) { if (verbose|| partition_verbose) printf("%d ",multiplex[i].l1 ); } else { recursive_print(multiplex, multiplex[i].l1,i, M,Mmod, copy,verbose,partition_verbose); } if(multiplex[i].l2 < M) { if (verbose|| partition_verbose) printf("%d ",multiplex[i].l2 ); } else { recursive_print(multiplex, multiplex[i].l2,i, M,Mmod, copy,verbose,partition_verbose); } } if(multiplex[i].l1 < M && multiplex[i].l2 =M ;i --) { flag =0; // if i belongs to indexes_to_evaluate -> flag =1 for (j =0;j