/*******************************************************************************
  author       : Achim Gaedke
  filename     : ghmm/tests/coin_toss_test.c
  created      : DATE: 2001-04-25
  $Id: chmm.c 1733 2006-10-24 11:42:57Z christoph_mpg $
*******************************************************************************/

#ifdef HAVE_CONFIG_H
#  include "../config.h"
#endif

#include <stdio.h>
#include <unistd.h>

#include <ghmm/matrix.h>
#include <ghmm/rng.h>
#include <ghmm/smodel.h>
#include <ghmm/matrixop.h>
#include <ghmm/ghmm_internals.h>

#include <ghmm/obsolete.h>

/*
  Simple model with one state and 2 symbols, like a coin toss
*/

int single_state_continuous()
{
  ghmm_cstate single_state;
  ghmm_cmodel my_model;
  ghmm_c_emission state_emission;


  double trans_prob_single_state[]={1.0};
  double trans_prob_single_state_rev[]={1.0};
  double *trans_prob_single_state_array;
  double *trans_prob_single_state_rev_array;
  int trans_id_single_state[]={0};
  int dimension=1;
  double c[]={1.0};
  double mue[]={0.0};
  double u[]={1.0};
  ghmm_density_t density = normal;
  ghmm_cseq* my_output;

  /* initialise transition array */
  trans_prob_single_state_array=trans_prob_single_state;
  trans_prob_single_state_rev_array=trans_prob_single_state_rev;

  /* initialise the emission */
  state_emission.type = density;
  state_emission.dimension = dimension;
  state_emission.mean.val = *mue;
  state_emission.variance.val = *u;
  state_emission.fixed = 0;

  /* initialise this state */
  single_state.pi = 1.0;
  single_state.M=1;
  single_state.c=c; /* weight of distribution */
  single_state.e=&state_emission;
  single_state.out_id=trans_id_single_state;
  single_state.in_id=trans_id_single_state;
  single_state.out_a=&trans_prob_single_state_array;
  single_state.in_a=&trans_prob_single_state_rev_array;
  single_state.out_states=1;
  single_state.in_states=1;
  single_state.fix=0; /* training of output functions */

  /* initialise model */
  my_model.N=1; /* states */
  my_model.M=1; /* density functions per state */
  my_model.dim=1; /* number of dimesions */
  my_model.cos=1; /* class of states */
  my_model.prior=-1; /* a priori probability */
  my_model.s=&single_state; /* states array*/

  /* generate sequences */
  my_output=ghmm_cmodel_generate_sequences(&my_model,
                                           1,  /* random seed */
                                           10, /* length of sequences */
                                           10, /* sequences */
                                           0  /* maximal sequence length 0: no limit*/
                                           );
  /* print out sequences */

#if 0

  ghmm_cseq_print(stdout,    /* output file */
                  my_output, /* sequence */
                  0          /* do not truncate to integer*/
                  );

  ghmm_cseq_free(&my_output);

#endif
  return 0;
}

int single_state_continuous_multidim()
{
  ghmm_cstate single_state;
  ghmm_cmodel my_model;
  ghmm_c_emission state_emission;

  ghmm_cmodel *this_model;
  ghmm_cmodel **ptrto_this_model;

  double *trans_prob_single_state;
  double *trans_prob_single_state_rev;
  double *trans_prob_single_state_array;
  double *trans_prob_single_state_rev_array;
  int *trans_id_single_state;
  int dimension=3;
  double *c;
  double *mue;
  double *u;
  ghmm_density_t density = multinormal;
  ghmm_cseq* my_output;

  /* allocate memory for various variables*/
  mue = calloc(dimension, sizeof(double));
  mue[0] = 0.0;
  mue[1] = 0.0;
  mue[2] = 0.0;
  u = calloc(dimension*dimension, sizeof(double));
  u[0] = 1.0;
  u[1] = 0.0;
  u[2] = 0.0;
  u[3] = u[1];
  u[4] = 1.0;
  u[5] = 0.0;
  u[6] = u[2];
  u[7] = u[5];
  u[8] = 1.0;
  trans_prob_single_state = calloc(1, sizeof(double));
  trans_prob_single_state[0] = 1.0;
  trans_prob_single_state_rev = calloc(1, sizeof(double));
  trans_prob_single_state_rev[0] = 1.0;
  trans_id_single_state = calloc(1, sizeof(int));
  trans_id_single_state[0] = 0;
  c = calloc(1, sizeof(double));
  c[0] = 1.0;

  /* initialise transition array */
  trans_prob_single_state_array=trans_prob_single_state;
  trans_prob_single_state_rev_array=trans_prob_single_state_rev;

  /* initialise the emission */
  state_emission.type = density;
  ghmm_c_emission_alloc(&state_emission, dimension);
  state_emission.dimension = dimension;
  state_emission.mean.vec = mue;
  state_emission.variance.mat = u;
  state_emission.fixed = 0;

  /* initialise this state */
  ghmm_cstate_alloc(&single_state, 1, 1, 1 ,1);
  single_state.pi = 1.0;
  single_state.M=1;
  single_state.c=c; /* weight of distribution */
  single_state.e=&state_emission;
  single_state.out_id=trans_id_single_state;
  single_state.in_id=trans_id_single_state;
  single_state.out_a=&trans_prob_single_state_array;
  single_state.in_a=&trans_prob_single_state_rev_array;
  single_state.out_states=1;
  single_state.in_states=1;
  single_state.fix=0; /* training of output functions */

  /* initialise model */
  this_model = &my_model;
  ptrto_this_model = &this_model;
  my_model.N=1; /* states */
  my_model.M=1; /* density functions per state */
  my_model.dim=dimension; /* number of dimensions */
  my_model.cos=1; /* class of states */
  my_model.prior=-1; /* a priori probability */
  my_model.s=&single_state; /* states array*/

  /* calculate inverse of covariance matrix */
  printf("\ncalculate inverse of covariance matrix\n");

  /* call every time after setting the covariance matrix */
  ighmm_invert_det(this_model->s[0].e[0].sigmainv, &(this_model->s[0].e[0].det),
                   this_model->dim, this_model->s[0].e[0].variance.mat);

  /* call this before generating random data */
  ighmm_cholesky_decomposition(this_model->s[0].e[0].sigmacd, this_model->dim,
                               this_model->s[0].e[0].variance.mat);

  my_output=ghmm_cmodel_generate_sequences(this_model,
                                           1,  /* random seed */
                                           10, /* length of sequences (in time points) */
                                           10, /* sequences */
                                           0  /* maximal sequence length 0: no limit*/
                                           );



  printf("determinant is %f \n",my_model.s[0].e[0].det);
  /*
  fprintf("det is %f \n",&my_model.s[0].e[0].det);
  */

  /* free memory */
  ghmm_c_emission_free(&state_emission);
  /* ghmm_c_free(ptrto_this_model); */

  return 0;
}

int main()
{
  int ret;
  printf("\ninitialise rng\n");
  /* Important! initialise rng  */
  ghmm_rng_init();

  printf("\nset up model\n");

  ret = single_state_continuous_multidim();

  return ret;
}
