refactoring & add invertion

This commit is contained in:
MaxanRus 2021-10-05 17:03:03 +03:00
parent 1fd4158840
commit aad17d8c8c
12 changed files with 286 additions and 154 deletions

View file

@ -18,8 +18,8 @@ set(CMAKE_CXX_STANDARD 17)
set(SOURCE_FILES
src/regular/RegularTree.cpp
src/regular/RegularTreeNode.cpp
src/NFA/NFAGraph.cpp
src/NFA/NFATreeVertex.cpp
src/NFA/NFAGraph.cpp
src/NFA/NFAGraphVertex.cpp
src/converters/RegularToNFA.cpp
src/converters/NFAToDFA.cpp
src/DFA/DFAGraph.cpp
@ -27,18 +27,20 @@ set(SOURCE_FILES
src/converters/DFAToFDFA.cpp
src/converters/DFAToMinDFA.cpp
src/converters/DFAToRegular.cpp
src/converters/InvertFDFA.cpp
)
set(TEST_FILES
tests/regular/parse_regular.cpp
tests/NFAToDFA/check_equivalence.cpp
tests/regularToDFA/regularToDFA.cpp
tests/regular/ParseRegular.cpp
tests/NFAToDFA/CheckEquivalence.cpp
tests/regularToDFA/RegularToDFA.cpp
tests/DFAToRegular/DFAToRegular.cpp
tests/invertFDFA/InvertFDFA.cpp
)
add_executable(Formalang src/main.cpp ${SOURCE_FILES})
add_executable(Tests tests/test_main.cpp ${TEST_FILES} ${SOURCE_FILES})
add_executable(Tests tests/MainTest.cpp ${TEST_FILES} ${SOURCE_FILES})
target_link_libraries(Tests ${GTEST_LIBRARIES} Threads::Threads)
target_link_libraries(Formalang Threads::Threads)

View file

@ -38,10 +38,10 @@ class DFAGraph {
DFAGraph() = default;
DFAGraph(const DFAGraph&) = delete;
DFAGraph(DFAGraph&&) = default;
DFAGraph(DFAGraph&&);
DFAGraph& operator=(const DFAGraph&) = delete;
DFAGraph& operator=(DFAGraph&&) = default;
DFAGraph& operator=(DFAGraph&&);
size_t AddNewVertex();
void AddFinalVertex(size_t number);

View file

@ -0,0 +1,7 @@
#pragma once
#include "DFA/DFAGraph.hpp"
namespace converters {
using namespace DFA;
DFAGraph InvertFDFAGraph(DFAGraph&&);
}

View file

@ -3,6 +3,30 @@
#include <iostream>
namespace DFA {
DFAGraph::DFAGraph(DFAGraph&& another) {
std::swap(count_vertexes_, another.count_vertexes_);
std::swap(vertexes_, another.vertexes_);
std::swap(final_vertexes_, another.final_vertexes_);
std::swap(start_vertexes_, another.start_vertexes_);
for (auto& i: vertexes_)
i.second->owner_ = this;
for (auto& i: another.vertexes_)
i.second->owner_ = &another;
}
DFAGraph& DFAGraph::operator=(DFAGraph&& another) {
std::swap(count_vertexes_, another.count_vertexes_);
std::swap(vertexes_, another.vertexes_);
std::swap(final_vertexes_, another.final_vertexes_);
std::swap(start_vertexes_, another.start_vertexes_);
for (auto& i: vertexes_)
i.second->owner_ = this;
for (auto& i: another.vertexes_)
i.second->owner_ = &another;
return *this;
}
size_t DFAGraph::AddNewVertex() {
vertexes_[count_vertexes_] = std::make_shared<Vertex>(this);
vertexes_[count_vertexes_]->number_ = count_vertexes_;

View file

@ -0,0 +1,12 @@
#include "converters/InvertFDFA.hpp"
namespace converters {
DFAGraph InvertFDFAGraph(DFAGraph&& fdfa_graph) {
const size_t n = fdfa_graph.GetCountVertexes();
for (int i = 0; i < n; ++i) {
if (!fdfa_graph.GetVertex(i)) continue;
fdfa_graph.GetVertex(i)->SetFinal(!fdfa_graph.GetVertex(i)->IsFinal());
}
return std::move(fdfa_graph);
}
}

View file

@ -6,6 +6,7 @@
#include "converters/DFAToFDFA.hpp"
#include "converters/DFAToMinDFA.hpp"
#include "converters/DFAToRegular.hpp"
#include "converters/InvertFDFA.hpp"
using namespace regular;
using namespace regular;
@ -13,161 +14,66 @@ using namespace NFA;
using namespace DFA;
using namespace converters;
void example1() {
RegularTree r("a*");
NFAGraph NFA_tree = RegularToNFAGraph(std::move(r)); // Regular to FA
DFAGraph DFA_graph = NFAGraphToDFAGraph(std::move(NFA_tree)); // to DFA
DFA_graph = DFAGraphToMinDFAGraph(std::move(DFA_graph)); // minimize
std::string reg = DFAGraphToRegular(std::move(DFA_graph)); // DFA to regular
r = RegularTree(reg); // create regular
NFA_tree = RegularToNFAGraph(std::move(r)); // to FA
DFA_graph = NFAGraphToDFAGraph(std::move(NFA_tree)); // to DFA
DFA_graph = DFAGraphToMinDFAGraph(std::move(DFA_graph)); // minimize
DFA_graph.Print(); // print
}
void example2() {
NFAGraph nfa_graph;
const size_t N = 10;
size_t a[N];
for (size_t i = 0; i < N; ++i)
a[i] = nfa_graph.AddNewVertex();
auto AddEdge = [&nfa_graph, &a](char symbol, int u, int v) {
nfa_graph.GetVertex(a[u])->AddEdge(symbol, a[v]);
};
AddEdge('a', 0, 1);
AddEdge('b', 0, 2);
AddEdge('b', 1, 3);
AddEdge('b', 2, 4);
DFAGraph dfa_graph = NFAGraphToDFAGraph(std::move(nfa_graph));
dfa_graph = DFAGraphToMinDFAGraph(std::move(dfa_graph));
dfa_graph.Print();
}
int main() {
{
RegularTree r("a*");
NFAGraph NFA_tree = RegularToNFAGraph(std::move(r));
DFAGraph DFA_graph = NFAGraphToDFAGraph(std::move(NFA_tree));
DFA_graph = DFAGraphToMinDFAGraph(std::move(DFA_graph));
DFA_graph = DFAGraphToFDFAGraph(std::move(DFA_graph), {'a', 'b', 'c', 'd'});
DFA_graph.Print();
std::string reg = DFAGraphToRegular(std::move(DFA_graph));
r = RegularTree(reg);
NFA_tree = RegularToNFAGraph(std::move(r));
DFA_graph = NFAGraphToDFAGraph(std::move(NFA_tree));
DFA_graph = InvertFDFAGraph(std::move(DFA_graph));
return 0;
DFA_graph = DFAGraphToMinDFAGraph(std::move(DFA_graph));
DFA_graph.Print();
}
return 0;
RegularTree r("a*");
auto nfa = RegularToNFAGraph(std::move(r));
auto dfa = NFAGraphToDFAGraph(std::move(nfa));
dfa = DFAGraphToMinDFAGraph(std::move(dfa));
auto fdfa = DFAGraphToFDFAGraph(std::move(dfa), {'a', 'b'});
fdfa.Print();
fdfa = InvertFDFAGraph(std::move(fdfa));
fdfa.Print();
dfa = DFAGraphToMinDFAGraph(std::move(fdfa));
auto s = DFAGraphToRegular(std::move(dfa));
{
RegularTree r("a+");
r.Print();
NFA::NFAGraph NFA_tree = converters::RegularToNFAGraph(std::move(r));
NFA_tree.Print();
DFA::DFAGraph DFA_graph = converters::NFAGraphToDFAGraph(std::move(NFA_tree));
DFA_graph.Print();
DFA_graph = DFAGraphToMinDFAGraph(std::move(DFA_graph));
DFA_graph.Print();
}
return 0;
NFA::NFAGraph tree;
const int N = 10;
int a[N];
for (int i = 0; i < N; ++i)
a[i] = tree.AddNewVertex();
/*
tree.GetVertex(a[1])->AddEdge('a', a[1]);
tree.GetVertex(a[1])->AddEdge('b', a[1]);
tree.GetVertex(a[1])->AddEdge('a', a[2]);
tree.GetVertex(a[1])->AddEdge('a', a[8]);
tree.GetVertex(a[2])->AddEdge('b', a[3]);
tree.GetVertex(a[3])->AddEdge('a', a[4]);
tree.GetVertex(a[4])->AddEdge('b', a[4]);
tree.GetVertex(a[4])->AddEdge('a', a[7]);
tree.GetVertex(a[7])->AddEdge('b', a[7]);
tree.GetVertex(a[8])->AddEdge('a', a[6]);
tree.GetVertex(a[6])->AddEdge('a', a[6]);
tree.GetVertex(a[6])->AddEdge('b', a[6]);
tree.GetVertex(a[6])->AddEdge('b', a[5]);
tree.GetVertex(a[5])->AddEdge('b', a[4]);
tree.GetVertex(a[1])->SetStart(true);
tree.GetVertex(a[7])->SetFinal(true);
*/
/*
tree.GetVertex(a[0])->AddEdge('a', a[1]);
tree.GetVertex(a[1])->AddEdge('a', a[2]);
tree.GetVertex(a[2])->AddEdge('a', a[3]);
tree.GetVertex(a[3])->AddEdge('b', a[4]);
tree.GetVertex(a[4])->AddEdge('a', a[5]);
tree.GetVertex(a[5])->AddEdge('a', a[6]);
tree.GetVertex(a[6])->AddEdge('b', a[7]);
tree.GetVertex(a[2])->AddEdge(' ', a[4]);
tree.GetVertex(a[4])->AddEdge(' ', a[2]);
tree.GetVertex(a[5])->AddEdge(' ', a[7]);
tree.GetVertex(a[7])->AddEdge(' ', a[5]);
tree.GetVertex(a[7])->AddEdge(' ', a[1]);
tree.GetVertex(a[1])->AddEdge('b', a[1]);
tree.GetVertex(a[0])->SetStart(true);
tree.GetVertex(a[1])->SetFinal(true);
*/
/*
tree.GetVertex(a[0])->AddEdge('a', a[1]);
tree.GetVertex(a[0])->AddEdge('a', a[2]);
tree.GetVertex(a[1])->AddEdge('b', a[1]);
tree.GetVertex(a[2])->AddEdge('c', a[2]);
tree.GetVertex(a[0])->SetStart(true);
tree.GetVertex(a[1])->SetFinal(true);
tree.GetVertex(a[2])->SetFinal(true);
*/
tree.GetVertex(a[0])->AddEdge('a', a[1]);
tree.GetVertex(a[0])->AddEdge('b', a[2]);
tree.GetVertex(a[1])->AddEdge('b', a[3]);
tree.GetVertex(a[2])->AddEdge('b', a[4]);
tree.GetVertex(a[0])->SetStart(true);
tree.GetVertex(a[3])->SetFinal(true);
tree.GetVertex(a[4])->SetFinal(true);
DFA::DFAGraph res = converters::NFAGraphToDFAGraph(std::move(tree));
// FDFA::FDFAGraph res2 = converters::DFAGraphToFDFAGraph(std::move(res), {'a', 'b'});
// res2.Print();
// std::cout << "\n#####################\n\n";
// res = converters::DFAGraphToFDFAGraph(std::move(res), {'a', 'b'});
res = converters::DFAGraphToMinDFAGraph(std::move(res));
res.Print();
std::string reg = converters::DFAGraphToRegular(std::move(res));
std::cout << reg << std::endl;
/*
tree = converters::AddAllEpsilonTransitions(std::move(tree));
tree.Print();
std::cout << "\n#####################\n\n";
tree = converters::DeleteEpsilonTransitions(std::move(tree));
tree.Print();
std::cout << "\n#####################\n\n";
tree = converters::DeleteTransitionsByOneLetter(std::move(tree));
tree.Print();
std::cout << "\n#####################\n\n";
*/
/*
DFA::DFAGraph res = converters::NFATreeToDFAGraph(std::move(tree));
res.Print();
*/
std::cout << "END" << std::endl;
return 0;
std::string str;
std::cin >> str;
RegularTree reg_tree(str);
reg_tree.Print();
auto NFA_tree = converters::RegularToNFAGraph(std::move(reg_tree));
std::cout << std::endl;
NFA_tree.Print();
// RegularTree r("(a|b)+bab(a|b)+");
// std::cout << DFAGraphToRegular(DFAGraphToMinDFAGraph(InvertFDFAGraph(DFAGraphToFDFAGraph(DFAGraphToMinDFAGraph(NFAGraphToDFAGraph(RegularToNFAGraph(std::move(r)))), {'a', 'b'})))) << std::endl;
}

View file

@ -0,0 +1,181 @@
#include <gtest/gtest.h>
#include <random>
#include "regular/RegularTree.hpp"
#include "converters/RegularToNFA.hpp"
#include "converters/NFAToDFA.hpp"
#include "converters/DFAToMinDFA.hpp"
#include "converters/DFAToFDFA.hpp"
#include "converters/InvertFDFA.hpp"
using namespace regular;
using namespace NFA;
using namespace DFA;
using namespace converters;
extern std::mt19937 rnd;
extern std::string GenerateRandomString(std::vector<char> alphabet, size_t len);
TEST(invert_DFA, a_star) {
RegularTree r("a*");
NFAGraph NFA_tree = RegularToNFAGraph(std::move(r));
DFAGraph DFA_graph = NFAGraphToDFAGraph(std::move(NFA_tree));
DFA_graph = DFAGraphToMinDFAGraph(std::move(DFA_graph));
DFA_graph = DFAGraphToFDFAGraph(std::move(DFA_graph), {'a', 'b', 'c', 'd'});
DFA_graph = InvertFDFAGraph(std::move(DFA_graph));
DFA_graph = DFAGraphToMinDFAGraph(std::move(DFA_graph));
std::string s = "";
for (int i = 0; i < 100; ++i) {
ASSERT_EQ(DFA_graph.Accepted(s), false);
s += "a";
}
}
TEST(invert_DFA, a_plus) {
std::string regulars[] = {"a+", "(a)+", "(a+)"};
for (const auto& regular: regulars) {
RegularTree r(regular);
NFAGraph NFA_tree = RegularToNFAGraph(std::move(r));
DFAGraph DFA_graph = NFAGraphToDFAGraph(std::move(NFA_tree));
DFA_graph = DFAGraphToMinDFAGraph(std::move(DFA_graph));
DFA_graph = DFAGraphToFDFAGraph(std::move(DFA_graph), {'a', 'b', 'c', 'd'});
DFA_graph = InvertFDFAGraph(std::move(DFA_graph));
DFA_graph = DFAGraphToMinDFAGraph(std::move(DFA_graph));
std::string s = "";
ASSERT_EQ(DFA_graph.Accepted(s), true);
s += "a";
for (int i = 0; i < 100; ++i) {
ASSERT_EQ(DFA_graph.Accepted(s), false);
s += "a";
}
}
}
TEST(invert_DFA, abc) {
std::string regulars[] = {"abc"};
for (const auto& regular: regulars) {
RegularTree r(regular);
NFAGraph NFA_tree = RegularToNFAGraph(std::move(r));
DFAGraph DFA_graph = NFAGraphToDFAGraph(std::move(NFA_tree));
DFA_graph = DFAGraphToMinDFAGraph(std::move(DFA_graph));
DFA_graph = DFAGraphToFDFAGraph(std::move(DFA_graph), {'a', 'b', 'c', 'd'});
DFA_graph = InvertFDFAGraph(std::move(DFA_graph));
DFA_graph = DFAGraphToMinDFAGraph(std::move(DFA_graph));
ASSERT_EQ(DFA_graph.Accepted("abc"), false);
for (int i = 0; i < 1000; ++i) {
auto s = GenerateRandomString({'a', 'b', 'c', 'd'}, rnd() % 10);
if (s == "abc") continue;
ASSERT_EQ(DFA_graph.Accepted(s), true);
}
}
}
TEST(invert_DFA, a_or_b_or_c) {
std::string regulars[] = {};
for (const auto& regular: regulars) {
RegularTree r("a|b|c");
NFAGraph NFA_tree = RegularToNFAGraph(std::move(r));
DFAGraph DFA_graph = NFAGraphToDFAGraph(std::move(NFA_tree));
DFA_graph = DFAGraphToMinDFAGraph(std::move(DFA_graph));
DFA_graph = DFAGraphToFDFAGraph(std::move(DFA_graph), {'a', 'b', 'c', 'd'});
DFA_graph = InvertFDFAGraph(std::move(DFA_graph));
DFA_graph = DFAGraphToMinDFAGraph(std::move(DFA_graph));
ASSERT_EQ(DFA_graph.Accepted("a"), false);
ASSERT_EQ(DFA_graph.Accepted("b"), false);
ASSERT_EQ(DFA_graph.Accepted("c"), false);
for (int i = 0; i < 1000; ++i) {
auto s = GenerateRandomString({'a', 'b', 'c', 'd'}, rnd() % 10);
if (s == "a") continue;
if (s == "b") continue;
if (s == "c") continue;
ASSERT_EQ(DFA_graph.Accepted(s), true);
}
}
}
TEST(invert_DFA, a_star_or_b_star_or_c_star) {
std::string regulars[] = {"a*|b*|c*", "(a*)|(b*|c*)", "(a*|b*|c*)", "((a*)|(b*)|(c*))"};
for (const auto& regular: regulars) {
RegularTree r(regular);
NFAGraph NFA_tree = RegularToNFAGraph(std::move(r));
DFAGraph DFA_graph = NFAGraphToDFAGraph(std::move(NFA_tree));
DFA_graph = DFAGraphToMinDFAGraph(std::move(DFA_graph));
DFA_graph = DFAGraphToFDFAGraph(std::move(DFA_graph), {'a', 'b', 'c', 'd'});
DFA_graph = InvertFDFAGraph(std::move(DFA_graph));
DFA_graph = DFAGraphToMinDFAGraph(std::move(DFA_graph));
auto check = [](const std::string str) {
std::set<char> s(str.begin(), str.end());
if (s.size() == 0)
return true;
else {
if (s.size() == 1)
return *s.begin() != 'd';
else
return false;
}
};
ASSERT_EQ(DFA_graph.Accepted(""), false);
for (int i = 0; i < 1000; ++i) {
auto s = GenerateRandomString({'a', 'b', 'c', 'd'}, rnd() % 10);
ASSERT_EQ(DFA_graph.Accepted(s), !check(s));
}
}
}
TEST(invert_DFA, _a_star_or_b_star_or_c_star_plus) {
RegularTree r("(a*|b*|c*)+");
NFAGraph NFA_tree = RegularToNFAGraph(std::move(r));
DFAGraph DFA_graph = NFAGraphToDFAGraph(std::move(NFA_tree));
DFA_graph = DFAGraphToMinDFAGraph(std::move(DFA_graph));
DFA_graph = DFAGraphToFDFAGraph(std::move(DFA_graph), {'a', 'b', 'c', 'd'});
DFA_graph = InvertFDFAGraph(std::move(DFA_graph));
DFA_graph = DFAGraphToMinDFAGraph(std::move(DFA_graph));
auto check = [](const std::string str) {
std::set<char> s(str.begin(), str.end());
return s.find('d') == s.end();
};
ASSERT_EQ(DFA_graph.Accepted(""), false);
for (int i = 0; i < 1000; ++i) {
auto s = GenerateRandomString({'a', 'b', 'c', 'd'}, rnd() % 10);
ASSERT_EQ(DFA_graph.Accepted(s), !check(s));
}
}
TEST(invert_DFA, _a_or_b_or_c_star_plus) {
RegularTree r("(a|b|c*)+");
NFAGraph NFA_tree = RegularToNFAGraph(std::move(r));
DFAGraph DFA_graph = NFAGraphToDFAGraph(std::move(NFA_tree));
DFA_graph = DFAGraphToMinDFAGraph(std::move(DFA_graph));
DFA_graph = DFAGraphToFDFAGraph(std::move(DFA_graph), {'a', 'b', 'c', 'd'});
DFA_graph = InvertFDFAGraph(std::move(DFA_graph));
DFA_graph = DFAGraphToMinDFAGraph(std::move(DFA_graph));
auto check = [](const std::string str) {
std::set<char> s(str.begin(), str.end());
return s.find('d') == s.end();
};
ASSERT_EQ(DFA_graph.Accepted(""), false);
for (int i = 0; i < 1000; ++i) {
auto s = GenerateRandomString({'a', 'b', 'c', 'd'}, rnd() % 10);
ASSERT_EQ(DFA_graph.Accepted(s), !check(s));
}
}