/* libirt.h
 *
 * Copyright (C) 2005 Stephane Germain
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or (at
 * your option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 */

/**
   \file
   \brief The exported functions definition of the libirt library.

   \author Stephane Germain <germste@gmail.com>
*/

#ifndef LIBIRT_H

/** \brief Define a flag if this header file is already included. */
#define LIBIRT_H 1

#include <gsl/gsl_matrix.h>
#include <gsl/gsl_vector.h>

/** \brief Define the representation of blank as integer. */
#define BLANK -1
/** \brief Define the representation of false as integer. */
#define FALSE 0
/** \brief Define the representation of true as integer. */
#define TRUE 1
/** \brief Define the smallest probability allowed. */
#define VERY_SMALL_PROB ((double)1.0e-10)
/** \brief Define the smallest frequency allowed. */
#define VERY_SMALL_FREQ ((double)1.0e-3)
/** \brief Define the biggest logit allowed in absolute value. */
#define VERY_BIG_LOGIT ((double)23.0)
/** \brief Define the biggest absolute polyserial correlation allowed. */
#define MAX_POLYCOR ((double)0.9999)

/** \brief Define the code for the 1PLM. */
#define CODE_1PLM 1
/** \brief Define the code for the 2PLM. */
#define CODE_2PLM 2
/** \brief Define the code for the 3PLM. */
#define CODE_3PLM 3
/** \brief Define the code for the nominal model. */
#define CODE_NOMINAL 4
/** \brief Define the code for the graded model. */
#define CODE_GRADED 5
/** \brief Define the code for the PMMLE model. */
#define CODE_PMMLE 6
/** \brief Define the code for the kernel model. */
#define CODE_KERNEL 7

/**
   \brief Used to passed extra parameter to the score gradient/hesian functions.

   This is used to comply with the root finding functions in
   the gsl (GNU scientific library).
*/
typedef struct
{
  /** \brief The middle point of the quadrature classes. */
  gsl_vector *quad_points;

  /** \brief The expected number of subject in each quadrature classes. */
  gsl_vector *quad_sizes;

  /** \brief The expected number of subject in each quadrature classes 
      and in each options. */
  gsl_matrix *quad_freqs;

  /** \brief A place to compute the responses functions. */
  gsl_matrix *probs;

  /** \brief A place to compute the boundary functions. */
  gsl_matrix *bounds;

} like_2plm_mc_struct;

extern const char *libirt_version;

extern int libirt_verbose;

int read_bin_patterns_delimited (FILE * file, int nbr_item,
				 int nbr_subject, int skip,
				 char delimiter, int offset, int extra,
				 char *true_string, char *false_string,
				 char *blank_string, int trimming,
				 gsl_matrix_int ** patterns);

int read_mc_patterns_delimited (FILE * file, int nbr_item,
				int nbr_subject, int skip,
				char delimiter, int offset, int extra,
				int trimming,
				gsl_matrix_int ** patterns, 
				gsl_vector_int ** nbr_options);

double logit (double p);

double logistic (double t);

double prob_3plm (double ability,
		  double slope, double threshold, double asymptote);

void quadrature (int nbr_quad, double from, double to,
		 gsl_vector * quad_points,
		 gsl_vector * quad_weights);

void patterns_counts (gsl_matrix_int * subjects, gsl_vector_int ** index,
		      gsl_matrix_int ** patterns, gsl_vector ** counts);

void probs_3plm (gsl_vector * slopes, gsl_vector * thresholds,
		 gsl_vector * asymptotes, gsl_vector * quad_points,
		 gsl_matrix * probs);

void likelihood (gsl_matrix_int * patterns, gsl_matrix * probs,
		 gsl_matrix * like);

void likelihood_mc (gsl_matrix_int * patterns, gsl_matrix * probs,
		    gsl_vector_int * nbr_options, gsl_vector_int * items_pos, 
		    gsl_matrix * like);

void posteriors (gsl_matrix_int * patterns, gsl_matrix * probs,
		 gsl_vector * quad_weights, gsl_matrix * post);

void posteriors_mc (gsl_matrix_int * patterns, gsl_matrix * probs,
		    gsl_vector_int * nbr_options, gsl_vector_int * items_pos, 
		    gsl_vector * quad_weights, gsl_matrix * post);

void frequencies (gsl_matrix_int * patterns, gsl_vector * counts,
		  gsl_matrix * post, gsl_matrix * probs,
		  gsl_vector * quad_sizes, gsl_matrix * quad_freqs);

int set_ignore (gsl_matrix_int * patterns, gsl_matrix * probs, 
		gsl_vector * thresholds, gsl_vector_int * ignore);

void constrain_probs (gsl_matrix * probs, double eps);

void patterns_expand (gsl_matrix_int * patterns_mc, 
		      gsl_vector_int * items_nbr, 
		      gsl_matrix_int * patterns, gsl_vector_int * items_pos);

int mle_abilities_3plm (int max_iter, double prec,
			gsl_matrix_int * patterns, gsl_vector * slopes,
			gsl_vector * thresholds,
			gsl_vector * asymptotes,
			gsl_vector * abilities,
			gsl_vector * abilities_stddev);

void eap_abilities (gsl_matrix * post,
		    gsl_vector * quad_points,
		    gsl_vector * quad_weights,
		    gsl_vector * abilities,
		    gsl_vector * abilities_stddev);

int em_bme_3plm (int nbr_par, int max_em_iter, int max_nr_iter,
		 double prec, gsl_matrix_int * patterns,
		 gsl_vector * counts, gsl_vector * quad_points,
		 gsl_vector * quad_weights, int slope_prior,
		 double slope_mean, double slope_dev, int thresh_prior,
		 double thresh_mean, double thresh_dev,
		 int asymp_prior, double asymp_mean,
		 double asymp_weight, gsl_vector * slopes,
		 gsl_vector * thresholds, gsl_vector * asymptotes,
		 gsl_vector * slopes_stddev, gsl_vector * thresh_stddev,
		 gsl_vector * asymp_stddev, gsl_vector_int * ignore,
		 int * nbr_notconverge, gsl_vector_int * notconverge,
		 int adjust_weights);

int em_mple_wave (int max_em_iter, int max_nr_iter, double prec,
		  double smooth_factor, gsl_matrix_int * patterns,
		  gsl_vector * counts, gsl_vector * quad_points,
		  gsl_vector * quad_weights, gsl_matrix * probs,
		  gsl_matrix * probs_stddev, gsl_vector_int * ignore,
		  int * nbr_notconverge, gsl_vector_int * notconverge,
		  int adjust_weights);

void nadaraya_watson (double bandwidth, gsl_matrix_int * patterns,
		      gsl_vector * quad_points, gsl_vector * quad_weights,
		      gsl_matrix * probs, gsl_matrix * probs_stddev);

void patterns_expand (gsl_matrix_int * patterns_mc, 
		      gsl_vector_int * nbr_options, 
		      gsl_matrix_int * patterns, gsl_vector_int * items_pos);

void logits_from_probs (gsl_matrix * probs, gsl_matrix * logits);

void probs_from_logits (gsl_matrix * logits, gsl_matrix * probs);

int em_mple_wave_mc (int max_em_iter, int max_nr_iter, 
		     double prec, double smooth_factor, 
		     gsl_matrix_int * patterns, gsl_vector * counts,
		     gsl_vector * quad_points, gsl_vector * quad_weights, 
		     gsl_vector_int * items_pos, gsl_vector_int * items_nbr,
		     gsl_matrix * probs, gsl_matrix * probs_stddev,
		     gsl_vector_int * ignore, 
		     int * nbr_notconverge, gsl_vector_int * notconverge,
		     int adjust_weights);

int set_ignore_mc (gsl_matrix_int * patterns,
		   gsl_vector_int * nbr_options, gsl_vector_int * items_pos,
		   gsl_matrix * probs, gsl_vector * thresholds, 
		   gsl_vector_int * ignore);

void nadaraya_watson_mc (double bandwidth, gsl_matrix_int * patterns,
			 gsl_vector_int * items_pos,
			 gsl_vector_int * nbr_options,
			 gsl_vector * options_weights,
			 gsl_vector * quad_points, gsl_vector * quad_weights,
			 gsl_matrix * probs, gsl_matrix * probs_stddev);

void prob_2plm_mc (gsl_vector * slopes, gsl_vector * thresholds,
		   gsl_vector * quad_points, gsl_matrix * probs);

void probs_2plm_mc (gsl_vector * slopes, gsl_vector * thresholds,
		    gsl_vector_int * nbr_options, gsl_vector_int * items_pos,
		    gsl_vector * quad_points, gsl_matrix * probs);

int like_2plm_mc_fdfdf2 (const gsl_vector * par, void *params,
			 double * f, gsl_vector * df, gsl_matrix * df2);

int like_2plm_grad_fdfdf2 (const gsl_vector * par, void *params,
			   double * f, gsl_vector * df, gsl_matrix * df2);

int mle_2plm_mc (int max_iter, double prec,
		 like_2plm_mc_struct * params,
		 gsl_vector * thresholds, gsl_vector * thresh_stddev,
		 gsl_vector * slopes, gsl_vector * slopes_stddev,
		 double * mllk);

int mmle_2plm_mc (int max_em_iter, int max_nr_iter, double prec,
		  gsl_matrix_int * patterns, gsl_vector * counts,
		  gsl_vector * quad_points, gsl_vector * quad_weights, 
		  gsl_vector_int * items_pos, gsl_vector_int * nbr_options,
		  gsl_vector * thresholds, gsl_vector * thresh_stddev,
		  gsl_vector * slopes, gsl_vector * slopes_stddev,
		  gsl_vector_int * ignore, 
		  int * nbr_notconverge, gsl_vector_int * notconverge,
		  int adjust_weights);

void prob_2plm_grad (gsl_vector * slopes, gsl_vector * thresholds,
		     gsl_vector * quad_points, gsl_matrix * probs,
		     gsl_matrix * bounds);

void probs_2plm_grad (gsl_vector * slopes, gsl_vector * thresholds,
		      gsl_vector_int * nbr_options, gsl_vector_int * items_pos,
		      gsl_vector * quad_points, gsl_matrix * probs,
		      gsl_matrix * bounds);

int mle_2plm_grad (int max_iter, double prec,
		   like_2plm_mc_struct * params,
		   gsl_vector * thresholds, gsl_vector * thresh_stddev,
		   gsl_vector * slopes, gsl_vector * slopes_stddev,
		   double * mllk);

int mmle_2plm_grad (int max_em_iter, int max_nr_iter, double prec,
		    gsl_matrix_int * patterns, gsl_vector * counts,
		    gsl_vector * quad_points, gsl_vector * quad_weights, 
		    gsl_vector_int * items_pos, gsl_vector_int * nbr_options,
		    gsl_vector * thresholds, gsl_vector * thresh_stddev,
		    gsl_vector * slopes, gsl_vector * slopes_stddev,
		    gsl_vector_int * ignore,
		    int * nbr_notconverge, gsl_vector_int * notconverge,
		    int adjust_weights);

void probs_2plm_mixed (gsl_vector * slopes, gsl_vector * thresholds,
		       gsl_vector_int * item_models, gsl_vector_int * nbr_options, gsl_vector_int * items_pos,
		       gsl_vector * quad_points, gsl_matrix * probs, gsl_matrix * bounds);

int mmle_mixed (int max_em_iter, int max_nr_iter, double prec,
		gsl_matrix_int * patterns, gsl_vector * counts,
		gsl_vector * quad_points, gsl_vector * quad_weights, 
		gsl_vector_int * items_models, gsl_vector_int * items_pos, gsl_vector_int * nbr_options,
		gsl_vector * thresholds, gsl_vector * thresh_stddev,
		gsl_vector * slopes, gsl_vector * slopes_stddev,
		gsl_vector_int * ignore,
		int * nbr_notconverge, gsl_vector_int * notconverge);

void icc_from_probs (gsl_matrix *probs, gsl_matrix *probs_stddev,
		     gsl_vector *options_weights,
		     gsl_vector_int * nbr_options, gsl_vector_int * items_pos,
		     gsl_matrix *iccs, gsl_matrix *iccs_stddev);

void info_from_probs (gsl_matrix *probs, gsl_vector *quad_points,
		      gsl_matrix *infos, gsl_vector *test_info);

void info_from_probs_mc (gsl_matrix *probs, gsl_vector *quad_points,
			 gsl_vector_int *nbr_options,
			 gsl_vector_int *items_pos,
			 gsl_matrix *options_infos, gsl_matrix *infos,
			 gsl_vector *test_info);

void llk_ratio_fit_test (gsl_vector *quad_sizes, gsl_matrix *quad_freqs,
			 gsl_vector *quad_weights, gsl_matrix *probs,
			 int nbr_inter, gsl_vector *chi2, gsl_vector_int *df,
			 gsl_vector *p_value);

void llk_ratio_fit_test_mc (gsl_vector *quad_sizes, gsl_matrix *quad_freqs,
			    gsl_vector *quad_weights, gsl_matrix *probs,
			    gsl_vector_int *nbr_options, gsl_vector_int *items_pos,
			    int nbr_inter, gsl_vector *chi2, gsl_vector_int *df, 
			    gsl_vector *p_value);

void classical_statistics(gsl_matrix_int * patterns,
						  gsl_vector * items_mean, gsl_vector * items_sd, 
						  gsl_vector * items_corr, gsl_vector * items_bis_corr, 
						  gsl_vector_int * items_nbr,
						  gsl_vector * subjects_mean, gsl_vector_int * subjects_nbr,
						  int * nbr, double * mean, double * sd, double * alpha,
						  gsl_matrix * pairs_corr,  gsl_matrix_int * freq_table);

void classical_statistics_mc(gsl_matrix_int * patterns, gsl_vector * options_weights,
							 gsl_vector_int * items_pos, gsl_vector_int * nbr_options,
							 gsl_vector * items_mean, gsl_vector * items_sd, 
							 gsl_vector * items_corr, gsl_vector * items_poly_corr, 
							 gsl_vector_int * items_nbr,
							 gsl_vector * subjects_score, gsl_vector_int * subjects_nbr,
							 int * nbr, double * mean, double * sd, double * alpha,
							 gsl_matrix * pairs_corr,  gsl_vector_int * freq_table);

void llk_ratio_ld_test (gsl_matrix_int * patterns, gsl_matrix *probs,
			gsl_vector *quad_weights,
			gsl_matrix *chi2, gsl_matrix_int *df, gsl_matrix *p_value);

void llk_ratio_ld_test_mc (gsl_matrix_int * patterns, gsl_matrix *probs,
			   gsl_vector *quad_weights,
			   gsl_vector_int *nbr_options, gsl_vector_int *items_pos,
			   gsl_matrix *chi2, gsl_matrix_int *df, gsl_matrix *p_value);

void adjust_quad_weights (double nbr_subject, gsl_vector * quad_sizes, 
			  gsl_vector * quad_points, gsl_vector * quad_weights);

int wmle_abilities (int max_iter, double prec,
		    gsl_matrix * like, gsl_vector * info, gsl_vector * quad_points,
		    gsl_vector * abilities, gsl_vector * abilities_stddev);

double polyserial_factor(gsl_vector_int * patterns, int nbr_option, int offset, 
			 gsl_vector * options_weights);

#endif

