
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <math.h>
#include <stdlib.h>

main(int argc, char *argv[])
{
  int i,j,k,l,p1,p2,seguir,mayor,na,flag;        ;
  FILE *grafo,*matriz,*malet,*fmf,*fco,*fcoconn;
  char a[20],b[20],d[20],command[30];
  
  int **m,**mrand;
  //  void calcula();
  char **nodos;
  int car;

  double *mf,*mfo,*mfe,*s,*c,*cg,*conng;
  //  double *mfv,*mfov,*mfev;
  double ecm(),media(),conexa();
  time_t t1;
  long kkk;
  void nomemo(),**principal(),**aleatcon();

  k=atoi(argv[2]);
  na=atoi(argv[4]);
  l=0;
  i=0;
  seguir=1;
  mayor=0;

  printf("\n\n");
  flag=(strcmp(argv[5],"c")==0);

  if (!((argc==5) | ((argc==6)&(flag))))
    {
      printf("\n\n *** Sintax incorrect \n");
      printf("\nUse: \t ./redes  <input_file>   number_of_nodes  file_format   random_networks  [c]\n");
      printf("\n\t\t file_format = 2 \t\t edges list in two columns");
      printf("\n\t\t file_format = 3 \t\t edges list in two columns");
      printf("\n\t\t file_format = M \t\t adjacency matrix");
      printf("\n\t\t file_format = L \t\t nodes list\n");
      printf("\n\t\t c  -- >  print values to file\n\n");
      exit(1);
    }

  m = (int **) malloc(k * sizeof(int *)); if (m==NULL) nomemo();
  for (i=0;i<k;i++)
    {
      m[i] = (int *) malloc (k * sizeof(int)); if (m[i]==NULL) nomemo();
    }  
  nodos = (char **) malloc(k * sizeof(char *)); if (nodos==NULL) nomemo();
  for (i=0;i<k;i++)
    {
      nodos[i] = (char *) malloc (16 *sizeof(char)); if (nodos[i]==NULL) nomemo();
    }
 
    t1=time(&t1);
  //    kkk=1115118459;
  //    kkk=1115647526;
    //printf("seed=%d\n",(long)kkk);
    printf("seed=%d\n",(long)t1);
    srand48((long) t1);  
    //    srand48(kkk);

  if ( (grafo = fopen(argv[1],"r")) == NULL )
    {
      printf("\n\t Unable to open file %s\n",argv[1]);
      exit(1);
    }


  for(i=0;i<k;i++)
    {
      for(j=0;j<k;j++)
	{
	  m[i][j]=0;
	}
    }

  if (!strcmp(argv[3],"M"))
    {
      //      printf("LEO MATRIZ\n");
      //      do
      while ((!feof(grafo)) & (l<k))
	{
	  for(i=0;i<k;i++)
	    {
	      fscanf(grafo,"%s",a);	  
	      if (atoi(a)==1){m[l][i]=1;m[i][l]=1;}
	    }
	  l++;
	}
      mayor=l;
    }
  else if (!strcmp(argv[3],"L"))
    {
      car=fgetc(grafo);
      while ((!feof(grafo)))
	{
	  //	  car=fgetc(grafo);
	  i=0;
	  while ((car!=9)&(car!=32)) // \t | espacio
	    {
	      a[i]= car;
	      i++;
	      car=fgetc(grafo);
	    }
	  a[i]=0;
	  p1=busca(a,nodos,&l,k,&mayor);	  
	  car=fgetc(grafo);
	  i=0;
	  while (car!=10) // \n
	    {
	      while ((car!=9)&(car!=32)&(car!=10))  // \t | espacio | \n
		{
		  a[i]=car;
		  i++;
		  car=getc(grafo);
		}
	      a[i]=0;
	      p2=busca(a,nodos,&l,k,&mayor);	  
	      if ((p1==-1) | (p2==-1))
		{
		  seguir=0;
		}
	      else
		{
		  m[p1][p2]=1;
		  m[p2][p1]=1;
		}
	      i=0;
	      if (car!=10) car=fgetc(grafo);
	    }
	  car=fgetc(grafo);
	}
      //      mayor=l;
    }
  else
    {
      while ((!feof(grafo)))
	{
	  fscanf(grafo,"%s",a);
	  fscanf(grafo,"%s",b);
	  if (atoi(argv[3])== 3) {fscanf(grafo,"%s",d);}
	  
	  p1=busca(a,nodos,&l,k,&mayor);
	  p2=busca(b,nodos,&l,k,&mayor);

	  if ((p1==-1) | (p2==-1))
	    {
	      seguir=0;
	    }
	  else
	    {
	      m[p1][p2]=1;
	      m[p2][p1]=1;
	      //    if(p1==p2) {m[p1][p2]=0}
	    }
	}
    }

  if ((l!=k) | (seguir==0))
    {
      printf("\n *** ERROR %d,%d,%d\n",l,k,mayor);
      printf("\n *** ERROR \n");
      if (seguir==0)
	{
	  if (mayor!=0) {printf("\n\t The number of nodes given is different to the number of nodes in the file: %d\n\n",mayor);}
	  else 
	    {
	      printf("\n\t The number of nodes given is different to the number of nodes in the file:");
	      strcpy(command,"count ");
	      strcat(command,argv[1]);
	      system(command);
	      printf("\n\n");
	    }
	}
      else
	{
	  printf("\n\t The number of nodes given is different to the number of nodes in the file:  %d\n\n",l);
	}
      exit(1);
    }
 
  //  printf("Red leida, voy a ver si es conexa\n");
  //  printf("conexa=%g\n",conexa(m,k));
  if (fabs(conexa(m,k)) < 1.0E-10)
    {
      printf ("\n\n\t*** Disconnected network *** \n\n");
      principal(m,&k,nodos);
      printf ("Number of nodes of the main connected component: %d\n\n",k);
    }

  matriz = fopen(strncat(argv[1],".A",2),"w");

  for(i=0;i<k;i++)
    {
      m[i][i]=0;
      for(j=0;j<k;j++)
	{
	  fprintf(matriz,"%d ",m[i][j]);
	  //	  	  printf("%d ",m[i][j]);
	}
      fprintf(matriz,"\n");
      //          printf("\n");
    }
  
  printf("\nAdjacency matrix stored in file: %s\n\n",argv[1]);
  argv[1][strlen(argv[1])-2]=argv[1][strlen(argv[1])];

 
 /***  CALCULOS  ***/

  mrand = (int **) malloc(k * sizeof(int *)); if (mrand==NULL) nomemo();
  for (i=0;i<k;i++)
    {
      mrand[i] = (int *) malloc (k * sizeof(int)); if (mrand[i]==NULL) nomemo();
    }

  mf=(double*) malloc(na*sizeof(double)); if (mf==NULL) nomemo();
  mfo=(double*) malloc(na*sizeof(double));if (mfo==NULL) nomemo(); 
  mfe=(double*) malloc(na*sizeof(double)); if (mfe==NULL) nomemo();
  s=(double*) malloc(na*sizeof(double)); if (s==NULL) nomemo();
  c=(double*) malloc(na*sizeof(double)); if (c==NULL) nomemo();
  cg=(double*) malloc(na*sizeof(double)); if (cg==NULL) nomemo();
  conng=(double*) malloc(na*sizeof(double));if (conng==NULL) nomemo(); 

  if (flag==1)
    {
      fmf = fopen(strncat(argv[1],".SC",3),"w");
      argv[1][strlen(argv[1])-3]=argv[1][strlen(argv[1])];
      fco = fopen(strncat(argv[1],".C",2),"w");
      fcoconn = fopen(strncat(argv[1],"conn",4),"w");
    }

  calcula(m,k,mf,mfo,mfe,s,c,cg,conng,flag,fco,fcoconn,fmf,nodos);

 printf("\tsubgraph centrality \t\t\tSC \t = \t%g\n",*mf);
 printf("\tsubgraph centrality odd \t\tSCodd \t = \t%g\n",*mfo);
 printf("\tsubgraph centrality even \t\tSCeven \t = \t%g\n",*mfe);
 printf("\tbipartivity \t\t\t\tB(G) \t = \t%g\n",(*mfe)/(*mf));
 printf("\tentrophy \t\t\t\tS \t = \t%g\n",*s);
 printf("\tcommunicability \t\t\tC(G) \t = \t%g\n",*cg);
 printf("\tcommunicability for connected nodes \tCconn(G) = \t%g\n",*conng);

 if (flag==1)
   {
     printf("\nCconn(G) stored in file: %s\n\n",argv[1]);
     argv[1][strlen(argv[1])-4]=argv[1][strlen(argv[1])];
     printf("\nC(G) stored in file: %s\n\n",argv[1]);
     argv[1][strlen(argv[1])-2]=argv[1][strlen(argv[1])];
     printf("\nCentralities stored in file: %s\n\n",strncat(argv[1],".SC",3));
     argv[1][strlen(argv[1])-3]=argv[1][strlen(argv[1])];
   }


 /***  ALEATORIAS  ***/

 printf("\nRandom Matrix: \n");
 for(i=0;i<na;i++)
   {
     printf("\r\t%d ",i+1);
     fflush(stdout);
     aleatcon(m,k,mrand);
     printf("\b*");
     fflush(stdout);
     calcula(mrand,k,&mf[i],&mfo[i],&mfe[i],&s[i],&c[i],&cg[i],&conng[i],0,NULL,NULL,NULL,nodos);
     //     mf[i]=media(mfv,k);
     //     mfo[i]=media(mfov,k);
     //     mfe[i]=media(mfev,k);
     if (isunordered(s[i],s[i])) i--;  // elimita matrices aleatorias que dan NaN en S
   }

 printf("\n\n");

 if (na!=0)
   {
     malet = fopen(strncat(argv[1],".R",2),"w");

     printf("\tsubgraph centrality \t\t\tSC \t = \t%g\t\tO(%g)\n",media(mf,na),ecm(mf,media(mf,na),na));
     printf("\tsubgraph centrality odd \t\tSCodd \t = \t%g\t\tO(%g)\n",media(mfo,na),ecm(mfo,media(mfo,na),na));
     printf("\tsubgraph centrality even \t\tSCeven \t = \t%g\t\tO(%g)\n",media(mfe,na),ecm(mfe,media(mfe,na),na));
     printf("\tbipartivity \t\t\t\tB(G) \t = \t%g\n",media(mfe,na)/media(mf,na));
     printf("\tentrophy \t\t\t\tS \t = \t%g\t\tO(%g)\n",media(s,na),ecm(s,media(s,na),na));
     printf("\tcommunicability \t\t\tC(G) \t = \t%g\t\tO(%g)\n",media(cg,na),ecm(cg,media(cg,na),na));
     printf("\tcommunicability for connected nodes \tCconn(G) = \t%g\t\tO(%g)\n",media(conng,na),ecm(conng,media(conng,na),na));


     
     /*    for(i=0;i<k-1;i++)
       {
	 if(!strcmp(nodos[i],"68")) j=i;
       }
     printf("68=%d\n",j);
    for(i=0;i<k-1;i++)
       {
	 if(!strcmp(nodos[i],"69")) j=i;
       }
     printf("69=%d\n",j);

     j=0;
    for(i=0;i<k-1;i++)
       {
	 j+=m[145][i];
       }
     printf("unos en fila 145=%d\n",j);
     j=0;
    for(i=0;i<k-1;i++)
       {
	 j+=m[106][i];
       }
     printf("unos en fila 106=%d\n",j);
     j=0;
    for(i=0;i<k-1;i++)
       {
	 j+=m[i][145];
       }
     printf("unos en columna 145=%d\n",j);
     j=0;
    for(i=0;i<k-1;i++)
       {
	 j+=m[i][106];
       }
     printf("unos en columna 106=%d\n",j);

     printf("ALEATORIA \n\n");
     j=0;
    for(i=0;i<k-1;i++)
       {
	 j+=mrand[145][i];
       }
     printf("unos en fila 145=%d\n",j);
     j=0;
    for(i=0;i<k-1;i++)
       {
	 j+=mrand[106][i];
       }
     printf("unos en fila 106=%d\n",j);
     j=0;
    for(i=0;i<k-1;i++)
       {
	 j+=mrand[i][145];
       }
     printf("unos en columna 145=%d\n",j);
     j=0;
    for(i=0;i<k-1;i++)
       {
	 j+=mrand[i][106];
       }
     printf("unos en columna 106=%d\n",j);

     */

     if (!strcmp(argv[3],"M"))
       {
	 for(i=0;i<k-1;i++)
	   {
	     for(j=i+1;j<k;j++)
	       {
		 if(mrand[i][j]==1)
		   {
		     fprintf(malet,"%d\t%d\n",i+1,j+1);
		   }
	       }
	   }
       }
     else
       {
	 for(i=0;i<k-1;i++)
	   {
	     for(j=i+1;j<k;j++)
	       {
		 if(mrand[i][j]==1)
		   {
		     fprintf(malet,"%s\t%s\n",nodos[i],nodos[j]);
		   }
	       }
	   }
       }

     printf("\nRandom Network stored in file: %s\n\n",argv[1]);

     /*for(i=0;i<k;i++)
    {
      sum=0;
      sum2=0;
      for(j=0;j<k;j++)
	{
	  if (i!=j)
	    {
	  sum+=m[i][j];
	  sum2+=mrand[i][j];
	  //	  printf("|%d,%d|",sum2,mrand[i][j]);
	    }
	}
      if (sum!=sum2) printf("i=%d,%d,%d ",i,sum,sum2);
    }
    printf("\n");*/

   }
 else {printf("\tNo Random Networks requested \n");}

 for (i=0;i<k;i++)
   {
     free(m[i]);
     free(mrand[i]);
     free(nodos[i]);
   }
 
 free(m);
 free(mrand);
 free(nodos);

 free(mf);
 free(mfo);
 free(mfe);
 free(s);
 free(c);
 free(cg);
 free(conng);

 printf("\n -- Successful execution --\n\n");
 printf("\nRedes v0.7  Copytight (c) CESGA. All rights reserved.\n");
 printf("\nThanks to:\t J. Carlos Mouriño, Ernesto Estrada and Andrés Gómez.\n\n");

}

int busca( char *a, char **nodos, int *l, int k, int *mayor)
{
  int i,valor;

    i=0;
    while (i<*l)
    {
      if (!strcmp(nodos[i],a))
	{
	  valor=i;
          i=*l+1;
	  //	  if (atoi(a)>*mayor) {*mayor=atoi(a);}
	}
      else
	{
	  i=i+1;
	}
    }
  if (i==*l)
    {
      if (i<k)
	{
	  nodos[i]=strcpy(nodos[i],a);
	  valor=i;
	  (*l)++;
	}
      else
	{
	  valor=-1;
	  //	  if (atoi(a)>*l) {*l=atoi(a);}
	  //	  printf("nuevo valor = %s",a);
	}
      if (atoi(a)>*mayor) {*mayor=atoi(a);}
    }
  return(valor);
}

void nomemo()
{
  printf("\nERROR: Memoria insuficiente\n");
  exit(1);
}

double ecm(double *vector, double media, int k)
{
  int i;
  double sum=0;

  for(i=0;i<k;i++)
    {
      //      printf("xxx%g,%g",vector[i],media);
      sum+=(vector[i]-media)*(vector[i]-media);
    }
  if (k>1) {return(sqrt(sum/(k*(k-1))));}
  else {return(0);}
}

