Example #1
0
int* nip_mapper(nip_variable *set, nip_variable *subset, 
		int nset, int nsubset){
  int i, j;
  int* mapping = NULL;
  
  /* Check stuff */
  if(!(set && subset && nset > 0 && nsubset > 0 && nset >= nsubset)){
    if(nsubset != 0)
      nip_report_error(__FILE__, __LINE__, NIP_ERROR_INVALID_ARGUMENT, 1);
    return NULL;
  }

  mapping = (int*) calloc(nsubset, sizeof(int));
  if(!mapping){
    nip_report_error(__FILE__, __LINE__, NIP_ERROR_OUTOFMEMORY, 1);
    return NULL;
  }

  for(i = 0; i < nsubset; i++){
    for(j = 0; j < nset; j++){ /* linear search */
      if(nip_equal_variables(subset[i], set[j])){
	mapping[i] = j;
	break;
      }
    }
  }

  return mapping;
}
Example #2
0
nip_variable* nip_sort_variables(nip_variable* vars, int nvars){
  int i, j;
  nip_variable *sorted;
  nip_variable temp;

  if(nvars < 1){
    nip_report_error(__FILE__, __LINE__, NIP_ERROR_INVALID_ARGUMENT, 1);
    return NULL;
  }

  sorted = (nip_variable *) calloc(nvars, sizeof(nip_variable));

  if(!sorted){
    nip_report_error(__FILE__, __LINE__, NIP_ERROR_OUTOFMEMORY, 1);
    return NULL;
  }

  /* Selection sort (simple, fast enough) */

  /* Fill the sorted array naively (unsorted) */
  for(i = 0; i < nvars; i++)
    sorted[i] = vars[i];

  /* Sort in place (lots of swaps, I know...) */
  for(i = 0; i < nvars - 1; i++)
    for(j = 1; j < nvars; j++)
      if(sorted[j]->id < sorted[i]->id){
	temp = sorted[j];
	sorted[j] = sorted[i];
	sorted[i] = temp;
      }

  return sorted;
}
Example #3
0
nip_error_code nip_set_parents(nip_variable v, 
			       nip_variable* parents, 
			       int nparents){
  int i;
  if(v == NULL || (nparents > 0 && parents == NULL)){
    nip_report_error(__FILE__, __LINE__, NIP_ERROR_NULLPOINTER, 1);
    return NIP_ERROR_NULLPOINTER;
  }

  free(v->parents); /* in case it previously had another array */
  
  if(nparents > 0){
    v->parents = (nip_variable *) calloc(nparents, sizeof(nip_variable));
    if(!(v->parents)){
      nip_report_error(__FILE__, __LINE__, NIP_ERROR_OUTOFMEMORY, 1);
      return NIP_ERROR_OUTOFMEMORY;
    }
    
    for(i = 0; i < nparents; i++)
      v->parents[i] = parents[i]; /* makes a copy of the array */
  }
  
  v->num_of_parents = nparents;  
  return NIP_NO_ERROR;
}
Example #4
0
nip_variable* nip_variable_union(nip_variable* a, nip_variable* b, 
				 int na, int nb, int* nc){
  int i, j, n, found;
  nip_variable* c = NULL;

  /* Check stuff */
  if((nc == NULL) || (na > 0 && a == NULL) || (nb > 0 && b == NULL)){
    nip_report_error(__FILE__, __LINE__, NIP_ERROR_INVALID_ARGUMENT, 1);
    if(nc)
      *nc = -1;
    return NULL;
  }

  if(na <= 0 && nb <= 0){
    *nc = 0;
    return NULL;
  }
  
  /* Size of the union */
  n = na + nb;
  for(i = 0; i < na; i++){
    for(j = 0; j < nb; j++){
      if(nip_equal_variables(a[i], b[j])){
	n--;
	break;
      }
    }
  }
  *nc = n; /* save */
  if(!n)
    return NULL; /* empty set... shouldn't happen at this phase though */

  /* The union operation */
  c = (nip_variable*) calloc(*nc, sizeof(nip_variable));
  if(!c){
    nip_report_error(__FILE__, __LINE__, NIP_ERROR_OUTOFMEMORY, 1);
    if(nc)
      *nc = -1;
    return NULL;
  }
  for(i = 0; i < na; i++){ /* first the set a */
    c[i] = a[i];
  }
  n = na;
  for(i = 0; i < nb; i++){ /* then the missing ones from b */
    found = 0;
    for(j = 0; j < n; j++){
      if(nip_equal_variables(b[i], c[j])){
	found = 1;
	break;
      }
    }
    if(!found)
      c[n++] = b[i];
  }
  /* assert(*nc==n); */
  return c;
}
Example #5
0
/* Useful? Get rid of this function? */
nip_variable nip_copy_variable(nip_variable v){
  int i;
  int len;
  nip_variable copy;

  if(v == NULL)
    return NULL;

  copy = (nip_variable) malloc(sizeof(nip_variable_struct));
  if(!copy){
    nip_report_error(__FILE__, __LINE__, NIP_ERROR_OUTOFMEMORY, 1);
    return NULL;
  }

  copy->cardinality = v->cardinality;
  copy->id = v->id;

  len = strlen(v->name);
  nip_set_variable_text(&(copy->name), v->name);
  /* symbol etc? */

  copy->num_of_parents = v->num_of_parents;
  if(v->parents){
    copy->parents = (nip_variable*) calloc(v->num_of_parents, 
					   sizeof(nip_variable));
    if(!(copy->parents)){
      nip_report_error(__FILE__, __LINE__, NIP_ERROR_OUTOFMEMORY, 1);
      free(copy);
      return NULL;
    }
    for(i = 0; i < v->num_of_parents; i++)
      copy->parents[i] = v->parents[i];
  }
  else
    copy->parents = NULL;
  copy->family_clique = v->family_clique;

  copy->likelihood = (double*) calloc(copy->cardinality, sizeof(double));
  if(!(copy->likelihood)){
    nip_report_error(__FILE__, __LINE__, NIP_ERROR_OUTOFMEMORY, 1);
    free(copy->parents);
    free(copy);
    return NULL;
  }
  for(i = 0; i < copy->cardinality; i++)
    copy->likelihood[i] = v->likelihood[i];

  /* FIXME: also other fields, like copy->prior, copy->previous, etc... */

  return copy;
}
Example #6
0
double* nip_get_prior(nip_variable v){
  if(v == NULL){
    nip_report_error(__FILE__, __LINE__, NIP_ERROR_NULLPOINTER, 1);
    return NULL;
  }
  return v->prior;
}
Example #7
0
int nip_number_of_parents(nip_variable v){
  if(v == NULL){
    nip_report_error(__FILE__, __LINE__, NIP_ERROR_NULLPOINTER, 1);
    return -1;
  }
  return v->num_of_parents;
}
Example #8
0
nip_variable* nip_variable_isect(nip_variable *a, nip_variable *b, 
				 int na, int nb, int* nc){
  int i, j, n;
  nip_variable *c = NULL;
  
  /* Check stuff */
  if(!(a && b && na > 0 && nb > 0)){
    nip_report_error(__FILE__, __LINE__, NIP_ERROR_INVALID_ARGUMENT, 1);
    if(nc)
      *nc = -1;
    return NULL;
  }
  
  /* Size of the intersection */
  n = 0;
  for(i = 0; i < na; i++){
    for(j = 0; j < nb; j++){
      if(nip_equal_variables(a[i], b[j])){
	n++;
	break;
      }
    }
  }
  *nc = n; /* save */
  if(n == 0)
    return NULL; /* empty set */

  /* The intersection operation */
  c = (nip_variable*) calloc(*nc, sizeof(nip_variable));
  if(!c){
    nip_report_error(__FILE__, __LINE__, NIP_ERROR_OUTOFMEMORY, 1);
    if(nc)
      *nc = -1;
    return NULL;
  }
  n = 0;
  for(i = 0; i < na; i++){
    for(j = 0; j < nb; j++){
      if(nip_equal_variables(a[i], b[j])){
	c[n++] = a[i];
	break;
      }
    }
  }
  /* assert(*nc==n); */
  return c;
}
Example #9
0
void nip_get_variable_position(nip_variable v, int* x, int* y){
  if(v && x && y){
    *x = v->pos_x;
    *y = v->pos_y;
  }
  else
    nip_report_error(__FILE__, __LINE__, NIP_ERROR_NULLPOINTER, 1);
}
Example #10
0
void nip_set_variable_position(nip_variable v, int x, int y){
  if(v){
    v->pos_x = x;
    v->pos_y = y;
  }
  else
    nip_report_error(__FILE__, __LINE__, NIP_ERROR_NULLPOINTER, 1);
}
Example #11
0
void nip_reset_likelihood(nip_variable v){
  int i;
  if(v == NULL){
    nip_report_error(__FILE__, __LINE__, NIP_ERROR_NULLPOINTER, 1);
    return;
  }
  
  for(i = 0; i < v->cardinality; i++)
    (v->likelihood)[i] = 1;
}
Example #12
0
nip_error_code nip_update_likelihood(nip_variable v, double likelihood[]){

  int i;
  if(v == NULL || likelihood == NULL){
    nip_report_error(__FILE__, __LINE__, NIP_ERROR_NULLPOINTER, 1);
    return NIP_ERROR_NULLPOINTER;
  }

  for(i = 0; i < v->cardinality; i++)
    (v->likelihood)[i] = likelihood[i];

  return NIP_NO_ERROR;
}
Example #13
0
nip_error_code nip_set_prior(nip_variable v, double* prior){
  int i;
  if(v == NULL){
    nip_report_error(__FILE__, __LINE__, NIP_ERROR_NULLPOINTER, 1);
    return NIP_ERROR_NULLPOINTER;
  }
  if(!prior)
    return NIP_NO_ERROR;

  free(v->prior); /* reuse the allocated space??? */
  v->prior = (double*) calloc(v->cardinality, sizeof(double));
  for(i = 0; i < v->cardinality; i++)
    v->prior[i] = prior[i]; /* makes a copy of the array */

  return NIP_NO_ERROR;
}
Example #14
0
nip_variable nip_new_variable(const char* symbol, const char* name, 
			      char** states, int cardinality){
  /* NOTE: This id-stuff may overflow if variables are created and 
   * freed over and over again. */
  static long id = NIP_VAR_MIN_ID;
  int i, j;
  double *dpointer;
  nip_variable v;

  v = (nip_variable) malloc(sizeof(nip_variable_struct));
  if(!v){
    nip_report_error(__FILE__, __LINE__, NIP_ERROR_OUTOFMEMORY, 1);
    return NULL;
  }

  v->cardinality = cardinality;
  v->id = id++;
  v->previous = NULL;
  v->next = NULL;

  v->parents = NULL;
  v->prior = NULL; /* Usually prior == NULL  =>  num_of_parents > 0 */
  v->prior_entered = 0;
  v->num_of_parents = 0;
  v->family_clique = NULL;
  v->family_mapping = NULL;
  v->interface_status = NIP_INTERFACE_NONE; /* does not belong to interfaces */
  v->pos_x = 100;
  v->pos_y = 100;
  v->mark = NIP_MARK_OFF; /* If this becomes 0x00, there will be a bug (?) */

  v->symbol = NULL;
  nip_set_variable_text(&(v->symbol), symbol);

  v->name = NULL;
  if(name)
    nip_set_variable_text(&(v->name), name);
  /* DANGER! The name can be omitted and consequently be NULL */

  if(states){
    v->state_names = (char **) calloc(cardinality, sizeof(char *));
    if(!(v->state_names)){
      nip_report_error(__FILE__, __LINE__, NIP_ERROR_OUTOFMEMORY, 1);
      free(v);
      return NULL;
    }
    for(i = 0; i < cardinality; i++){
      if(nip_set_variable_text(&(v->state_names[i]), states[i]) == 
	 NIP_ERROR_OUTOFMEMORY){
	nip_report_error(__FILE__, __LINE__, NIP_ERROR_OUTOFMEMORY, 1);
	for(j = 0; j < i; j++)
	  free(v->state_names[j]);
	free(v->state_names);
	free(v);
      }
    }
  }
  else
    nip_report_error(__FILE__, __LINE__, NIP_ERROR_INVALID_ARGUMENT, 1);

  v->likelihood = (double *) calloc(cardinality, sizeof(double));
  if(!(v->likelihood)){
    nip_report_error(__FILE__, __LINE__, NIP_ERROR_OUTOFMEMORY, 1);
    for(i = 0; i < v->cardinality; i++)
      free(v->state_names[i]);
    free(v->state_names);
    free(v);
  }

  /* initialise likelihoods to 1 */
  for(dpointer=v->likelihood, i=0; i < cardinality; *dpointer++ = 1, i++);

  return v;
}
Example #15
0
int main(int argc, char *argv[]){

  int i, n;
  int num_of_vars = 0;
  nip_potential result = NULL;

  nip model = NULL;
  time_series ts = NULL;
  time_series *ts_set = NULL;
  nip_variable v = NULL;
  nip_variable *vars = NULL;

  double m1, m2;

  printf("nipjoint:\n");

  /*****************************************/
  /* Parse the model from a Hugin NET file */
  /*****************************************/

  /* -- Start parsing the network definition file */
  if(argc < 3){
    printf("Give the names of the net-file and data file please!\n");
    return 0;
  }
  
  /* read the model */
  model = parse_model(argv[1]);
  if(!model)
    return -1;
  use_priors(model, !NIP_HAD_A_PREVIOUS_TIMESLICE);

  /* read the data */
  n = read_timeseries(model, argv[2], &ts_set);
  if(n == 0)
    return -1;
  ts = ts_set[0];

  make_consistent(model); /* no side effects ? */

  /* compute probability mass before entering evidence */
  m1 = nip_probability_mass(model->cliques, model->num_of_cliques);

  /* enter the evidence... */
  i = insert_ts_step(ts, 0, model, NIP_MARK_BOTH);
  /* ...and distribute it */
  make_consistent(model);

  /* compute probability mass after making the model consistent */
  m2 = nip_probability_mass(model->cliques, model->num_of_cliques);
  
  /* It's possible to select the variables as
   * the third...N'th command line parameters.
   */
  if(argc > 3){
    num_of_vars = argc - 3;
    vars = (nip_variable *) calloc(num_of_vars, sizeof(nip_variable));
    for(i = 0; i < num_of_vars; i++){
      v = model_variable(model, argv[3 + i]);
      if(!v){
	nip_report_error(__FILE__, __LINE__, NIP_ERROR_INVALID_ARGUMENT, 1);
	fprintf(stderr, "  Variable %s unknown\n", argv[3 + i]);
	return -1;
      }
      vars[i] = v;
    }
  }
  else{ /* argc == 3 */
    if(ts->num_of_hidden > 0){
      /* else we just take the hidden variables */
      num_of_vars = ts->num_of_hidden;
      vars = ts->hidden;
    }
    else{
      /* or only the first observed variable */
      num_of_vars = 1;
      vars = ts->observed;
    }
  }
  /* The inputs have been parsed. -- */
  
  /****************************************************/
  /* The joint probability computation not tested yet */
  /****************************************************/
  result = get_joint_probability(model, vars, num_of_vars);

  /* Print stuff */
  printf("P(");
  for(i = 0; i < num_of_vars-1; i++){
    printf("%s, ", nip_variable_symbol(vars[i]));
  }
  printf("%s) equals: \n", nip_variable_symbol(vars[num_of_vars-1]));
  nip_fprintf_potential(stdout, result);

  printf("Marginal probability before evidence: m1 = %g\n", m1);
  printf("Marginal probability after evidence : m2 = %g\n", m2);
  printf("Log. likelihood: ln(m2/m1) = %g\n", log(m2/m1));
  
  free(vars);
  nip_free_potential(result);
  for(i = 0; i < n; i++)
    free_timeseries(ts_set[i]);
  free(ts_set);
  free_model(model);

  return 0;
}
Example #16
0
int main(int argc, char *argv[]) {

  int i, k, n=0;
  int iformat, oformat;
  nip_model model = NULL;
  time_series* ts_set = NULL;

  if(argc < 6){
    printf("You must specify: \n"); 
    printf(" - the NET file for the model, \n");
    printf(" - input format ('univariate'), \n");
    printf(" - input file name, \n");
    printf(" - output format ('unary'), \n");
    printf(" - output file name, please!\n");
    return 0;
  }
  
  /* read the model */
  model = parse_model(argv[1]);
  if(!model){
    printf("Unable to parse the NET file: %s?\n", argv[1]);
    return -1;
  }

  /* read file formats */
  /* Reminder: strcasecmp() is NOT ANSI C. */
  if(strcasecmp(argv[2], S_UNIVARIATE) == 0)
    iformat = UNIVARIATE;
  /* additional formats here */
  else{
    printf("Invalid input file format: %s?\n", argv[2]);
    free_model(model);
    return -1;
  }

  if(strcasecmp(argv[4], S_UNARY) == 0)
    oformat = UNARY;
  /* additional formats here */
  else{
    printf("Invalid output file format: %s?\n", argv[4]);
    free_model(model);
    return -1;
  }

  /* Read the input data file */
  switch (iformat) {
  case UNIVARIATE:
  case MULTIVARIATE:
    n = read_timeseries(model, argv[3], &ts_set);
    break;
  default:
    n = 0; /* should be impossible */
  }
  if(n < 1){
    fprintf(stderr, "There were errors while reading %s\n", argv[3]);
    free_model(model);
    /* no ts_set to free (?) */
    return -1;
  }

  /* Write the results to the file */
  k = NIP_NO_ERROR;
  switch (oformat) {
  case UNARY:
    k = write_unary_timeseries(ts_set, n, argv[5]);
    break;
  default:
    ; /* shouldn't happen */
  }
  if(k != NIP_NO_ERROR){
    fprintf(stderr, "Failed to write the data into %s\n", argv[5]);
    nip_report_error(__FILE__, __LINE__, k, 1);
    for(i = 0; i < n; i++)
      free_timeseries(ts_set[i]);
    free(ts_set);
    free_model(model);
    return -1;
  }

  for(i = 0; i < n; i++)
    free_timeseries(ts_set[i]);
  free(ts_set);
  free_model(model);
  return 0;
}
Example #17
0
int write_unary_timeseries(time_series *ts_set, int n_series, char* filename){
  int i, n, t;
  int d;
  int *record;
  int n_observed;
  nip_variable v;
  nip_variable *observed;
  nip_variable *observed_more;
  time_series ts;
  nip_model the_model;
  FILE *f = NULL;

  /* Check stuff */
  if(!(n_series > 0 && ts_set && filename)){
    nip_report_error(__FILE__, __LINE__, NIP_ERROR_INVALID_ARGUMENT, 1);
    return NIP_ERROR_INVALID_ARGUMENT;
  }

  /* Check all the models are same */
  the_model = ts_set[0]->model;
  for(n = 1; n < n_series; n++){
    if(ts_set[n]->model != the_model){
      nip_report_error(__FILE__, __LINE__, NIP_ERROR_INVALID_ARGUMENT, 1);
      return NIP_ERROR_INVALID_ARGUMENT;
    }
  }

  /* Find out union of observed variables */
  ts = ts_set[0];
  observed = nip_variable_union(ts->observed, NULL, 
				the_model->num_of_vars - ts->num_of_hidden,
				0, &n_observed);
  if(n_observed < 0){
    nip_report_error(__FILE__, __LINE__, NIP_ERROR_GENERAL, 1);
    return NIP_ERROR_GENERAL;
  }

  for(n = 1; n < n_series; n++){
    ts = ts_set[n];
    observed_more = nip_variable_union(observed, ts->observed, n_observed,
				       the_model->num_of_vars - 
				       ts->num_of_hidden,
				       &n_observed);
    free(observed); /* nice to create the same array again and again? */
    observed = observed_more;
  }

  if(n_observed < 1){ /* no observations in any time series? */
    nip_report_error(__FILE__, __LINE__, NIP_ERROR_INVALID_ARGUMENT, 1);
    return NIP_ERROR_INVALID_ARGUMENT;
  }

  /** NOTE: Actually this assumes there is only one observed variable! **/

  /* Temporary space for a sorted record (unary values) */
  v = observed[0];
  record = (int*) calloc(NIP_CARDINALITY(v), sizeof(int));
  if(!record){
    nip_report_error(__FILE__, __LINE__, NIP_ERROR_OUTOFMEMORY, 1);
    free(observed);
    return NIP_ERROR_OUTOFMEMORY;
  }

  /* Try to open the file for write */
  f = fopen(filename, "w");
  if(!f){
    nip_report_error(__FILE__, __LINE__, NIP_ERROR_IO, 1);
    free(observed);
    free(record);
    return NIP_ERROR_IO;
  }

  /* Write names of the variable states */
  for(i = 0; i < NIP_CARDINALITY(v); i++){
    if(i > 0)
      fprintf(f, "%c", NIP_FIELD_SEPARATOR);
    fprintf(f, "%s", nip_variable_state_name(v, i));
  }
  fputs("\n", f);

  /* Write the data */
  for(n = 0; n < n_series; n++){ /* for each time series */
    ts = ts_set[n];

    for(t = 0; t < TIME_SERIES_LENGTH(ts); t++){ /* for each time step */

      /* Fill record with indicators of missing data */
      for(i = 0; i < NIP_CARDINALITY(v); i++)
	record[i] = 0;

      /* Extract data from the time series */
      d = ts->data[t][0];
      if(d >= 0 && d < NIP_CARDINALITY(v))
	record[d] = 1;

      /* Print the data */
      for(i = 0; i < NIP_CARDINALITY(v); i++){
	if(i > 0)
	  fprintf(f, "%c", NIP_FIELD_SEPARATOR);
	if(record[i])
	  fputs("1", f);
	else
	  fputs("0", f);
      }
      fputs("\n", f);
    }
    fputs("\n", f); /* TS separator */
  }  
  free(observed);
  free(record);

  /* Close the file */
  if(fclose(f)){
    nip_report_error(__FILE__, __LINE__, NIP_ERROR_IO, 1);
    return NIP_ERROR_IO;
  }
  return NIP_NO_ERROR;
}
Example #18
0
int main(int argc, char *argv[]){

  int i, j, k, n, t = 0;
  double** quotient = NULL;
  double*** result = NULL; /* probs of the hidden variables */

  nip model = NULL;
  nip_clique clique_of_interest = NULL;

  nip_variable temp = NULL;
  nip_variable interesting = NULL;

  time_series *ts_set = NULL;
  time_series ts = NULL;

  /*************************************/
  /* Some experimental timeslice stuff */
  /*************************************/

  /*****************************************/
  /* Parse the model from a Hugin NET file */
  /*****************************************/

  /* -- Start parsing the network definition file */
  if(argc < 3){
    printf("Give the names of the net-file and data file, please!\n");
    return 0;
  }
  else
    model = parse_model(argv[1]);
    
  if(model == NULL)
    return -1;
  /* The input file has been parsed. -- */


  /*****************************/
  /* read the data from a file */
  /*****************************/
  n = read_timeseries(model, argv[2], &ts_set); /* 1. Open */
  if(n == 0){
    free_model(model);
    nip_report_error(__FILE__, __LINE__, NIP_ERROR_INVALID_ARGUMENT, 1);
    fprintf(stderr, "%s\n", argv[2]);
    return -1;
  }
  ts = ts_set[0];

  /* Allocate some space for filtering */
  assert(ts->num_of_hidden > 0);
  result = (double***) calloc(TIME_SERIES_LENGTH(ts) + 1, sizeof(double**));
  quotient = (double**) calloc(ts->num_of_hidden, sizeof(double*));
  if(!(result && quotient)){
    free_model(model);
    nip_report_error(__FILE__, __LINE__, NIP_ERROR_OUTOFMEMORY, 1);
    return 1;
  }
  for(t = 0; t < TIME_SERIES_LENGTH(ts) + 1; t++){
    result[t] = (double**) calloc(ts->num_of_hidden, sizeof(double*));
    if(!result[t]){
      free_model(model);
      nip_report_error(__FILE__, __LINE__, NIP_ERROR_OUTOFMEMORY, 1);
      return 1;
    }

    for(i = 0; i < ts->num_of_hidden; i++){
      result[t][i] = (double*) calloc(NIP_CARDINALITY(ts->hidden[i]), 
				      sizeof(double));
      if(!result[t][i]){
	free_model(model);
	nip_report_error(__FILE__, __LINE__, NIP_ERROR_OUTOFMEMORY, 1);
	return 1;
      }
    }
  }
  for(i = 0; i < ts->num_of_hidden; i++){
    quotient[i] = (double*) calloc(NIP_CARDINALITY(ts->hidden[i]), 
				   sizeof(double));
    if(!quotient[i]){
      free_model(model);
      nip_report_error(__FILE__, __LINE__, NIP_ERROR_OUTOFMEMORY, 1);
      return 1;
    }
  }


  /*****************/
  /* Forward phase */
  /*****************/
  printf("## Forward phase ##\n");  

  reset_model(model); /* Reset the clique tree */
  use_priors(model, !NIP_HAD_A_PREVIOUS_TIMESLICE);

  for(t = 0; t < TIME_SERIES_LENGTH(ts); t++){ /* FOR EVERY TIMESLICE */
    
    printf("-- t = %d --\n", t);
        
    /********************/
    /* Do the inference */
    /********************/
    
    make_consistent(model);
    
    
    /* an experimental forward phase (a.k.a. filtering)... */
    /* Calculates the result values */
    for(i = 0; i < ts->num_of_hidden; i++){
      
      /*********************************/
      /* Check the result of inference */
      /*********************************/
      
      /* 1. Decide which variable you are interested in */
      interesting = ts->hidden[i];
      
      /* 2. Find the clique that contains the family of 
       *    the interesting variable */
      clique_of_interest = nip_find_family(model->cliques, 
					   model->num_of_cliques, 
					   interesting);
      if(!clique_of_interest){
	free_model(model);
	free_timeseries(ts);
	printf("In hmmtest.c : No clique found! Sorry.\n");
	return 1;
      }  

      /* 3. Marginalisation (memory for the result must have been allocated) */
      nip_marginalise_clique(clique_of_interest, interesting, result[t][i]);

      /* 4. Normalisation */
      nip_normalise_array(result[t][i], NIP_CARDINALITY(interesting));

      /* 5. Print the result */
      for(j = 0; j < NIP_CARDINALITY(interesting); j++)
	printf("P(%s=%s) = %f\n", nip_variable_symbol(interesting),
	       (interesting->state_names)[j], result[t][i][j]);
      printf("\n");
    }

    if(t < TIME_SERIES_LENGTH(ts)){
      /* forget old evidence */
      reset_model(model);
      use_priors(model, NIP_HAD_A_PREVIOUS_TIMESLICE);

      for(i = 0; i < ts->num_of_hidden; i++){
	/* old posteriors become new priors */
	temp = ts->hidden[i];
	if(temp->next != NULL)
	  nip_update_likelihood(temp->next, result[t][i]);
      }

      nip_global_retraction(model->variables, model->num_of_vars, 
			    model->cliques, model->num_of_cliques);

      /* 0. Put some data in */
      for(i = 0; i < model->num_of_vars - ts->num_of_hidden; i++)
	if(ts->data[t][i] >= 0)
	  nip_enter_index_observation(model->variables, model->num_of_vars,
				      model->cliques, model->num_of_cliques,
				      ts->observed[i],
				      ts->data[t][i]);
    }
  }


  /******************/
  /* Backward phase */
  /******************/

  printf("## Backward phase ##\n");  

  /* forget old evidence */
  reset_model(model);
  use_priors(model, NIP_HAD_A_PREVIOUS_TIMESLICE); /* JJT: Not sure... */

  for(t = TIME_SERIES_LENGTH(ts)-1; t >= 0; t--){ /* FOR EVERY TIMESLICE */

    printf("-- t = %d --\n", t);

    if(t > 0){
      for(i = 0; i < model->num_of_vars - ts->num_of_hidden; i++){
	temp = ts->observed[i];
	assert(temp);
	if(ts->data[t - 1][i] >= 0)
	  nip_enter_index_observation(model->variables, model->num_of_vars, 
				      model->cliques, model->num_of_cliques, 
				      temp, 
				      ts->data[t - 1][i]);
      }

      for(i = 0; i < ts->num_of_hidden; i++){
	temp = ts->hidden[i];
	if(temp->next != NULL)
	  nip_enter_evidence(model->variables, model->num_of_vars, 
			     model->cliques, model->num_of_cliques, 
			     temp->next, result[t-1][i]);
      }
    }

    if(t < TIME_SERIES_LENGTH(ts)){
      
      for(i = 0; i < ts->num_of_hidden; i++){
	temp = ts->hidden[i];
	if(temp->previous != NULL){
	  /* search for the other index */
	  for(k = 0; k < ts->num_of_hidden; k++)
	    if(nip_equal_variables(temp->previous, ts->hidden[k]))
	      break;
	  
	  /* FIXME: Get rid of the quotient array */
	  printf("result[%d][%d][%d] / result[%d][%d][%d]\n", 
		 t+1, i, j, t, k, j);

	  for(j = 0; j < NIP_CARDINALITY(temp); j++)
	    quotient[i][j] = result[t + 1][i][j] / result[t][k][j]; 
	  
	  nip_enter_evidence(model->variables, model->num_of_vars, 
			     model->cliques, model->num_of_cliques, 
			     temp->previous, quotient[i]);
	}
      }
    }
    
    /********************/
    /* Do the inference */
    /********************/
    
    make_consistent(model);
    
    /*********************************/
    /* Check the result of inference */
    /*********************************/
    for(i = 0; i < ts->num_of_hidden; i++){
      
      /* 1. Decide which variable you are interested in */
      interesting = ts->hidden[i];
      
      /* 2. Find the clique that contains the family of 
       *    the interesting variable */
      clique_of_interest = nip_find_family(model->cliques, 
					   model->num_of_cliques, 
					   interesting);
      if(!clique_of_interest){
	free_model(model);
	free_timeseries(ts);
	printf("In hmmtest.c : No clique found! Sorry.\n");
	return 1;
      }  
      
      /* 3. Marginalisation (the memory must have been allocated) */
      nip_marginalise_clique(clique_of_interest, interesting, result[t][i]);
      
      /* 4. Normalisation */
      nip_normalise_array(result[t][i], NIP_CARDINALITY(interesting));
      
      /* 5. Print the result */
      for(j = 0; j < NIP_CARDINALITY(interesting); j++)
	printf("P(%s=%s) = %f\n", nip_variable_symbol(interesting),
	       (interesting->state_names)[j], result[t][i][j]);
      printf("\n");
    }
    
    /* forget old evidence */
    reset_model(model);
    use_priors(model, NIP_HAD_A_PREVIOUS_TIMESLICE);
  }
  
  for(t = 0; t < TIME_SERIES_LENGTH(ts) + 1; t++){
    for(i = 0; i < ts->num_of_hidden; i++)
      free(result[t][i]);
    free(result[t]);
  }
  for(i = 0; i < ts->num_of_hidden; i++)
    free(quotient[i]);

  free(result);
  free(quotient);

  for(i = 0; i < n; i++)
    free_timeseries(ts_set[i]);
  free(ts_set);
  
  free_model(model);

  return 0;
}