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; }
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; }
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; }
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; }
/* 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; }
double* nip_get_prior(nip_variable v){ if(v == NULL){ nip_report_error(__FILE__, __LINE__, NIP_ERROR_NULLPOINTER, 1); return NULL; } return v->prior; }
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; }
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; }
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); }
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); }
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; }
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; }
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; }
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; }
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; }
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; }
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; }
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; }