bool ArithmeticExpressionInterpreter::interpret(std::string &expression, double &result)
{
	if (automaton.checkSynthax(expression) == false)
	{
		return false;
	}
	std::queue<AbstractNode *> queue = automaton.getNodeQueue();
	astBuilder.setQueue(queue);
	AbstractNode *root = astBuilder.buildAST();
	automaton.clear();
	if (root == NULL)
	{
		return false;
	}
	result = computeTree(root);
	return true;
}
void DecisionTree::computeTree(Pool& pool)
{
    double max =0;
    int varChosen=0;

    std::vector<int> occurrencesInResp(pool.levelSize());

    for(int j=0;j<pool.levelSize();j++)
        occurrencesInResp[j] = pool.idxs(j).size();

    double firstTerm = entropy(occurrencesInResp,pool.sampleSize());

    for(int i=0;i<matComp.size();i++)
    {
        double calc = infoGain(matComp[i],pool,firstTerm);
        if(calc>=max)
        {
            max = calc;
            varChosen = i;
        }
    }
    if(max>0)
    {
        pool.setVarIdx(varChosen);
        pool.setInfoGain(max);
        int splits = matComp[varChosen].levelSize();

        for(int j=0;j<splits;j++)
        {
            std::vector<int> descIdxs = matComp[varChosen].idxs(j);
            std::vector<int> respIdxs = pool.allIdxs();
            std::vector<int> intersec;
            intersec.reserve(pool.sampleSize());
            std::set_intersection(descIdxs.begin(),descIdxs.end(),respIdxs.begin(),
                                    respIdxs.end(),std::back_inserter(intersec));

            pool.add_node(Pool(intersec,pool.labsFromIdx(intersec),matComp[varChosen].getLevel(j)));

            Pool& poolToCheck = pool.getNext(j);
            if(poolToCheck.levelSize()<=1)
                continue;
            else
                computeTree(poolToCheck);
        }
    }
}
//void AssociationTree::solve(std::vector<std::pair<unsigned int, unsigned int> > & _pairs, std::vector<unsigned int> &  _unassoc)
void AssociationTree::solve(std::vector<std::pair<unsigned int, unsigned int> > & _pairs, std::vector<bool> & _associated_mask)
{
    std::list<AssociationNode*>::iterator best_node;
    bool rootReached = false;
    AssociationNode *anPtr;
    
    //grows tree exploring all likely hypothesis
    growTree();
    
    //computes tree probs
    computeTree();
    
    //normalizes tree probs
    normalizeTree();

    //if terminus_node_list_ is empty exit withou pairing
    if ( terminus_node_list_.empty() ) return;
    
    //choose best node based on best tree probability
    chooseBestTerminus(best_node);
    
    //resize _associated_mask and resets it to false
    _associated_mask.resize(nd_,false);

    //set pairs
    anPtr = *best_node; //init pointer
    int ii=0;
    while( ! anPtr->isRoot() ) //set pairs
    {
//         if ( anPtr->getTargetIndex() == nt_) //detection with void target -> unassociated detection
//         {
//             _unassoc.push_back(anPtr->getDetectionIndex());
//         }
//         else
//         {
//             _pairs.push_back( std::pair<unsigned int, unsigned int>(anPtr->getDetectionIndex(), anPtr->getTargetIndex()) );
//         }
        if ( anPtr->getTargetIndex() < nt_ ) //association pair
        {
            _associated_mask.at(anPtr->getDetectionIndex()) = true; 
            _pairs.push_back( std::pair<unsigned int, unsigned int>(anPtr->getDetectionIndex(), anPtr->getTargetIndex()) );
        }
        anPtr = anPtr->upNodePtr();
    }        
}
DecisionTree::DecisionTree(const AbstractMatType& mat,const CategoricalDescriptor& resp,int groups)
    :response(resp)
{
    matOri.resize(mat.size());

    for(int i=0;i<matOri.size();i++)
        matOri[i] = mat[i]->clone();

    matComp.clear();
    matComp.reserve(matOri.size());

    for(int i=0;i<matOri.size();i++)
    {
        if((matOri[i])->isConvertible())
        {
            std::shared_ptr<ContinuousDescriptor> ContPtr = std::dynamic_pointer_cast<ContinuousDescriptor>(matOri[i]);
            auto addVec = ContPtr->toCategorical();
            int sizeAdded = addVec.size();                          //We add the vector of CategoricalDescriptors generated by Continuous
            std::move(addVec.begin(), addVec.end(), std::back_inserter(matComp));
            addVec.clear();

            std::vector<int> idxVec(sizeAdded);                     //We add the relations between matComp ID and matOri ID
            std::iota(idxVec.begin(),idxVec.end(),matComp.size()-sizeAdded);
            std::transform(idxVec.begin(),idxVec.end(),std::inserter(idxsRelations,idxsRelations.end()),[i](int a){return std::make_pair(a,i);});
        }
        else
        {
            std::shared_ptr<CategoricalDescriptor> CatPtr = std::dynamic_pointer_cast<CategoricalDescriptor>(matOri[i]);
            matComp.push_back(*CatPtr);

            idxsRelations.emplace(matComp.size()-1,i);
        }
    }

    std::vector<int> vecRespIdx(resp.dataSize());
    std::iota(vecRespIdx.begin(),vecRespIdx.end(),0);
    Pool first(vecRespIdx,resp.getLabels());

    firstPool = std::move(first);

    computeTree(firstPool);
}