Beispiel #1
0
/*
  ---------------------------------------------------------------------
  
  ---------------------------------------------------------------------
*/
void
GibbsThermalizeLSMCMB_OD(double *H,
			 double linC,
			 struct node_gra **nlist,
			 struct group **glist,
			 struct group *part,
			 int nnod,
			 int **G2G,
			 int *n2gList,
			 double **LogChooseList,
			 int LogChooseListSize,
			 double *LogFactList, int LogFactListSize,
		         double *HarmonicList,	
		         gsl_rng *gen,
			 char verbose_sw)
{
  double HMean0=1.e10, HStd0=1.e-10, HMean1, HStd1, *Hvalues;
  int rep, nrep=20;
  int equilibrated=0;

  Hvalues = allocate_d_vec(nrep);

  do {
    
    /* MC steps */
    for (rep=0; rep<nrep; rep++) {
      GibbsLinkScoreStepMB_OD(H, linC, nlist, glist, part,
			 nnod, G2G, n2gList, LogChooseList, LogChooseListSize,
			 LogFactList, LogFactListSize, HarmonicList,
			 gen);
      switch (verbose_sw) {
      case 'q':
	/*PartitionHMB(part, linC, HarmonicList);*/ /* Number of groups */
	break;
      case 'd':
	fprintf(stderr, "%lf %lf %d\n", *H, PartitionHMB(part, linC, HarmonicList),
		NNonEmptyGroups(part));
	break;
      default:
	fprintf(stderr, "%lf\n", *H);
	break;
      }
      Hvalues[rep] = *H;
    }
    
    /* Check for equilibration */
    HMean1 = mean(Hvalues, nrep);
    HStd1 = stddev(Hvalues, nrep);
    if ((HMean0 - HStd0 / sqrt(nrep)) - (HMean1 + HStd1 / sqrt(nrep))
	< EPSILON) {
      equilibrated++;
      switch (verbose_sw) {
      case 'q':
	break;
      default:
	fprintf(stderr, "#\tequilibrated (%d/5) H=%lf\n",
		equilibrated, HMean1);
	break;
      }
    }
    else {
      switch (verbose_sw) {
      case 'q':
	break;
      default:
	fprintf(stderr, "#\tnot equilibrated yet H0=%g+-%g H1=%g+-%g\n",
		HMean0, HStd0 / sqrt(nrep), HMean1, HStd1 / sqrt(nrep));
	break;
      }
      HMean0 = HMean1;
      HStd0 = HStd1;
      equilibrated = 0;
    }

  } while (equilibrated < 5);
  
  /* Clean up */
  free_d_vec(Hvalues);

  return;
}
Beispiel #2
0
/*
  ---------------------------------------------------------------------
  
  ---------------------------------------------------------------------
*/
int
GetDecorrelationStepMB_OD(double *H,
		       double linC,
		       struct node_gra **nlist,
		       struct group **glist,
		       struct group *part,
		       int nnod,
		       int **G2G,
		       int *n2gList,
		       double **LogChooseList,
		       int LogChooseListSize,
		       double *LogFactList, int LogFactListSize,
		       double *HarmonicList,
		       gsl_rng *gen,
		       char verbose_sw)
{
  struct group *partRef;
  int step, x1, x2;
  double y1, y2;
  double mutualInfo;
  int rep, nrep=10;
  double *decay, meanDecay, sigmaDecay, result;
  int norm=0;

  x2 = nnod / 5;
  x1 = x2 / 4;

  /* Get the nrep initial estimates */
  decay = allocate_d_vec(nrep);
  for (rep=0; rep<nrep; rep++) {
    switch (verbose_sw) {
    case 'q':
      break;
    default:
      fprintf(stderr, "#\n# Estimating decorrelation time (%d/%d)\n",
	      rep + 1, nrep);
      break;
    }
    partRef = CopyPartition(part);
    for (step=0; step<=x2; step++) {
      LSMCStepMB_OD(1, H, linC, nlist, glist, part,
		 nnod, G2G, n2gList,
		 LogChooseList, LogChooseListSize,
		 LogFactList, LogFactListSize, HarmonicList,
		 gen);
      if (step == x1)
	y1 = MutualInformation(partRef, part);
    }
    y2 = MutualInformation(partRef, part);
    RemovePartition(partRef);
    decay[rep] = 2. * CalculateDecay(nnod, x1, y1, x2, y2);
    switch (verbose_sw) {
    case 'q':
      break;
    default:
      fprintf(stderr, "# Decorrelation time (estimate %d) = %g\n",
	      rep + 1, decay[rep]);
      break;
    }
    if (decay[rep] < 0) {
      rep--;
      switch (verbose_sw) {
      case 'q':
	break;
      default:
	fprintf(stderr, "#\tignoring...\n");
	break;
      }
    }
  }
  
  /* Get rid of bad estimates (Chauvenet criterion)  */
  meanDecay = mean(decay, nrep);
  sigmaDecay = stddev(decay, nrep);
  result = meanDecay * nrep;
  for (rep=0; rep<nrep; rep++) {
    if (fabs(decay[rep] - meanDecay) / sigmaDecay > 2) {
      result -= decay[rep];
      switch (verbose_sw) {
      case 'q':
	break;
      default:
	fprintf(stderr, "# Disregarding estimate %d\n", rep + 1);
	break;
      }
    }
    else {
      norm++;
    }
  }
  
  /* Clean up */
  free_d_vec(decay);

  return result / norm;
}
Beispiel #3
0
/*
  ---------------------------------------------------------------------
  Do a Gibbs Monte Carlo step for the prediction of missing links.
  ---------------------------------------------------------------------
*/
void
GibbsLinkScoreStepMB_OD(double *H,
		   double linC,
		   struct node_gra **nlist,
		   struct group **glist,
		   struct group *part,
		   int nnod,
		   int **G2G,
		   int *n2gList,
		   double **LogChooseList,
		   int LogChooseListSize,
		   double *LogFactList, int LogFactListSize, double *HarmonicList,	
		   gsl_rng *gen)
{
  double *dH;
  struct group *g, *oldg, *newg;
  int oldgnum, newgnum, n2g, oldg2g, newg2g, ng, noldg, nnewg;
  struct node_gra *node;
  int n2oldg, n2newg, newg2oldg, oldg2oldg, newg2newg;
  int r, l;
  int i, j, ngroup=nnod;
  int move;
  int effectng;
  /* Shortlist of groups. Groups not in this list are empty for
     sure. Note that, during a step, we may have to add groups to this
     list (groups that were initially empty but got filled) but we
     never remove groups from it (even if they loose all their nodes
     during a step). slgXsize is the size of slgX. */
  int *slg=NULL;
  int slgn, slgsize, isinlist;
  int newgn, target;
  double dice, norm, dHempty, cum;
  double Href;
  
  /* Preliminaries */

  dH = allocate_d_vec(nnod);
  slg = allocate_i_vec(nnod);  // Shortlist of groups
  slgsize = 0;
  g = part;
  while ((g=g->next) != NULL)
    if (g->size > 0)
      slg[slgsize++] = g->label;

  /* Steps */
  for (move=0; move<nnod; move++) {
    node = nlist[move];
    oldgnum = node->inGroup;
    oldg = glist[oldgnum];
    norm = 0.0;

    /* Loop over destination groups */
    for (newgn=0; newgn<slgsize; newgn++) {
      newgnum = slg[newgn];
      newg = glist[newgnum];

      if (newgnum != oldgnum) {	
	/* Calculate the change of energy */
	dH[newgnum] = 0.0;
	noldg = oldg->size;
	nnewg = newg->size;
	if (noldg == 1)  /* number of groups would decrease by one */ 
	  dH[newgnum] -= linC;
	if (nnewg == 0)  /* number of groups would increase by one */
	  dH[newgnum] += linC;
	n2oldg = NLinksToGroup(node, oldg);
	n2newg = NLinksToGroup(node, newg);
	newg2oldg = NG2GLinks(newg, oldg);
	oldg2oldg = oldg->inlinks;
	newg2newg = newg->inlinks;
	effectng = 0;
	for (slgn=0; slgn<slgsize; slgn++) {
	  g = glist[slg[slgn]];
	  if (g->size > 0) {  /* group is not empty */
	    effectng++;
	    n2gList[g->label] = NLinksToGroup(node, g);
	    if (g->label == oldg->label) {
	      /* old conf, oldg-oldg */
	      r = noldg * (noldg - 1) / 2;
	      l = oldg2oldg;
	      dH[newgnum] -= log(r + 1) + FastLogChoose(r, l,
							LogChooseList,
							LogChooseListSize);
	      /*dH[newgnum] -= -log(HarmonicList[r + 1] - HarmonicList[l]);*/
	      /* new conf, oldg-olg */
	      r = (noldg - 1) * (noldg - 2) / 2;
	      l = oldg2oldg - n2oldg;
	      dH[newgnum] += log(r + 1) + FastLogChoose(r, l,
							LogChooseList,
							LogChooseListSize);
	      /*dH[newgnum] += -log(HarmonicList[r + 1] - HarmonicList[l]);*/
	      /* old conf, newg-oldg */
	      r = nnewg * noldg;
	      l = newg2oldg;
	      dH[newgnum] -= log(r + 1) + FastLogChoose(r, l,
							LogChooseList,
							LogChooseListSize);
	      /*dH[newgnum] -= -log(HarmonicList[r + 1] - HarmonicList[l]);*/
	      /* new conf, newg-oldg */
	      r = (nnewg + 1) * (noldg - 1);
	      l = newg2oldg + n2oldg - n2newg;
	      dH[newgnum] += log(r + 1) + FastLogChoose(r, l,
							LogChooseList,
							LogChooseListSize);
	      /*dH[newgnum] += -log(HarmonicList[r + 1] - HarmonicList[l]);*/
	    }
	    else if (g->label == newg->label) {
	      /* old conf, newg-newg */
	      r = nnewg * (nnewg - 1) / 2;
	      l = newg2newg;
	      dH[newgnum] -= log(r + 1) + FastLogChoose(r, l,
							LogChooseList,
							LogChooseListSize);
	      /*dH[newgnum] -= -log(HarmonicList[r + 1] - HarmonicList[l]);*/
	      /* new conf, newg-olg */
	      r = (nnewg + 1) * nnewg / 2;
	      l = newg2newg + n2newg;
	      dH[newgnum] += log(r + 1) + FastLogChoose(r, l,
							LogChooseList,
							LogChooseListSize);
	      /*dH[newgnum] += -log(HarmonicList[r + 1] - HarmonicList[l]);*/
	    }
	    else {
	      n2g = n2gList[g->label];
	      oldg2g = G2G[oldg->label][g->label];
	      newg2g = G2G[newg->label][g->label];
	      ng = g->size;
	      /* old conf, oldg-g */
	      r = noldg * ng;
	      l = oldg2g;
	      dH[newgnum] -= log(r + 1) + FastLogChoose(r, l,
							LogChooseList,
							LogChooseListSize);
	      /*dH[newgnum] -= -log(HarmonicList[r + 1] - HarmonicList[l]);*/
	      /* new conf, oldg-g */
	      r = (noldg - 1) * ng;
	      l = oldg2g - n2g;
	      dH[newgnum] += log(r + 1) + FastLogChoose(r, l,
							LogChooseList,
							LogChooseListSize);
	      /*dH[newgnum] += -log(HarmonicList[r + 1] - HarmonicList[l]);*/
	      /* old conf, newg-g */
	      r = nnewg * ng;
	      l = newg2g;
	      dH[newgnum] -= log(r + 1) + FastLogChoose(r, l,
							LogChooseList,
							LogChooseListSize);
	      /*dH[newgnum] -= -log(HarmonicList[r + 1] - HarmonicList[l]);*/
	      /* new conf, newg-g */
	      r = (nnewg + 1) * ng;
	      l = newg2g + n2g;
	      dH[newgnum] += log(r + 1) + FastLogChoose(r, l,
							LogChooseList,
							LogChooseListSize);
	      /*dH[newgnum] += -log(HarmonicList[r + 1] - HarmonicList[l]);*/
	    }
	  }
	  else { /* group is empty */
	    n2gList[g->label] = 0.0;
	  }
	}


	/* Labeled-groups sampling correction */
	if (noldg == 1 && nnewg != 0) { // effectng would decrease by one
	  dH[newgnum] -= -FastLogFact(ngroup - effectng, LogFactList, LogFactListSize);
	  dH[newgnum] += -FastLogFact(ngroup - (effectng-1), LogFactList, LogFactListSize);
	  dH[newgnum] += LogDegeneracy_OD(effectng) - LogDegeneracy_OD(effectng - 1);
	}
	else if (noldg != 1 && nnewg == 0) {  // effectng would increase by one
	  dH[newgnum] -= -FastLogFact(ngroup - effectng, LogFactList, LogFactListSize);
	  dH[newgnum] += -FastLogFact(ngroup - (effectng+1), LogFactList, LogFactListSize);
	  dH[newgnum] += LogDegeneracy_OD(effectng) - LogDegeneracy_OD(effectng + 1);
	}
      }

      else { // oldg and newg are the same: nothing changes
	dH[newgnum] = 0.0;
      }

      norm += exp(-dH[newgnum]);
    }

    /** Calculate the change of energy to go to an empty group **/
    dHempty = 0.0;
    nnewg = 0;
    if (noldg == 1)  /* number of groups would decrease by one */ 
      dHempty -= linC;
    if (nnewg == 0)  /* number of groups would increase by one */
      dHempty += linC;
    n2newg = 0;
    newg2oldg = 0;
    newg2newg = 0;

    for (slgn=0; slgn<slgsize; slgn++) {
      g = glist[slg[slgn]];
      if (g->size > 0) {  /* group is not empty */
	if (g->label == oldg->label) {
	  /* old conf, oldg-oldg */
	  r = noldg * (noldg - 1) / 2;
	  l = oldg2oldg;
	  dHempty -= log(r + 1) + FastLogChoose(r, l,
						LogChooseList,
						LogChooseListSize);
	  /*dHempty -= -log(HarmonicList[r + 1] - HarmonicList[l]);*/
	  /* new conf, oldg-olg */
	  r = (noldg - 1) * (noldg - 2) / 2;
	  l = oldg2oldg - n2oldg;
	  dHempty += log(r + 1) + FastLogChoose(r, l,
						LogChooseList,
						LogChooseListSize);
	  /*dHempty += -log(HarmonicList[r + 1] - HarmonicList[l]);*/
	  /* old conf, newg-oldg */
	  r = nnewg * noldg;
	  l = newg2oldg;
	  dHempty -= log(r + 1) + FastLogChoose(r, l,
						LogChooseList,
						LogChooseListSize);
	  /*dHempty -= -log(HarmonicList[r + 1] - HarmonicList[l]);*/
	  /* new conf, newg-oldg */
	  r = (nnewg + 1) * (noldg - 1);
	  l = newg2oldg + n2oldg - n2newg;
	  dHempty += log(r + 1) + FastLogChoose(r, l,
						LogChooseList,
						LogChooseListSize);
	  /*dHempty += -log(HarmonicList[r + 1] - HarmonicList[l]);*/
	}
	else {
	  n2g = n2gList[g->label];
	  oldg2g = G2G[oldg->label][g->label];
	  newg2g = 0;
	  ng = g->size;
	  /* old conf, oldg-g */
	  r = noldg * ng;
	  l = oldg2g;
	  dHempty -= log(r + 1) + FastLogChoose(r, l,
						LogChooseList,
						LogChooseListSize);
	  /*dHempty -= -log(HarmonicList[r + 1] - HarmonicList[l]);*/
	  /* new conf, oldg-g */
	  r = (noldg - 1) * ng;
	  l = oldg2g - n2g;
	  dHempty += log(r + 1) + FastLogChoose(r, l,
						LogChooseList,
						LogChooseListSize);
	  /*dHempty += -log(HarmonicList[r + 1] - HarmonicList[l]);*/
	  /* old conf, newg-g */
	  r = nnewg * ng;
	  l = newg2g;
	  dHempty -= log(r + 1) + FastLogChoose(r, l,
						LogChooseList,
						LogChooseListSize);
	  /*dHempty -= -log(HarmonicList[r + 1] - HarmonicList[l]);*/
	  /* new conf, newg-g */
	  r = (nnewg + 1) * ng;
	  l = newg2g + n2g;
	  dHempty += log(r + 1) + FastLogChoose(r, l,
						LogChooseList,
						LogChooseListSize);
	  /*dHempty += -log(HarmonicList[r + 1] - HarmonicList[l]);*/
	}
      }
    }

    /* Labeled-groups sampling correction */
    if (noldg == 1 && nnewg != 0) { // effectng would decrease by one
      dHempty -= -FastLogFact(ngroup - effectng, LogFactList, LogFactListSize);
      dHempty += -FastLogFact(ngroup - (effectng-1), LogFactList, LogFactListSize);
      dHempty += LogDegeneracy_OD(effectng) - LogDegeneracy_OD(effectng - 1);
    }
    else if (noldg != 1 && nnewg == 0) {  // effectng would increase by one
      dHempty -= -FastLogFact(ngroup - effectng, LogFactList, LogFactListSize);
      dHempty += -FastLogFact(ngroup - (effectng+1), LogFactList, LogFactListSize);
      dHempty += LogDegeneracy_OD(effectng) - LogDegeneracy_OD(effectng + 1);
    }

    norm += exp(-dHempty) * (double)(nnod - slgsize);
    
    /** CHOOSE THE MOVE **/
    dice = norm * gsl_rng_uniform(gen);

    if (dice > (norm - (double)(nnod - slgsize) * exp(-dHempty))) {
      /* Select an empty group */
      newg = GetEmptyGroup(part);
      newgnum = newg->label;
      dH[newgnum] = dHempty;
    }
    else {
      /* Select group in shortlist */
      target = 0;
      cum = 0.0;
      while (cum < dice) {
	cum += exp(-dH[slg[target++]]);
      }
      newgnum = slg[target - 1];
      newg = glist[newgnum];
    }
    
    /* MAKE THE MOVE AND UPDATE MATRICES */
    MoveNode(node, oldg, newg);
    *H += dH[newgnum];
    
    /* update G2G */
    for (slgn=0; slgn<slgsize; slgn++) {
      G2G[slg[slgn]][oldgnum] -= n2gList[slg[slgn]];
      G2G[oldgnum][slg[slgn]] = G2G[slg[slgn]][oldgnum];
      G2G[slg[slgn]][newgnum] += n2gList[slg[slgn]];
      G2G[newgnum][slg[slgn]] = G2G[slg[slgn]][newgnum];
    }
    
    /* Add newg to shortlist (if it's not there already!) */
    isinlist = 0;
    for (slgn=0; slgn<slgsize; slgn++)
      if (newgnum == slg[slgn])
	isinlist = 1;
    if (isinlist == 0)
      slg[slgsize++] = newgnum;
  }  /* nnod moves completed: done! */

  free_i_vec(slg);
  free_d_vec(dH);
}
int
main(int argc, char **argv)
{
  long seed = 1111;
  FILE *inFile,*outFile;
  struct node_gra *net = NULL;
  struct node_gra *netran = NULL;
  struct node_gra *p = NULL;
  int S;
  int c;
  struct group *part = NULL;
  struct group *roles = NULL;
  int i,t1;
  int rep = 0;
  double realmod;
  double ranmodav, ranmodst;
  double *ranmodlis;
  double Tsched = 0.995, Tf = 0.0;
  double iterfac = 1.0;
  gsl_rng *rand_gen;
  char *netF;
  /*
    ------------------------------------------------------------
    Prompt for user-defined parameters
    ------------------------------------------------------------
  */
  printf ("%d\n",argc);
  if (argc == 1) {

  printf("\n# Enter random number seed (POSITIVE integer): ");
  scanf("%d", &seed);

  printf("\n# Enter the name of the network file: ");
  scanf("%s", &netF);

  printf("\n# Enter iteration factor (recommended 1.0): ");
  scanf("%lf", &iterfac);

  printf("\n# Enter the cooling factor (recommended 0.950-0.995): ");
  scanf("%lf", &Tsched);

  printf("\n# Enter the number of randomizations: ");
  scanf("%d", &rep);
  } else {
while ((c = getopt(argc, argv, "hf:s:i:c:r:")) != -1)
	  switch (c) {
	  case 'h':
		printf(USAGE ARGUMENTS);
		return -1;
		break;
	  case 'f':
		netF = optarg;
		break;
	  case 's':
		seed = atoi(optarg);
		break;
	  case 'r':
		rep = atoi(optarg);
		break;
	  case 'i':
		iterfac = atof(optarg);
		break;
	  case 'c':
		Tsched = atof(optarg);
		break;
	  }
  }
  ranmodlis = allocate_d_vec(rep);

  /*
    ------------------------------------------------------------
    Initialize the random number generator
    ------------------------------------------------------------
  */
  rand_gen = gsl_rng_alloc(gsl_rng_mt19937);
  gsl_rng_set(rand_gen, seed);

  /*
    ------------------------------------------------------------
    Build the network
    ------------------------------------------------------------
  */
  fprintf(stderr, "\n# Creating the network\n");

  inFile=fopen(netF,"r");
  net = FBuildNetwork(inFile, 0, 0, 0, 1);
  fclose(inFile);

  S = CountNodes(net);
  fprintf(stderr, "\n# The network has %d nodes\n", S);

  /*
    ------------------------------------------------------------
    Find and print the modules
    ------------------------------------------------------------
  */
  fprintf(stderr, "\n# Starting the simulated annealing\n");
  fprintf(stderr, "\n# 1/T\tM\tT\n");

  part = SACommunityIdent(net,
			  2.0 / (double)S, Tf, Tsched,
			  iterfac, 0, 'o', 1, 's', rand_gen);

  outFile = fopen("modules.dat", "w");
  FPrintPartition(outFile, part, 0);
  realmod = Modularity(part);
  fprintf(outFile, "# Modularity = %g\n", realmod);
  fclose(outFile);

  FPrintPajekFile("network.net", net, 0, 0, 1);
  FPrintPajekPartitionFile("modules.clu", net);

  /*
    ------------------------------------------------------------
    Calculate and print node properties
    ------------------------------------------------------------
  */
  outFile=fopen("node_prop.dat","w");
  p = net;
  while ((p = p->next) != NULL) {
    fprintf(outFile,"%s %d %lf %lf\n",
	    p->label, NodeDegree(p),
	    ParticipationCoefficient(p),
	    WithinModuleRelativeDegree(p, part));
  }
  fclose(outFile);

  /*
    ------------------------------------------------------------
    Find and print the roles
    ------------------------------------------------------------
  */
  fprintf(stderr, "\n# Finding node roles\n");
  roles = CatalogRoleIdent(net, part);

  outFile = fopen("roles.dat","w");
  FPrintPartition(outFile, roles, 0);
  fclose(outFile);

  MapPartToNet(roles, net);
  FPrintPajekPartitionFile("roles.clu", net);

  /*
    ------------------------------------------------------------
    Calculate properties for the randomized graph
    ------------------------------------------------------------
  */
  ranmodav = 0.0;
  for (i=0; i<rep; i++) {
    fprintf(stderr, "\nRandomization %d\n", i+1);

    RemovePartition(part);
    if ( netran != NULL)
      RemoveGraph(netran);

    netran = RandomizeSymmetricNetwork(CopyNetwork(net), 100, rand_gen);
    part = SACommunityIdent(netran,
			    2.0 / (double)S, Tf, Tsched,
			    iterfac, 0, 'o', 1, 'n', rand_gen);
    ranmodlis[i] = Modularity(part);
    ranmodav += ranmodlis[i];
  }

  /* Average and standard deviation */
  ranmodav /= (double)rep;
  ranmodst = 0.0;
  for (i=0; i<rep; i++) {
    ranmodst += (ranmodlis[i] - ranmodav) * (ranmodlis[i] - ranmodav);
  }
  ranmodst = sqrt(ranmodst / (double)rep);

  outFile = fopen("randomized_mod.dat", "w");
  fprintf(outFile, "# M\tMrand\tsimga_Mrand\n");
  fprintf(outFile, "%lf %lf %lf\n", realmod, ranmodav, ranmodst);
  fclose(outFile);

  /*
    ------------------------------------------------------------
    Free memory
    ------------------------------------------------------------
  */
  gsl_rng_free(rand_gen);
  free_d_vec(ranmodlis);
  RemovePartition(part);
  RemovePartition(roles);
  RemoveGraph(net);
  if (netran != NULL)
    RemoveGraph(netran);
  return 0;
}