Как создать NFA в C ++, который поддерживает переходы, которые возвращаются в уже посещенное состояние?

Я пытаюсь построить NFA из текстового файла в формате:

state   1   start
state   2
state   3   accept
transition  1   0   2
transition  1   1   3
transition  2   0   1
transition  2   0   3

где состояние:
состояние [состояние #] [начать или принять] [начать или принять] переход: переход [переход состояния из] [символ] [переход состояния в]

Я смог заставить программу работать, пока не было перехода из одного состояния обратно в то же самое состояние. (например: добавление в переход 1 0 1 в файл выше не работает). Я застрял на этом в течение нескольких часов и решил, что мне придется попытаться реализовать способ отслеживания конфигураций, чтобы заставить его работать, чтобы убедиться, что одна и та же конфигурация не пробовалась более одного раза, но я не могу получить это.
Я думал о создании структуры для конфигураций и как-то реализовать ее в функцииvaluInput (), но я застрял на том, как это сделать.

Вот мой код:

#include <iostream>
#include <string>
#include <sstream>
#include <fstream>
#include <stdlib.h>
#include <vector>

using namespace std;

string num, currentState, tranState;
char symbol;

struct Transition;

struct State{
bool startS = false;
bool acceptS = false;
string sym;
vector<Transition> transitions;//transition between states
};

struct Transition{
string symb;
State to;
State from;
bool eval = false;
};

struct NFA{
vector<State> NFAStates;
State start;
};

void evaluateInput(string in, NFA F)
{
vector<State> currStates;
vector<State> numAccept;

for(int n = 0; n < F.NFAStates.size(); n++)
{
if(F.NFAStates[n].startS)
{
currStates.push_back(F.NFAStates[n]);
}
}
for(int i = 0; i < in.length(); i++)
{
vector<State> next;
for(int j = 0; j < currStates.size(); j++)
{
int tranSize = currStates[j].transitions.size();
for(int k = 0; k < tranSize; k++)
{
if((currStates[j].transitions[k].eval == false) && (in.at(i) == currStates[j].transitions[k].symb))
{
currStates[j].transitions[k].eval = true;
for(int m = 0; m < F.NFAStates.size(); m++)
{
if(F.NFAStates[m].sym == currStates[j].transitions[k].to.sym)
{
next.push_back(F.NFAStates[m]);
if(F.NFAStates[m].acceptS)
{
numAccept.push_back(F.NFAStates[m]);
}
}
}
}
}
currStates = next;
}
}

if(numAccept.size() > 0)
{
cout << "Accept!" << endl;
}
}

int main(int argc, char* argv[])
{
char* fileName;
string stringInput;
if(argc > 1)
{
fileName = argv[1];
stringInput = argv[2];
//cout << stringInput << endl;
}

ifstream file(fileName);

if(file.is_open())
{
NFA FA;
string line;
while(getline(file, line)){
//cout << "1: " << line << endl;
string ST;

stringstream ss(line);
getline(ss, ST, '\t');

if(ST == "state")
{
State S;
string SoA1;
string SoA2;
getline(ss, num, '\t');
getline(ss, SoA1, '\t');
getline(ss, SoA2);

int num_i = stoi(num);
S.sym = num_i;
if((SoA1 == "start") || (SoA2 == "start"))
{
S.startS = true;
}

if((SoA1 == "accept") || (SoA2 == "accept"))
{
S.acceptS = true;
}

FA.NFAStates.push_back(S);
if(S.startS == true){
FA.start = S;
}
}else if(ST == "transition")
{
Transition T;
string symbol1;
getline(ss, currentState, '\t');
getline(ss, symbol, '\t');
getline(ss, tranState);

symbol = symbol1[0];
int currentState_i = stoi(currentState);
int tranState_i = stoi(tranState);
T.symb = symbol;

for(int j = 0; j < FA.NFAStates.size(); j++)
{
if(FA.NFAStates[j].sym == tranState)
{
T.to = FA.NFAStates[j];
}
}

for(int i = 0; i < FA.NFAStates.size(); i++)
{
if(FA.NFAStates[i].sym == currentState)
{
T.from = FA.NFAStates[i];
FA.NFAStates[i].transitions.push_back(T);
}
}
}
}
evaluateInput(stringInput, FA);
}
}

Спасибо за помощь.

-1

Решение

Ваш код не имеет большого смысла, так как у вас есть много (неполных) копий объектов состояния, которые создаются copy-ctor при попытке создать представление конечного автомата.

каждый State объект содержит вектор Transition объекты, и каждый Transition объект в свою очередь содержит два State объекты, from а также to, которые будут копиями State объекты, созданные в точке, где вы анализируете переходную строку (поэтому будут содержать уже проанализированные переходы, но не те, которые еще не проанализированы).

Было бы гораздо больше смысла, если вы измените Transition объект для использования State * или же State & ссылаться непосредственно на State задействованные объекты, а не их копирование.

Кроме того, когда вы пытаетесь оценить NFA, вы снова делаете копии состояний, что означает, что вы можете легко получить одно и то же состояние несколько раз в векторах. Было бы больше смысла использовать std::set<State *> вместо этого. Точно так же в вашем NFA объект, вы бы предпочли std::map<std::string, State> чтобы упростить поиск состояний по имени (и чтобы все указатели не становились недействительными при вызове push_back по вектору)

0

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]