/** 
 * @file KMeansHeuristic.h
 * @brief K-Means
 * @author Erik Rodner, Michael Koch, Michael Trummer, Alexander Freytag
 * @date 02/04/2011

 */
#ifndef KMeansHeuristicINCLUDE
#define KMeansHeuristicINCLUDE

#include <core/basics/Config.h>
#include <core/vector/Distance.h>
#include <core/vector/VectorT.h>
#include <core/vector/MatrixT.h>

#include "ClusterAlgorithm.h"


namespace OBJREC
{

/** K-Means (but what does Heuristic actually mean? )*/
class KMeansHeuristic: public ClusterAlgorithm
{

  protected:
    
    /************************
    * 
    *   protected variables
    * 
    **************************/         
    int noClusters;
    
    std::string distanceType;
    
    NICE::VectorDistance<double> *distancefunction;
    
    /************************
    * 
    *   protected methods
    * 
    **************************/     
    
    double compute_assignments(const NICE::VVector & features,
        const NICE::VVector & prototypes, std::vector<int> & assignment);

    double compute_weights(const NICE::VVector & features,
        std::vector<double> & weights, std::vector<int> & assignment);

    double compute_delta(const NICE::VVector & oldprototypes,
        const NICE::VVector & prototypes);


    void initial_guess(const NICE::VVector & features, NICE::VVector & prototypes);

    void print_iteration(int iterations, NICE::VVector & prototypes, double delta);
    int robust_prototypes(const NICE::VVector &features, NICE::VVector &prototypes, std::vector<
        double> & weights, const std::vector<int> & assignment);
    
  public:
    
    ///////////////////// ///////////////////// /////////////////////
    //                   CONSTRUCTORS / DESTRUCTORS
    ///////////////////// ///////////////////// ///////////////////// 

    /** 
     * @brief default constructor
     * @date 13-02-2014 (dd-mm-yyyy )
     * @author Alexander Freytag
     */
    KMeansHeuristic ( );         

    /** simple constructor */
    KMeansHeuristic(int noClusters, std::string distanceMode = "euclidean");
    
    /**
    * @brief standard constructor
    * @param conf config file specifying all relevant variable settings
    * @param _section name of the section within the configfile where the settings can be found (default: KMeansHeuristic)
    * @date 14-06-2013 (dd-mm-yyyy)
    * @author Alexander Freytag
    */
    KMeansHeuristic( const NICE::Config * _conf, const std::string & _confSection = "KMeansHeuristic");    

    /** simple destructor */
    virtual ~KMeansHeuristic();
    
    /** 
     * @brief Jobs previously performed in the config-version of the constructor, read settings etc.
     * @author Alexander Freytag
     * @date 13-02-2014 ( dd-mm-yyyy )
     */    
    void initFromConfig ( const NICE::Config * _conf, const std::string & _confSection = "KMeansHeuristic");     
    
    ///////////////////// ///////////////////// /////////////////////
    //                      CLUSTERING STUFF
    ///////////////////// ///////////////////// //////////////////       

    void cluster(const NICE::VVector & features, NICE::VVector & prototypes, std::vector<double> & weights, std::vector<int> & assignment);
    
    ///////////////////// INTERFACE PERSISTENT /////////////////////
    // interface specific methods for store and restore
    ///////////////////// INTERFACE PERSISTENT /////////////////////      
    
    /**
    * @brief Load object from external file (stream)
    * @author Alexander Freytag
    * @date 13-02-2014 ( dd-mm-yyyy )
    */
    void restore ( std::istream & is, int format = 0 );

    /**
    * @brief Save object to external file (stream)
    * @author Alexander Freytag
    * @date 13-02-2014 ( dd-mm-yyyy )
    */
    void store ( std::ostream & os, int format = 0 ) const;

    /**
    * @brief Clear object
    * @author Alexander Freytag
    * @date 13-02-2014 ( dd-mm-yyyy )
    */
    void clear ();       

  };

} // namespace

#endif
