Skip to content
Snippets Groups Projects
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
FsmGraph.cpp 5.91 KiB
#include "aidge/graphRegex/matchFsm/FsmGraph.hpp"

using namespace Aidge;



FsmGraph::FsmGraph(/* args */){

}

//TODO
    std::shared_ptr<MatchResult> FsmGraph::test(std::vector<NodePtr>& startNodes){
    std::vector<std::shared_ptr<Aidge::FsmNode>> startNodesFsm = getStartNodes();
    if(startNodes.size() != startNodesFsm.size()){
         throw std::runtime_error("bad number of Start nodes");
    }

    std::vector<std::shared_ptr<FsmRunTimeContext>> walks;
    for(std::size_t i = 0; i < startNodes.size(); i++){
        walks.push_back(std::make_shared<FsmRunTimeContext>(startNodesFsm[i],startNodes[i]));
    }
    std::vector<std::shared_ptr<FsmRunTimeContext>> nextWalks;

    std::vector<std::shared_ptr<FsmRunTimeContext>> allValidContext;
    std::vector<std::shared_ptr<FsmRunTimeContext>> allContextSee;




    while (!walks.empty())
    {
        for(auto fsmContext : walks){
            allContextSee.push_back(fsmContext);
            //if we are in a valid st we save it
            //it's one solution of the posible solution of the matching
            if(fsmContext->isOnValidState()){
                //not save 2 time the same end point
                if(!std::any_of(allValidContext.begin(), allValidContext.end(),
                    [&](std::shared_ptr<Aidge::FsmRunTimeContext> oldValid) {
                        return fsmContext->areEqual(oldValid);
                })){
                    allValidContext.push_back(fsmContext);
                }

            }

            //dont test 2 time a fsmContext
            std::vector<std::shared_ptr<FsmRunTimeContext>> tmpNextWalks = fsmContext->getActState()->test(fsmContext);
            for(auto PotentialFsmContext : tmpNextWalks){

                if(!std::any_of(allContextSee.begin(), allContextSee.end(),
                    [&](std::shared_ptr<Aidge::FsmRunTimeContext> oldSee) {
                        return PotentialFsmContext->areEqual(oldSee);
                })){
                    nextWalks.push_back(PotentialFsmContext);
                }
            }

        }
        walks.swap(nextWalks);
        nextWalks.clear();
    }


    return std::make_shared<MatchResult>(allValidContext,getNbSubFsm());

}


///////////////
// FSM construction
///////////////
const std::set<std::shared_ptr<FsmEdge>>& FsmGraph::getEdge(void){
    return mEdges;
}

void FsmGraph::addEdge(std::shared_ptr<FsmEdge>& edge){
    edge->updateWeak();
    mEdges.insert(edge);
    mAllOrigine.insert(edge->getDestNode()->getOrigine());
    mAllOrigine.insert(edge->getSourceNode()->getOrigine());
}

const std::vector<std::shared_ptr<FsmNode>> FsmGraph::getStartNodes(void){
    std::set<std::shared_ptr<FsmNode>> nodes = getNodes();
    std::vector<std::shared_ptr<FsmNode>> startNodes;
    for(auto node :nodes){
        if(node->isStart()){
            startNodes.push_back(node);
        }
    }
    return startNodes;
}

const std::set<std::shared_ptr<FsmNode>> FsmGraph::getValidNodes(void){
    std::set<std::shared_ptr<FsmNode>> nodes = getNodes();
    std::set<std::shared_ptr<FsmNode>> ValidNodes;
    for(auto node :nodes){
        if(node->isValid()){
            ValidNodes.insert(node);
        }
    }
    //may short
    return ValidNodes;
}

const std::set<std::shared_ptr<FsmNode>> FsmGraph::getNodes(void){
    std::set<std::shared_ptr<FsmNode>> nodes;
    for(auto edge : mEdges){
        nodes.insert(edge->getDestNode());
        nodes.insert(edge->getSourceNode());
    }
    return nodes;
}

void FsmGraph::setGroupe(std::size_t groupeIdx){
    std::set<std::shared_ptr<FsmNode>> nodes = getNodes();
    for(auto node :nodes){
        node->setGroupe(groupeIdx);
    }
}

void FsmGraph::unionG(const std::shared_ptr<FsmGraph> fsmGraph){

    for(auto edge : fsmGraph->getEdge()){
        addEdge(edge);
    }
}

void FsmGraph::mergeOneStartOneValid(const std::shared_ptr<FsmGraph> fsmGraph){
    std::set<std::shared_ptr<FsmNode>> validNodes = getValidNodes();
    std::vector<std::shared_ptr<FsmNode>> startNodes = fsmGraph->getStartNodes();

    if (startNodes.size() != 1 || validNodes.size() != 1){

        std::ostringstream errorMessage;
        errorMessage <<"mergeOneStartOneValid  start size: " << startNodes.size() << " valide size : " << validNodes.size()
        <<" can only merge FSM 1 start 1 valide";
        throw std::runtime_error(errorMessage.str());
    }

    unionG(fsmGraph);
    //for loop useless but for future merge it's coudl be used
    for(auto valid : validNodes){
        valid->unValid();
        for(auto start : startNodes){
            start->unStart();
            _mergeNode(start,valid);
        }
    }
}

std::size_t FsmGraph::getNbSubFsm(void){
    return mAllOrigine.size();
}

void FsmGraph::incOrigineAllNodeBy(std::size_t incr){
    std::set<std::shared_ptr<FsmNode>> nodes = getNodes();
    for(auto node :nodes){
        node->incOrigine(incr);
    }
    std::set<std::size_t> updatedOrigin;
    for(auto origin : mAllOrigine){
        updatedOrigin.insert(origin + incr);
    }
    mAllOrigine.swap(updatedOrigin);
}

void FsmGraph::_mergeNode(std::shared_ptr<FsmNode> source,std::shared_ptr<FsmNode> dest){
    std::set<std::shared_ptr<FsmNode>> nodes = getNodes();

    if(nodes.find(source) == nodes.end() || nodes.find(dest) == nodes.end()){
        throw std::runtime_error("FsmGraph can not merge node not in the graph");
    }
    nodes.clear();

    //probagate source attribut
    if(source->isValid()){
        dest->valid();
    }
    if(source->isStart()){
        dest->start();
    }

    //merge source to dest by replace source by dest in all EDGE
    for(auto edge : mEdges){
        if(edge->getDestNode() == source ){
            edge->reSetDestNode(dest);
        }else if(edge->getSourceNode() == source ){
            edge->reSetSouceNode(dest);
        }

    }
    //check is source is not in graph
    nodes = getNodes();
    if(nodes.find(source) != nodes.end() ){
        throw std::runtime_error("FsmGraph merge node not effective");
    }
    nodes.clear();

}