コード例 #1
0
ファイル: ode_smmala.c プロジェクト: a-kramer/mcmc_clib
/* Initializes MPI,
 * loads defaults, 
 *       command line arguments,
 *       hdf5 data,
 *       ode model from shared library @code dlopen@
 * allocates kernel, 
 *           ode model parameters
 *           MPI communivcation buffers
 * calls MCMC routines
 * finalizes and frees (most) structs
 */
int/*always returns success*/
main(int argc,/*count*/ char* argv[])/*array of strings*/ {
  int i=0;
  int warm_up=0; // sets the number of burn in points at command line
  char lib_name[BUFSZ];
  ode_model_parameters omp[1];
  omp->size=(problem_size*) malloc(sizeof(problem_size));

  char global_sample_filename_stem[BUFSZ]="Sample.h5"; // filename basis
  char rank_sample_file[BUFSZ]; // filename for sample output
  char resume_filename[BUFSZ]="resume.h5";
  double seed = 1;
  double gamma= 2;
  double t0=-1;
  int sampling_action=SMPL_FRESH;
  
  int start_from_prior=no;
  int sensitivity_approximation=no;

  main_options cnf_options=get_default_options(global_sample_filename_stem, lib_name);
  
  MPI_Init(&argc,&argv);
  int rank,R;
  MPI_Comm_size(MPI_COMM_WORLD,&R);
  MPI_Comm_rank(MPI_COMM_WORLD,&rank);
  char *h5file=NULL;

  gsl_set_error_handler_off();
  
  /* process command line arguments
   */  
  for (i=0;i<argc;i++){
    if (strcmp(argv[i],"-p")==0 || strcmp(argv[i],"--prior-start")==0) {
      start_from_prior=1;
    } else if (strcmp(argv[i],"-d")==0 || strcmp(argv[i],"--hdf5")==0) {
      h5file=argv[i+1];
    } else if (strcmp(argv[i],"-t")==0 || strcmp(argv[i],"--init-at-t")==0) {
      t0=strtod(argv[i+1],NULL);
      //printf("[main] t0=%f\n",t0);
    } else if (strcmp(argv[i],"-w")==0 || strcmp(argv[i],"--warm-up")==0) warm_up=strtol(argv[i+1],NULL,10);
    else if (strcmp(argv[i],"--resume")==0 || strcmp(argv[i],"-r")==0) sampling_action=SMPL_RESUME;
    else if (strcmp(argv[i],"--sens-approx")==0) sensitivity_approximation=1;
    else if (strcmp(argv[i],"-l")==0) strcpy(cnf_options.library_file,argv[i+1]);
    //    else if (strcmp(argv[i],"-n")==0) Tuning=0;
    else if (strcmp(argv[i],"-s")==0) cnf_options.sample_size=strtol(argv[i+1],NULL,0);
    else if (strcmp(argv[i],"-o")==0) strncpy(cnf_options.output_file,argv[i+1],BUFSZ);
    else if (strcmp(argv[i],"-a")==0) cnf_options.target_acceptance=strtod(argv[i+1],NULL);
    else if (strcmp(argv[i],"-i")==0 || strcmp(argv[i],"--initial-step-size")==0) cnf_options.initial_stepsize=strtod(argv[i+1],NULL);
    else if (strcmp(argv[i],"-m")==0 || strcmp(argv[i],"--initial-step-size-rank-multiplier")==0) cnf_options.initial_stepsize_rank_factor=strtod(argv[i+1],NULL);

    else if (strcmp(argv[i],"-g")==0) gamma=strtod(argv[i+1],NULL);
    else if (strcmp(argv[i],"--abs-tol")==0) cnf_options.abs_tol=strtod(argv[i+1],NULL);
    else if (strcmp(argv[i],"--rel-tol")==0) cnf_options.rel_tol=strtod(argv[i+1],NULL);
    else if (strcmp(argv[i],"--seed")==0) seed=strtod(argv[i+1],NULL);
    else if (strcmp(argv[i],"-h")==0 || strcmp(argv[i],"--help")==0) {
      print_help();
      MPI_Abort(MPI_COMM_WORLD,0);
    }
  }
  
  seed=seed*137+13*rank;

  /* load Data from hdf5 file
   */
  if (h5file){
    printf("# [main] (rank %i) reading hdf5 file, loading data.\n",rank);
    fflush(stdout);
    read_data(h5file,omp);
    fflush(stdout);
  } else {
    fprintf(stderr,"# [main] (rank %i) no data provided (-d option), exiting.\n",rank);
    MPI_Abort(MPI_COMM_WORLD,-1);
  }
    
  /* load model from shared library
   */
  ode_model *odeModel = ode_model_loadFromFile(lib_name);  /* alloc */
  if (!odeModel) {
    fprintf(stderr, "# [main] (rank %i) Library %s could not be loaded.\n",rank,lib_name);
    exit(1);
  } else printf( "# [main] (rank %i) Library %s loaded.\n",rank, lib_name);
  
  /* construct an output file from rank, library name, and user
   * supplied string.
   */
  char *dot;
  char *lib_base;
  lib_base=basename(lib_name);
  dot=strchr(lib_base,'.');
  dot[0]='\0';
  sprintf(resume_filename,"%s_resume_%02i.h5",lib_base,rank);
  sprintf(rank_sample_file,"mcmc_rank_%02i_of_%i_%s_%s",rank,R,lib_base,basename(cnf_options.output_file));
  cnf_options.output_file=rank_sample_file;
  cnf_options.resume_file=resume_filename;
  
  /* allocate a solver for each experiment for possible parallelization
   */
  ode_solver **solver;
  int c,C=omp->size->C;
  int c_success=0;
  solver=malloc(sizeof(ode_solver*)*C);
  for (c=0;c<C;c++){
    solver[c]=ode_solver_alloc(odeModel);
    if (solver[c]) c_success++;
  }
  if (c_success==C) {
    printf("# [main] Solver[0:%i] for «%s» created.\n",C,lib_base);
  } else {
    fprintf(stderr, "# [main] Solvers for «%s» could not be created.\n",lib_base);
    ode_model_free(odeModel);
    MPI_Abort(MPI_COMM_WORLD,-1);
  }

  /* sensitivity analysis is not feasible for large models. So, it can
   *  be turned off.
   */
  if (sensitivity_approximation){
    //printf("# [main] experimental: Sensitivity approximation activated.\n");
    for (c=0;c<C;c++) ode_solver_disable_sens(solver[c]);
    /* also: make sensitivity function unavailable; that way
     * ode_model_has_sens(model) will return «FALSE»;
     */
    odeModel->vf_sens=NULL;
  }
  
  /* init solver 
   */
  realtype solver_param[3] = {cnf_options.abs_tol, cnf_options.rel_tol, 0};

  const char **x_name=ode_model_get_var_names(odeModel);
  const char **p_name=ode_model_get_param_names(odeModel);
  const char **f_name=ode_model_get_func_names(odeModel);
  
  /* local variables for parameters and inital conditions as presented
     in ode model lib: */
  int N = ode_model_getN(odeModel);
  int P = ode_model_getP(odeModel);
  int F = ode_model_getF(odeModel);

  /* save in ode model parameter struct: */
  set_number_of_state_variables(omp,N);
  set_number_of_model_parameters(omp,P);
  set_number_of_model_outputs(omp,F);

  omp->t0=t0;
  /* ode model parameter struct has pointers for sim results that need
     memory allocation: */
  ode_model_parameters_alloc(omp);
  ode_model_parameters_link(omp);
  fflush(stdout);

  /* get default parameters from the model file
   */
  double p[P];
  gsl_vector_view p_view=gsl_vector_view_array(p,P);
  ode_model_get_default_params(odeModel, p, P);
  if (rank==0)  gsl_printf("default parameters",&(p_view.vector),GSL_IS_DOUBLE | GSL_IS_VECTOR);
  omp->solver=solver;

  /* All MCMC meta-parameters (like stepsize) here are positive (to
   * make sense). Some command line arguments can override parameters
   * read from files; but, input files are processed after the command
   * line parameters. So, to check whether default parameters were
   * altered by the command line, the variable declaration defaults
   * are negative at first. Alterations to some meta-parameter p can
   * be checked by: if (cnf_options.p<0)
   * cnf_options.p=read_from_file(SOME FILE);
   */
  cnf_options.initial_stepsize=fabs(cnf_options.initial_stepsize);
  cnf_options.target_acceptance=fabs(cnf_options.target_acceptance);
  cnf_options.sample_size=fabs(cnf_options.sample_size);

  /* load default initial conditions
   */
  double y[N];
  gsl_vector_view y_view=gsl_vector_view_array(y,N);
  ode_model_get_initial_conditions(odeModel, y, N);
  
  print_experiment_information(rank,R,omp,&(y_view.vector));

  /* initialize the ODE solver with initial time t, default ODE
   * parameters p and default initial conditions of the state y; In
   * addition error tolerances are set and sensitivity initialized.
   */
  //printf("# [main] (rank %i) init ivp: t0=%g\n",rank,omp->t0);
  for (c=0;c<C;c++){
    ode_solver_init(solver[c], omp->t0, omp->E[c]->init_y->data, N, p, P);
    //printf("# [main] solver initialised.\n");    
    ode_solver_setErrTol(solver[c], solver_param[1], &solver_param[0], 1);
    if (ode_model_has_sens(odeModel)) {
      ode_solver_init_sens(solver[c], omp->E[0]->yS0->data, P, N);
    }
  }
  /* An smmala_model is a struct that contains the posterior
   * probablity density function and a pointer to its parameters and
   * pre-allocated work-memory.
   */
  smmala_model* model = smmala_model_alloc(LogPosterior, NULL, omp);
  if (model){
    printf("[main] (rank %i) smmala_model allocated.\n",rank);
  }else{
    fprintf(stderr,"[main] (rank %i) smmala_model could not be allocated.\n",rank);
    MPI_Abort(MPI_COMM_WORLD,-1);
  }
  
  /* initial parameter values; after allocating an mcmc_kernel of the
   * right dimensions we set the initial Markov chain state from
   * either the model's default parametrization p, the prior's μ, or the
   * state of a previously completed mcmc run (resume).
   */
  int D=omp->size->D;
  double init_x[D];
  double beta=assign_beta(rank,R,round(gamma));
  double tgac=cnf_options.target_acceptance;
  double m=cnf_options.initial_stepsize_rank_factor;
  double step=cnf_options.initial_stepsize;
  if (m>1.0 && rank>0) step*=gsl_pow_int(m,rank);
  pdf_normalisation_constant(omp);
  printf("[main] (rank %i) likelihood log(normalisation constant): %g\n",rank,omp->pdf_lognorm);
  mcmc_kernel* kernel = smmala_kernel_alloc(beta,D,step,model,seed,tgac);
  
  int resume_load_status;
  if (sampling_action==SMPL_RESUME){
    resume_load_status=load_resume_state(resume_filename, rank, R, kernel);
    assert(resume_load_status==EXIT_SUCCESS);
    for (i=0;i<D;i++) init_x[i]=kernel->x[i];
  } else if (start_from_prior){     
    if (rank==0) printf("# [main] setting initial mcmc vector to prior mean.\n");
    for (i=0;i<D;i++) init_x[i]=gsl_vector_get(omp->prior->mu,i);
  } else {
    if (rank==0) printf("# [main] setting mcmc initial value to log(default parameters)\n");
    for (i=0;i<D;i++) init_x[i]=gsl_sf_log(p[i]);
  }
  fflush(stdout);
  //display_prior_information(omp->prior);
  
  /* here we initialize the mcmc_kernel; this makes one test
   * evaluation of the log-posterior density function. 
   */
  
  /*
  if (rank==0){
    printf("# [main] initializing MCMC.\n");
    printf("# [main] init_x:");
    for (i=0;i<D;i++) printf(" %g ",init_x[i]);
    printf("\n");
  }
  */
  
  mcmc_init(kernel, init_x);
  /* display the results of that test evaluation
   *
   */
  if (rank==0){
    printf("# [main] rank %i init complete .\n",rank);
    display_test_evaluation_results(kernel);
    ode_solver_print_stats(solver[0], stdout);
    fflush(stdout);
    fflush(stderr);  
  }
  
  size_t SampleSize = cnf_options.sample_size;  
  
  /* in parallel tempering th echains can swap their positions;
   * this buffers the communication between chains.
   */
  void *buffer=(void *) smmala_comm_buffer_alloc(D);
  
  /* Initialization of burin in length
   */
  size_t BurnInSampleSize;
  if (warm_up==0){
    BurnInSampleSize = 7 * (int) sqrt(cnf_options.sample_size);
  } else {
    BurnInSampleSize=warm_up;
  }
  if (rank==0){
    printf("# Performing Burn-In with step-size (%g) tuning: %lu iterations\n",get_step_size(kernel),BurnInSampleSize);
    fflush(stdout);
  }
  /* Burn In: these iterations are not recorded, but are used to find
   * an acceptable step size for each temperature regime.
   */
  int mcmc_error;
  mcmc_error=burn_in_foreach(rank,R, BurnInSampleSize, omp, kernel, buffer);
  assert(mcmc_error==EXIT_SUCCESS);
  if (rank==0){
    fprintf(stdout, "\n# Burn-in complete, sampling from the posterior.\n");
  }
  /* this struct contains all necessary id's and size arrays
   * for writing sample data to an hdf5 file in chunks
   */
  hdf5block_t *h5block = h5block_init(cnf_options.output_file,
				      omp,SampleSize,
				      x_name,p_name,f_name);
  
  /* The main loop of MCMC sampling
   * these iterations are recorded and saved to an hdf5 file
   * the file is set up and identified via the h5block variable.
   */  
  mcmc_error=mcmc_foreach(rank, R, SampleSize, omp, kernel, h5block, buffer, &cnf_options);
  assert(mcmc_error==EXIT_SUCCESS);
  append_meta_properties(h5block,&seed,&BurnInSampleSize, h5file, lib_base);
  h5block_close(h5block);

  /* clear memory */
  smmala_model_free(model);
  mcmc_free(kernel);
  ode_model_parameters_free(omp);
  MPI_Finalize();
  return EXIT_SUCCESS;
}
コード例 #2
0
int parse_config(FILE *cnf, ode_model_parameters *omp, main_options *cnf_options){
  /* This function parses the configuration file The configuration
   * file contains xml like expressions containing data, measurement
   * time points, etc.
   * We start by defining regular expressions for the field names
   * 
   */
  int D=0,U=0,C=0,F=0,T=0,N=0;
  int i,l;
  int n=10; // number of fields
  regex_t cpt[2*n]; // defines the patterns for the field names
  regex_t comment;
  int bsize=2048;
  char buffer[bsize];
  gsl_matrix *reference_data;
  gsl_matrix *sd_reference_data;
  omp->data_is_relative=0; // assume data to be absolute
  char *var_value, *var_value_newline;

  //comments in file
  regcomp(&comment,"#|//|%",REG_EXTENDED);

  regcomp(&cpt[0],"\\[time\\]",REG_EXTENDED);
  regcomp(&cpt[1],"\\[reference_input\\]",REG_EXTENDED);
  regcomp(&cpt[2],"\\[reference_data\\]",REG_EXTENDED);
  regcomp(&cpt[3],"\\[sd_reference_data\\]",REG_EXTENDED);
  regcomp(&cpt[4],"\\[input\\]",REG_EXTENDED);
  regcomp(&cpt[5],"\\[data\\]",REG_EXTENDED);
  regcomp(&cpt[6],"\\[sd_data\\]",REG_EXTENDED);
  regcomp(&cpt[7],"\\[prior_mu\\]",REG_EXTENDED);
  regcomp(&cpt[8],"\\[prior_inv(erse)?_cov(ariance)?\\]",REG_EXTENDED);
  regcomp(&cpt[9],"\\[output\\]",REG_EXTENDED);

  regcomp(&cpt[n+0],"\\[/time\\]",REG_EXTENDED);
  regcomp(&cpt[n+1],"\\[/reference_input\\]",REG_EXTENDED);
  regcomp(&cpt[n+2],"\\[/reference_data\\]",REG_EXTENDED);
  regcomp(&cpt[n+3],"\\[/sd_reference_data\\]",REG_EXTENDED);
  regcomp(&cpt[n+4],"\\[/input\\]",REG_EXTENDED);
  regcomp(&cpt[n+5],"\\[/data\\]",REG_EXTENDED);
  regcomp(&cpt[n+6],"\\[/sd_data\\]",REG_EXTENDED);
  regcomp(&cpt[n+7],"\\[/prior_mu\\]",REG_EXTENDED);
  regcomp(&cpt[n+8],"\\[/prior_inv(erse)?_cov(ariance)?\\]",REG_EXTENDED);
  regcomp(&cpt[n+9],"\\[/output\\]",REG_EXTENDED);

  /* now that we have several regular expressions, we parse the file
   * once to get the problem size: D,P,F,U,C; then we allocate mamory
   * and parse the file a second time to read the data, inputs and so
   * forth.
   */


  /* relevant interfaces:
   * count_rows(FILE *cnf, regex_t *end, regex_t *comment)
   * count_columns(const char *c)
   * read_columns(char *c, double *vector, const int length)
   * read_block(int rows, int columns, FILE *f, double *target, regex_t *comment)
   */

  while (!feof(cnf)){
    do fgets(buffer,bsize,cnf);
    while (regexec(&comment,buffer,0,NULL,0)==0);
    var_value=strchr(buffer,'='); // string looks like this: [var_name]=[var_value]
    if (var_value!=NULL) { // we have a variable definition
      var_value[0]='\0'; //mark the end of the variable name
      /*printf("var_name=%s\n",buffer);
        printf("var_value=%s\n",var_value+1);
       *printf("removing newline....\n");
       */
      var_value_newline=strchr(++var_value,'\n');
      if (var_value_newline!=NULL) var_value_newline[0]='\0';      
      printf("# [cfg] {%s} ← {%s}\n",buffer,var_value);
      
      if (strcmp(cnf_options->output_file,"sample.dat")==0 && strcmp(buffer,"output")==0) strcpy(cnf_options->output_file,var_value);
      else if (cnf_options->sample_size<0 && strcmp(buffer,"sample_size")==0) cnf_options->sample_size=strtol(var_value,NULL,0);
      else if (cnf_options->target_acceptance<0 && strcmp(buffer,"acceptance")==0) cnf_options->target_acceptance=strtod(var_value,NULL);
      else if (cnf_options->initial_stepsize<0 && strcmp(buffer,"step_size")==0) cnf_options->initial_stepsize=strtod(var_value,NULL);
      else if (strcmp(buffer,"t0")==0) {omp->t0=strtod(var_value,NULL); printf("# t0 = %f\n",omp->t0);}
    }
    else { 
      for (i=0;i<n;i++){
	if (regexec(&cpt[i],buffer,0,NULL,0)==0){
	  /* printf("found match with regular expression %i.\n",i); */
	  /* printf(buffer); */
	  switch (i){ // counting columns and/or rows
	  case 0: /*time*/
	    do fgets(buffer,bsize,cnf);
	    while (regexec(&comment,buffer,0,NULL,0)==0);
	    T=count_rows(cnf, &cpt[n+i], &comment);
	    break;
	  case 1: /* reference input */
	    omp->data_is_relative=1;
	    printf("data is relative.\n");
	    break;
	  case 4: /* inputs */
	    do fgets(buffer,bsize,cnf);
	    while (regexec(&comment,buffer,0,NULL,0)==0);
	    U=count_columns(buffer);
	    C=count_rows(cnf, &cpt[n+i], &comment);
	    //	  printf("# input field has %i lines. (%i experimental conditions)\n",l,C);
	    break;
	  case 5: /* data */
	    do fgets(buffer,bsize,cnf);
	    while (regexec(&comment,buffer,0,NULL,0)==0);
	    F=count_columns(buffer);
	    l=count_rows(cnf, &cpt[n+i], &comment);
	    printf("# data has %i (%i × %i) lines.\n",l,C,T);
	    break;
	  case 7: /* problem size */
	    do fgets(buffer,bsize,cnf);
	    while (regexec(&comment,buffer,0,NULL,0)==0);
	    D=count_rows(cnf, &cpt[n+i], &comment);
	    break;
	  case 9: /* output structure */
	    do fgets(buffer,bsize,cnf);
	    while (regexec(&comment,buffer,0,NULL,0)==0);
	    N=count_columns(buffer);
	    F=count_rows(cnf, &cpt[n+i], &comment);
	  }// switch
	  break;
	}// if match
      }// for (regular expressions)
    }// while !EOF
  }
  printf("# file read once to determine the size of data and inputs.\n");
  printf("# D=%i\tN=%i\tF=%i\tU=%i\tC=%i\tT=%i\n",D,N,F,U,C,T);
  omp->D=D;
  /* now we must allocate the necessary memory and fill it with values
   */
  ode_model_parameters_alloc(omp, D, N, F, T, U, C);
  reference_data=gsl_matrix_alloc(T,F);
  sd_reference_data=gsl_matrix_alloc(T,F);
  printf("# memory allocated.\n");
  /* we reset the FILE structure and parse again, now reading the
   * values.
   */
  rewind(cnf);
  printf("# rewind.\n");
  while (!feof(cnf)){
    do fgets(buffer,bsize,cnf);
    while (regexec(&comment,buffer,0,NULL,0)==0);
    for (i=0;i<n;i++){
      if (    regexec(&cpt[i],buffer,0,NULL,0)==0){
        /* printf("found match with regular expression %i.\n",i); */
        /* printf(buffer); */
	switch (i){// reading the data
	case 0: /*time*/
	  read_block(T,1,cnf,omp->t->data,&comment);
	  printf("# measurement time(s) read.\n");
	  break;
	case 1: /* reference input */
	  //printf("# reading reference input.\n");
	  read_block(1,U,cnf,omp->reference_u->data,&comment);
	  printf("# reference input read.\n");
	  break;
	case 2: /* reference data */
	  read_block(T,F,cnf,reference_data->data,&comment);
	  printf("# reference data read.\n");
	  break;
	case 3: /* sd reference data */
	  read_block(T,F,cnf,sd_reference_data->data,&comment);
	  printf("# standard deviation of reference data read.\n");
	  break;
	case 4: /* inputs */
	  read_block(C,U,cnf,omp->input_u->data,&comment);
	  printf("# input read.\n");
	  break;
	case 5: /* data */
	  read_block(C*T,F,cnf,omp->Data->data,&comment);
	  printf("# data read.\n");
	  break;
	case 6: /* sd data */
	  read_block(C*T,F,cnf,omp->sdData->data,&comment);
	  printf("# standard deviation of data read.\n");
	  break;
	case 7:
	  read_block(D,1,cnf,omp->prior_mu->data,&comment);
	  printf("# prior mean read.\n");
	  break;
	case 8: /* prior inverse covariance */
	  read_block(D,D,cnf,omp->prior_inverse_cov->data,&comment);
	  printf("# prior inverse covariance matrix read.\n");
	  break;
	case 9: /* output structure */
	  read_block(F,N,cnf,omp->output_C->data,&comment);
	}// switch
	break;
      }// if match
    }// for (regular expressions)
  }// while !EOF
  printf("# configuration read.\n");
  /* now we take the ratios of data and reference data
   */

  if (omp->data_is_relative){
    printf("# calculating relative data (ratios)...");
    ratio_with_sd(omp->Data,omp->sdData,reference_data,sd_reference_data);
    printf("# done.\n");
  }

  //  omp->t0=0.0;

  // cleanup
  gsl_matrix_free(reference_data);
  gsl_matrix_free(sd_reference_data);
  for (i=0;i<2*n;i++)  regfree(&cpt[i]);

  return EXIT_SUCCESS;
}