示例#1
0
文件: demo.c 项目: wbuntine/libstb
int main(int argc, char* argv[])
{
  int i, j, c, iter, ITER=200;
  unsigned long int seed=0;
  int bcycle = 0;
  float bstart = 0;
  int acycle = 0;
  float astart = 0;
  int burnin = 0;
  stable_t *ST = NULL;
  int useN = DIM*2;

  MAXN = 1;
  MAXT = MAXSTAB;
  /*
   *  default values for args
   */
  while ( (c=getopt(argc, argv,"a:b:B:C:I:hH:I:N:P:S:s:T:v"))>=0 ) {
    switch ( c ) {
    case 'h':
      usage(burnin?burnin:ITER/2, ITER, useN);
      exit(0);
    case 'b':
      if ( !optarg || sscanf(optarg,"%f,%f",&bpar, &bstart)<1 )
	yaps_quit("Need a valid 'b' argument\n");
      break;
    case 'a':
      if ( !optarg || sscanf(optarg,"%f,%f",&apar,&astart)<1 )
	yaps_quit("Need a valid 'a' argument\n");
      break;
    case 'H':
      if ( !optarg || sscanf(optarg,"%d",&bcycle)!=1 )
	yaps_quit("Need a valid 'G' argument\n");
      break;
    case 'T':
      if ( !optarg || sscanf(optarg,"%d",&MAXT)!=1 )
	yaps_quit("Need a valid 'T' argument\n");
      break;
     case 'I':
      if ( !optarg || sscanf(optarg,"%d",&acycle)!=1 )
	yaps_quit("Need a valid 'H' argument\n");
      break;
    case 'N':
      if ( !optarg || sscanf(optarg,"%d",&useN)!=1 )
	yaps_quit("Need a valid 'N' argument\n");
      break;
    case 'C':
      if ( !optarg || sscanf(optarg,"%d",&ITER)!=1 )
	yaps_quit("Need a valid 'C' argument\n");
       break;
    case 'B':
      if ( !optarg || sscanf(optarg,"%d",&burnin)!=1 )
	yaps_quit("Need a valid 'B' argument\n");
      break;
    case 's':
      if ( !optarg || sscanf(optarg,"%lu",&seed)!=1 )
	yaps_quit("Need a valid 's' argument\n");
      break;
    case 'v':
      verbose++;
      break;
#ifdef S_USE_THREADS
      case 'P':
      if ( !optarg || sscanf(optarg,"%u",&threads)!=1 )
	yaps_quit("Need a valid 'P' argument\n");
      break;
#endif
    default:
      yaps_message("Bad command line argument\n\n");
      usage(burnin?burnin:ITER/2, ITER, useN);
      exit(0);
    }
  }
  if ( useN>=MAXDATA ) 
    yaps_quit("N too large\n");
  
  if ( burnin==0 )
    burnin = ITER/2;
  else
    if ( burnin>=ITER-1 )
      yaps_quit("Burnin %d too large for cycles %d\n", burnin, ITER);

  yaps_message("Configuration details\n");
  yaps_message("=====================\n");
  /*
   *   set random number generator
   */
  if ( seed ) {
    rng_seed(rng,seed);
  } else {
    rng_time(rng,&seed);
  }
  yaps_message("Setting seed for data = %lu\n", seed);
    
  if ( acycle && apar==0 )
    apar = 0.5;
 
  yaps_message("Setting a=%f, b=%f, N=%d, D=%d\n", 
	       apar, bpar, useN, NUMMN);
  yaps_message("             burnin=%d,", burnin);
  yaps_message(" cycles=%d\n", ITER);
  
  /*
   *    fix pointers
   */
  for (j=0; j<NUMMN; j++) {
    n[j] = &n_data[j*DIM];
    t[j] = &t_data[j*DIM];
    tave[j] = &tave_data[j*DIM];
  }

  /*
   *    initialise everything
   */
  for (j=0; j<NUMMN; j++) {
    N[j] = useN;
    T[j] = 0;
    Tave[j] = 0;
    for (i=0; i<DIM; i++) {
      n[j][i] = 0;
      t[j][i] = 0;
      tave[j][i] = 0;
    }
  }

  /*
   *  fix base distribution, uniform
   */ 
  {
    for (i=0; i<DIM; i++) {
      H[i] = 1.0/DIM;
    }
  } 
  
  /*
   *     create data using a CRP to get initialisation for n[]
   */
  c = 0;
  for (j=0; j<NUMMN; j++) {
    int cc;
    i = sampleH();
    data[c++] = i;
    //  first entry always adds a table
    n[j][i]++;  
    t[j][i]++;
    T[j]++;
    for (cc=1; cc<N[j]; cc++) {
      float val = (cc+bpar)*rng_unit(rng);
      val -=  T[j]*apar+bpar;
      if ( val<=0 ) {
	//  new table
	i = sampleH();
	t[j][i]++;
	T[j]++;
      } else {
	for (i=0; i<DIM; i++) {
	  val -= n[j][i] - t[j][i]*apar;
	  if ( val<0 )
	    break;
	}
      }
      assert(i<DIM);
      n[j][i]++;  
      data[c++] = i;
    }
  }
  
  binit = bpar;
  
  /*
   *   record maximum entries in data
   *   do this where possible so that one can get the table
   *   sizes right
   *
   */
  MAXN = n[0][0]+1;
  MAXT = 1;
  for (j=0; j<NUMMN; j++) {
    for (i=0; i<DIM; i++) {
      if ( MAXN<=n[j][i] ) MAXN = n[j][i]+1;
      if ( MAXT<t[j][i] ) MAXT = t[j][i]*1.1+1;
    }
  }
  if ( MAXT>MAXN )
    MAXT = MAXN;
  
  yaps_message("Making S for N=%d M=%d a=%lf\n", MAXN,MAXT,apar);
  ST = S_make(MAXN, MAXT, MAXN, MAXTAB,
	      apar, S_STABLE | S_UVTABLE);
  if ( ST==NULL )
    yaps_quit("Making S failed!\n");
  S_report(ST,stdout);

  /*
   *    the seed only sets the data/sample,
   *    the seed for the simulation/Gibbs is always random
   */
  rng_free(rng);
  rng_time(rng,&seed);
  //yaps_message("Resetting seed = %lu\n", seed);
  
  /*
   *   report on initial data statistics
   */
  yaps_message("\nData sampled\n");
  yaps_message("============\n");
  for (j=0; j<NUMMN; j++) {
    yaps_message("n[%d] =", j);
    for (i=0; i<DIM; i++)
      yaps_message(" %d", n[j][i]);
    yaps_message(" = %d\n", N[j]);
    yaps_message("t[%d] =",j);
    for (i=0; i<DIM; i++)
      yaps_message(" %d", t[j][i]);
    yaps_message(" = %d\n", T[j]);
  }

  /*
   *   set the hyperparameters used in Gibbs,
   *   can be different to data
   */
  if ( bstart==0 ) 
    bstart = bpar;
  if ( astart==0 ) 
    astart = apar;

  //  initialise latent stats and reporting info
  for (j=0; j<NUMMN; j++) {
    T[j] = 0;
    Tave[j] = 0;
  }
  tcnt = 0;
  bave = 0;
  bcnt = 0;
  aave = 0;
  acnt = 0;

  bpar = bstart;
  if ( verbose && bcycle!=0 )
    yaps_message("Starting with initial b=%f\n", bpar);
  
  apar = astart;
  if ( verbose && acycle!=0 )
    yaps_message("Starting with initial a=%f\n", apar);
  
  for (j=0; j<NUMMN; j++) {
    for (i=0; i<DIM; i++) {
      tave[j][i] = 0;
      t[j][i] = 0;
      if ( n[j][i]>0 ) {
	/*
	 *  initialise to a single table
	 */
	t[j][i] = 1;
	T[j]++;
      }
    }
  }

  for ( iter=0; iter<ITER; iter++) {
    /*
     *   sampling with table indicators
     */
    c = 0;
    for (j=0; j<NUMMN; j++) {
      int cc;
      for (cc=0; cc<N[j]; cc++) {
	float one;
	i = data[c++];
	assert(n[j][i]);
	if ( n[j][i]==1 )
	  //    this indicator must always be 1, no sampling
	  continue;
	//   sample whether it contributes to a table
	if ( t[j][i]>1 &&
	     (n[j][i]-1)*rng_unit(rng)<(t[j][i]-1) ) {
	  t[j][i]--;  
	  T[j]--;
	} 
	assert(t[j][i]<n[j][i]);
	//  sample new table indicator
	one = H[i] * (bpar + T[j]*apar) * (t[j][i]) / (n[j][i]-t[j][i]+1)
	  * S_V(ST, n[j][i],t[j][i]+1);
	if ( rng_unit(rng) < one/(one+1.0) ) {
	  t[j][i]++;
	  T[j]++;
	} 
      }
    }
    
    /*
     *   one major cycle of Gibbs sampler finished
     */
    if ( verbose>1 ) {
      for (j=0; j<NUMMN; j++) {
	for (i=0; i<DIM; i++)
	  printf(" %d", t[j][i]);
	printf(" = %d\n", T[j]);
      }
    }
    /*
     *     sample & record b 
     */
    if ( bcycle!=0 && iter%bcycle==0 ) {
      //   Gibbs on bpar (concentration par) too
      if ( bcycle<0 ) {
	  int bc = -bcycle;
	  for (bc-- ; bc>0; bc--)
	    bpar = sampleb(bpar, 1, PB_shape, PB_scale, N, T, 
			   apar, rng, 1, 1);
      }
      bpar = sampleb(bpar, 1, PB_shape, PB_scale, N, T, 
		     apar, rng, 1, 1);
      if ( iter>=burnin ) {
	bave += bpar;
	bcnt ++;
      }
    }
    /*
     *     sample & record a
     */
    if ( acycle!=0 && iter%acycle==0 ) {
      int dimI[NUMMN];
      double dimb[NUMMN];
      for (j=0; j<NUMMN; j++)  {
	dimI[j] = DIM;
	dimb[j] = bpar;
      }
      //   Gibbs on apar (discount par) too
      if ( acycle<0 ) {
	int bc = -acycle;
	for (bc-- ; bc>0; bc--)
	  apar = samplea(apar, NUMMN, dimI, T, n, t, NULL, dimb, rng, 1, 1);
      }
      apar = samplea(apar, NUMMN, dimI, T, n, t, NULL, dimb, rng, 1, 1);
      if ( iter>=burnin ) {
	aave += apar;
	acnt ++;
      }
      if ( verbose>1 )
	yaps_message("Extending S for a=%lf\n", apar);
      if ( S_remake(ST,apar) )
	yaps_message("Extending S failed\n");
    }
    /*
     *    full statistics collection
     */
    if ( iter>=burnin ) {
      for (j=0; j<NUMMN; j++) {
	for (i=0; i<DIM; i++) {
	  tave[j][i] += t[j][i];
	}
	Tave[j] += T[j];
      }
      tcnt ++;
    }
  }	  
  
  /*
   *     report for this experiment
   */
  yaps_message("\nEstimates\n");
  yaps_message("=========\n");
  for (j=0; j<NUMMN; j++) {
    yaps_message("t[%d] = ", j);
    for (i=0; i<DIM; i++)
      yaps_message(" %.2f", tave[j][i]/tcnt);
    yaps_message("\nT[%d]=%.2f\n", j, Tave[j]/tcnt);
  }
  if ( bcycle!=0 && bcnt>0 ) 
    yaps_message("\nb=%.2f", bave/bcnt);
  if ( acycle!=0 && acnt>0 ) 
    yaps_message("\na=%.3f", aave/acnt);
  yaps_message("\n");
  
  S_free(ST);
  rng_free(rng);
  return 0;
}
示例#2
0
/*==========================================
 * main
 *========================================== */
int main(int argc, char* argv[])
{
  int c, iter, ITER=0, seed=0;
  enum dataType data = LdaC;
  enum dataType testdata = LdaC;
  int dots = 0;

  enum GibbsType fix_hold = GibbsNone;
  char *stem;
  char *resstem;
  int topwords = 20;
  int noerrorlog = 0;
  int displayed = 0;
  int load_vocab = 0;
  int checkpoint = 0;
  int restart = 0;
  int dopmi = 0;
  int restart_hca = 0;
  int load_phi = 0;
  int load_mu = 0;
  int procs = 1;
  int maxW = 0;
  enum ScoreType score=ST_idf;
  
  double BM0val=0, BM1val =0, BP0val=0, BP1val=0;
  
  clock_t t1=0, t2=0, t3=0;
  double tot_time = 0;
  double psample_time = 0;
  enum ParType par;
  /*
   *  default values
   */
  ddN.T = 10;
  ITER = 100;
  ddN.TEST = 0;

  pctl_init();

  while ( (c=getopt(argc, argv,"b:c:C:d:ef:F:g:G:h:K:l:L:N:o:pq:vr:s:S:t:T:vVW:"))>=0 ) {
    switch ( c ) {
    case 'b':
      if ( !optarg || sscanf(optarg,"%d",&ddP.back)!=1 )
        yap_quit("Need a valid 'b' argument\n");
      break;
    case 'c':
      if ( !optarg || sscanf(optarg,"%d",&checkpoint)!=1 )
        yap_quit("Need a valid 'c' argument\n");
      break;
    case 'C':
      if ( !optarg || sscanf(optarg,"%d",&ITER)!=1 )
	yap_quit("Need a valid 'C' argument\n");
      break;
    case 'd':
      if ( !optarg || sscanf(optarg,"%d",&dots)!=1 )
	yap_quit("Need a valid 'd' argument\n");
      break;
    case 'e':
      noerrorlog++;
      break;
    case 'f':
      if ( strcmp(optarg,"witdit")==0 ) 
	data = WitDit;
      else if ( strcmp(optarg,"docword")==0 ) 
	data = Docword;
      else if ( strcmp(optarg,"ldac")==0 ) 
	data = LdaC;
      else if ( strcmp(optarg,"bag")==0 ) 
	data = TxtBag;
      else if ( strcmp(optarg,"lst")==0 ) 
	data = SeqTxtBag;
       else
	yap_quit("Illegal data type for -f\n");
      break;
    case 'F':
      if ( strcmp(optarg,"all")==0 ) {
	for (par=ParAM; par<=ParBB; par++) 
	  ddT[par].fix = 1;
      } else {
	par = findpar(optarg);
	if ( par==ParNone )
	  yap_quit("Illegal arg for -F\n");
	ddT[par].fix = 1;
      }
      break;
    case 'g':
	{
	  char var[100];
	  int st=0;
	  if ( !optarg || sscanf(optarg,"%[^, ],%d", &var[0], &st)<1  )
            yap_quit("Need a valid 'g' argument\n");
          par = findpar(var);
          if ( par==ParBP1 )
            ddP.kbatch = st;
          else
            yap_quit("Illegal var for -g\n");
        }
        break;      
    case 'G':
      {
	char var[100];
	int st=0, cy=0;
	if ( !optarg || sscanf(optarg,"%[^, ],%d,%d",
			       &var[0], &cy, &st)<2 || st<0 || cy<0 )
	  yap_quit("Need a valid 'G' argument\n");
	par = findpar(var);
	if ( par==ParNone || par==ParB0P || par==ParB0M )
	  yap_quit("Illegal var for -G\n");
        ddT[par].fix = 0;
	ddT[par].start = st;
	ddT[par].cycles = cy;
      }
      break;
    case 'h':
      {
	fix_hold = GibbsHold;
	if ( !optarg  )
	  yap_quit("Need a valid 'h' argument\n");
        if ( strncmp(optarg,"dict,",5)==0 ) {
          if ( sscanf(&optarg[5],"%d",&ddP.hold_dict)<1 || ddP.hold_dict<2 )
            yap_quit("Need a valid 'hdict' argument\n");
        } else if ( strncmp(optarg,"fract,",6)==0 ) {
          if ( sscanf(&optarg[6],"%lf",&ddP.hold_fraction)<1 
               || ddP.hold_fraction<=0 || ddP.hold_fraction>=1 )
            yap_quit("Need a valid 'hfract' argument\n");
        } else if ( strncmp(optarg,"doc,",4)==0 ) {
          if ( sscanf(&optarg[4],"%d",&ddP.hold_every)<1 || ddP.hold_every<2 )
            yap_quit("Need a valid 'hdoc' argument\n");
        } else
          yap_quit("Need a valid 'h' argument\n");
      }
      break;
   case 'K':
      if ( !optarg || sscanf(optarg,"%d",&ddN.T)!=1 )
	yap_quit("Need a valid 'K' argument\n");
      break;
    case 'l':
      if ( !optarg )
	yap_quit("Need a valid 'l ' argument\n");
      if ( strncmp(optarg,"phi,",4)==0 ) {
	if ( sscanf(&optarg[4],"%d,%d",&ddP.phiiter, &ddP.phiburn)<2 )
	  yap_quit("Need a valid 'l word,' argument\n");      
      } else if ( strncmp(optarg,"theta,",6)==0 ) {
	if ( sscanf(&optarg[6],"%d,%d",&ddP.thetaiter, &ddP.thetaburn)<2 )
	  yap_quit("Need a valid 'l word,' argument\n");      
      } else if ( strncmp(optarg,"mu,",3)==0 ) {
	if ( sscanf(&optarg[3],"%d,%d",&ddP.muiter, &ddP.muburn)<2 )
	  yap_quit("Need a valid 'l word,' argument\n");      
      } else if ( strncmp(optarg,"prog,",5)==0 ) {
	if ( sscanf(&optarg[5],"%d,%d",&ddP.progiter, &ddP.progburn)<2 )
	  yap_quit("Need a valid 'l prog,' argument\n");
      } else
	yap_quit("Need a valid DIAG code in 'l' argument\n");
      break;
    case 'L':
      if ( !optarg )
	yap_quit("Need a valid 'L ' argument\n");
      if ( strncmp(optarg,"like,",5)==0 ) {
	if ( sscanf(&optarg[5],"%d,%d",&ddP.mltiter, &ddP.mltburn)<1 )
	  yap_quit("Need a valid 'L like' argument\n");
      } else
	yap_quit("Need a valid DIAG code in 'L' argument\n");
      break;
    case 'N':
      if ( !optarg || sscanf(optarg,"%d,%d", &ddP.maxN, &ddP.maxM)<1 )
	yap_quit("Need a valid 'N' argument\n");
      break;
    case 'o':
      {
	char *ptr = strchr(optarg, ',');
	int len = strlen(optarg);
	if ( ptr ) 
	  len = ptr - optarg;
        if ( strncmp(optarg,"idf",len)==0 )
          score = ST_idf;
        else if ( strncmp(optarg,"count",len)==0 )
          score = ST_count;
        else if ( strncmp(optarg,"Q",len)==0 )
          score = ST_Q;
        else if ( strncmp(optarg,"cost",len)==0 )
          score = ST_cost;
        else
          yap_quit("Need a valid parameter for 'o' argument\n");
	if ( ptr ) {
	  /*  there was a second arg */
	  if ( sscanf(ptr+1, "%d", &topwords) != 1)
	    yap_quit("Need a valid second 'o' argument\n");
	}
      break;
      }
      break;
   case 'p':
      dopmi++;
      break;
   case 'q':
      if(!optarg || sscanf(optarg, "%d", &procs) != 1)
	yap_quit("Need a valid 'q' argument\n");
      break;
    case 'r':
      if(!optarg )
	yap_quit("Need a valid 'r' argument\n");
      if ( strcmp(optarg,"tca")==0 )
	restart++;
      else if ( strcmp(optarg,"hca")==0 )
	restart_hca++;
      else if ( strcmp(optarg,"phi")==0 )
	load_phi++;
      else if ( strcmp(optarg,"mu")==0 )
	load_mu++;
      else
	yap_quit("Need a valid 'r' argument\n");
      break;
    case 's':
      if ( !optarg || sscanf(optarg,"%d",&seed)!=1 )
	yap_quit("Need a valid 's' argument\n");
      break;
    case 'S':
      {
	char var[100];
	double vin=0;
	if ( !optarg || sscanf(optarg,"%[^=, ]=%lf",
			       &var[0], &vin)<2  )
	  yap_quit("Need a valid 'S' argument\n");
	par = findpar(var);
	if ( par==ParNone )
	  yap_quit("Illegal var for -S\n");
	else if ( par==ParBM0 ) 
	  BM0val = vin;
	else if ( par==ParBM1 ) 
	  BM1val = vin;
	else if ( par==ParBP0 ) 
	  BP0val = vin;
	else if ( par==ParBP1 ) 
	  BP1val = vin;
	else
	  *(ddT[par].ptr) = vin;
      }   
      break;
    case 't':
      if ( !optarg || sscanf(optarg,"%d",&ddP.training)!=1 )
	yap_quit("Need a valid 't' argument\n");
      break;
    case 'T':
      if ( !optarg )
	yap_quit("Need a valid 'T' argument\n");
      {
	char *tname = data_name(optarg,data);
	FILE *fp = fopen(tname,"r");
	if ( fp==NULL ) {
          free(tname);
	  tname = data_name(optarg,testdata);
	  fp = fopen(tname,"r");
        } else {
	  testdata = data;
        }
        free(tname);
	if ( fp!=NULL ) {
	  /*  its a valid test filename */
          ddP.teststem = optarg;
	  fclose(fp);
	} else if ( sscanf(optarg,"%d",&ddN.TEST)!=1 )
	  yap_quit("Need a valid 'T' argument\n");
      }
      break;
    case 'v':
      verbose++;
      break;
    case 'V':
      load_vocab = 1;
      break;
    case 'W':
      if ( !optarg || sscanf(optarg,"%d",&maxW)<1 )
	yap_quit("Need a valid 'W' argument\n");
      break;
    default:
      yap_quit("Unknown option '%c'\n", c);
    }
  }

  if (argc-optind != 2) {
    usage();
    exit(-1);
  }
  if ( optind>=argc ) {
    yap_quit("No arguments given\n");
  }
  stem = strdup(argv[optind++]);
  resstem = strdup(argv[optind++]);

  if ( dopmi )
    load_vocab = 1;
  if ( dopmi && verbose !=2 ) {
    /*  
     *   due to the use of the ".top" file
     *   its really multi-purpose 
     */
    yap_quit("When computing PMI verbose must be exactly 2\n");
  }

  if ( noerrorlog==0 ) {
    char *wname = yap_makename(resstem, ".log");
    yap_file(wname);
    free(wname);
  }
  
  yap_commandline(argc, argv);
#ifdef H_THREADS
  yap_message(" Threads,");
#endif

  if ( restart || restart_hca ) {
    char *fname = yap_makename(resstem,".par");
    FILE *fp = fopen(fname,"r");
    char *buf;
    if ( !fp ) 
      yap_quit("Parameter file '%s' doesn't exist\n", fname);
    fclose(fp);
    free(fname);
    buf = readpar(resstem,"T",50);
    if ( !buf ) 
      yap_quit("Parameter file '%s' has no T\n", fname);
    ddN.T = atoi(buf);
    free(buf);
    if ( restart ) {
      buf = readpar(resstem,"E",50);
      if ( !buf ) 
	yap_quit("Parameter file '%s' has no E\n", fname);
      ddN.E = atoi(buf);
      free(buf);
      pctl_read(resstem);
    }
    if ( maxW==0 ) {
      buf = readpar(resstem,"W",50);
      if ( buf ) {
	maxW = atoi(buf);
	free(buf);
      }
    }
    if ( ddP.training==0 ) {
      buf = readpar(resstem,"TRAIN",50);
      if ( buf ) {
	ddP.training = atoi(buf);
	free(buf);
      } 
    }
    if ( ddN.TEST==0 ) {
      buf = readpar(resstem,"TEST",50);
      if ( buf ) {
	ddN.TEST = atoi(buf);
	free(buf);
      }
    }
  } 

  assert(ddN.T>0);
  assert(ddN.TEST>=0);
  assert(restart || restart_hca || ITER>0);
	
  if ( load_phi && ddP.phiiter>0 )
    yap_quit("Options '-l phi,...' and '-r phi' incompatible\n");
  if ( load_mu && ddP.muiter>0 )
    yap_quit("Options '-l mu,...' and '-r mu' incompatible\n");

  /*
   *   set random number generator
   */
  if ( seed ) {
    rng_seed(rngp,seed);
  } else {
    rng_time(rngp,&seed);
  }
  yap_message("Setting seed = %lu\n", seed);
  
  /*
   *  read data and get dimensions
   */
  {
    D_bag_t *dbp = data_read(stem, data);
    int training = pctl_training(dbp->D);
    if ( ddP.teststem ) {
      D_bag_t *dbpt = data_read(ddP.teststem, testdata);
      /* need to load a separate test set, strip to bare training */
      data_shrink(dbp, training);
      ddN.TEST = dbpt->D;
      data_append(dbp, dbpt);
      free(dbpt->w);  free(dbpt->d); free(dbpt);
    }
    if ( maxW>0 ) {
      if ( dbp->W <= maxW ) 
        dbp->W = maxW;
      if ( dbp->W > maxW )
        data_vocabshrink(dbp, maxW);
    }
    /*
     *  transfer into system
     */
    ddN.D = dbp->D;
    ddN.W = dbp->W;    
    ddN.N = dbp->N;
    ddN.NT = dbp->N;
    ddN.DT = training;
    ddD.w = dbp->w;
    ddD.d = dbp->d;
    free(dbp);
    if ( ddN.DT<ddN.D ) {
      /*  recompute NT */
      int i;
      for (i=0; i<ddN.N; i++)
        if ( ddD.d[i]>=ddN.DT )
          break;
      ddN.NT = i;
    }
  }

  data_read_epoch(stem);

  /*
   *  at this point, dimensions are fixed, so load phi and mu if needed
   */
  if ( load_phi )
    pctl_loadphi(resstem);
  if ( load_mu )
    pctl_loadmu(resstem);

  /*
   *   correct parameters after command line
   */
  pctl_fix(ITER);
  if ( BM0val>0 ) {
    ddP.b_mu[0] = BM0val;
  }
  if ( BM1val>0 ) {
    int i;
    for (i=1; i<ddN.E; i++)
      ddP.b_mu[i] = BM1val;
  }
  if ( BP0val>0 ) {
    int i;
    for (i=0; i<ddN.T; i++)
      ddP.b_phi[0][i] = BP0val;
  }
  if ( BP1val>0 ) {
    int i;
    if ( ddN.E==1 )
      yap_quit("b_phi[1] invalid when epochs==1\n");
    for (i=0; i<ddN.T; i++)
      ddP.b_phi[1][i] = BP1val;
  }
  pctl_samplereport();

  /*
   *   all data structures
   */
  data_alloc();
  if ( ddP.phiiter>0 )
    phi_init(resstem);
  else 
    ddS.phi = NULL;
  if ( ddP.muiter>0 )
    mu_init(resstem);
  else 
    ddS.mu = NULL;
  if ( ddP.thetaiter>0 )
    theta_init(resstem);
  else 
    ddS.theta = NULL;
  tca_alloc();
  if ( PCTL_BURSTY() ) 
    dmi_init(&ddM, ddS.z, ddD.w, ddD.N_dTcum,
             ddN.T, ddN.N, ddN.W, ddN.D, ddN.DT,
	     (fix_hold==GibbsHold)?pctl_hold:NULL);
  if ( load_vocab ) {
    data_vocab(stem);
  }

  cache_init();
  
  /*
   *  yap some details
   */
  data_report(ITER, seed);
  pctl_report();
 
  /*
   *  load/init topic assignments and prepare statistics
   */
  if ( restart || restart_hca) {
    tca_read_z(resstem, 0, ddN.DT);
    tca_rand_z(ddN.T, ddN.DT, ddN.D);
  } else {
    tca_rand_z(ddN.T, 0, ddN.D);
  }
  tca_reset_stats(resstem, restart, 0);

  if ( (restart || restart_hca ) && ITER ) 
      yap_message("Initial log_2(perp)=%lf\n", -M_LOG2E * likelihood()/ddN.NT);

  if ( ITER )
      yap_report("cycles: ");
  
  for (iter=0; iter<ITER; iter++) {
    int  pro;
    double thislp = 0;
    int   thisNd = 0;
    int doc;
#ifdef H_THREADS
    pthread_t thread[procs];
#endif
    D_pargs_p parg[procs];
    
#ifdef MU_CACHE
    mu_side_fact_reinit();
#endif
#ifdef PHI_CACHE
    phi_cache_reinit();
#endif

    t1 = clock();
    
    /*
     *  sampling
     */
#ifdef IND_STATS
    ddP.doc_ind_stats = u32tri(ddN.T,ddN.E,ddN.E);
    ddP.word_ind_stats = u32tri(ddN.T,ddN.E,ddN.E);
#endif

   /*  a bit complex if no threads!  */
    doc = 0;
    for (pro = 0 ; pro < procs ; pro++){
      parg[pro].dots=dots;
      parg[pro].procs=procs;
      parg[pro].doc = &doc;
#ifndef H_THREADS
      sampling_p(&parg[pro]);
#else
      if ( procs==1 ) 
	sampling_p(&parg[pro]);
      else if( pthread_create(&thread[pro],NULL,sampling_p,(void*) &parg[pro]) != 0){
        yap_message("thread failed %d\n",pro+1 );
      }
#endif
    }
#ifdef H_THREADS
    if ( procs>1 ) {
       //waiting for threads to finish
       for (pro = 0; pro < procs; pro++){
         pthread_join(thread[pro], NULL);
       }
    }
#endif

    // getting lp, Nd and clock
    for(pro = 0; pro < procs; pro++){
      thislp +=  parg[pro].thislp;
      thisNd +=  parg[pro].thisNd;
      tot_time += parg[pro].tot_time;
    }
#ifdef H_THREADS
    if ( procs>1 )
      tca_reset_stats(NULL,1,1);
#endif
    /*
     *  full check
     */
#ifndef NDEBUG
    {
      int e, d;
      check_cp_et();
      for (e=0; e<ddN.E; e++)
        check_m_vte(e);
      for (d=0; d<ddN.DT; d++)
        check_n_dt(d);
    }
#endif

#ifdef IND_STATS
    {
      char *fname = yap_makename(resstem,".istats");
      FILE *ifp = fopen(fname,"a");
      int e1, e2, kk;
      fprintf(ifp,"Iteration %d\n", iter);
      for (kk=0; kk<ddN.T; kk++) {
	fprintf(ifp," Topic %d\n", kk);
	for (e1=0; e1<ddN.E; e1++) {
	  fprintf(ifp,"  Epoch %d\n     ", e1);
	  for (e2=0; e2<ddN.E; e2++)
	    fprintf(ifp," %u", (unsigned)ddP.doc_ind_stats[kk][e1][e2]);
	  fprintf(ifp,"\n     ");
	  for (e2=0; e2<ddN.E; e2++)
	    fprintf(ifp," %u", (unsigned)ddP.word_ind_stats[kk][e1][e2]);
	  fprintf(ifp,"\n");
	}
      }
      fclose(ifp);
      free(ddP.doc_ind_stats[0][0]); free(ddP.doc_ind_stats[0]); 
      free(ddP.doc_ind_stats); 
      free(ddP.word_ind_stats[0][0]); free(ddP.word_ind_stats[0]); 
      free(ddP.word_ind_stats);
      free(fname);
    }
#endif
    
    /*
     *   sample hyperparameters
     */
    t3 = clock();
    pctl_sample(iter, procs);
   
    /*
     *   do time calcs here to remove diagnostics+reporting
     */
    t2 = clock();
    tot_time += (double)(t2 - t1) / CLOCKS_PER_SEC;
    psample_time += (double)(t2 - t3) / CLOCKS_PER_SEC;
    /*
     *   progress reports
     */
    if ( ( iter>ddP.progburn && (iter%ddP.progiter)==0 ) || iter+1>=ITER ) {
      yap_message(" %d\nlog_2(perp)=%lf,%lf", iter, 
		  -M_LOG2E * likelihood()/ddN.NT, -M_LOG2E * thislp/thisNd);
      pctl_update(iter);
      if ( verbose && iter%10==0 )
	yap_probs();
      if ( iter>0 && verbose>1 ) {
	if ( ddN.tokens ) {
	  tca_displaytopics(resstem,topwords,score);
	  displayed++;
	}
      }
      if ( iter+1<ITER ) {
	// yap_message("\n");
	yap_report("cycles: ");
      }
    } else {
      yap_message(" %d", iter);
      if ( verbose>1)  yap_message("\n");
    }
  
    if ( checkpoint>0 && iter>0 && iter%checkpoint==0 ) {
      data_checkpoint(resstem, stem, iter+1);
      yap_message(" checkpointed\n");
      tca_report(resstem, stem, ITER, procs, fix_hold, 
		 (dopmi&&displayed>0)?1:0);
    }
    if ( ddP.phiiter>0 && iter>ddP.phiburn && (iter%ddP.phiiter)==0 )
      phi_update();
    if ( ddP.thetaiter>0 && iter>ddP.thetaburn && (iter%ddP.thetaiter)==0 )
      theta_update();
    if ( ddP.muiter>0 && iter>ddP.muburn && (iter%ddP.muiter)==0 )
      mu_update();
  } // over iter
  
  if ( ITER ) 
      yap_report("Finished after %d cycles on average of %lf+%lf(s) per cycle\n",
	     iter,  (tot_time-psample_time)/iter, psample_time/iter);
  
  if ( ( verbose==1 || ((iter+1)%5!=0 && verbose>1) ) ) {
    if ( ddN.tokens ) {
       tca_displaytopics(resstem,topwords,score);
       displayed++;
    }
  }

  yap_probs();

  if ( ITER>0 ) 
	data_checkpoint(resstem, stem, ITER);
 
  tca_report(resstem, stem, ITER, procs, fix_hold, (dopmi&&displayed>0)?1:0);

  if ( ddP.phiiter>0 )
      phi_save(resstem);
  if ( ddP.thetaiter>0 )
      theta_save(resstem);
  if ( ddP.muiter>0 )
      mu_save(resstem);

  /*
   *  free
   */
  phi_free();
  theta_free();
  mu_free();
  cache_free();
  pctl_free();
  data_free();
  dmi_free(&ddM);
  tca_free();
  free(stem);
  free(resstem);
  rng_free(rngp);

  return 0;
}