-
Cyril Moineau authoredCyril Moineau authored
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();
}