/** 
* @file MutualInformation.h
* @brief Part selection and thresholding with Mutual Information
* @author Erik Rodner
* @date 02/20/2008

*/
#ifndef MUTUALINFORMATIONINCLUDE
#define MUTUALINFORMATIONINCLUDE

#include "core/vector/VVector.h"
#include "vislearning/cbaselib/LabeledSet.h"


namespace OBJREC {

/** Part selection and thresholding with mutual information */
class MutualInformation
{
  protected:

    //! verbose handling
    bool verbose;

    /**
    * @brief helper function: loop through all vectors and count how often f[d]>threshold
    *
    * @param v multi-dimensional features
    * @param d feature index used
    * @param threshold used to generate the binary feature
    * @param ones number of times f[d] is above threshold
    */
	  void addStatistics ( const std::vector<NICE::Vector *> & v, size_t d, double threshold, size_t & ones ) const;

    
    /**
    * @brief Compute the entropy of 2-bin discrete distribution
    *
    * @param n1 number of elements for bin 1
    * @param n2 number of elements for bin 2
    *
    * @return entropy value
    */
	  double entropy ( size_t n1, size_t n2 ) const;

  public:
  
    /** simple constructor */
    MutualInformation( bool verbose = false );
        
    /** simple destructor */
    virtual ~MutualInformation();
 
    /**
    * @brief Compute the mutual information between a one-dimensional thresholded feature and the class information
    *
    * @param ls labeled set of multi-dimensional feature vectors
    * @param dimension feature index to use
    * @param threshold threshold used to binarize the feature
    *
    * @return mutual information value
    */
    double mutualInformationOverall ( const LabeledSetVector & ls, size_t dimension, double threshold ) const;
    double mutualInformationClass ( const LabeledSetVector & ls, size_t classno, size_t dimension, double threshold ) const;
	
    /**
    * @brief Compute an optimal threshold for a one-dimensional feature that best retains class information, i.e.
    * maximizes the mutual information between the feature B and the class label C
    * @param ls labeled set of multi-dimensional feature vectors
    * @param dimension feature index to use
    * @param opt_threshold resulting optimal threshold
    *
    * @return resulting mutual information of the optimal threshold
    */
    double computeThresholdOverall ( const LabeledSetVector & ls, size_t dimension, double & opt_threshold ) const;
    double computeThresholdClass ( const LabeledSetVector & ls, size_t classno, size_t dimension, double & opt_threshold ) const;

    /**
    * @brief Compute optimal thresholds for each dimension of a multi-dimensional feature trying to retain class information
    *
    * @param ls labeled set of multi-dimensional feature vectors
    * @param thresholds vector of thresholds for each dimension
    * @param mis vector of resulting mutual information values
    */
    void computeThresholdsOverall ( const LabeledSetVector & ls, NICE::Vector & thresholds, NICE::Vector & mis ) const;
    void computeThresholdsClass ( const LabeledSetVector & ls, size_t classno, NICE::Vector & thresholds, NICE::Vector & mis ) const;
    
};


} // namespace

#endif
