Пример #1
0
/** The main function.

    The function implementing the algorithm described in

    arXiv:hep-lat/0306017 v1 13 Jun 2003 \em Wolff, U. \em Monte Carlo errors with less errors.
*/
int UWerr_f(Tcl_Interp *interp, Tcl_CmdInfo * cmdInfo, int argc, char ** argv,
	    double ** data, int rows, int cols,
	    int * n_rep, int len, double s_tau, int plot)
{
  struct UWerr_t ret;
  int a, k, i, sum = 0, W_opt = 0, W_max = 0;
  double Fbb = 0, bF = 0, Fb = 0, * abb = 0L, tau = 0, tmp;
  double ** abr = 0L, * Fbr = 0L, * fgrad = 0L, * delpro = 0L;
  double * gFbb = 0L, CFbb_opt = 0, G_int = 0, std_a;
  char flag = 0;
  char * str = 0L;
  char * tcl_vector = 0L;
  char ** my_argv;

  FILE * plotDataf, * plotScriptf;

  ret.Q_val = 0;

  if (!data) {
    Tcl_AppendElement(interp, "No data matrix given.");
    return TCL_ERROR;
  }
  if (rows < 1) {
    Tcl_AppendElement(interp, "Data matrix has no rows.");
    return TCL_ERROR;
  }
  if (cols < 1) {
    Tcl_AppendElement(interp, "Data matrix has no columns.");
    return TCL_ERROR;
  }
  if(!cmdInfo && !cmdInfo->proc) {
    Tcl_AppendElement(interp, "No function to call given.");
    return TCL_ERROR;
  }
  if (!n_rep) {
    Tcl_AppendElement(interp, "No representations vector given.");
    return TCL_ERROR;
  }
  if (len < 1) {
    Tcl_AppendElement(interp, "Representations vector is empty.");
    return TCL_ERROR;
  }
  
  /* \sum_{i=1}^{len} n_rep[i-1] = rows */

  k = rows; /* for now k is going to be min(n_rep) */
  for (i = 0; i < len; ++i) {
    sum += n_rep[i];
    if (n_rep[i] < k)
      k = n_rep[i];
  }

  if (sum != rows || k <= 0) {
    Tcl_AppendElement(interp, "Representations vector is invalid.");
    return TCL_ERROR;
  }

  if (s_tau > 0) {
    W_max = (int)rint(k/2.); /* until here: k = min(n_rep) */
    flag = 1;
    if (W_max < 1) W_max = 1;
  }

  /* string for output of numbers */
  str = (char *)malloc((TCL_INTEGER_SPACE + TCL_DOUBLE_SPACE)*sizeof(char));

  if (!(delpro = (double*)malloc(rows*sizeof(double)))) {
    Tcl_AppendResult(interp, "Out of Memory.", __LINE__, (char *) NULL);
    free(str);
    return TCL_ERROR;
  }

  if (!(Fbr = (double*)malloc(len*sizeof(double)))) {
    free(delpro);
    free(str);
    Tcl_AppendResult(interp, "Out of Memory.", __LINE__, (char *) NULL);
    return TCL_ERROR;
  }

  if (!(fgrad = (double*)malloc(cols*sizeof(double)))) {
    free(delpro);
    free(Fbr);
    free(str);
    Tcl_AppendResult(interp, "Out of Memory.", __LINE__, (char *) NULL);
    return TCL_ERROR;
  }

  if (!(abb = (double*)malloc(cols*sizeof(double)))) {
    free(delpro);
    free(Fbr);
    free(fgrad);
    free(str);
    Tcl_AppendResult(interp, "Out of Memory.", __LINE__, (char *) NULL);
    return TCL_ERROR;
  }

  /* abr \in (\Real)_{len, cols} */
  if (!(abr = (double**)malloc(len*sizeof(double*)))) {
    free(delpro);
    free(Fbr);
    free(fgrad);
    free(abb);
    free(str);
    Tcl_AppendResult(interp, "Out of Memory.", __LINE__, (char *) NULL);
    return TCL_ERROR;
  }
  for (i = 0; i < len; ++i)
    if (!(abr[i] = (double*)malloc(cols*sizeof(double)))) {
      for (k = 0; k < i; ++k)
	free(abr[k]);

      free(abr);
      free(delpro);
      free(Fbr);
      free(fgrad);
      free(abb);
      free(str);
    
      Tcl_AppendResult(interp, "Out of Memory.", __LINE__, (char *) NULL);
      return TCL_ERROR;
    }

  
  if (W_max > 0) {
    if (!(gFbb = (double*)malloc((W_max+1)*sizeof(double)))) {
      free(delpro);
      free(Fbr);
      free(fgrad);
      free(abb);
      for (k = 0; k < len; ++k)
	free(abr[k]);
      free(abr);

      free(str);
      Tcl_AppendResult(interp, "Out of Memory.", __LINE__, (char *) NULL);
      return TCL_ERROR;
    }
  }
  
  if (uwerr_create_tcl_vector(&tcl_vector, cols)) {
      free(delpro);
      free(Fbr);
      free(fgrad);
      free(abb);
      for (k = 0; k < len; ++k)
	free(abr[k]);
      free(abr);
      free(gFbb);

      free(str);
      Tcl_AppendResult(interp, "Out of Memory.", __LINE__, (char *) NULL);
      return TCL_ERROR;
  }

  if (!(my_argv=(char**)malloc((argc+1)*sizeof(char*)))) {
      free(delpro);
      free(Fbr);
      free(fgrad);
      free(abb);
      for (k = 0; k < len; ++k)
	free(abr[k]);
      free(abr);
      free(gFbb);

      free(str);
      uwerr_free_tcl_vector(tcl_vector);
      Tcl_AppendResult(interp, "Out of Memory.", __LINE__, (char *) NULL);
      return TCL_ERROR;
  }

  my_argv[0] = argv[0];
  my_argv[1] = tcl_vector;
  for (i = 1; i < argc; ++i)
    my_argv[i+1] = argv[i];


  /* first we calculate N_r\bar{a}_\alpha^r \forall r, alpha */
  
  sum = 0;
  for (k = 0; k < len; ++k) {
    for (i = 0; i < n_rep[k]; ++i) {
      for (a = 0; a < cols; ++a) {
	if (i > 0)
	  abr[k][a] += data[sum + i][a];
	else
	  abr[k][a] = data[sum][a];
      }
    }
    sum += n_rep[k];
  }

  /* now we calculate \bar{\bar{a}}_\alpha \forall \alpha */

  for (k = 0; k < len; ++k) {
    for (a = 0; a < cols; ++a) {
      if (k > 0)
	abb[a] += abr[k][a];
      else
	abb[a] = abr[k][a];
    }
  }
  for (a =0; a < cols; ++a)
    abb[a] /= rows;

  /* now we calculate \bar{a}_\alpha^r with \forall \alpha */
  for (k = 0; k < len; ++k)
    for (a = 0; a < cols; ++a)
      abr[k][a] /= n_rep[k];

  uwerr_write_tcl_vector(interp, abb, cols, tcl_vector);
  Tcl_ResetResult(interp);

  if (cmdInfo->proc(cmdInfo->clientData, interp, argc+1, my_argv) != TCL_OK)
    goto err_exit;

  Fbb = strtod(Tcl_GetStringResult(interp),0);
  for (k = 0; k < len; ++k) {
    uwerr_write_tcl_vector(interp, abr[k], cols, tcl_vector);
    Tcl_ResetResult(interp);

    if (cmdInfo->proc(cmdInfo->clientData, interp, argc+1, my_argv) != TCL_OK)
      goto err_exit;
    Fbr[k] = strtod(Tcl_GetStringResult(interp),0);
  }

  Fb  = UWerr_dsum_int(n_rep, Fbr, len);
  Fb /= rows;

  for (a = 0; a < cols; ++a) {
    std_a = 0;
    for (k = 0; k < rows; ++k)
      std_a += (data[k][a]-abb[a])*(data[k][a]-abb[a]);
    std_a = sqrt(std_a)/rows;

    
    /* calc the gradient of f using df/da ~ (f(a+h)-f(a-h))/2*h 
       where h is the standard deviation divided by the sqrt of the 
       number of samples (= rows).
       Remember: abb[a] is the average for column a of data */

    if (std_a == 0)
      fgrad[a] = 0;
    else {
      tmp = abb[a];
      abb[a] += std_a;

      uwerr_write_tcl_vector(interp, abb, cols, tcl_vector);
      Tcl_ResetResult(interp);
      if (cmdInfo->proc(cmdInfo->clientData, interp, argc+1, my_argv) != TCL_OK)
	goto err_exit;
      fgrad[a] = strtod(Tcl_GetStringResult(interp),0);

      abb[a] = tmp - std_a;

      uwerr_write_tcl_vector(interp, abb, cols, tcl_vector);
      Tcl_ResetResult(interp);
      if (cmdInfo->proc(cmdInfo->clientData, interp, argc+1, my_argv) != TCL_OK)
	goto err_exit;
      fgrad[a] -= strtod(Tcl_GetStringResult(interp),0);

      abb[a] = tmp;
      fgrad[a] /= 2*std_a;
    }
  }

  /* calc delpro = data*fgrad - abb.*fgrad and
     the mean of delpro.^2 = gFbb[0] */

  tmp = UWerr_dsum_double(abb, fgrad, cols);
  gFbb[0] = 0;
  for (i = 0; i < rows; ++i) {
    delpro[i] = 0;

    for (a = 0; a < cols; a++) {
      delpro[i] += data[i][a]*fgrad[a];
    }
    delpro[i] -= tmp;

    gFbb[0] += delpro[i]*delpro[i];
  }
  gFbb[0] /= rows;

  i = 0;
  while(i < W_max) {
    gFbb[i+1] = 0;
    sum = 0;
    for (k = 0; k < len; ++k) {
      gFbb[i+1] += UWerr_dsum_double(delpro + sum, delpro + sum + i + 1, n_rep[k]-i-1);
      sum += n_rep[k];
    }
    gFbb[i+1] /= rows-(i+1)*len;

    if (flag) {
      G_int += gFbb[i+1]/gFbb[0];
      if (G_int <= 0)
	tau = UW_EPS;
      else
	tau = s_tau/log((G_int+1)/G_int);
      if (exp(-(i+1)/tau)-tau/sqrt((i+1)*rows) < 0) {
	W_opt = i+1;
	W_max = (W_max < 2*W_opt) ? W_max : 2*W_opt;
	flag = 0;
      }
    }
    ++i;
  }
  --i;

  if (flag) {
    W_opt = W_max;
    sprintf(str, "%d", W_max);
    Tcl_AppendResult(interp, "Windowing condition failed up to W = ", str, ".\n", (char *)NULL);
  }
  ret.W = W_opt;

  CFbb_opt = (gFbb[0] + 2*UWerr_sum(gFbb+1, W_opt))/rows;
  for (k = 0; k < i; ++k)
    gFbb[k] += CFbb_opt;
  CFbb_opt = (gFbb[0] + 2*UWerr_sum(gFbb+1, W_opt));

  ret.dvalue = sqrt(CFbb_opt/rows); /* sigmaF */
  
  if (len >= 2) {
    bF = (Fb-Fbb)/(len-1);
    Fbb -= bF;
    if (fabs(bF) > ret.dvalue/4) {
      Tcl_PrintDouble(interp, bF/ret.dvalue, str);
      Tcl_AppendResult(interp, "A ", str, " sigma bias of the mean has been cancelled./n", (char *)NULL);
    }
    for (i = 0; i < len; ++i)
      Fbr[i] -= bF*rows/n_rep[i];
    Fb -= bF*len;
    
    ret.bias = bF/ret.dvalue;
  }

  ret.tau_int = 0;
  for (i = 0; i <= W_opt; ++i)
    ret.tau_int += gFbb[i];
      
  ret.tau_int /= gFbb[0];
  ret.tau_int -= .5;

  ret.value  = Fbb;
  ret.ddvalue = ret.dvalue*sqrt((W_opt + .5)/rows);
  ret.dtau_int = 2 * ret.tau_int * sqrt((W_opt + .5 - ret.tau_int)/rows);

  if (len > 1) {
    for (i = 0; i < len; ++i)
      Fbr[i] = (Fbr[i] - Fb)*(Fbr[i] - Fb)*n_rep[i];
    
    ret.Q_val = UWerr_sum(Fbr, len);
    ret.Q_val /= CFbb_opt;
    ret.Q_val = gammaq((len-1)/2., ret.Q_val/2.);
  }

  if (plot) {
    plotScriptf = fopen("uwerr_plot_script", "w");

    fprintf(plotScriptf, "set ylabel \"Gamma\"; set xlabel \"W\"; set label \"W_opt=%d\" at %d,0 center; plot f(x) = 0, f(x) notitle, 'uwerr_plot_data' using 1:2 title \"normalized autocorrelation\" with lines; show label; pause -1\n", W_opt, W_opt);
    fprintf(plotScriptf, "set ylabel \"tau_int\"; plot f(x) = %.3f, 'uwerr_plot_data' using 1:3 title \"tau_int with statistical errors\" with lines,", ret.tau_int);
    fprintf(plotScriptf, " 'uwerr_plot_data' using 1:3:4 notitle with errorbars, f(x) title \"estimate\"; pause -1\n");

    fclose(plotScriptf);

    plotDataf = fopen("uwerr_plot_data", "w");
    tmp = 0;
    for (i = 0; i < W_max; ++i) {
      tmp += gFbb[i];
      /* print values for x-Axis, Gamma/Gamma[0], tau_int, and its errors */
      fprintf(plotDataf, "%d %.3f %.3f %.3f\n", i, gFbb[i]/gFbb[0],
	      tmp/gFbb[0]-.5, 2*sqrt((i+tmp/gFbb[0])/rows));
    }
    fclose(plotDataf);

    puts("Press Return to continue ...");
    Tcl_Eval(interp, "[exec gnuplot uwerr_plot_script]");
  }

  Tcl_ResetResult(interp);
  Tcl_PrintDouble(interp, ret.value, str);
  Tcl_AppendResult(interp, str, " ", (char *)NULL);
  Tcl_PrintDouble(interp, ret.dvalue, str);
  Tcl_AppendResult(interp, str, " ", (char *)NULL);
  Tcl_PrintDouble(interp, ret.ddvalue, str);
  Tcl_AppendResult(interp, str, " ", (char *)NULL);
  Tcl_PrintDouble(interp, ret.tau_int, str);
  Tcl_AppendResult(interp, str, " ", (char *)NULL);
  Tcl_PrintDouble(interp, ret.dtau_int, str);
  Tcl_AppendResult(interp, str, (char *)NULL);
  if (len > 1) {
    Tcl_PrintDouble(interp, ret.Q_val, str);
    Tcl_AppendResult(interp, " ", str, (char *)NULL);
  }

 err_exit:
  free(abb);
  for (k = 0; k < len; ++k)
    free(abr[k]);
  free(abr);
  free(delpro);
  free(gFbb);
  free(Fbr);
  free(fgrad);
  free(str);
  free(my_argv);
  uwerr_free_tcl_vector(tcl_vector);

  return TCL_OK;
}
Пример #2
0
double cumpoisson(double k,double mean)
{
	return gammaq(k+1,mean);
}