#include #include #include #include #include #include #include #include #include #include // These variables are required for 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; FILE *fp_save_prime_weight; unsigned long long int *dimension_string; unsigned long long int *string_counter; unsigned long long int *string_counter_aggregate; //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; }; 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" "** Computation of the Kolmogorov complexity **\n" "** of a multiplex system **\n" "** **\n" "** **\n" "** list containing the ordered list of node IDs **\n" "** in the multiplex **\n" "** **\n" "** should be a list of the layers composing the **\n" "** multiplex network **\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) **\n" "** **\n" "** <-s 'filename'> save the prime-weight matrix in the file 'filename' **\n" "** as an ordered weighted edge list **\n" "** **\n" "** <-v> be more verbose -- show misc extra info **\n" "** OUTPUT: by default the algorithm returns the following info: **\n" "** KC_multiplex, NLinks_multiplex,KC_aggregate,Nlinks_aggregate,Complexity **\n" "** **\n" "******************************************************************************\n"); printf("Usage: %s [ITER = 100] [-p #core] [-s ]\n\n" , argv[0]); } unsigned long long int *load_unique_nodes(char *, unsigned long long int *, unsigned long long int *,unsigned int); struct layer *load_data(char *, 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 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 ,unsigned int, char *,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 *); int mpz_cmp_flag_to_01(int); void tdestroy(void *); int delete_root(const void *, const void *); int compare_keys(const void *, const void *); void free_structgmp_multiplex(struct layer *, struct layer *, unsigned int ); unsigned long long int print_file_bothfast_onstring(void **,unsigned long long int *, unsigned 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 free_structure(unsigned long long int *,unsigned long long int *,struct layer *, unsigned int ); void chopN_string(char *, size_t ); struct layer *multiplex_into_binarytree_saving(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); struct layer *update_nodelabel_saving(struct layer *,unsigned int,unsigned long long int , unsigned long long int *); void print_elements_onfile_saving(const void *, const VISIT , const int ); int main(int argc, char *argv[]) { unsigned int M,i,j,k,ITER,parallel=1,save_prime_weight=0,verbose=0; unsigned long long int *nodes_unique,length_unique, MAX_NODE,*primeslist; struct layer *multiplex; unsigned int randval,esc; char *str_par,*prime_weight_filename; 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); } } for (i = 1; i < argc; i++) { //Checking for the parallel option 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); } //Checking for the verbose option if (argv[i][0] == '-' && argv[i][1] == 'v') { fprintf(stderr,"Verbose activated\n"); verbose = 1; } //Checking for saving the prime-weight edge list option if (argv[i][0] == '-' && argv[i][1] == 's') { fprintf(stderr,"Save prime-weight edge list activated\n"); save_prime_weight = 1; prime_weight_filename = argv[i+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); allocate_memory(multiplex,M); // //**************************************************** //Check if the data has been loaded in the correct way // for (i=0; i Number of links: %llu\n\n",token,array[i].nlinks); i++; } fclose(fp); *M=i; array= (struct layer *)realloc(array,(*M)*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 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; } void free_structgmp_multiplex(struct layer *temporarystruct, struct layer *multiplex, unsigned int M) { unsigned int i; unsigned long long int j; for (i = 0; i (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); mpz_init(temporary_mpz); //mpz_ui_pow_ui(temporary_mpz,prime_layer,maximum_overlap[thread_number]); mpz_set(temporary_mpz,maximum_prime_product[thread_number]); // gmp_printf("%u %u %Zd --- prime_layer: %u -- maximum_overlap: %u\n", e->node_i, e->node_j,temporary_mpz,prime_layer,maximum_overlap[thread_number]); 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 free_structure(unsigned long long int *list_prime,unsigned long long int *nodes_unique,struct layer *multiplex, unsigned int M) { unsigned long long int i,k; for (k=0;k len) return; memmove(str, str+n, len - n + 1); } struct layer *multiplex_into_binarytree_saving(void **root,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 long long int *length_nedges_intersection, unsigned int nthread) { unsigned long long int i,j,k, nodei,nodej; struct edge *update; unsigned long long int *distr1; struct layer *temporarystruct; distr1=particular_primes_sequence(multiplex, M); temporarystruct = update_nodelabel_saving(multiplex,M,length_unique,nodes_unique); //mpz_init(maximum_prime_product[nthread]); //mpz_set_ui(maximum_prime_product[nthread],primeslist[M-1]); 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; } 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); return(temporarystruct); } struct layer *update_nodelabel_saving(struct layer *multiplex, unsigned int M,unsigned long long int length_unique, unsigned long long int *nodes_unique) { unsigned int i; unsigned long long int nodei,nodej,j; struct layer *new_duplex= (struct layer *) malloc(M * sizeof(struct layer)); for (i=0; inode_i, e->node_j,e->weight_link); mpz_clear(temporary_mpz); break; default: break; } }