Skip to content
Snippets Groups Projects
Forked from Eclipse Projects / aidge / aidge_core
2156 commits behind the upstream repository.
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
MatchResult.cpp 5.28 KiB
#include "aidge/graphRegex/matchFsm/MatchResult.hpp"

using namespace Aidge; 

    MatchSolution::MatchSolution(std::vector<std::shared_ptr<FsmRunTimeContext>>& precedence,const std::string query,const std::vector<NodePtr> startNode):mQueryFrom(query),mStartNode(startNode){
            //reformat the solution
            for (const auto& context : precedence) {
                for (const auto& pair : context->getValid()) {
                    
                    if(mSolution.find(pair.first->getKey()) == mSolution.end()){
                        mSolution[pair.first->getKey()] = pair.second;
                    }else{
                         mSolution[pair.first->getKey()].insert(pair.second.begin(), pair.second.end());
                    }
                }
            }
    }


    const std::set<NodePtr> & MatchSolution::at(const std::string key){

        return mSolution[key];

    }

    const std::set<NodePtr> MatchSolution::getAll(){

            // Create a unique set to store all the elements
            std::set<NodePtr> uniqueSet;

            // Iterate through the map and insert elements from each set into the unique set
            for (const auto& pair : mSolution) {
                const std::set<NodePtr>& nodeSet = pair.second;
                
                // Insert elements from the current set into the unique set
                uniqueSet.insert(nodeSet.begin(), nodeSet.end());
            }
            
            return uniqueSet;

    }

    bool MatchSolution::areCompatible(std::shared_ptr<MatchSolution> solution){
        std::set<NodePtr> set1 = solution->getAll();
        std::set<NodePtr> set2 = getAll();
        std::set<NodePtr> intersection ;
        std::set_intersection(set1.begin(), set1.end(), set2.begin(), set2.end(), std::inserter(intersection, intersection.begin()));
        if (intersection.empty()) {
            return true;
        }
        return false;
    }

    

////////////////////////////////
//
////////////////////////////////
MatchResult::MatchResult(std::vector<std::shared_ptr<FsmRunTimeContext>> allValid, std::size_t nbSubStm,
const std::string& query,const std::vector<NodePtr>& startNodes):mIdToRunTime(nbSubStm),mNbSubStm(nbSubStm){
        mAllValid = allValid;

        //mIdToRunTimm
        for (const auto& contextPtr : allValid) {
            mIdToRunTime[contextPtr->getSubStmId()].push_back(contextPtr);
        }

        std::vector<std::shared_ptr<FsmRunTimeContext>> precedence;
        //make all solution possible 
        _generateCombination(0,precedence,query,startNodes);
        //sort by solution number of elements
        std::sort(mSolve.begin(), mSolve.end(), [](std::shared_ptr<MatchSolution>& set1, std::shared_ptr<MatchSolution>& set2) {
        return set1->getAll().size() < set2->getAll().size();
        });


}

void MatchResult::_generateCombination( std::size_t idxSubStm, std::vector<std::shared_ptr<FsmRunTimeContext>>& precedence,
const std::string& query,const std::vector<NodePtr>& startNodes){

    //it's end , we are below the number of stm
    if (idxSubStm == mNbSubStm)
    {
        //precedence contain a list of FSM compatible, we just need to 
        //check if all the nodes have been validated by at least one context 
        
        //1) make the set of all node for the compute graph that are valid in all the  FsmRunTimeContext
        std::set<NodePtr> validNode;
        std::set<NodePtr> rejectNode;
        for (const auto& contextPtr : precedence) {
            std::set<NodePtr> tmpV =  contextPtr->getValidNodes();
            validNode.insert(tmpV.begin(), tmpV.end());
            std::set<NodePtr> tmpR =  contextPtr->getRejectedNodes();
            rejectNode.insert(tmpR.begin(),tmpR.end());
        }
        // 2) all  RejectedNodes need to be valid by an others stm 
        // if it's not the case the match is not valid
        if(std::includes(validNode.begin(), validNode.end(), rejectNode.begin(), rejectNode.end())){
            //we can save the solution 
            mSolve.push_back(std::make_shared<MatchSolution>(precedence,query,startNodes));
        }
        precedence.pop_back();
        return;
    }


    for (const auto& contextPtrOneFsm : mIdToRunTime[idxSubStm]) 
    {
        if(idxSubStm == 0){
            precedence.push_back(contextPtrOneFsm);
            _generateCombination(idxSubStm+1,precedence,query,startNodes);
            
        }else{
            //test if the new context is compatible with all the context in the precedence
            //
            bool compatibleSolutionFsm = true;
            for (const auto& contextPtrOfOtherFsm : precedence) {
                if(!(contextPtrOneFsm->areCompatible(contextPtrOfOtherFsm))){
                    compatibleSolutionFsm = false;
                    break;
                }
            }

            if(compatibleSolutionFsm){
                precedence.push_back(contextPtrOneFsm);
                _generateCombination(idxSubStm+1,precedence,query,startNodes);
            }

        }
    }

    if(idxSubStm != 0){
        precedence.pop_back();
    }
    return;

}

std::shared_ptr<MatchSolution> MatchResult::getBiggerSolution(void){

    if(mSolve.empty()){
        return nullptr;
    }else{
        return mSolve[0];
    }
    
}

std::vector<std::shared_ptr<MatchSolution>> MatchResult::getSolutions(void){
    return mSolve;
}