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; }