#ifndef SVM_H
#define SVM_H

#include <stdlib.h>
#include <stdio.h>


#define TRUE 1
#define FALSE 0

#define SORT_ASCENDING 1
#define SORT_DESCENDING 2

#define DIST_SQUARED_EUCLIDEAN 1
#define DIST_EUCLIDEAN 2


#define SVM_KERNEL_LINEAR 1
#define SVM_KERNEL_GAUSSIAN 2
#define SVM_KERNEL_POLINOMIAL 3
#define SVM_KERNEL_TVERSKY 4

#define BAGGING 1
#define AGGREGATE 2
#define ADABOOST 3


/*SVM*/

typedef struct
{
  int n;                                       /*number of examples*/
  int d;                                       /*number of features*/
  double **x;                           /*training data*/
  int *y;                               /*class labels*/
  double C;                                    /*bias/variance parameter*/
  double tolerance;                            /*tolerance for testing KKT conditions*/
  double eps;                                  /*convergence parameters:used in both takeStep and mqc functions*/
  int kernel_type;                             /*kernel type:1 linear, 2 gaussian, 3 polynomial*/
  double two_sigma_squared;                    /*kernel parameter*/
  double *alph;                         /*lagrangian coefficients*/
  double b;                                    /*offset*/
  double *w;                            /*hyperplane parameters (linearly separable  case)*/
  double *error_cache;                  /*error for each training point*/ 
  int end_support_i;                           /*set to N, never changed*/
  double (*learned_func)();                    /*the SVM*/
  double (*kernel_func)();                     /*the kernel*/
  double delta_b;                              /*gap between old and updated offset*/
  double *precomputed_self_dot_product; /*squared norm of the training data*/
  double *Cw;                           /*weighted C parameter (sen/spe)*/
  int non_bound_support;                       /*number of non bound SV*/
  int bound_support;                           /*number of bound SV*/
  int maxloops;                                /*maximum number of optimization loops*/
  int convergence;                             /*to assess convergence*/
  int verbose;                                 /*verbosity */
  double **K;                           /*precomputed kernel matrix (for RSFN)*/
  double alpha_tversky;                
  double beta_tversky;
} SupportVectorMachine;


typedef struct
{
  SupportVectorMachine *svm; /*the svm's*/
  int nmodels; /*number of svm's*/
  double *weights; /*modeles weights*/
} ESupportVectorMachine;


/*RSFN*/

typedef struct
{
  double *w;
  double *b;
  int *i;
  int *j;
  int nsf;
} SlopeFunctions;

typedef struct
{
  double **x;
  int d;
  SupportVectorMachine svm;
  SlopeFunctions sf;
  double threshold;
}RegularizedSlopeFunctionNetworks;

typedef struct
{
  RegularizedSlopeFunctionNetworks *rsfn; 
  int nmodels; 
  double *weights;
} ERegularizedSlopeFunctionNetworks;



/***************
FUNCTIONS
***************/

/*memory*/
int *ivector(long n);
double *dvector(long n);
double **dmatrix(long n, long m);
int **imatrix(long n, long m);
int free_ivector(int *v);
int free_dvector(double *v);
int free_dmatrix(double **M, long n, long m);
int free_imatrix(int **M, long n, long m);

/*sorting*/
void dsort(double a[], int ib[],int n, int action);
void isort(int a[], int ib[],int n, int action);

/*random sampling*/
int sample(int n, double prob[], int nsamples, int **samples, int replace,
	   int seed);

/*unique*/
int iunique(int y[], int n, int **values);
int dunique(double y[], int n, double **values);

/*distance*/
double l1_distance(double x[],double y[],int n);
double euclidean_squared_distance(double x[],double y[],int n);
double euclidean_distance(double x[],double y[],int n);
double scalar_product(double x[],double y[],int n);
double euclidean_norm(double x[],int n);

/*inverse matrix and determinant*/
int inverse(double *A[],double *inv_A[],int n);
double determinant(double *A[],int n);

/*svm*/
int compute_svm(SupportVectorMachine *svm,int n,int d,double *x[],int y[],
		int kernel,double kp,double C,double tol,
		double eps,int maxloops,int verbose, double W[], double alpha_tversky, double beta_tversky);

double predict_svm(SupportVectorMachine *svm,double x[],double **margin);

/*rsfn*/
int compute_rsfn(RegularizedSlopeFunctionNetworks *rsfn,int n,int d,
		 double *x[],int y[],double C,double tol,
		 double eps,int maxloops,int verbose,double W[],
		 double threshold,int knn);

double predict_rsfn(RegularizedSlopeFunctionNetworks *rsfn,double x[],
		    double **margin);

/*rnd.c*/
double svm_drand48 (void);
void svm_srand48 (long int seed);

#endif /* SVM_H */
