/** 
* @file PLSA.h
* @brief implementation of the pLSA model
* @author Erik Rodner
* @date 02/05/2009

*/
#ifndef PLSAINCLUDE
#define PLSAINCLUDE

#include "core/vector/VectorT.h"
#include "core/vector/MatrixT.h"
  

namespace OBJREC {

/** implementation of the pLSA model */
class PLSA
{

    protected:
	int maxiterations;
	double delta_eps;
	double betadecrease;
	double holdoutportion;

	void pLSA_EMstep ( const double *counts, 
	    double *pw_z, double *pd, double *pz_d,
	    double *pw_z_out, double *pd_out, double *pz_d_out, double *p_dw,
	    int n, int m, int d,
	    double beta, 
	    bool update_pw_z );


    public:
  
	/** simple constructor */
	PLSA( int maxiterations = 5000,
	    double delta_eps = 1e-3,
	    double betadecrease = 0.9,
	    double holdoutportion = 0.2 );
      
	/** simple destructor */
	virtual ~PLSA();

	double pLSA ( const double *counts, 
	    double *pw_z,
	    double *pd,
	    double *pz_d,
	    int n,
	    int m,
	    int total_documents,
	    bool update_pw_z = true,
	    bool tempered = false,
	    bool optimization_verbose = false );

	double computeLikelihood ( const double *counts,
			   const double *pw_z,
			   const double *pd,
			   const double *pz_d,
			   int n,
			   int m,
			   int d,
			   int dtrained = -1) const;

  	double computePerplexity ( const double *counts,
			   const double *pw_z,
			   const double *pz_d,
			   int n,
			   int m,
			   int d) const;

	double algebraicFoldIn ( const double *counts,
			double *pw_z,
			double *pd,
			double *pz_d, 
			int n, int m );

    public: /** static functions */
	static void randomizeBuffer ( double *A, long size );
	static void uniformDistribution ( double *x, int size  );
	static void normalizeRows ( double *A, int r, int c );
	static void normalizeCols ( double *A, int r, int c );
	static double computeSparsity ( const double *A, long int size );


};


} // namespace

#endif