Raw File
mhloop.h

/* 
   mhloop.h

   This file contains the iteration loop 
   for the Metropolis-Hastings algorithm methas.c 

   It is #included several times in methas.c
   with different #defines for the following variables

   MH_MARKED    whether the simulation is marked
               (= the variable 'marked' is TRUE)

   MH_SINGLE    whether there is a single interaction 
              (as opposed to a hybrid of several interactions)

   MH_TRACKING  whether to save transition history

   MH_DEBUG     whether to print debug information
   
   MH_SNOOP     whether to run visual debugger

   $Revision: 1.18 $  $Date: 2013/05/27 02:09:10 $ 

*/

#ifndef MH_DEBUG
#define MH_DEBUG NO
#endif

OUTERCHUNKLOOP(irep, algo.nrep, maxchunk, 1024) {
  R_CheckUserInterrupt();
  INNERCHUNKLOOP(irep, algo.nrep, maxchunk, 1024) {

#if MH_DEBUG
    Rprintf("iteration %d\n", irep);
#endif

    if(verb) {
      /* print progress message every nverb iterations */
      iverb = irep + 1 + algo.nrep0;
      if((iverb % algo.nverb) == 0)
	Rprintf("iteration %d\n", iverb);
    }

    itype = REJECT;

    nfree = state.npts - algo.ncond;  /* number of 'free' points */

    /* ................  generate proposal ..................... */
    /* Shift or birth/death: */
    if(unif_rand() > algo.p) {
#if MH_DEBUG
      Rprintf("propose birth or death\n");
#endif
      /* Birth/death: */
      if(unif_rand() > algo.q) {
	/* Propose birth: */
	birthprop.u = xpropose[irep];
	birthprop.v = ypropose[irep];
#if MH_MARKED
	birthprop.mrk = mpropose[irep];
#endif
#if MH_DEBUG
#if MH_MARKED
	Rprintf("propose birth at (%lf, %lf) with mark %d\n", 
		birthprop.u, birthprop.v, birthprop.mrk);
#else
	Rprintf("propose birth at (%lf, %lf)\n", birthprop.u, birthprop.v);
#endif
#endif
	/* evaluate conditional intensity */

#if MH_MARKED
	betavalue = model.beta[birthprop.mrk];
#endif

#if MH_SINGLE
	anumer = betavalue * (*(thecif.eval))(birthprop, state, thecdata);
#else
	anumer = betavalue;
	for(k = 0; k < Ncif; k++)
	  anumer *= (*(cif[k].eval))(birthprop, state, cdata[k]);
#endif

	adenom = qnodds*(nfree+1);

#if MH_DEBUG
	Rprintf("cif = %lf, Hastings ratio = %lf\n", anumer, anumer/adenom);
#endif

	/* accept/reject */
	if(unif_rand() * adenom < anumer) {
#if MH_DEBUG
	  Rprintf("accepted birth\n");
#endif
	  itype = BIRTH;  /* Birth proposal accepted. */
	}
#if MH_SNOOP
	/* visual debug */
	mhsnoop(&snooper, irep, &algo, &state, &birthprop, 
		anumer, adenom, &itype);
#endif
#if MH_TRACKING
	/* save transition history */
	if(irep < history.nmax) {
	  history.n++;
	  history.proptype[irep] = BIRTH;
	  history.accepted[irep] = (itype == REJECT) ? 0 : 1;
#ifdef HISTORY_INCLUDES_RATIO
	  history.numerator[irep] = anumer;
	  history.denominator[irep] = adenom;
#endif
	}
#endif
      } else if(nfree > 0) {
	/* Propose death: */
	ix = floor(nfree * unif_rand());
	if(ix < 0) ix = 0;
	ix = algo.ncond + ix;
	if(ix >= state.npts) ix = state.npts - 1;
	deathprop.ix = ix;
	deathprop.u  = state.x[ix];
	deathprop.v  = state.y[ix];
#if MH_MARKED
	deathprop.mrk = state.marks[ix];
#endif
#if MH_DEBUG
#if MH_MARKED
	Rprintf("propose death of point %d = (%lf, %lf) with mark %d\n", 
		ix, deathprop.u, deathprop.v, deathprop.mrk);
#else
	Rprintf("propose death of point %d = (%lf, %lf)\n", 
		ix, deathprop.u, deathprop.v);
#endif
#endif
	/* evaluate conditional intensity */

#if MH_MARKED
	betavalue = model.beta[deathprop.mrk];
#endif

#if MH_SINGLE
	adenom = betavalue * (*(thecif.eval))(deathprop, state, thecdata);
#else
	adenom = betavalue;
	for(k = 0; k < Ncif; k++)
	  adenom *= (*(cif[k].eval))(deathprop, state, cdata[k]);
#endif
	anumer = qnodds * nfree;
#if MH_DEBUG
	Rprintf("cif = %lf, Hastings ratio = %lf\n", adenom, anumer/adenom);
#endif
	/* accept/reject */
	if(unif_rand() * adenom < anumer) {
#if MH_DEBUG
	  Rprintf("accepted death\n");
#endif
	  itype = DEATH; /* Death proposal accepted. */
	}
#if MH_SNOOP
	/* visual debug */
	mhsnoop(&snooper, irep, &algo, &state, &deathprop, 
		anumer, adenom, &itype);
#endif
#if MH_TRACKING
	/* save transition history */
	if(irep < history.nmax) {
	  history.n++;
	  history.proptype[irep] = DEATH;
	  history.accepted[irep] = (itype == REJECT) ? 0 : 1;
#ifdef HISTORY_INCLUDES_RATIO
	  history.numerator[irep] = anumer;
	  history.denominator[irep] = adenom;
#endif
	}
#endif
      }
    } else if(nfree > 0) {
      /* Propose shift: */
      /* point to be shifted */
      ix = floor(nfree * unif_rand());
      if(ix < 0) ix = 0;
      ix = algo.ncond + ix;
      if(ix >= state.npts) ix = state.npts - 1;
      deathprop.ix = ix;
      deathprop.u  = state.x[ix];
      deathprop.v  = state.y[ix];
#if MH_MARKED
      deathprop.mrk = state.marks[ix];
#endif
      /* where to shift */
      shiftprop.u = xpropose[irep]; 
      shiftprop.v = ypropose[irep];
#if MH_MARKED
      shiftprop.mrk = (algo.fixall) ? deathprop.mrk : mpropose[irep];
#endif
      shiftprop.ix = ix;
#if MH_DEBUG
#if MH_MARKED
      Rprintf("propose shift of point %d = (%lf, %lf)[mark %d] to (%lf, %lf)[mark %d]\n", 
	      ix, deathprop.u, deathprop.v, deathprop.mrk, 
	      shiftprop.u, shiftprop.v, shiftprop.mrk);
#else
      Rprintf("propose shift of point %d = (%lf, %lf) to (%lf, %lf)\n", 
	      ix, deathprop.u, deathprop.v, shiftprop.u, shiftprop.v);
#endif
#endif
      /* evaluate cif in two stages */
#if MH_SINGLE
      cvd = (*(thecif.eval))(deathprop, state, thecdata);
      cvn = (*(thecif.eval))(shiftprop, state, thecdata);
#else
      cvd = cvn = 1.0;
      for(k = 0; k < Ncif; k++) {
	cvd *= (*(cif[k].eval))(deathprop, state, cdata[k]);
	cvn *= (*(cif[k].eval))(shiftprop, state, cdata[k]);
      }
#endif

#if MH_MARKED
      if(!algo.fixall) {
	cvn *= model.beta[shiftprop.mrk];
	cvd *= model.beta[deathprop.mrk];
      }
#endif

#if MH_DEBUG
      Rprintf("cif[old] = %lf, cif[new] = %lf, Hastings ratio = %lf\n", 
	      cvd, cvn, cvn/cvd);
#endif
      /* accept/reject */
      if(unif_rand() * cvd < cvn) {
#if MH_DEBUG
	Rprintf("accepted shift\n");
#endif
	itype = SHIFT;          /* Shift proposal accepted . */
      }
#if MH_SNOOP
	/* visual debug */
	mhsnoop(&snooper, irep, &algo, &state, &shiftprop, 
		cvn, cvd, &itype);
#endif
#if MH_TRACKING
      /* save transition history */
      if(irep < history.nmax) {
	history.n++;
	history.proptype[irep] = SHIFT;
	history.accepted[irep] = (itype == REJECT) ? 0 : 1;
#ifdef HISTORY_INCLUDES_RATIO
	  history.numerator[irep] = cvn;
	  history.denominator[irep] = cvd;
#endif
      }
#endif
    }

    if(itype != REJECT) {
      /* ....... implement the transition ............  */
      if(itype == BIRTH) {      
	/* Birth transition */
	/* add point at (u,v) */
#if MH_DEBUG
#if MH_MARKED
	Rprintf("implementing birth at (%lf, %lf) with mark %d\n", 
		birthprop.u, birthprop.v, birthprop.mrk);
#else
	Rprintf("implementing birth at (%lf, %lf)\n", 
		birthprop.u, birthprop.v);
#endif
#endif
	if(state.npts + 1 > state.npmax) {
#if MH_DEBUG
	  Rprintf("!!!!!!!!!!! storage overflow !!!!!!!!!!!!!!!!!\n");
#endif
	  /* storage overflow; allocate more storage */
	  Nmore = 2 * state.npmax;
	  state.x = (double *) S_realloc((char *) state.x, 
					 Nmore,  state.npmax, 
					 sizeof(double));
	  state.y = (double *) S_realloc((char *) state.y, 
					 Nmore,  state.npmax, 
					 sizeof(double));
#if MH_MARKED
	  state.marks = (int *) S_realloc((char *) state.marks, 
					  Nmore,  state.npmax, 
					  sizeof(int));
#endif
	  state.npmax = Nmore;

	  /* call the initialiser again, to allocate additional space */
#if MH_SINGLE
	  thecdata = (*(thecif.init))(state, model, algo);
#else
	  model.ipar = iparvector;
	  for(k = 0; k < Ncif; k++) {
	    if(k > 0)
	      model.ipar += plength[k-1];
	    cdata[k] = (*(cif[k].init))(state, model, algo);
	  }	
#endif
#if MH_DEBUG
	  Rprintf("........... storage extended .................\n");
#endif
	}
	
	if(mustupdate) {
	  /* Update auxiliary variables first */
#if MH_SINGLE
	  (*(thecif.update))(state, birthprop, thecdata);
#else
	  for(k = 0; k < Ncif; k++) {
	    if(needupd[k])
	      (*(cif[k].update))(state, birthprop, cdata[k]);
	  }
#endif
	}
	/* Now add point */
	state.x[state.npts] = birthprop.u;
	state.y[state.npts] = birthprop.v;
#if MH_MARKED
	state.marks[state.npts] = birthprop.mrk;
#endif
	state.npts     = state.npts + 1;
#if MH_DEBUG
	Rprintf("\tnpts=%d\n", state.npts);
#endif
      } else if(itype==DEATH) { 
	/* Death transition */
	/* delete point x[ix], y[ix] */
	if(mustupdate) {
	  /* Update auxiliary variables first */
#if MH_SINGLE
	  (*(thecif.update))(state, deathprop, thecdata);
#else
	  for(k = 0; k < Ncif; k++) {
	    if(needupd[k])
	      (*(cif[k].update))(state, deathprop, cdata[k]);
	  }
#endif
	}
	ix = deathprop.ix;
	state.npts = state.npts - 1;
#if MH_DEBUG
	Rprintf("implementing death of point %d\n", ix);
	Rprintf("\tnpts=%d\n", state.npts);
#endif
	if(ix < state.npts) {
	  for(j = ix; j < state.npts; j++) {
	    state.x[j] = state.x[j+1];
	    state.y[j] = state.y[j+1];
#if MH_MARKED
	    state.marks[j] = state.marks[j+1];
#endif
	  }
	}
      } else {
	/* Shift transition */
	/* Shift (x[ix], y[ix]) to (u,v) */
#if MH_DEBUG
#if MH_MARKED
	Rprintf("implementing shift from %d = (%lf, %lf)[%d] to (%lf, %lf)[%d]\n", 
		deathprop.ix, deathprop.u, deathprop.v, deathprop.mrk,
		shiftprop.u, shiftprop.v, shiftprop.mrk);
#else
	Rprintf("implementing shift from %d = (%lf, %lf) to (%lf, %lf)\n", 
		deathprop.ix, deathprop.u, deathprop.v,
		shiftprop.u, shiftprop.v);
	Rprintf("\tnpts=%d\n", state.npts);
#endif
#endif
	if(mustupdate) {
	  /* Update auxiliary variables first */
#if MH_SINGLE
	  (*(thecif.update))(state, shiftprop, thecdata);
#else
	  for(k = 0; k < Ncif; k++) {
	    if(needupd[k])
	      (*(cif[k].update))(state, shiftprop, cdata[k]);
	  }
#endif
	}
	ix = shiftprop.ix;
	state.x[ix] = shiftprop.u;
	state.y[ix] = shiftprop.v;
#if MH_MARKED
	state.marks[ix] = shiftprop.mrk;
#endif
      }
#if MH_DEBUG
    } else {
      Rprintf("rejected\n");
#endif
    }
  }
}
back to top