/** 
* @file DTEstimateAPriori.h
* @brief estimate decision structure using a priori density
* @author Erik Rodner
* @date 05/27/2008

*/
#ifndef DTESTIMATEAPRIORIINCLUDE
#define DTESTIMATEAPRIORIINCLUDE

#include "core/vector/VectorT.h"
#include "core/vector/MatrixT.h"
 
#include "core/basics/Config.h"
#include "vislearning/optimization/mapestimation/MAPEstimation.h"

#include "DecisionTree.h"


namespace OBJREC {

/** estimate decision structure using a priori density */
class DTEstimateAPriori
{
    private:
	MAPEstimation *map_estimator;	

    public:
	
	/** calculates a-posteriori probabilities by substituting support class
	    values with new ones
	*/
	void calcPosteriori ( DecisionTree & tree, 
		const FullVector & aprioriOld,
		const std::map<DecisionNode *, FullVector> & nodeprobOld,
	 std::map<DecisionNode *, double> & nodeprobNew,
		const std::set<int> & supportClassNo,
		int newClassNo,
	 std::map<DecisionNode *, FullVector> & posterioriResult );

	/** calculating node probabilities recursive 
	    using the following formula:
	    p(n | i) = p(p | i) ( c(i | n) c( i | p)^{-1} )
	    @remark do not use normalized a posteriori values !
	*/
	void calculateNodeProbabilitiesRec ( 
	    std::map<DecisionNode *, FullVector> & p, 
	    DecisionNode *node );

	void calculateNodeProbabilities ( std::map<DecisionNode *, FullVector> & p, DecisionTree & tree );

	void calculateNodeProbVec 
	    ( std::map<DecisionNode *, FullVector> & nodeProbs, 
	    int classno,
	    // refactor-nice.pl: check this substitution
	    // old: Vector & p );
	    NICE::Vector & p );

	double calcInnerNodeProbs ( 
	    DecisionNode *node, 
	    std::map<DecisionNode *, double> & p );

	/** calculates a-posteriori probabilities using the formula:
	    p(i | n) = p(n | i) p(i) ( \sum_j p(n | j) p(j) )^{-1}
	*/
	void calcPosteriori ( 
	    DecisionNode *node, 
	    const FullVector & apriori,
	    const std::map<DecisionNode *, FullVector> & nodeprob,
	    std::map<DecisionNode *, FullVector> & posterioriResult );


	void mapEstimateClass ( DecisionTree & tree,
				   Examples & new_examples,
				   int newClassNo,
				   std::set<int> muClasses,
				   std::set<int> substituteClasses,
				   double sigmaq,
				   int maxClassNo );

    public:
  
	/** simple constructor */
	// refactor-nice.pl: check this substitution
	// old: DTEstimateAPriori( const NICE::Config *conf, const std::string & section );
	DTEstimateAPriori( const NICE::Config *conf, const std::string & section );
      
	/** simple destructor */
	virtual ~DTEstimateAPriori();

	void reestimate ( DecisionTree & dt, 
			  Examples & examples,
			  double sigmaq,
			  int newClassNo,
			  std::set<int> muClasses,
			  std::set<int> substituteClasses,
			  int maxClassNo );
	
};


} // namespace

#endif
