/** 
* @file DecisionTree.h
* @brief decision tree implementation
* @author Erik Rodner
* @date 04/24/2008

*/
#ifndef DECISIONTREEINCLUDE
#define DECISIONTREEINCLUDE

#include <map>
#include <set>

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

#include "core/basics/triplet.h"
#include "core/basics/Config.h"
#include "core/basics/Persistent.h"
#include "DecisionNode.h"
#include "vislearning/cbaselib/FeaturePool.h"
#include "vislearning/cbaselib/CachedExample.h"




namespace OBJREC {

/** decision tree implementation */
class DecisionTree : public NICE::Persistent
{

    protected:
	DecisionNode *root;
	const NICE::Config *conf; // for restore operation
	int maxClassNo;

    public:
	static void normalize (DecisionNode *node);
	static void deleteNodes ( DecisionNode *tree );
	static DecisionNode *pruneTreeEntropy ( DecisionNode *node, double minEntropy );
	static DecisionNode *pruneTreeScore ( DecisionNode *node, double minScore );


	/** simple constructor */
	DecisionTree( const NICE::Config *conf, int maxClassNo );
      
	/** simple destructor */
	virtual ~DecisionTree();
 
	void traverse ( const Example & ce, 
			FullVector & distribution );
	    
	void resetCounters ();

    void statistics ( int & depth, int & count) const;
 	
	void restore (std::istream & is, int format = 0);
	void store (std::ostream & os, int format = 0) const;
	void clear ();
	
	void indexDescendants ( std::map<DecisionNode *, std::pair<long, int> > & index, 
				long & maxindex ) const;

	DecisionNode *getLeafNode ( Example & pce, int maxdepth = 100000 );
	std::vector<DecisionNode *> getAllLeafNodes();
	void getLeaves(DecisionNode *node, std::vector<DecisionNode*> &leaves);
	DecisionNode *getRoot ( ) const { return root; };

	void pruneTreeEntropy ( double minEntropy );
	void pruneTreeScore ( double minScore );

	void normalize ();

	void setRoot ( DecisionNode *newroot );
};


} // namespace

#endif