From a1843f48985d4bed8b6ec25035d83942ef12664c Mon Sep 17 00:00:00 2001 From: MaxanRus Date: Fri, 24 Sep 2021 18:28:10 +0300 Subject: [PATCH 01/17] Add regular --- CMakeLists.txt | 4 +++- include/regular/RegularTree.hpp | 31 +++++++++++++++++++++++++++++++ src/main.cpp | 4 +++- src/regular/RegularTree.cpp | 22 ++++++++++++++++++++++ 4 files changed, 59 insertions(+), 2 deletions(-) create mode 100644 include/regular/RegularTree.hpp create mode 100644 src/regular/RegularTree.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index db8dc50..5be6ab5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -15,7 +15,9 @@ include_directories( set(CMAKE_CXX_STANDARD 17) -set(SOURCE_FILES) +set(SOURCE_FILES + src/regular/RegularTree.cpp + ) set(TEST_FILES) diff --git a/include/regular/RegularTree.hpp b/include/regular/RegularTree.hpp new file mode 100644 index 0000000..02dd856 --- /dev/null +++ b/include/regular/RegularTree.hpp @@ -0,0 +1,31 @@ +#pragma once +#include +#include +#include +#include +#include + +namespace regular { +class RegularTree { + public: + class Node { + public: + Node(); + + void Parse(const std::string&); + void Parse(const std::string_view); + + enum class Type { + Addition, Concatenation + }; + std::variant>, std::string> value; + Type type; + private: + }; + + RegularTree(const std::string&); + + private: + Node node_; +}; +} diff --git a/src/main.cpp b/src/main.cpp index a03be09..14eb3b0 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,5 +1,7 @@ #include +#include "regular/RegularTree.hpp" int main() { - std::cout << "hello world"; + using namespace regular; + RegularTree reg_tree("(ab)*"); } diff --git a/src/regular/RegularTree.cpp b/src/regular/RegularTree.cpp new file mode 100644 index 0000000..96128e8 --- /dev/null +++ b/src/regular/RegularTree.cpp @@ -0,0 +1,22 @@ +#include "regular/RegularTree.hpp" +#include + +namespace regular { +RegularTree::Node::Node() {} + +void RegularTree::Node::Parse(const std::string& regular) { + Parse(std::string_view(regular.c_str(), regular.size())); +} + +void RegularTree::Node::Parse(const std::string_view regular) { + const int n = regular.size(); + for (int i = 0; i < n; ++i) { + std::cout << regular[i]; + } + std::cout << std::endl; +} + +RegularTree::RegularTree(const std::string& regular) { + node_.Parse(regular); +} +} From f3848d88b3c9fc46498a805083990b0236d2c6a4 Mon Sep 17 00:00:00 2001 From: MaxanRus Date: Mon, 27 Sep 2021 02:59:08 +0300 Subject: [PATCH 02/17] Add parsing regular expressions --- CMakeLists.txt | 4 +- include/regular/RegularTree.hpp | 22 ++-- src/main.cpp | 5 +- src/regular/RegularTree.cpp | 178 ++++++++++++++++++++++++++++++-- tests/regular/parse_regular.cpp | 40 +++++++ 5 files changed, 235 insertions(+), 14 deletions(-) create mode 100644 tests/regular/parse_regular.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 5be6ab5..527b984 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -19,7 +19,9 @@ set(SOURCE_FILES src/regular/RegularTree.cpp ) -set(TEST_FILES) +set(TEST_FILES + tests/regular/parse_regular.cpp + ) add_executable(Formalang src/main.cpp ${SOURCE_FILES}) diff --git a/include/regular/RegularTree.hpp b/include/regular/RegularTree.hpp index 02dd856..7cbae74 100644 --- a/include/regular/RegularTree.hpp +++ b/include/regular/RegularTree.hpp @@ -10,20 +10,30 @@ class RegularTree { public: class Node { public: + enum class Type { + Addition, Concatenation, Word + }; + enum class Modifier { + Plus, Star, None + }; + Node(); + Node(Type); void Parse(const std::string&); - void Parse(const std::string_view); - - enum class Type { - Addition, Concatenation - }; - std::variant>, std::string> value; + void Print() const; + std::vector> children; + std::string word; Type type; + Modifier modifier = Modifier::None; private: + void ParseCurrentType(const std::string_view); + void Print(int nesting_level) const; }; RegularTree(const std::string&); + const Node& GetNode() const; + void Print() const; private: Node node_; diff --git a/src/main.cpp b/src/main.cpp index 14eb3b0..080b2cb 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -3,5 +3,8 @@ int main() { using namespace regular; - RegularTree reg_tree("(ab)*"); + std::string str; + std::cin >> str; + RegularTree reg_tree(str); + reg_tree.Print(); } diff --git a/src/regular/RegularTree.cpp b/src/regular/RegularTree.cpp index 96128e8..24e840c 100644 --- a/src/regular/RegularTree.cpp +++ b/src/regular/RegularTree.cpp @@ -1,22 +1,188 @@ #include "regular/RegularTree.hpp" #include +#include namespace regular { RegularTree::Node::Node() {} +RegularTree::Node::Node(Type type) : type(type) {} void RegularTree::Node::Parse(const std::string& regular) { - Parse(std::string_view(regular.c_str(), regular.size())); + type = Type::Addition; + ParseCurrentType(std::string_view(regular.c_str(), regular.size())); } -void RegularTree::Node::Parse(const std::string_view regular) { - const int n = regular.size(); - for (int i = 0; i < n; ++i) { - std::cout << regular[i]; +void RegularTree::Node::Print() const { + Print(0); +} + +void RegularTree::Node::ParseCurrentType(const std::string_view regular) { + const size_t n = regular.size(); + children.clear(); + word.clear(); + + auto AddChild = [this](const std::string_view regular) { + this->children.push_back(std::make_unique(Type::Addition)); + this->children.back()->ParseCurrentType(regular); + }; + + if (n == 1) { + type = Type::Word; + } + + if (type == Type::Addition) { + int balance = 0; + int begin_child = 0; + bool wrapped_brackets = (regular[0] == '('); + + for (size_t i = 0; i < n; ++i) { + if (regular[i] == '(') { + ++balance; + } else if (regular[i] == ')') { + --balance; + } + + if (regular[i] == '|') { + if (balance == 0) { + AddChild(regular.substr(begin_child + wrapped_brackets, i - + begin_child - 2 * + wrapped_brackets)); + begin_child = i + 1; + + if (i + 1 < n) + wrapped_brackets = (regular[i + 1] == '('); + } + } else { + if (i + 1 == n) { + if (children.size() == 0) { + type = Type::Concatenation; + break; + } else { + AddChild(regular.substr(begin_child + wrapped_brackets, i - + begin_child + 1 - 2 * + wrapped_brackets)); + begin_child = i + 1; + if (i + 1 < n) + wrapped_brackets = (regular[i + 1] == '('); + } + } else if (balance == 0) { + wrapped_brackets = false; + } + } + } + } + + if (type == Type::Concatenation) { + int balance = 0; + int begin_child = 0; + + for (size_t i = 0; i < n; ++i) { + if (regular[i] == '(') { + ++balance; + if (balance == 1) { + if (begin_child < i) { + AddChild(regular.substr(begin_child, i - begin_child)); + begin_child = i + 1; + } + } + } else if (regular[i] == ')') { + --balance; + if (balance == 0) { + AddChild(regular.substr(begin_child + 1, i - begin_child - 1)); + begin_child = i + 1; + } + } else if (i + 1 == n) { + if (balance != 0) { + throw std::logic_error("invalid regular"); + } + if (children.size() == 0) { + type = Type::Word; + break; + } else { + AddChild(regular.substr(begin_child, i - begin_child + 1)); + begin_child = i + 1; + } + } else if (balance == 0) { + if (regular[i] == '+') { + if (begin_child < i) { + AddChild(regular.substr(begin_child, i - begin_child)); + } + children.back()->modifier = Modifier::Plus; + begin_child = i + 1; + } else if (regular[i] == '*') { + if (begin_child < i) { + AddChild(regular.substr(begin_child, i - begin_child)); + } + children.back()->modifier = Modifier::Star; + begin_child = i + 1; + } + } + } + } + + if (type == Type::Word) { + bool exist_modifire = regular.back() == '+' || regular.back() == '*'; + if (regular.back() == '+') { + modifier = Modifier::Plus; + } else if (regular.back() == '*') { + modifier = Modifier::Star; + } + for (size_t i = 0; i < n - exist_modifire; ++i) { + if (regular[i] == '|' || regular[i] == '(' || regular[i] == ')') { + throw std::logic_error("invalid regular"); + } + word += regular[i]; + } + } +} + +void RegularTree::Node::Print(int nesting_level) const { + auto PrintNesingLevel = [](int nesting_level) { + for (int i = 0; i < nesting_level; ++i) { + std::cout << " "; + } + }; + + PrintNesingLevel(nesting_level); + if (type == Type::Addition) { + std::cout << "Addition"; + if (modifier == Modifier::Plus) { + std::cout << "+"; + } else if (modifier == Modifier::Star) { + std::cout << "*"; + } + std::cout << " " << std::to_string(children.size()) << ":" << std::endl; + } else if (type == Type::Concatenation) { + std::cout << "Concatenation"; + if (modifier == Modifier::Plus) { + std::cout << "+"; + } else if (modifier == Modifier::Star) { + std::cout << "*"; + } + std::cout << " " << children.size() << ":" << std::endl; + } else if (type == Type::Word) { + std::cout << "Word"; + if (modifier == Modifier::Plus) { + std::cout << "+"; + } else if (modifier == Modifier::Star) { + std::cout << "*"; + } + std::cout << ": " << word << std::endl; + } + + for (const auto& i: children) { + i->Print(nesting_level + 1); } - std::cout << std::endl; } RegularTree::RegularTree(const std::string& regular) { node_.Parse(regular); } + +const RegularTree::Node& RegularTree::GetNode() const { + return node_; +} + +void RegularTree::Print() const { + node_.Print(); +} } diff --git a/tests/regular/parse_regular.cpp b/tests/regular/parse_regular.cpp new file mode 100644 index 0000000..25bf34a --- /dev/null +++ b/tests/regular/parse_regular.cpp @@ -0,0 +1,40 @@ +#include +#include "regular/RegularTree.hpp" + +using namespace regular; + +TEST(parse_regular, only_addition) { + RegularTree("a"); + RegularTree("aa"); + RegularTree("aaa"); + RegularTree("aaaa"); + RegularTree("aaaaa"); + RegularTree("a|aaaa"); + RegularTree("a|a|a|a|a"); + RegularTree("hello|world"); + RegularTree("qe|wr|lkj|alk"); +} + +TEST(parse_regular, only_folding) { + RegularTree("(kajfkasf(aksdjf)jka(((aksjdf)K)))jakd"); + RegularTree("(kajsdfk(aksdjf)kajsdf)kjasdkfja(skdjf(((aksjdkadf)ksjf(kdja))))"); + RegularTree("((((kdjf))))"); + RegularTree("kasjf(akjsfkjasdg)kajsdg"); + RegularTree("akjsdf(akjdf(kdjfak(jkasdf)))"); + RegularTree("123k4j1k351kk21jkj21k6j2k36j1(((((ajkfajsdfkafdalkdjflk)))))"); +} + +TEST(parse_regular, only_modifiers) { + RegularTree("jlakjdf*aksdjflaf8*laksfj*lakjsf*alksjdf"); + RegularTree("jlakjdf*aksdjflaf8+laksfj*lakjsf*alksjdf*"); + RegularTree("jlakjdf*aksdjflaf8*laksfj*lakjsf+alksjdf"); + RegularTree("jlakjd+aksdjflaf8*laksfj*lakjsf*alksjdf+"); +} + +TEST(parse_regular, all_operations) { + RegularTree("(alkjdfaksdf*|lkasdj*|(kasjdf|kajdf*|kjd)*|laksjf*)+"); + RegularTree("(alkjdfaksdf|lkasdj*|(kas+jdf|kajdf*|kjd)*|laksjf*)+"); + RegularTree("a|(a|(a|(a|)*))*"); + RegularTree("kj*|kjadf*|(kajsdf|(kajsd|kjadf|(kasjdf)|kajs)*)*"); +} + From 8e014193cc61259c42c0bffa8fe23f16f09b7cc4 Mon Sep 17 00:00:00 2001 From: MaxanRus Date: Mon, 27 Sep 2021 03:12:08 +0300 Subject: [PATCH 03/17] Add compress regular tree --- include/regular/RegularTree.hpp | 1 + src/regular/RegularTree.cpp | 11 +++++++++++ 2 files changed, 12 insertions(+) diff --git a/include/regular/RegularTree.hpp b/include/regular/RegularTree.hpp index 7cbae74..d6c031e 100644 --- a/include/regular/RegularTree.hpp +++ b/include/regular/RegularTree.hpp @@ -28,6 +28,7 @@ class RegularTree { Modifier modifier = Modifier::None; private: void ParseCurrentType(const std::string_view); + void Compression(); void Print(int nesting_level) const; }; diff --git a/src/regular/RegularTree.cpp b/src/regular/RegularTree.cpp index 24e840c..712c3d2 100644 --- a/src/regular/RegularTree.cpp +++ b/src/regular/RegularTree.cpp @@ -9,6 +9,7 @@ RegularTree::Node::Node(Type type) : type(type) {} void RegularTree::Node::Parse(const std::string& regular) { type = Type::Addition; ParseCurrentType(std::string_view(regular.c_str(), regular.size())); + Compression(); } void RegularTree::Node::Print() const { @@ -135,6 +136,16 @@ void RegularTree::Node::ParseCurrentType(const std::string_view regular) { } } +void RegularTree::Node::Compression() { + for (auto& i: children) { + i->Compression(); + } + if (children.size() == 1 && modifier == Modifier::None) { + auto tmp = std::move(*children[0]); + *this = std::move(tmp); + } +} + void RegularTree::Node::Print(int nesting_level) const { auto PrintNesingLevel = [](int nesting_level) { for (int i = 0; i < nesting_level; ++i) { From 65fffffe8e7d09fb39a7fd06add5bc3b4f7ef00a Mon Sep 17 00:00:00 2001 From: MaxanRus Date: Mon, 27 Sep 2021 23:12:42 +0300 Subject: [PATCH 04/17] Reformat --- CMakeLists.txt | 1 + src/regular/RegularTree.cpp | 184 ------------------------------- src/regular/RegularTreeNode.cpp | 185 ++++++++++++++++++++++++++++++++ 3 files changed, 186 insertions(+), 184 deletions(-) create mode 100644 src/regular/RegularTreeNode.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 527b984..ed99c37 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -17,6 +17,7 @@ set(CMAKE_CXX_STANDARD 17) set(SOURCE_FILES src/regular/RegularTree.cpp + src/regular/RegularTreeNode.cpp ) set(TEST_FILES diff --git a/src/regular/RegularTree.cpp b/src/regular/RegularTree.cpp index 712c3d2..3cde403 100644 --- a/src/regular/RegularTree.cpp +++ b/src/regular/RegularTree.cpp @@ -1,190 +1,6 @@ #include "regular/RegularTree.hpp" -#include -#include namespace regular { -RegularTree::Node::Node() {} -RegularTree::Node::Node(Type type) : type(type) {} - -void RegularTree::Node::Parse(const std::string& regular) { - type = Type::Addition; - ParseCurrentType(std::string_view(regular.c_str(), regular.size())); - Compression(); -} - -void RegularTree::Node::Print() const { - Print(0); -} - -void RegularTree::Node::ParseCurrentType(const std::string_view regular) { - const size_t n = regular.size(); - children.clear(); - word.clear(); - - auto AddChild = [this](const std::string_view regular) { - this->children.push_back(std::make_unique(Type::Addition)); - this->children.back()->ParseCurrentType(regular); - }; - - if (n == 1) { - type = Type::Word; - } - - if (type == Type::Addition) { - int balance = 0; - int begin_child = 0; - bool wrapped_brackets = (regular[0] == '('); - - for (size_t i = 0; i < n; ++i) { - if (regular[i] == '(') { - ++balance; - } else if (regular[i] == ')') { - --balance; - } - - if (regular[i] == '|') { - if (balance == 0) { - AddChild(regular.substr(begin_child + wrapped_brackets, i - - begin_child - 2 * - wrapped_brackets)); - begin_child = i + 1; - - if (i + 1 < n) - wrapped_brackets = (regular[i + 1] == '('); - } - } else { - if (i + 1 == n) { - if (children.size() == 0) { - type = Type::Concatenation; - break; - } else { - AddChild(regular.substr(begin_child + wrapped_brackets, i - - begin_child + 1 - 2 * - wrapped_brackets)); - begin_child = i + 1; - if (i + 1 < n) - wrapped_brackets = (regular[i + 1] == '('); - } - } else if (balance == 0) { - wrapped_brackets = false; - } - } - } - } - - if (type == Type::Concatenation) { - int balance = 0; - int begin_child = 0; - - for (size_t i = 0; i < n; ++i) { - if (regular[i] == '(') { - ++balance; - if (balance == 1) { - if (begin_child < i) { - AddChild(regular.substr(begin_child, i - begin_child)); - begin_child = i + 1; - } - } - } else if (regular[i] == ')') { - --balance; - if (balance == 0) { - AddChild(regular.substr(begin_child + 1, i - begin_child - 1)); - begin_child = i + 1; - } - } else if (i + 1 == n) { - if (balance != 0) { - throw std::logic_error("invalid regular"); - } - if (children.size() == 0) { - type = Type::Word; - break; - } else { - AddChild(regular.substr(begin_child, i - begin_child + 1)); - begin_child = i + 1; - } - } else if (balance == 0) { - if (regular[i] == '+') { - if (begin_child < i) { - AddChild(regular.substr(begin_child, i - begin_child)); - } - children.back()->modifier = Modifier::Plus; - begin_child = i + 1; - } else if (regular[i] == '*') { - if (begin_child < i) { - AddChild(regular.substr(begin_child, i - begin_child)); - } - children.back()->modifier = Modifier::Star; - begin_child = i + 1; - } - } - } - } - - if (type == Type::Word) { - bool exist_modifire = regular.back() == '+' || regular.back() == '*'; - if (regular.back() == '+') { - modifier = Modifier::Plus; - } else if (regular.back() == '*') { - modifier = Modifier::Star; - } - for (size_t i = 0; i < n - exist_modifire; ++i) { - if (regular[i] == '|' || regular[i] == '(' || regular[i] == ')') { - throw std::logic_error("invalid regular"); - } - word += regular[i]; - } - } -} - -void RegularTree::Node::Compression() { - for (auto& i: children) { - i->Compression(); - } - if (children.size() == 1 && modifier == Modifier::None) { - auto tmp = std::move(*children[0]); - *this = std::move(tmp); - } -} - -void RegularTree::Node::Print(int nesting_level) const { - auto PrintNesingLevel = [](int nesting_level) { - for (int i = 0; i < nesting_level; ++i) { - std::cout << " "; - } - }; - - PrintNesingLevel(nesting_level); - if (type == Type::Addition) { - std::cout << "Addition"; - if (modifier == Modifier::Plus) { - std::cout << "+"; - } else if (modifier == Modifier::Star) { - std::cout << "*"; - } - std::cout << " " << std::to_string(children.size()) << ":" << std::endl; - } else if (type == Type::Concatenation) { - std::cout << "Concatenation"; - if (modifier == Modifier::Plus) { - std::cout << "+"; - } else if (modifier == Modifier::Star) { - std::cout << "*"; - } - std::cout << " " << children.size() << ":" << std::endl; - } else if (type == Type::Word) { - std::cout << "Word"; - if (modifier == Modifier::Plus) { - std::cout << "+"; - } else if (modifier == Modifier::Star) { - std::cout << "*"; - } - std::cout << ": " << word << std::endl; - } - - for (const auto& i: children) { - i->Print(nesting_level + 1); - } -} - RegularTree::RegularTree(const std::string& regular) { node_.Parse(regular); } diff --git a/src/regular/RegularTreeNode.cpp b/src/regular/RegularTreeNode.cpp new file mode 100644 index 0000000..7b4637b --- /dev/null +++ b/src/regular/RegularTreeNode.cpp @@ -0,0 +1,185 @@ +#include "regular/RegularTree.hpp" +#include + +using Node = regular::RegularTree::Node; +Node::Node() {} +Node::Node(Type type) : type(type) {} + +void Node::Parse(const std::string& regular) { + type = Type::Addition; + ParseCurrentType(std::string_view(regular.c_str(), regular.size())); + Compression(); +} + +void Node::Print() const { + Print(0); +} + +void Node::ParseCurrentType(const std::string_view regular) { + const size_t n = regular.size(); + children.clear(); + word.clear(); + + auto AddChild = [this](const std::string_view regular) { + this->children.push_back(std::make_unique(Type::Addition)); + this->children.back()->ParseCurrentType(regular); + }; + + if (n == 1) { + type = Type::Word; + } + + if (type == Type::Addition) { + int balance = 0; + int begin_child = 0; + bool wrapped_brackets = (regular[0] == '('); + + for (size_t i = 0; i < n; ++i) { + if (regular[i] == '(') { + ++balance; + } else if (regular[i] == ')') { + --balance; + } + + if (regular[i] == '|') { + if (balance == 0) { + AddChild(regular.substr(begin_child + wrapped_brackets, i - + begin_child - 2 * + wrapped_brackets)); + begin_child = i + 1; + + if (i + 1 < n) + wrapped_brackets = (regular[i + 1] == '('); + } + } else { + if (i + 1 == n) { + if (children.size() == 0) { + type = Type::Concatenation; + break; + } else { + AddChild(regular.substr(begin_child + wrapped_brackets, i - + begin_child + 1 - 2 * + wrapped_brackets)); + begin_child = i + 1; + if (i + 1 < n) + wrapped_brackets = (regular[i + 1] == '('); + } + } else if (balance == 0) { + wrapped_brackets = false; + } + } + } + } + + if (type == Type::Concatenation) { + int balance = 0; + int begin_child = 0; + + for (size_t i = 0; i < n; ++i) { + if (regular[i] == '(') { + ++balance; + if (balance == 1) { + if (begin_child < i) { + AddChild(regular.substr(begin_child, i - begin_child)); + begin_child = i + 1; + } + } + } else if (regular[i] == ')') { + --balance; + if (balance == 0) { + AddChild(regular.substr(begin_child + 1, i - begin_child - 1)); + begin_child = i + 1; + } + } else if (i + 1 == n) { + if (balance != 0) { + throw std::logic_error("invalid regular"); + } + if (children.size() == 0) { + type = Type::Word; + break; + } else { + AddChild(regular.substr(begin_child, i - begin_child + 1)); + begin_child = i + 1; + } + } else if (balance == 0) { + if (regular[i] == '+') { + if (begin_child < i) { + AddChild(regular.substr(begin_child, i - begin_child)); + } + children.back()->modifier = Modifier::Plus; + begin_child = i + 1; + } else if (regular[i] == '*') { + if (begin_child < i) { + AddChild(regular.substr(begin_child, i - begin_child)); + } + children.back()->modifier = Modifier::Star; + begin_child = i + 1; + } + } + } + } + + if (type == Type::Word) { + bool exist_modifire = regular.back() == '+' || regular.back() == '*'; + if (regular.back() == '+') { + modifier = Modifier::Plus; + } else if (regular.back() == '*') { + modifier = Modifier::Star; + } + for (size_t i = 0; i < n - exist_modifire; ++i) { + if (regular[i] == '|' || regular[i] == '(' || regular[i] == ')') { + throw std::logic_error("invalid regular"); + } + word += regular[i]; + } + } +} + +void Node::Compression() { + for (auto& i: children) { + i->Compression(); + } + if (children.size() == 1 && modifier == Modifier::None) { + auto tmp = std::move(*children[0]); + *this = std::move(tmp); + } +} + +void Node::Print(int nesting_level) const { + auto PrintNesingLevel = [](int nesting_level) { + for (int i = 0; i < nesting_level; ++i) { + std::cout << " "; + } + }; + + PrintNesingLevel(nesting_level); + if (type == Type::Addition) { + std::cout << "Addition"; + if (modifier == Modifier::Plus) { + std::cout << "+"; + } else if (modifier == Modifier::Star) { + std::cout << "*"; + } + std::cout << " " << std::to_string(children.size()) << ":" << std::endl; + } else if (type == Type::Concatenation) { + std::cout << "Concatenation"; + if (modifier == Modifier::Plus) { + std::cout << "+"; + } else if (modifier == Modifier::Star) { + std::cout << "*"; + } + std::cout << " " << children.size() << ":" << std::endl; + } else if (type == Type::Word) { + std::cout << "Word"; + if (modifier == Modifier::Plus) { + std::cout << "+"; + } else if (modifier == Modifier::Star) { + std::cout << "*"; + } + std::cout << ": " << word << std::endl; + } + + for (const auto& i: children) { + i->Print(nesting_level + 1); + } +} From 82822d316f37539a8bbe60b6a5348aa2d1bca84a Mon Sep 17 00:00:00 2001 From: MaxanRus Date: Mon, 27 Sep 2021 23:13:02 +0300 Subject: [PATCH 05/17] Add NFA --- CMakeLists.txt | 2 ++ include/NFA/NFATree.hpp | 38 +++++++++++++++++++++++ src/NFA/NFATree.cpp | 65 +++++++++++++++++++++++++++++++++++++++ src/NFA/NFATreeVertex.cpp | 25 +++++++++++++++ 4 files changed, 130 insertions(+) create mode 100644 include/NFA/NFATree.hpp create mode 100644 src/NFA/NFATree.cpp create mode 100644 src/NFA/NFATreeVertex.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index ed99c37..3e62eeb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -18,6 +18,8 @@ set(CMAKE_CXX_STANDARD 17) set(SOURCE_FILES src/regular/RegularTree.cpp src/regular/RegularTreeNode.cpp + src/NFA/NFATree.cpp + src/NFA/NFATreeVertex.cpp ) set(TEST_FILES diff --git a/include/NFA/NFATree.hpp b/include/NFA/NFATree.hpp new file mode 100644 index 0000000..4358931 --- /dev/null +++ b/include/NFA/NFATree.hpp @@ -0,0 +1,38 @@ +#pragma once + +#include +#include +#include + +namespace NFA { +class NFATree { + public: + class Vertex { + public: + Vertex(); + Vertex(bool is_finale, bool is_start); + + bool IsFinal() const; + bool IsStart() const; + void SetFinal(bool value); + void SetStart(bool value); + + std::map>> transitions; + private: + bool is_final_ = false; + bool is_start_ = false; + }; + + void RemoveVertex(std::shared_ptr); + void RemoveFinalVertex(std::shared_ptr); + void RemoveStartVertex(std::shared_ptr); + + void Composition(NFATree&&, std::vector> + start_vertexes, std::vector> + final_vertexes); + private: + std::vector> vertexes_; + std::vector> final_vertexes_; + std::vector> start_vertexes_; +}; +} diff --git a/src/NFA/NFATree.cpp b/src/NFA/NFATree.cpp new file mode 100644 index 0000000..73bfb65 --- /dev/null +++ b/src/NFA/NFATree.cpp @@ -0,0 +1,65 @@ +#include "NFA/NFATree.hpp" +#include + +namespace NFA { +void NFATree::RemoveVertex(std::shared_ptr vertex) { + RemoveFinalVertex(vertex); + RemoveStartVertex(vertex); + for (size_t i = 0; i < vertexes_.size(); ++i) { + if (vertexes_[i] == vertex) { + std::swap(vertexes_[i], vertexes_.back()); + vertexes_.pop_back(); + break; + } + } +} + +void NFATree::RemoveFinalVertex(std::shared_ptr vertex) { + for (size_t i = 0; i < final_vertexes_.size(); ++i) { + if (final_vertexes_[i].lock() == vertex) { + final_vertexes_[i].lock()->SetFinal(false); + std::swap(final_vertexes_[i], final_vertexes_.back()); + final_vertexes_.pop_back(); + break; + } + } +} + +void NFATree::RemoveStartVertex(std::shared_ptr vertex) { + for (size_t i = 0; i < start_vertexes_.size(); ++i) { + if (start_vertexes_[i].lock() == vertex) { + start_vertexes_[i].lock()->SetStart(false); + std::swap(start_vertexes_[i], start_vertexes_.back()); + start_vertexes_.pop_back(); + break; + } + } +} + +void NFATree::Composition(NFATree&& tree, + std::vector> start_vertexes, + std::vector> final_vertexes) { + auto add_final_vertexes = tree.final_vertexes_; + auto add_start_vertexes = tree.start_vertexes_; + + vertexes_.insert(vertexes_.begin(), tree.vertexes_.begin(), tree.vertexes_.end()); + + for (auto& i: start_vertexes) { + for (auto& j: add_start_vertexes) { + i->transitions[' '].push_back(j); + } + } + for (auto& i: add_final_vertexes) { + for (auto& j: final_vertexes) { + i.lock()->transitions[' '].push_back(j); + } + } + for (auto& i: add_final_vertexes) { + i.lock()->SetFinal(false); + } + for (auto& i: add_start_vertexes) { + i.lock()->SetStart(false); + } +} +} + diff --git a/src/NFA/NFATreeVertex.cpp b/src/NFA/NFATreeVertex.cpp new file mode 100644 index 0000000..3f4f4bf --- /dev/null +++ b/src/NFA/NFATreeVertex.cpp @@ -0,0 +1,25 @@ +#include "NFA/NFATree.hpp" + +using Vertex = NFA::NFATree::Vertex; + +Vertex::Vertex() {} + +Vertex::Vertex(bool is_final, bool is_start) : is_final_(is_final), + is_start_(is_start) {} + +bool Vertex::IsFinal() const { + return is_final_; +} + +bool Vertex::IsStart() const { + return is_start_; +} + +void Vertex::SetFinal(bool value) { + is_final_ = value; +} + +void Vertex::SetStart(bool value) { + is_start_ = value; +} + From 45527d2c06d0a12c0e5a126a80be14b007845ccf Mon Sep 17 00:00:00 2001 From: MaxanRus Date: Sun, 3 Oct 2021 16:42:51 +0300 Subject: [PATCH 06/17] Add converter regular to NFA --- CMakeLists.txt | 1 + include/NFA/NFATree.hpp | 49 ++++++++++---- src/NFA/NFATree.cpp | 109 +++++++++++++++++++++++++------- src/NFA/NFATreeVertex.cpp | 8 +-- src/converters/RegularToNFA.cpp | 50 +++++++++++++++ src/main.cpp | 9 +++ src/regular/RegularTreeNode.cpp | 3 +- 7 files changed, 187 insertions(+), 42 deletions(-) create mode 100644 src/converters/RegularToNFA.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 3e62eeb..3edb7f2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -20,6 +20,7 @@ set(SOURCE_FILES src/regular/RegularTreeNode.cpp src/NFA/NFATree.cpp src/NFA/NFATreeVertex.cpp + src/converters/RegularToNFA.cpp ) set(TEST_FILES diff --git a/include/NFA/NFATree.hpp b/include/NFA/NFATree.hpp index 4358931..d67a199 100644 --- a/include/NFA/NFATree.hpp +++ b/include/NFA/NFATree.hpp @@ -2,6 +2,7 @@ #include #include +#include #include namespace NFA { @@ -10,29 +11,51 @@ class NFATree { class Vertex { public: Vertex(); - Vertex(bool is_finale, bool is_start); bool IsFinal() const; bool IsStart() const; - void SetFinal(bool value); - void SetStart(bool value); + size_t GetNumber() const; - std::map>> transitions; + std::multimap transitions; private: + Vertex(bool is_final, bool is_start); + + size_t number_; bool is_final_ = false; bool is_start_ = false; + + friend class NFATree; }; - void RemoveVertex(std::shared_ptr); - void RemoveFinalVertex(std::shared_ptr); - void RemoveStartVertex(std::shared_ptr); + NFATree() = default; + NFATree(const NFATree&) = delete; + NFATree(NFATree&&) = default; - void Composition(NFATree&&, std::vector> - start_vertexes, std::vector> - final_vertexes); + NFATree& operator=(const NFATree&) = delete; + NFATree& operator=(NFATree&&) = default; + + size_t AddNewVertex(); + void AddFinalVertex(size_t number); + void AddStartVertex(size_t number); + + void RemoveVertex(size_t number); + void RemoveFinalVertex(size_t number); + void RemoveStartVertex(size_t number); + + void Composition(NFATree&&, + std::vector start_vertexes, + std::vector final_vertexes); + + std::shared_ptr GetVertex(size_t number); + size_t GetCountVertexes() const; + const std::vector& GetFinalVertexes() const; + const std::vector& GetStartVertexes() const; + + void Print() const; private: - std::vector> vertexes_; - std::vector> final_vertexes_; - std::vector> start_vertexes_; + size_t count_vertexes_ = 0; + std::map> vertexes_; + std::vector final_vertexes_; + std::vector start_vertexes_; }; } diff --git a/src/NFA/NFATree.cpp b/src/NFA/NFATree.cpp index 73bfb65..cf2f8f8 100644 --- a/src/NFA/NFATree.cpp +++ b/src/NFA/NFATree.cpp @@ -1,23 +1,38 @@ #include "NFA/NFATree.hpp" #include +#include namespace NFA { -void NFATree::RemoveVertex(std::shared_ptr vertex) { - RemoveFinalVertex(vertex); - RemoveStartVertex(vertex); - for (size_t i = 0; i < vertexes_.size(); ++i) { - if (vertexes_[i] == vertex) { - std::swap(vertexes_[i], vertexes_.back()); - vertexes_.pop_back(); - break; - } +size_t NFATree::AddNewVertex() { + vertexes_[count_vertexes_] = std::make_shared(); + vertexes_[count_vertexes_]->number_ = count_vertexes_; + return count_vertexes_++; +} + +void NFATree::AddFinalVertex(size_t number) { + if (!vertexes_[number]->is_final_) { + vertexes_[number]->is_final_ = true; + final_vertexes_.push_back(number); } } -void NFATree::RemoveFinalVertex(std::shared_ptr vertex) { +void NFATree::AddStartVertex(size_t number) { + if (!vertexes_[number]->is_start_) { + vertexes_[number]->is_start_ = true; + start_vertexes_.push_back(number); + } +} + +void NFATree::RemoveVertex(size_t number) { + RemoveFinalVertex(number); + RemoveStartVertex(number); + vertexes_.erase(number); +} + +void NFATree::RemoveFinalVertex(size_t number) { for (size_t i = 0; i < final_vertexes_.size(); ++i) { - if (final_vertexes_[i].lock() == vertex) { - final_vertexes_[i].lock()->SetFinal(false); + if (final_vertexes_[i] == number) { + vertexes_[number]->is_final_ = false; std::swap(final_vertexes_[i], final_vertexes_.back()); final_vertexes_.pop_back(); break; @@ -25,10 +40,10 @@ void NFATree::RemoveFinalVertex(std::shared_ptr vertex) { } } -void NFATree::RemoveStartVertex(std::shared_ptr vertex) { +void NFATree::RemoveStartVertex(size_t number) { for (size_t i = 0; i < start_vertexes_.size(); ++i) { - if (start_vertexes_[i].lock() == vertex) { - start_vertexes_[i].lock()->SetStart(false); + if (start_vertexes_[i] == number) { + vertexes_[number]->is_start_ = false; std::swap(start_vertexes_[i], start_vertexes_.back()); start_vertexes_.pop_back(); break; @@ -37,29 +52,79 @@ void NFATree::RemoveStartVertex(std::shared_ptr vertex) { } void NFATree::Composition(NFATree&& tree, - std::vector> start_vertexes, - std::vector> final_vertexes) { + std::vector start_vertexes, + std::vector final_vertexes) { auto add_final_vertexes = tree.final_vertexes_; auto add_start_vertexes = tree.start_vertexes_; - vertexes_.insert(vertexes_.begin(), tree.vertexes_.begin(), tree.vertexes_.end()); + size_t new_count_vertexes = count_vertexes_; + + for (auto& i: tree.vertexes_) { + new_count_vertexes = std::max(new_count_vertexes, i.first + count_vertexes_); + i.second->number_ += count_vertexes_; + for (auto& j: i.second->transitions) { + j.second += count_vertexes_; + } + vertexes_[i.second->number_] = std::move(i.second); + } + + for (auto& i: add_start_vertexes) { + i += count_vertexes_; + } + for (auto& i: add_final_vertexes) { + i += count_vertexes_; + } + + count_vertexes_ = new_count_vertexes; for (auto& i: start_vertexes) { for (auto& j: add_start_vertexes) { - i->transitions[' '].push_back(j); + vertexes_[i]->transitions.emplace(' ', j); } } for (auto& i: add_final_vertexes) { for (auto& j: final_vertexes) { - i.lock()->transitions[' '].push_back(j); + vertexes_[i]->transitions.emplace(' ', j); } } for (auto& i: add_final_vertexes) { - i.lock()->SetFinal(false); + vertexes_[i]->is_final_ = false; } for (auto& i: add_start_vertexes) { - i.lock()->SetStart(false); + vertexes_[i]->is_start_ = false; } } + +std::shared_ptr NFATree::GetVertex(size_t number) { + if (vertexes_.count(number)) + return vertexes_[number]; + return nullptr; +} + +size_t NFATree::GetCountVertexes() const { + return count_vertexes_; +} + +const std::vector& NFATree::GetFinalVertexes() const { + return final_vertexes_; +} + +const std::vector& NFATree::GetStartVertexes() const { + return start_vertexes_; +} + +void NFATree::Print() const { + for (auto i: vertexes_) { + std::cout << i.second->number_ << " " << "f-" << i.second->is_final_ << " s-" << + i.second->is_start_ << std::endl; + } + for (auto& i: vertexes_) { + for (auto& j: i.second->transitions) { + std::cout << i.second->number_ << "->" << j.second << " <" << j.first << ">" << + std::endl; + } + } + std::cout << std::endl; +} } diff --git a/src/NFA/NFATreeVertex.cpp b/src/NFA/NFATreeVertex.cpp index 3f4f4bf..cc9ca82 100644 --- a/src/NFA/NFATreeVertex.cpp +++ b/src/NFA/NFATreeVertex.cpp @@ -15,11 +15,7 @@ bool Vertex::IsStart() const { return is_start_; } -void Vertex::SetFinal(bool value) { - is_final_ = value; -} - -void Vertex::SetStart(bool value) { - is_start_ = value; +size_t Vertex::GetNumber() const { + return number_; } diff --git a/src/converters/RegularToNFA.cpp b/src/converters/RegularToNFA.cpp new file mode 100644 index 0000000..12e3c7c --- /dev/null +++ b/src/converters/RegularToNFA.cpp @@ -0,0 +1,50 @@ +#include "converters/RegularToNFA.hpp" +#include "regular/RegularTree.hpp" +#include "NFA/NFATree.hpp" + +using namespace NFA; +using namespace regular; +using Node = RegularTree::Node; + +struct do_nothing_deleter{ + template + void operator()(T*) const {} +}; + +template +NFATree RegularToNFA(std::unique_ptr node) { + NFATree result; + if (node->type == Node::Type::Word) { + auto last = result.AddNewVertex(); + result.AddStartVertex(last); + for (char i: node->word) { + auto tmp = result.AddNewVertex(); + result.GetVertex(last)->transitions.emplace(i, tmp); + last = tmp; + } + result.AddFinalVertex(last); + } else if (node->type == Node::Type::Concatenation) { + result = RegularToNFA(std::move(node->children[0])); + for (auto it = node->children.begin() + 1; it != node->children.end(); ++it) { + auto tmp = RegularToNFA(std::move(*it)); + auto v = result.AddNewVertex(); + result.Composition(std::move(tmp), result.GetFinalVertexes(), {v}); + while (!result.GetFinalVertexes().empty()) { + result.RemoveFinalVertex(result.GetFinalVertexes()[0]); + } + result.AddFinalVertex(v); + } + + } else if (node->type == Node::Type::Addition) { + // TODO + } + return result; +} + +namespace converters { +NFATree RegularToNFA(RegularTree&& tree) { + const Node& root = tree.GetNode(); + return RegularToNFA(std::unique_ptr(&const_cast(tree.GetNode()))); +} +} diff --git a/src/main.cpp b/src/main.cpp index 080b2cb..3253512 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,5 +1,6 @@ #include #include "regular/RegularTree.hpp" +#include "converters/RegularToNFA.hpp" int main() { using namespace regular; @@ -7,4 +8,12 @@ int main() { std::cin >> str; RegularTree reg_tree(str); reg_tree.Print(); + + auto NFA_tree = converters::RegularToNFA(std::move(reg_tree)); + + std::cout << std::endl; + + NFA_tree.Print(); + + } diff --git a/src/regular/RegularTreeNode.cpp b/src/regular/RegularTreeNode.cpp index 7b4637b..3939d17 100644 --- a/src/regular/RegularTreeNode.cpp +++ b/src/regular/RegularTreeNode.cpp @@ -16,6 +16,7 @@ void Node::Print() const { } void Node::ParseCurrentType(const std::string_view regular) { + std::cout << "# " << regular << std::endl; const size_t n = regular.size(); children.clear(); word.clear(); @@ -87,7 +88,7 @@ void Node::ParseCurrentType(const std::string_view regular) { } else if (regular[i] == ')') { --balance; if (balance == 0) { - AddChild(regular.substr(begin_child + 1, i - begin_child - 1)); + AddChild(regular.substr(begin_child, i - begin_child)); begin_child = i + 1; } } else if (i + 1 == n) { From 32f8a3dcc6df5f8b2d347aae4ca1bb128027e76d Mon Sep 17 00:00:00 2001 From: MaxanRus Date: Tue, 5 Oct 2021 15:01:30 +0300 Subject: [PATCH 07/17] Many changes --- CMakeLists.txt | 11 + include/DFA/DFAGraph.hpp | 68 +++++++ include/FDFA/FDFAGraph.hpp | 67 ++++++ include/NFA/NFATree.hpp | 19 +- include/converters/DFAToFDFA.hpp | 10 + include/converters/DFAToMinDFA.hpp | 7 + include/converters/DFAToRegular.hpp | 8 + include/converters/NFAToDFA.hpp | 13 ++ include/converters/RegularToNFA.hpp | 10 + src/DFA/DFAGraph.cpp | 98 +++++++++ src/DFA/DFAGraphVertex.cpp | 58 ++++++ src/FDFA/FDFAGraph.cpp | 98 +++++++++ src/FDFA/FDFAGraphVertex.cpp | 58 ++++++ src/NFA/NFATree.cpp | 59 +++++- src/NFA/NFATreeVertex.cpp | 50 ++++- src/converters/DFAToFDFA.cpp | 90 ++++++++ src/converters/DFAToMinDFA.cpp | 111 ++++++++++ src/converters/DFAToRegular.cpp | 126 ++++++++++++ src/converters/NFAToDFA.cpp | 293 +++++++++++++++++++++++++++ src/converters/RegularToNFA.cpp | 50 ++++- src/main.cpp | 156 +++++++++++++- src/regular/RegularTreeNode.cpp | 22 +- tests/DFAToRegular/DFAToRegular.cpp | 202 ++++++++++++++++++ tests/NFAToDFA/check_equivalence.cpp | 111 ++++++++++ tests/regularToDFA/regularToDFA.cpp | 151 ++++++++++++++ 25 files changed, 1917 insertions(+), 29 deletions(-) create mode 100644 include/DFA/DFAGraph.hpp create mode 100644 include/FDFA/FDFAGraph.hpp create mode 100644 include/converters/DFAToFDFA.hpp create mode 100644 include/converters/DFAToMinDFA.hpp create mode 100644 include/converters/DFAToRegular.hpp create mode 100644 include/converters/NFAToDFA.hpp create mode 100644 include/converters/RegularToNFA.hpp create mode 100644 src/DFA/DFAGraph.cpp create mode 100644 src/DFA/DFAGraphVertex.cpp create mode 100644 src/FDFA/FDFAGraph.cpp create mode 100644 src/FDFA/FDFAGraphVertex.cpp create mode 100644 src/converters/DFAToFDFA.cpp create mode 100644 src/converters/DFAToMinDFA.cpp create mode 100644 src/converters/DFAToRegular.cpp create mode 100644 src/converters/NFAToDFA.cpp create mode 100644 tests/DFAToRegular/DFAToRegular.cpp create mode 100644 tests/NFAToDFA/check_equivalence.cpp create mode 100644 tests/regularToDFA/regularToDFA.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 3edb7f2..21991db 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -21,10 +21,21 @@ set(SOURCE_FILES src/NFA/NFATree.cpp src/NFA/NFATreeVertex.cpp src/converters/RegularToNFA.cpp + src/converters/NFAToDFA.cpp + src/DFA/DFAGraph.cpp + src/DFA/DFAGraphVertex.cpp + # src/FDFA/FDFAGraph.cpp + # src/FDFA/FDFAGraphVertex.cpp + src/converters/DFAToFDFA.cpp + src/converters/DFAToMinDFA.cpp + src/converters/DFAToRegular.cpp ) set(TEST_FILES tests/regular/parse_regular.cpp + tests/NFAToDFA/check_equivalence.cpp + tests/regularToDFA/regularToDFA.cpp + tests/DFAToRegular/DFAToRegular.cpp ) add_executable(Formalang src/main.cpp ${SOURCE_FILES}) diff --git a/include/DFA/DFAGraph.hpp b/include/DFA/DFAGraph.hpp new file mode 100644 index 0000000..af1f100 --- /dev/null +++ b/include/DFA/DFAGraph.hpp @@ -0,0 +1,68 @@ +#pragma once + +#include +#include +#include +#include + +namespace DFA { +class DFAGraph { + public: + class Vertex { + public: + Vertex(DFAGraph* owner); + + bool IsFinal() const; + bool IsStart() const; + size_t GetNumber() const; + + const std::map& GetTransitions() const; + const std::map& GetBackTransitions() const; + + void AddEdge(char, size_t); + void RemoveEdge(char); + void SetOwner(DFAGraph* owner); + void SetFinal(bool status); + void SetStart(bool status); + private: + DFAGraph* owner_; + std::map transitions_; + std::map back_transitions_; + + size_t number_; + bool is_final_ = false; + bool is_start_ = false; + + friend class DFAGraph; + }; + + DFAGraph() = default; + DFAGraph(const DFAGraph&) = delete; + DFAGraph(DFAGraph&&) = default; + + DFAGraph& operator=(const DFAGraph&) = delete; + DFAGraph& operator=(DFAGraph&&) = default; + + size_t AddNewVertex(); + void AddFinalVertex(size_t number); + void AddStartVertex(size_t number); + + void RemoveVertex(size_t number); + void RemoveFinalVertex(size_t number); + void RemoveStartVertex(size_t number); + + std::shared_ptr GetVertex(size_t number); + + size_t GetCountVertexes() const; + const std::vector& GetFinalVertexes() const; + const std::vector& GetStartVertexes() const; + + void Print() const; + bool Accepted(const std::string&) const; + private: + size_t count_vertexes_ = 0; + std::map> vertexes_; + std::vector final_vertexes_; + std::vector start_vertexes_; +}; +} diff --git a/include/FDFA/FDFAGraph.hpp b/include/FDFA/FDFAGraph.hpp new file mode 100644 index 0000000..591a50f --- /dev/null +++ b/include/FDFA/FDFAGraph.hpp @@ -0,0 +1,67 @@ +#pragma once +#include +#include +#include +#include + +namespace FDFA { +class FDFAGraph { + public: + class Vertex { + public: + Vertex(FDFAGraph* owner); + + bool IsFinal() const; + bool IsStart() const; + size_t GetNumber() const; + + const std::map& GetTransitions() const; + const std::map& GetBackTransitions() const; + + void AddEdge(char, size_t); + void RemoveEdge(char); + void SetOwner(FDFAGraph* owner); + void SetFinal(bool status); + void SetStart(bool status); + private: + FDFAGraph* owner_; + std::map transitions_; + std::map back_transitions_; + + size_t number_; + bool is_final_ = false; + bool is_start_ = false; + + friend class FDFAGraph; + }; + + FDFAGraph() = default; + FDFAGraph(const FDFAGraph&) = delete; + FDFAGraph(FDFAGraph&&) = default; + + FDFAGraph& operator=(const FDFAGraph&) = delete; + FDFAGraph& operator=(FDFAGraph&&) = default; + + size_t AddNewVertex(); + void AddFinalVertex(size_t number); + void AddStartVertex(size_t number); + + void RemoveVertex(size_t number); + void RemoveFinalVertex(size_t number); + void RemoveStartVertex(size_t number); + + std::shared_ptr GetVertex(size_t number); + + size_t GetCountVertexes() const; + const std::vector& GetFinalVertexes() const; + const std::vector& GetStartVertexes() const; + + void Print() const; + bool Accepted(const std::string&) const; + private: + size_t count_vertexes_ = 0; + std::map> vertexes_; + std::vector final_vertexes_; + std::vector start_vertexes_; +}; +} diff --git a/include/NFA/NFATree.hpp b/include/NFA/NFATree.hpp index d67a199..02e0d56 100644 --- a/include/NFA/NFATree.hpp +++ b/include/NFA/NFATree.hpp @@ -10,15 +10,24 @@ class NFATree { public: class Vertex { public: - Vertex(); + Vertex(NFATree* owner); bool IsFinal() const; bool IsStart() const; size_t GetNumber() const; - std::multimap transitions; + const std::map>& GetTransitions() const; + const std::map>& GetBackTransitions() const; + + void AddEdge(char, size_t); + void RemoveEdge(char, size_t); + void SetOwner(NFATree* owner); + void SetFinal(bool status); + void SetStart(bool status); private: - Vertex(bool is_final, bool is_start); + NFATree* owner_; + std::map> transitions_; + std::map> back_transitions_; size_t number_; bool is_final_ = false; @@ -29,10 +38,10 @@ class NFATree { NFATree() = default; NFATree(const NFATree&) = delete; - NFATree(NFATree&&) = default; + NFATree(NFATree&&); NFATree& operator=(const NFATree&) = delete; - NFATree& operator=(NFATree&&) = default; + NFATree& operator=(NFATree&&); size_t AddNewVertex(); void AddFinalVertex(size_t number); diff --git a/include/converters/DFAToFDFA.hpp b/include/converters/DFAToFDFA.hpp new file mode 100644 index 0000000..bdf1eda --- /dev/null +++ b/include/converters/DFAToFDFA.hpp @@ -0,0 +1,10 @@ +#pragma once +#include "DFA/DFAGraph.hpp" +#include "FDFA/FDFAGraph.hpp" + +namespace converters { +using namespace DFA; +using namespace FDFA; +DFAGraph DFAGraphToFDFAGraph(DFAGraph&&, const std::vector& alphabet); +// FDFAGraph DFAGraphToFDFAGraph(DFAGraph&&, const std::vector& alphabet); +} diff --git a/include/converters/DFAToMinDFA.hpp b/include/converters/DFAToMinDFA.hpp new file mode 100644 index 0000000..dd25402 --- /dev/null +++ b/include/converters/DFAToMinDFA.hpp @@ -0,0 +1,7 @@ +#pragma once +#include "DFA/DFAGraph.hpp" + +namespace converters { +using namespace DFA; +DFAGraph DFAToMinDFA(DFAGraph&&); +} diff --git a/include/converters/DFAToRegular.hpp b/include/converters/DFAToRegular.hpp new file mode 100644 index 0000000..4c825da --- /dev/null +++ b/include/converters/DFAToRegular.hpp @@ -0,0 +1,8 @@ +#pragma once +#include "DFA/DFAGraph.hpp" +#include + +namespace converters { +using namespace DFA; +std::string DFAGraphToRegular(DFAGraph&&); +} diff --git a/include/converters/NFAToDFA.hpp b/include/converters/NFAToDFA.hpp new file mode 100644 index 0000000..ecb0669 --- /dev/null +++ b/include/converters/NFAToDFA.hpp @@ -0,0 +1,13 @@ +#pragma once +#include "NFA/NFATree.hpp" +#include "DFA/DFAGraph.hpp" + +namespace converters { +using namespace NFA; +using namespace DFA; +NFATree AddAllEpsilonTransitions(NFATree&&); +NFATree AddAllPossibleStartFilnal(NFATree&&); +NFATree DeleteEpsilonTransitions(NFATree&&); +NFATree DeleteTransitionsByOneLetter(NFATree&&); +DFAGraph NFATreeToDFAGraph(NFATree&&); +} diff --git a/include/converters/RegularToNFA.hpp b/include/converters/RegularToNFA.hpp new file mode 100644 index 0000000..d4dd5f9 --- /dev/null +++ b/include/converters/RegularToNFA.hpp @@ -0,0 +1,10 @@ +#pragma once +#include "regular/RegularTree.hpp" +#include "NFA/NFATree.hpp" + +namespace converters { +using namespace NFA; +using namespace regular; + +NFATree RegularToNFA(RegularTree&&); +} diff --git a/src/DFA/DFAGraph.cpp b/src/DFA/DFAGraph.cpp new file mode 100644 index 0000000..01882a3 --- /dev/null +++ b/src/DFA/DFAGraph.cpp @@ -0,0 +1,98 @@ +#include "DFA/DFAGraph.hpp" +#include +#include + +namespace DFA { +size_t DFAGraph::AddNewVertex() { + vertexes_[count_vertexes_] = std::make_shared(this); + vertexes_[count_vertexes_]->number_ = count_vertexes_; + return count_vertexes_++; +} + +void DFAGraph::AddFinalVertex(size_t number) { + if (!vertexes_[number]->is_final_) { + vertexes_[number]->is_final_ = true; + final_vertexes_.push_back(number); + } +} + +void DFAGraph::AddStartVertex(size_t number) { + if (!vertexes_[number]->is_start_) { + vertexes_[number]->is_start_ = true; + start_vertexes_.push_back(number); + } +} + +void DFAGraph::RemoveVertex(size_t number) { + RemoveFinalVertex(number); + RemoveStartVertex(number); + vertexes_.erase(number); +} + +void DFAGraph::RemoveFinalVertex(size_t number) { + for (size_t i = 0; i < final_vertexes_.size(); ++i) { + if (final_vertexes_[i] == number) { + vertexes_[number]->is_final_ = false; + std::swap(final_vertexes_[i], final_vertexes_.back()); + final_vertexes_.pop_back(); + break; + } + } +} + +void DFAGraph::RemoveStartVertex(size_t number) { + for (size_t i = 0; i < start_vertexes_.size(); ++i) { + if (start_vertexes_[i] == number) { + vertexes_[number]->is_start_ = false; + std::swap(start_vertexes_[i], start_vertexes_.back()); + start_vertexes_.pop_back(); + break; + } + } +} + +std::shared_ptr DFAGraph::GetVertex(size_t number) { + if (vertexes_.count(number)) + return vertexes_[number]; + return nullptr; +} + +size_t DFAGraph::GetCountVertexes() const { + return count_vertexes_; +} + +const std::vector& DFAGraph::GetFinalVertexes() const { + return final_vertexes_; +} + +const std::vector& DFAGraph::GetStartVertexes() const { + return start_vertexes_; +} + +void DFAGraph::Print() const { + for (auto i: vertexes_) { + std::cout << i.second->number_ << " " << "f-" << i.second->is_final_ << " s-" << + i.second->is_start_ << std::endl; + } + for (auto& i: vertexes_) { + for (auto& j: i.second->transitions_) { + std::cout << i.second->number_ << "->" << j.second << " <" << j.first << ">" << + std::endl; + } + } + std::cout << std::endl; +} + +bool DFAGraph::Accepted(const std::string& str) const { + std::shared_ptr current = vertexes_.at(start_vertexes_[0]); + for (auto i: str) { + if (current->GetTransitions().count(i)) { + current = vertexes_.at(current->GetTransitions().at(i)); + } else { + return false; + } + } + return current->IsFinal(); +} +} + diff --git a/src/DFA/DFAGraphVertex.cpp b/src/DFA/DFAGraphVertex.cpp new file mode 100644 index 0000000..a5d0f78 --- /dev/null +++ b/src/DFA/DFAGraphVertex.cpp @@ -0,0 +1,58 @@ +#include "DFA/DFAGraph.hpp" +#include + +using Vertex = DFA::DFAGraph::Vertex; + +Vertex::Vertex(DFAGraph* owner) : owner_(owner) {} + +bool Vertex::IsFinal() const { + return is_final_; +} + +bool Vertex::IsStart() const { + return is_start_; +} + +size_t Vertex::GetNumber() const { + return number_; +} + +const std::map& Vertex::GetTransitions() const { + return transitions_; +} + +const std::map& Vertex::GetBackTransitions() const { + return back_transitions_; +} + +void Vertex::AddEdge(char symbol, size_t number) { + transitions_[symbol] = number; + owner_->GetVertex(number)->back_transitions_[symbol] = number_; +} + +void Vertex::RemoveEdge(char symbol) { + owner_->GetVertex(transitions_[symbol])->back_transitions_.erase(symbol); + transitions_.erase(symbol); +} + +void Vertex::SetOwner(DFAGraph* owner) { + owner_ = owner; +} + +void Vertex::SetFinal(bool status) { + if (status != is_final_) { + if (status) + owner_->AddFinalVertex(number_); + else + owner_->RemoveFinalVertex(number_); + } +} + +void Vertex::SetStart(bool status) { + if (status != is_start_) { + if (status) + owner_->AddStartVertex(number_); + else + owner_->RemoveStartVertex(number_); + } +} diff --git a/src/FDFA/FDFAGraph.cpp b/src/FDFA/FDFAGraph.cpp new file mode 100644 index 0000000..310bfec --- /dev/null +++ b/src/FDFA/FDFAGraph.cpp @@ -0,0 +1,98 @@ +#include "FDFA/FDFAGraph.hpp" +#include +#include + +namespace FDFA { +size_t FDFAGraph::AddNewVertex() { + vertexes_[count_vertexes_] = std::make_shared(this); + vertexes_[count_vertexes_]->number_ = count_vertexes_; + return count_vertexes_++; +} + +void FDFAGraph::AddFinalVertex(size_t number) { + if (!vertexes_[number]->is_final_) { + vertexes_[number]->is_final_ = true; + final_vertexes_.push_back(number); + } +} + +void FDFAGraph::AddStartVertex(size_t number) { + if (!vertexes_[number]->is_start_) { + vertexes_[number]->is_start_ = true; + start_vertexes_.push_back(number); + } +} + +void FDFAGraph::RemoveVertex(size_t number) { + RemoveFinalVertex(number); + RemoveStartVertex(number); + vertexes_.erase(number); +} + +void FDFAGraph::RemoveFinalVertex(size_t number) { + for (size_t i = 0; i < final_vertexes_.size(); ++i) { + if (final_vertexes_[i] == number) { + vertexes_[number]->is_final_ = false; + std::swap(final_vertexes_[i], final_vertexes_.back()); + final_vertexes_.pop_back(); + break; + } + } +} + +void FDFAGraph::RemoveStartVertex(size_t number) { + for (size_t i = 0; i < start_vertexes_.size(); ++i) { + if (start_vertexes_[i] == number) { + vertexes_[number]->is_start_ = false; + std::swap(start_vertexes_[i], start_vertexes_.back()); + start_vertexes_.pop_back(); + break; + } + } +} + +std::shared_ptr FDFAGraph::GetVertex(size_t number) { + if (vertexes_.count(number)) + return vertexes_[number]; + return nullptr; +} + +size_t FDFAGraph::GetCountVertexes() const { + return count_vertexes_; +} + +const std::vector& FDFAGraph::GetFinalVertexes() const { + return final_vertexes_; +} + +const std::vector& FDFAGraph::GetStartVertexes() const { + return start_vertexes_; +} + +void FDFAGraph::Print() const { + for (auto i: vertexes_) { + std::cout << i.second->number_ << " " << "f-" << i.second->is_final_ << " s-" << + i.second->is_start_ << std::endl; + } + for (auto& i: vertexes_) { + for (auto& j: i.second->transitions_) { + std::cout << i.second->number_ << "->" << j.second << " <" << j.first << ">" << + std::endl; + } + } + std::cout << std::endl; +} + +bool FDFAGraph::Accepted(const std::string& str) const { + std::shared_ptr current = vertexes_.at(start_vertexes_[0]); + for (auto i: str) { + if (current->GetTransitions().count(i)) { + current = vertexes_.at(current->GetTransitions().at(i)); + } else { + return false; + } + } + return current->IsFinal(); +} +} + diff --git a/src/FDFA/FDFAGraphVertex.cpp b/src/FDFA/FDFAGraphVertex.cpp new file mode 100644 index 0000000..8304387 --- /dev/null +++ b/src/FDFA/FDFAGraphVertex.cpp @@ -0,0 +1,58 @@ +#include "FDFA/FDFAGraph.hpp" +#include + +using Vertex = FDFA::FDFAGraph::Vertex; + +Vertex::Vertex(FDFAGraph* owner) : owner_(owner) {} + +bool Vertex::IsFinal() const { + return is_final_; +} + +bool Vertex::IsStart() const { + return is_start_; +} + +size_t Vertex::GetNumber() const { + return number_; +} + +const std::map& Vertex::GetTransitions() const { + return transitions_; +} + +const std::map& Vertex::GetBackTransitions() const { + return back_transitions_; +} + +void Vertex::AddEdge(char symbol, size_t number) { + transitions_[symbol] = number; + owner_->GetVertex(number)->back_transitions_[symbol] = number_; +} + +void Vertex::RemoveEdge(char symbol) { + owner_->GetVertex(transitions_[symbol])->back_transitions_.erase(symbol); + transitions_.erase(symbol); +} + +void Vertex::SetOwner(FDFAGraph* owner) { + owner_ = owner; +} + +void Vertex::SetFinal(bool status) { + if (status != is_final_) { + if (status) + owner_->AddFinalVertex(number_); + else + owner_->RemoveFinalVertex(number_); + } +} + +void Vertex::SetStart(bool status) { + if (status != is_start_) { + if (status) + owner_->AddStartVertex(number_); + else + owner_->RemoveStartVertex(number_); + } +} diff --git a/src/NFA/NFATree.cpp b/src/NFA/NFATree.cpp index cf2f8f8..aa57d47 100644 --- a/src/NFA/NFATree.cpp +++ b/src/NFA/NFATree.cpp @@ -3,8 +3,33 @@ #include namespace NFA { +NFATree::NFATree(NFATree&& 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; +} + +NFATree& NFATree::operator=(NFATree&& 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 NFATree::AddNewVertex() { - vertexes_[count_vertexes_] = std::make_shared(); + vertexes_[count_vertexes_] = std::make_shared(this); vertexes_[count_vertexes_]->number_ = count_vertexes_; return count_vertexes_++; } @@ -60,11 +85,24 @@ void NFATree::Composition(NFATree&& tree, size_t new_count_vertexes = count_vertexes_; for (auto& i: tree.vertexes_) { - new_count_vertexes = std::max(new_count_vertexes, i.first + count_vertexes_); + new_count_vertexes = std::max(new_count_vertexes, i.first + count_vertexes_ + 1); i.second->number_ += count_vertexes_; - for (auto& j: i.second->transitions) { - j.second += count_vertexes_; + std::map> new_transitions; + for (auto& j: i.second->transitions_) { + for (auto& k: j.second) { + new_transitions[j.first].insert(k + count_vertexes_); + } } + std::map> new_back_transitions; + for (auto& j: i.second->back_transitions_) { + for (auto& k: j.second) { + new_back_transitions[j.first].insert(k + count_vertexes_); + } + } + i.second->transitions_ = std::move(new_transitions); + i.second->back_transitions_ = std::move(new_back_transitions); + + i.second->SetOwner(this); vertexes_[i.second->number_] = std::move(i.second); } @@ -79,12 +117,14 @@ void NFATree::Composition(NFATree&& tree, for (auto& i: start_vertexes) { for (auto& j: add_start_vertexes) { - vertexes_[i]->transitions.emplace(' ', j); + vertexes_[i]->transitions_[' '].insert(j); + vertexes_[j]->back_transitions_[' '].insert(i); } } for (auto& i: add_final_vertexes) { for (auto& j: final_vertexes) { - vertexes_[i]->transitions.emplace(' ', j); + vertexes_[i]->transitions_[' '].insert(j); + vertexes_[j]->back_transitions_[' '].insert(i); } } for (auto& i: add_final_vertexes) { @@ -119,12 +159,13 @@ void NFATree::Print() const { i.second->is_start_ << std::endl; } for (auto& i: vertexes_) { - for (auto& j: i.second->transitions) { - std::cout << i.second->number_ << "->" << j.second << " <" << j.first << ">" << + for (auto& j: i.second->transitions_) { + for (auto k: j.second) { + std::cout << i.second->number_ << "->" << k << " <" << j.first << ">" << std::endl; + } } } std::cout << std::endl; } } - diff --git a/src/NFA/NFATreeVertex.cpp b/src/NFA/NFATreeVertex.cpp index cc9ca82..4060d82 100644 --- a/src/NFA/NFATreeVertex.cpp +++ b/src/NFA/NFATreeVertex.cpp @@ -1,11 +1,9 @@ #include "NFA/NFATree.hpp" +#include using Vertex = NFA::NFATree::Vertex; -Vertex::Vertex() {} - -Vertex::Vertex(bool is_final, bool is_start) : is_final_(is_final), - is_start_(is_start) {} +Vertex::Vertex(NFATree* owner) : owner_(owner) {} bool Vertex::IsFinal() const { return is_final_; @@ -19,3 +17,47 @@ size_t Vertex::GetNumber() const { return number_; } +const std::map>& Vertex::GetTransitions() const { + return transitions_; +} + +const std::map>& Vertex::GetBackTransitions() const { + return back_transitions_; +} + +void Vertex::AddEdge(char symbol, size_t number) { + transitions_[symbol].insert(number); + owner_->GetVertex(number)->back_transitions_[symbol]; + owner_->GetVertex(number)->back_transitions_[symbol].insert(number_); +} + +void Vertex::RemoveEdge(char symbol, size_t number) { + transitions_[symbol].erase(number); + if (transitions_[symbol].size() == 0) + transitions_.erase(symbol); + owner_->GetVertex(number)->back_transitions_[symbol].erase(number_); + if (owner_->GetVertex(number)->back_transitions_[symbol].size() == 0) + owner_->GetVertex(number)->back_transitions_.erase(symbol); +} + +void Vertex::SetOwner(NFATree* owner) { + owner_ = owner; +} + +void Vertex::SetFinal(bool status) { + if (status != is_final_) { + if (status) + owner_->AddFinalVertex(number_); + else + owner_->RemoveFinalVertex(number_); + } +} + +void Vertex::SetStart(bool status) { + if (status != is_start_) { + if (status) + owner_->AddStartVertex(number_); + else + owner_->RemoveStartVertex(number_); + } +} diff --git a/src/converters/DFAToFDFA.cpp b/src/converters/DFAToFDFA.cpp new file mode 100644 index 0000000..9d6ec37 --- /dev/null +++ b/src/converters/DFAToFDFA.cpp @@ -0,0 +1,90 @@ +#include "converters/DFAToFDFA.hpp" + +namespace converters { +DFAGraph DFAGraphToFDFAGraph(DFAGraph&& graph, const std::vector& alphabet) { + DFAGraph result; + const int n = graph.GetCountVertexes(); + std::map number_vertex_in_DFA; + for (int i = 0; i < n; ++i) { + if (!graph.GetVertex(i)) continue; + number_vertex_in_DFA[i] = result.AddNewVertex(); + } + for (int i = 0; i < n; ++i) { + if (!graph.GetVertex(i)) continue; + if (graph.GetVertex(i)->IsFinal()) + result.GetVertex(number_vertex_in_DFA[i])->SetFinal(true); + if (graph.GetVertex(i)->IsStart()) + result.GetVertex(number_vertex_in_DFA[i])->SetStart(true); + + const auto& transitions = graph.GetVertex(i)->GetTransitions(); + for (const auto& t: transitions) { + result.GetVertex(number_vertex_in_DFA[i])->AddEdge(t.first, t.second); + } + } + + size_t drain = result.AddNewVertex(); + + for (int i = 0; i < n; ++i) { + const auto& transitions = graph.GetVertex(i)->GetTransitions(); + for (char j: alphabet) { + if (!transitions.count(j)) { + result.GetVertex(i)->AddEdge(j, drain); + } + } + } + + if (result.GetVertex(drain)->GetBackTransitions().size() == 0) { + result.RemoveVertex(drain); + } else { + for (char j: alphabet) { + result.GetVertex(drain)->AddEdge(j, drain); + } + } + + return result; +} +/* +FDFAGraph DFAGraphToFDFAGraph(DFAGraph&& graph, const std::vector& alphabet) { + FDFAGraph result; + const int n = graph.GetCountVertexes(); + std::map number_vertex_in_DFA; + for (int i = 0; i < n; ++i) { + if (!graph.GetVertex(i)) continue; + number_vertex_in_DFA[i] = result.AddNewVertex(); + } + for (int i = 0; i < n; ++i) { + if (!graph.GetVertex(i)) continue; + if (graph.GetVertex(i)->IsFinal()) + result.GetVertex(number_vertex_in_DFA[i])->SetFinal(true); + if (graph.GetVertex(i)->IsStart()) + result.GetVertex(number_vertex_in_DFA[i])->SetStart(true); + + const auto& transitions = graph.GetVertex(i)->GetTransitions(); + for (const auto& t: transitions) { + result.GetVertex(number_vertex_in_DFA[i])->AddEdge(t.first, t.second); + } + } + + size_t drain = result.AddNewVertex(); + + for (int i = 0; i < n; ++i) { + const auto& transitions = graph.GetVertex(i)->GetTransitions(); + for (char j: alphabet) { + if (!transitions.count(j)) { + result.GetVertex(i)->AddEdge(j, drain); + } + } + } + + if (result.GetVertex(drain)->GetBackTransitions().size() == 0) { + result.RemoveVertex(drain); + } else { + for (char j: alphabet) { + result.GetVertex(drain)->AddEdge(j, drain); + } + } + + return result; +} +*/ +} diff --git a/src/converters/DFAToMinDFA.cpp b/src/converters/DFAToMinDFA.cpp new file mode 100644 index 0000000..2cc349c --- /dev/null +++ b/src/converters/DFAToMinDFA.cpp @@ -0,0 +1,111 @@ +#include "converters/DFAToMinDFA.hpp" +#include +#include + +namespace converters { +DFAGraph DFAToMinDFA(DFAGraph&& graph) { + const int n = graph.GetCountVertexes(); + DFAGraph result; + + std::vector alphabet; + + { + std::set salphabet; + for (int i = 0; i < n; ++i) { + for (auto i: graph.GetVertex(i)->GetTransitions()) { + salphabet.insert(i.first); + } + } + alphabet = std::vector(salphabet.begin(), salphabet.end()); + } + + std::vector>> table(n, + std::vector>(n, std::vector(alphabet.size() + 1))); + + { + std::vector>& layer(table[0]); + for (int i = 0; i < n; ++i) { + layer[i][0] = graph.GetVertex(i)->IsFinal(); + } + for (int i = 0; i < n; ++i) { + for (int j = 0; j < alphabet.size(); ++j) { + const auto& transitions = graph.GetVertex(i)->GetTransitions(); + if (transitions.count(alphabet[j])) + layer[i][j + 1] = layer[transitions.at(alphabet[j])][0]; + else + layer[i][j + 1] = -1; + } + } + } + + for (int number_layer = 1; number_layer < n; ++number_layer) { + size_t count_types = 0; + std::vector>& prev_layer(table[number_layer - 1]); + std::vector>& layer(table[number_layer]); + for (int i = 0; i < n; ++i) { + bool is_find = false; + for (int j = 0; j < i; ++j) { + if (prev_layer[j] == prev_layer[i]) { + layer[i][0] = layer[j][0]; + is_find = true; + break; + } + } + if (!is_find) { + layer[i][0] = count_types++; + } + } + for (int i = 0; i < n; ++i) { + for (int j = 0; j < alphabet.size(); ++j) { + const auto& transitions = graph.GetVertex(i)->GetTransitions(); + if (transitions.count(alphabet[j])) + layer[i][j + 1] = layer[transitions.at(alphabet[j])][0]; + else + layer[i][j + 1] = -1LL; + } + } + } + + /* + for (int i = 0; i < n; ++i) { + for (int k = 0; k < n; ++k) { + for (int j = 0; j < alphabet.size() + 1; ++j) { + std::cout << table[k][i][j] << " "; + } + std::cout << "| "; + } + std::cout << std::endl; + } + */ + + std::vector>& last_layer(table.back()); + size_t count_vertex = 0; + + for (int i = 0; i < n; ++i) { + count_vertex = std::max(count_vertex, last_layer[i][0]); + } + count_vertex++; + + std::map number_vertex_in_DFA; + for (int i = 0; i < count_vertex; ++i) { + number_vertex_in_DFA[i] = result.AddNewVertex(); + } + + for (int i = 0; i < n; ++i) { + size_t v = number_vertex_in_DFA[last_layer[i][0]]; + + const auto& transitions = graph.GetVertex(i)->GetTransitions(); + for (const auto& t: transitions) { + if (last_layer[t.second][0] != -1LL) { + size_t u = number_vertex_in_DFA[last_layer[t.second][0]]; + result.GetVertex(v)->AddEdge(t.first, u); + } + } + + if (graph.GetVertex(i)->IsStart()) result.GetVertex(v)->SetStart(true); + if (graph.GetVertex(i)->IsFinal()) result.GetVertex(v)->SetFinal(true); + } + + return result; +} +} diff --git a/src/converters/DFAToRegular.cpp b/src/converters/DFAToRegular.cpp new file mode 100644 index 0000000..c19834c --- /dev/null +++ b/src/converters/DFAToRegular.cpp @@ -0,0 +1,126 @@ +#include "converters/DFAToRegular.hpp" +#include +#include + +namespace converters { +std::string DFAGraphToRegular(DFAGraph&& graph) { + const size_t n = graph.GetCountVertexes() + 1; + std::string result = ""; + + std::vector>> transitions(n, + std::vector>(n)); + + std::map rename; + size_t start = -1; + + for (int i = 0; i < n - 1; ++i) { + if (!graph.GetVertex(i)) continue; + if (graph.GetVertex(i)->IsStart()) start = i; + } + + rename[start] = 1; + int cnt = 2; + + for (int i = 0; i < n - 1; ++i) { + if (i == start) continue; + rename[i] = cnt++; + } + + + for (int i = 0; i < n - 1; ++i) { + if (!graph.GetVertex(i)) continue; + const auto& vertex_transitions = graph.GetVertex(i)->GetTransitions(); + + for (auto j: vertex_transitions) { + transitions[rename[i]][rename[j.second]].insert(std::string(1, j.first)); + } + if (graph.GetVertex(i)->IsFinal()) { + transitions[rename[i]][0].insert("( )"); + } + } + + for (int i = n - 1; i > 1; --i) { + std::vector>> new_transitions(n, + std::vector>(n)); + std::string loop = ""; + if (transitions[i][i].size() != 0) { + for (const std::string s: transitions[i][i]) { + loop += "("; + loop += s; + loop += ")"; + loop += "|"; + } + if (loop.size()) + loop.pop_back(); + if (transitions[i][i].size() > 1) + loop = "(" + loop + ")*"; + else + loop += "*"; + } + + for (int j = 0; j < i; ++j) { + if (transitions[j][i].size() == 0) continue; + std::string j_to_i = ""; + for (const std::string s: transitions[j][i]) { + j_to_i += "("; + j_to_i += s; + j_to_i += ")"; + j_to_i += "|"; + } + if (j_to_i.size()) + j_to_i.pop_back(); + if (transitions[j][i].size() > 1) + j_to_i = "(" + j_to_i + ")"; + + for (int k = 0; k < i; ++k) { + if (transitions[i][k].size() == 0) continue; + std::string i_to_k = ""; + for (const std::string s: transitions[i][k]) { + i_to_k += "("; + i_to_k += s; + i_to_k += ")"; + i_to_k += "|"; + } + if (i_to_k.size()) + i_to_k.pop_back(); + if (transitions[i][k].size() > 1) + i_to_k = "(" + j_to_i + ")"; + + new_transitions[j][k].insert(j_to_i + loop + i_to_k); + } + } + + for (int j = 0; j < i; ++j) { + for (int k = 0; k < i; ++k) { + transitions[j][k].insert(new_transitions[j][k].begin(), new_transitions[j][k].end()); + } + } + } + + std::string loop; + std::string begin_to_end; + + if (transitions[1][1].size() != 0) { + for (const std::string s: transitions[1][1]) { + loop += "("; + loop += s; + loop += ")"; + loop += "|"; + } + if (loop.size()) + loop.pop_back(); + loop = "(" + loop + ")*"; + } + for (const std::string s: transitions[1][0]) { + begin_to_end += "("; + begin_to_end += s; + begin_to_end += ")"; + begin_to_end += "|"; + } + if (begin_to_end.size()) + begin_to_end.pop_back(); + + std::string res(loop + "(" + begin_to_end + ")"); + return res; +} +} diff --git a/src/converters/NFAToDFA.cpp b/src/converters/NFAToDFA.cpp new file mode 100644 index 0000000..c2ac47c --- /dev/null +++ b/src/converters/NFAToDFA.cpp @@ -0,0 +1,293 @@ +#include "converters/NFAToDFA.hpp" +#include +#include +#include + +namespace converters { +/* +OLD version + + +NFATree AddAllEpsilonTransitions(NFATree&& tree) { + // Algorithm from 2-sat + const int n = tree.GetCountVertexes(); + std::vector used(n, false); + std::vector component(n, -1); + std::vector order; + + std::function dfs_order = [&tree, &used, &order, &dfs_order](int v) -> void { + used[v] = true; + const auto& transitions = tree.GetVertex(v)->GetTransitions(); + if (transitions.count(' ')) { + const auto& s = transitions.at(' '); + for (auto i: s) { + if (!used[i]) { + dfs_order(i); + } + } + } + order.push_back(v); + }; + + std::function dfs_component = [&tree, &component, + &dfs_component](int v, int c) -> void { + component[v] = c; + const auto& transitions = tree.GetVertex(v)->GetBackTransitions(); + if (transitions.count(' ')) { + const auto& s = transitions.at(' '); + for (auto i: s) { + if (component[i] == -1) { + dfs_component(i, c); + } + } + } + }; + + for (int i = 0; i < n; ++i) { + if (!used[i] && tree.GetVertex(i)) { + dfs_order(i); + } + } + + int current_component = 0; + for (int i = 0; i < n; ++i) { + int v = order[n - i - 1]; + if (component[v] == -1 && tree.GetVertex(i)) { + dfs_component(v, current_component++); + } + } + + std::set> connectivity_components; + + used.assign(n, false); + std::vector> connectivity_from(current_component); + + std::function dfs_connectivity = [&tree, &component, + &used, &dfs_connectivity, &connectivity_from](int v) -> void { + used[v] = true; + const auto& transitions = tree.GetVertex(v)->GetTransitions(); + if (transitions.count(' ')) { + const auto& s = transitions.at(' '); + for (auto i: s) { + if (!used[i]) { + dfs_connectivity(i); + } + if (component[v] != component[i]) { + connectivity_from[component[v]].insert(connectivity_from[component[i]].begin(), + connectivity_from[component[i]].end()); + connectivity_from[component[v]].insert(component[i]); + } + } + } + }; + + for (int i = 0; i < n; ++i) { + if (!tree.GetVertex(i)) continue; + connectivity_components.emplace(component[i], component[i]); + if (!used[i]) { + dfs_connectivity(i); + } + for (int j: connectivity_from[component[i]]) { + std::cout << i << " " << j << std::endl; + connectivity_components.emplace(component[i], j); + } + } + + for (int i = 0; i < n; ++i) { + std::cout << component[i] << " "; + } + std::cout << std::endl; + for (int i: connectivity_from[1]) { + std::cout << i << " "; + } + std::cout << std::endl; + + + + for (int i = 0; i < n; ++i) { + for (int j = 0; j < n; ++j) { + if (i == j) continue; + if (connectivity_components.count(std::make_pair(component[i], component[j]))) { + tree.GetVertex(i)->AddEdge(' ', j); + } + } + } + + return std::move(tree); +} +*/ + +NFATree AddAllEpsilonTransitions(NFATree&& tree) { + const int n = tree.GetCountVertexes(); + std::vector used(n, false); + + std::function dfs = [&tree, &used, &dfs](int u, int v) -> void { + used[v] = true; + const auto& transitions = tree.GetVertex(v)->GetTransitions(); + if (transitions.count(' ')) { + const auto& s = transitions.at(' '); + for (auto i: s) { + if (!used[i]) { + if (u != i) + tree.GetVertex(u)->AddEdge(' ', i); + dfs(u, i); + } + } + } + }; + + for (int i = 0; i < n; ++i) { + if (!tree.GetVertex(i)) continue; + + used.assign(n, false); + dfs(i, i); + } + return std::move(tree); +} + +NFATree AddAllPossibleStartFilnal(NFATree&& tree) { + if (tree.GetStartVertexes().size() != 1) { + size_t start_vertex = tree.AddNewVertex(); + for (auto v: tree.GetStartVertexes()) { + tree.GetVertex(start_vertex)->AddEdge(' ', v); + } + } + for (const auto& v: tree.GetFinalVertexes()) { + const auto& transitions = tree.GetVertex(v)->GetBackTransitions(); + if (transitions.count(' ')) { + const auto& s = transitions.at(' '); + for (auto i: s) { + tree.GetVertex(i)->SetFinal(true); + } + } + } + return std::move(tree); +} + +NFATree DeleteEpsilonTransitions(NFATree&& tree) { + const int n = tree.GetCountVertexes(); + + for (int v = 0; v < n; ++v) { + if (!tree.GetVertex(v)) continue; + + const auto& transitions = tree.GetVertex(v)->GetTransitions(); + if (transitions.count(' ')) { + auto s = transitions.at(' '); + for (auto u: s) { + for (auto& i: tree.GetVertex(u)->GetTransitions()) { + if (i.first == ' ') continue; + for (auto t: i.second) { + tree.GetVertex(v)->AddEdge(i.first, t); + } + } + } + for (auto u: s) { + tree.GetVertex(v)->RemoveEdge(' ', u); + } + } + } + return std::move(tree); +} + +NFATree DeleteTransitionsByOneLetter(NFATree&& tree) { + const int n = tree.GetCountVertexes(); + + NFATree result_tree; + + std::map, char>, std::set> transitions; + std::map, size_t> number_vertex_in_result_tree; + std::queue> queue; + + std::set alphabet; + for (int i = 0; i < n; ++i) { + if (!tree.GetVertex(i)) continue; + for (const auto& j: tree.GetVertex(i)->GetTransitions()) { + if (j.second.size() > 0) + alphabet.insert(j.first); + } + } + + for (auto i: tree.GetStartVertexes()) { + queue.push({i}); + number_vertex_in_result_tree[{i}] = result_tree.AddNewVertex(); + } + + while (!queue.empty()) { + auto current = queue.front(); + queue.pop(); + + for (auto symbol: alphabet) { + std::set result; + for (auto v: current) { + const auto& transitions = tree.GetVertex(v)->GetTransitions(); + if (transitions.count(symbol)) { + const auto& s = transitions.at(symbol); + result.insert(s.begin(), s.end()); + } + } + + if (result.size() == 0) continue; + + transitions[std::make_pair(current, symbol)] = result; + if (!number_vertex_in_result_tree.count(result)) { + queue.push(result); + number_vertex_in_result_tree[result] = result_tree.AddNewVertex(); + } + } + } + + for (auto i: transitions) { + int v = number_vertex_in_result_tree[i.first.first]; + int u = number_vertex_in_result_tree[i.second]; + char symbol = i.first.second; + result_tree.GetVertex(v)->AddEdge(symbol, u); + } + + for (auto i: number_vertex_in_result_tree) { + auto s = i.first; + auto v = i.second; + + for (auto i: s) { + if (tree.GetVertex(i)->IsFinal()) + result_tree.GetVertex(v)->SetFinal(true); + if (tree.GetVertex(i)->IsStart()) + result_tree.GetVertex(v)->SetStart(true); + } + } + + return result_tree; +} + +DFAGraph NFATreeToDFAGraph(NFATree&& tree) { + /* + tree = AddAllEpsilonTransitions(std::move(tree)); + tree = AddAllPossibleStartFilnal(std::move(tree)); + tree = DeleteEpsilonTransitions(std::move(tree)); + tree = DeleteTransitionsByOneLetter(std::move(tree)); + */ + tree = DeleteTransitionsByOneLetter(DeleteEpsilonTransitions(AddAllPossibleStartFilnal( + AddAllEpsilonTransitions(std::move(tree))))); + + const int n = tree.GetCountVertexes(); + DFAGraph result; + std::map number_vertex_in_DFA; + for (int i = 0; i < n; ++i) { + if (!tree.GetVertex(i)) continue; + number_vertex_in_DFA[i] = result.AddNewVertex(); + } + for (int i = 0; i < n; ++i) { + if (!tree.GetVertex(i)) continue; + if (tree.GetVertex(i)->IsFinal()) + result.GetVertex(number_vertex_in_DFA[i])->SetFinal(true); + if (tree.GetVertex(i)->IsStart()) + result.GetVertex(number_vertex_in_DFA[i])->SetStart(true); + + const auto& transitions = tree.GetVertex(i)->GetTransitions(); + for (const auto& t: transitions) { + if (t.second.size() != 1) throw std::logic_error(""); + result.GetVertex(number_vertex_in_DFA[i])->AddEdge(t.first, *t.second.begin()); + } + } + return result; +} +} diff --git a/src/converters/RegularToNFA.cpp b/src/converters/RegularToNFA.cpp index 12e3c7c..54c59b2 100644 --- a/src/converters/RegularToNFA.cpp +++ b/src/converters/RegularToNFA.cpp @@ -1,6 +1,7 @@ #include "converters/RegularToNFA.hpp" #include "regular/RegularTree.hpp" #include "NFA/NFATree.hpp" +#include using namespace NFA; using namespace regular; @@ -15,14 +16,21 @@ template NFATree RegularToNFA(std::unique_ptr node) { NFATree result; if (node->type == Node::Type::Word) { - auto last = result.AddNewVertex(); - result.AddStartVertex(last); + auto end = result.AddNewVertex(); + auto start = end; + result.AddStartVertex(end); for (char i: node->word) { auto tmp = result.AddNewVertex(); - result.GetVertex(last)->transitions.emplace(i, tmp); - last = tmp; + result.GetVertex(end)->AddEdge(i, tmp); + end = tmp; } - result.AddFinalVertex(last); + if (node->modifier == Node::Modifier::Plus) { + result.GetVertex(end)->AddEdge(' ', start); + } else if (node->modifier == Node::Modifier::Star) { + result.GetVertex(end)->AddEdge(' ', start); + result.GetVertex(start)->AddEdge(' ', end); + } + result.AddFinalVertex(end); } else if (node->type == Node::Type::Concatenation) { result = RegularToNFA(std::move(node->children[0])); for (auto it = node->children.begin() + 1; it != node->children.end(); ++it) { @@ -34,9 +42,39 @@ NFATree RegularToNFA(std::unique_ptr node) { } result.AddFinalVertex(v); } + const auto& start_vertexes = result.GetStartVertexes(); + const auto& end_vertexes = result.GetFinalVertexes(); + + if (node->modifier == Node::Modifier::Plus) { + for (auto start: start_vertexes) { + for (auto end: end_vertexes) { + result.GetVertex(end)->AddEdge(' ', start); + } + } + } else if (node->modifier == Node::Modifier::Star) { + for (auto start: start_vertexes) { + for (auto end: end_vertexes) { + result.GetVertex(end)->AddEdge(' ', start); + result.GetVertex(start)->AddEdge(' ', end); + } + } + } } else if (node->type == Node::Type::Addition) { - // TODO + auto start = result.AddNewVertex(); + result.AddStartVertex(start); + auto end = result.AddNewVertex(); + result.AddFinalVertex(end); + for (auto& i: node->children) { + auto tmp = RegularToNFA(std::move(i)); + result.Composition(std::move(tmp), {start}, {end}); + } + if (node->modifier == Node::Modifier::Plus) { + result.GetVertex(end)->AddEdge(' ', start); + } else if (node->modifier == Node::Modifier::Star) { + result.GetVertex(end)->AddEdge(' ', start); + result.GetVertex(start)->AddEdge(' ', end); + } } return result; } diff --git a/src/main.cpp b/src/main.cpp index 3253512..0f1f819 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,9 +1,163 @@ #include +#include #include "regular/RegularTree.hpp" #include "converters/RegularToNFA.hpp" +#include "converters/NFAToDFA.hpp" +#include "converters/DFAToFDFA.hpp" +#include "converters/DFAToMinDFA.hpp" +#include "converters/DFAToRegular.hpp" + +using namespace regular; +using namespace regular; +using namespace NFA; +using namespace DFA; +using namespace converters; int main() { - using namespace regular; + { + RegularTree r("a*"); + NFATree NFA_tree = RegularToNFA(std::move(r)); + DFAGraph DFA_graph = NFATreeToDFAGraph(std::move(NFA_tree)); + DFA_graph = DFAToMinDFA(std::move(DFA_graph)); + DFA_graph.Print(); + + std::string reg = DFAGraphToRegular(std::move(DFA_graph)); + + r = RegularTree(reg); + NFA_tree = RegularToNFA(std::move(r)); + DFA_graph = NFATreeToDFAGraph(std::move(NFA_tree)); + DFA_graph = DFAToMinDFA(std::move(DFA_graph)); + DFA_graph.Print(); + } + + return 0; + + + { + RegularTree r("a+"); + r.Print(); + NFA::NFATree NFA_tree = converters::RegularToNFA(std::move(r)); + NFA_tree.Print(); + DFA::DFAGraph DFA_graph = converters::NFATreeToDFAGraph(std::move(NFA_tree)); + DFA_graph.Print(); + DFA_graph = DFAToMinDFA(std::move(DFA_graph)); + DFA_graph.Print(); + } + + return 0; + NFA::NFATree 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::NFATreeToDFAGraph(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::DFAToMinDFA(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); diff --git a/src/regular/RegularTreeNode.cpp b/src/regular/RegularTreeNode.cpp index 3939d17..f103293 100644 --- a/src/regular/RegularTreeNode.cpp +++ b/src/regular/RegularTreeNode.cpp @@ -16,7 +16,6 @@ void Node::Print() const { } void Node::ParseCurrentType(const std::string_view regular) { - std::cout << "# " << regular << std::endl; const size_t n = regular.size(); children.clear(); word.clear(); @@ -82,8 +81,8 @@ void Node::ParseCurrentType(const std::string_view regular) { if (balance == 1) { if (begin_child < i) { AddChild(regular.substr(begin_child, i - begin_child)); - begin_child = i + 1; } + begin_child = i + 1; } } else if (regular[i] == ')') { --balance; @@ -95,12 +94,27 @@ void Node::ParseCurrentType(const std::string_view regular) { if (balance != 0) { throw std::logic_error("invalid regular"); } + if (children.size() == 0) { type = Type::Word; break; } else { - AddChild(regular.substr(begin_child, i - begin_child + 1)); - begin_child = i + 1; + if (regular[i] == '+') { + if (begin_child < i) { + AddChild(regular.substr(begin_child, i - begin_child)); + } + children.back()->modifier = Modifier::Plus; + begin_child = i + 1; + } else if (regular[i] == '*') { + if (begin_child < i) { + AddChild(regular.substr(begin_child, i - begin_child)); + } + children.back()->modifier = Modifier::Star; + begin_child = i + 1; + } else { + AddChild(regular.substr(begin_child, i - begin_child + 1)); + begin_child = i + 1; + } } } else if (balance == 0) { if (regular[i] == '+') { diff --git a/tests/DFAToRegular/DFAToRegular.cpp b/tests/DFAToRegular/DFAToRegular.cpp new file mode 100644 index 0000000..01c465e --- /dev/null +++ b/tests/DFAToRegular/DFAToRegular.cpp @@ -0,0 +1,202 @@ +#include +#include +#include "regular/RegularTree.hpp" +#include "converters/RegularToNFA.hpp" +#include "converters/NFAToDFA.hpp" +#include "converters/DFAToMinDFA.hpp" +#include "converters/DFAToRegular.hpp" + +using namespace regular; +using namespace NFA; +using namespace DFA; +using namespace converters; + +extern std::mt19937 rnd; + +extern std::string GenerateRandomString(std::vector alphabet, size_t len); + +TEST(DFA_to_regular, a_star) { + RegularTree r("a*"); + NFATree NFA_tree = RegularToNFA(std::move(r)); + DFAGraph DFA_graph = NFATreeToDFAGraph(std::move(NFA_tree)); + DFA_graph = DFAToMinDFA(std::move(DFA_graph)); + + std::string reg = DFAGraphToRegular(std::move(DFA_graph)); + + r = RegularTree(reg); + NFA_tree = RegularToNFA(std::move(r)); + DFA_graph = NFATreeToDFAGraph(std::move(NFA_tree)); + DFA_graph = DFAToMinDFA(std::move(DFA_graph)); + + + std::string s = ""; + for (int i = 0; i < 100; ++i) { + ASSERT_EQ(DFA_graph.Accepted(s), true); + s += "a"; + } +} + +TEST(DFA_to_regular, a_plus) { + std::string regulars[] = {"a+", "(a)+", "(a+)"}; + for (const auto& regular: regulars) { + RegularTree r(regular); + NFATree NFA_tree = RegularToNFA(std::move(r)); + DFAGraph DFA_graph = NFATreeToDFAGraph(std::move(NFA_tree)); + DFA_graph = DFAToMinDFA(std::move(DFA_graph)); + + std::string reg = DFAGraphToRegular(std::move(DFA_graph)); + + r = RegularTree(reg); + NFA_tree = RegularToNFA(std::move(r)); + DFA_graph = NFATreeToDFAGraph(std::move(NFA_tree)); + DFA_graph = DFAToMinDFA(std::move(DFA_graph)); + + std::string s = ""; + ASSERT_EQ(DFA_graph.Accepted(s), false); + s += "a"; + for (int i = 0; i < 100; ++i) { + ASSERT_EQ(DFA_graph.Accepted(s), true); + s += "a"; + } + } +} + +TEST(DFA_to_regular, abc) { + std::string regulars[] = {"abc"}; + for (const auto& regular: regulars) { + RegularTree r(regular); + NFATree NFA_tree = RegularToNFA(std::move(r)); + DFAGraph DFA_graph = NFATreeToDFAGraph(std::move(NFA_tree)); + DFA_graph = DFAToMinDFA(std::move(DFA_graph)); + + std::string reg = DFAGraphToRegular(std::move(DFA_graph)); + + r = RegularTree(reg); + NFA_tree = RegularToNFA(std::move(r)); + DFA_graph = NFATreeToDFAGraph(std::move(NFA_tree)); + DFA_graph = DFAToMinDFA(std::move(DFA_graph)); + + ASSERT_EQ(DFA_graph.Accepted("abc"), true); + 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), false); + } + } +} + +TEST(DFA_to_regular, a_or_b_or_c) { + std::string regulars[] = {}; + for (const auto& regular: regulars) { + RegularTree r("a|b|c"); + NFATree NFA_tree = RegularToNFA(std::move(r)); + DFAGraph DFA_graph = NFATreeToDFAGraph(std::move(NFA_tree)); + DFA_graph = DFAToMinDFA(std::move(DFA_graph)); + + std::string reg = DFAGraphToRegular(std::move(DFA_graph)); + + r = RegularTree(reg); + NFA_tree = RegularToNFA(std::move(r)); + DFA_graph = NFATreeToDFAGraph(std::move(NFA_tree)); + DFA_graph = DFAToMinDFA(std::move(DFA_graph)); + + ASSERT_EQ(DFA_graph.Accepted("a"), true); + ASSERT_EQ(DFA_graph.Accepted("b"), true); + ASSERT_EQ(DFA_graph.Accepted("c"), true); + 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), false); + } + } +} + +TEST(DFA_to_regular, 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); + NFATree NFA_tree = RegularToNFA(std::move(r)); + DFAGraph DFA_graph = NFATreeToDFAGraph(std::move(NFA_tree)); + DFA_graph = DFAToMinDFA(std::move(DFA_graph)); + + std::string reg = DFAGraphToRegular(std::move(DFA_graph)); + + r = RegularTree(reg); + NFA_tree = RegularToNFA(std::move(r)); + DFA_graph = NFATreeToDFAGraph(std::move(NFA_tree)); + DFA_graph = DFAToMinDFA(std::move(DFA_graph)); + + auto check = [](const std::string str) { + std::set 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(""), true); + 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(DFA_to_regular, _a_star_or_b_star_or_c_star_plus) { + RegularTree r("(a*|b*|c*)+"); + NFATree NFA_tree = RegularToNFA(std::move(r)); + DFAGraph DFA_graph = NFATreeToDFAGraph(std::move(NFA_tree)); + DFA_graph = DFAToMinDFA(std::move(DFA_graph)); + + std::string reg = DFAGraphToRegular(std::move(DFA_graph)); + + r = RegularTree(reg); + NFA_tree = RegularToNFA(std::move(r)); + DFA_graph = NFATreeToDFAGraph(std::move(NFA_tree)); + DFA_graph = DFAToMinDFA(std::move(DFA_graph)); + + auto check = [](const std::string str) { + std::set s(str.begin(), str.end()); + return s.find('d') == s.end(); + }; + + ASSERT_EQ(DFA_graph.Accepted(""), true); + 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(DFA_to_regular, _a_or_b_or_c_star_plus) { + RegularTree r("(a|b|c*)+"); + NFATree NFA_tree = RegularToNFA(std::move(r)); + DFAGraph DFA_graph = NFATreeToDFAGraph(std::move(NFA_tree)); + DFA_graph = DFAToMinDFA(std::move(DFA_graph)); + + std::string reg = DFAGraphToRegular(std::move(DFA_graph)); + + r = RegularTree(reg); + NFA_tree = RegularToNFA(std::move(r)); + DFA_graph = NFATreeToDFAGraph(std::move(NFA_tree)); + DFA_graph = DFAToMinDFA(std::move(DFA_graph)); + + auto check = [](const std::string str) { + std::set s(str.begin(), str.end()); + return s.find('d') == s.end(); + }; + + ASSERT_EQ(DFA_graph.Accepted(""), true); + for (int i = 0; i < 1000; ++i) { + auto s = GenerateRandomString({'a', 'b', 'c', 'd'}, rnd() % 10); + + ASSERT_EQ(DFA_graph.Accepted(s), check(s)); + } +} diff --git a/tests/NFAToDFA/check_equivalence.cpp b/tests/NFAToDFA/check_equivalence.cpp new file mode 100644 index 0000000..579632c --- /dev/null +++ b/tests/NFAToDFA/check_equivalence.cpp @@ -0,0 +1,111 @@ +#include +#include +#include "DFA/DFAGraph.hpp" +#include "NFA/NFATree.hpp" +#include "converters/NFAToDFA.hpp" + +using namespace NFA; +using namespace DFA; +using namespace converters; + +std::mt19937 rnd(1337); + +std::string GenerateRandomString(std::vector alphabet, size_t len) { + std::string res(len, ' '); + for (auto& i: res) { + i = alphabet[rnd() % alphabet.size()]; + } + return res; +} + +TEST(check_equivalence_NFA_to_DFA, 1) { + NFA::NFATree tree; + + const int N = 10; + int a[N]; + for (int i = 0; i < N; ++i) + a[i] = tree.AddNewVertex(); + + tree.GetVertex(a[0])->AddEdge('a', a[1]); + tree.GetVertex(a[1])->AddEdge('a', a[2]); + tree.GetVertex(a[0])->AddEdge('a', a[3]); + + tree.GetVertex(a[0])->SetStart(true); + tree.GetVertex(a[2])->SetFinal(true); + tree.GetVertex(a[3])->SetFinal(true); + + DFA::DFAGraph res = converters::NFATreeToDFAGraph(std::move(tree)); + + EXPECT_FALSE(res.Accepted("")); + EXPECT_TRUE(res.Accepted("a")); + EXPECT_TRUE(res.Accepted("aa")); + EXPECT_FALSE(res.Accepted("aaa")); + EXPECT_FALSE(res.Accepted("aaaa")); + EXPECT_FALSE(res.Accepted("aaaaa")); + EXPECT_FALSE(res.Accepted("b")); +} + +TEST(check_equivalence_NFA_to_DFA, 2) { + NFA::NFATree tree; + + const int N = 10; + int a[N]; + for (int i = 0; i < N; ++i) + a[i] = tree.AddNewVertex(); + + 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); + + DFA::DFAGraph res = converters::NFATreeToDFAGraph(std::move(tree)); + + auto check = [](const std::string& str) { + if (str.size() > 0) { + if (str[0] == 'a') { + if (str.size() == 1) { + return true; + } + if (str[1] == 'b') { + for (int i = 1; i < str.size(); ++i) { + if (str[i] != 'b') { + return false; + } + } + return true; + } + if (str[1] == 'c') { + for (int i = 1; i < str.size(); ++i) { + if (str[i] != 'c') { + return false; + } + } + return true; + } + } + } + + return false; + }; + + EXPECT_FALSE(res.Accepted("")); + EXPECT_TRUE(res.Accepted("a")); + EXPECT_FALSE(res.Accepted("aa")); + EXPECT_FALSE(res.Accepted("aaa")); + EXPECT_FALSE(res.Accepted("aaaa")); + EXPECT_FALSE(res.Accepted("aaaaa")); + EXPECT_FALSE(res.Accepted("b")); + EXPECT_TRUE(res.Accepted("ab")); + EXPECT_TRUE(res.Accepted("abb")); + EXPECT_TRUE(res.Accepted("ac")); + EXPECT_TRUE(res.Accepted("acc")); + + for (int i = 0; i < 5000; ++i) { + auto str = GenerateRandomString({'a', 'b', 'c', 'd'}, 20); + ASSERT_EQ(res.Accepted(str), check(str)); + } +} diff --git a/tests/regularToDFA/regularToDFA.cpp b/tests/regularToDFA/regularToDFA.cpp new file mode 100644 index 0000000..3d157a1 --- /dev/null +++ b/tests/regularToDFA/regularToDFA.cpp @@ -0,0 +1,151 @@ +#include +#include +#include "regular/RegularTree.hpp" +#include "converters/RegularToNFA.hpp" +#include "converters/NFAToDFA.hpp" +#include "converters/DFAToMinDFA.hpp" + +using namespace regular; +using namespace NFA; +using namespace DFA; +using namespace converters; + +extern std::mt19937 rnd; + +extern std::string GenerateRandomString(std::vector alphabet, size_t len); + +TEST(regular_to_DFA, a_star) { + RegularTree r("a*"); + NFATree NFA_tree = RegularToNFA(std::move(r)); + DFAGraph DFA_graph = NFATreeToDFAGraph(std::move(NFA_tree)); + DFA_graph = DFAToMinDFA(std::move(DFA_graph)); + + std::string s = ""; + for (int i = 0; i < 100; ++i) { + ASSERT_EQ(DFA_graph.Accepted(s), true); + s += "a"; + } +} + +TEST(regular_to_DFA, a_plus) { + std::string regulars[] = {"a+", "(a)+", "(a+)"}; + for (const auto& regular: regulars) { + RegularTree r(regular); + NFATree NFA_tree = RegularToNFA(std::move(r)); + DFAGraph DFA_graph = NFATreeToDFAGraph(std::move(NFA_tree)); + DFA_graph = DFAToMinDFA(std::move(DFA_graph)); + + std::string s = ""; + ASSERT_EQ(DFA_graph.Accepted(s), false); + s += "a"; + for (int i = 0; i < 100; ++i) { + ASSERT_EQ(DFA_graph.Accepted(s), true); + s += "a"; + } + } +} + +TEST(regular_to_DFA, abc) { + std::string regulars[] = {"abc"}; + for (const auto& regular: regulars) { + RegularTree r(regular); + NFATree NFA_tree = RegularToNFA(std::move(r)); + DFAGraph DFA_graph = NFATreeToDFAGraph(std::move(NFA_tree)); + DFA_graph = DFAToMinDFA(std::move(DFA_graph)); + + ASSERT_EQ(DFA_graph.Accepted("abc"), true); + 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), false); + } + } +} + +TEST(regular_to_DFA, a_or_b_or_c) { + std::string regulars[] = {}; + for (const auto& regular: regulars) { + RegularTree r("a|b|c"); + NFATree NFA_tree = RegularToNFA(std::move(r)); + DFAGraph DFA_graph = NFATreeToDFAGraph(std::move(NFA_tree)); + DFA_graph = DFAToMinDFA(std::move(DFA_graph)); + + ASSERT_EQ(DFA_graph.Accepted("a"), true); + ASSERT_EQ(DFA_graph.Accepted("b"), true); + ASSERT_EQ(DFA_graph.Accepted("c"), true); + 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), false); + } + } +} + +TEST(regular_to_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); + NFATree NFA_tree = RegularToNFA(std::move(r)); + DFAGraph DFA_graph = NFATreeToDFAGraph(std::move(NFA_tree)); + DFA_graph = DFAToMinDFA(std::move(DFA_graph)); + + auto check = [](const std::string str) { + std::set 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(""), true); + 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(regular_to_DFA, _a_star_or_b_star_or_c_star_plus) { + RegularTree r("(a*|b*|c*)+"); + NFATree NFA_tree = RegularToNFA(std::move(r)); + DFAGraph DFA_graph = NFATreeToDFAGraph(std::move(NFA_tree)); + DFA_graph = DFAToMinDFA(std::move(DFA_graph)); + + auto check = [](const std::string str) { + std::set s(str.begin(), str.end()); + return s.find('d') == s.end(); + }; + + ASSERT_EQ(DFA_graph.Accepted(""), true); + 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(regular_to_DFA, _a_or_b_or_c_star_plus) { + RegularTree r("(a|b|c*)+"); + NFATree NFA_tree = RegularToNFA(std::move(r)); + DFAGraph DFA_graph = NFATreeToDFAGraph(std::move(NFA_tree)); + DFA_graph = DFAToMinDFA(std::move(DFA_graph)); + + auto check = [](const std::string str) { + std::set s(str.begin(), str.end()); + return s.find('d') == s.end(); + }; + + ASSERT_EQ(DFA_graph.Accepted(""), true); + for (int i = 0; i < 1000; ++i) { + auto s = GenerateRandomString({'a', 'b', 'c', 'd'}, rnd() % 10); + + ASSERT_EQ(DFA_graph.Accepted(s), check(s)); + } +} From 1fd415884033e044f9856f262320f7b8398b059f Mon Sep 17 00:00:00 2001 From: MaxanRus Date: Tue, 5 Oct 2021 16:11:24 +0300 Subject: [PATCH 08/17] refactor --- CMakeLists.txt | 4 +- include/FDFA/FDFAGraph.hpp | 67 ------- include/NFA/{NFATree.hpp => NFAGraph.hpp} | 22 +-- include/converters/DFAToFDFA.hpp | 3 - include/converters/DFAToMinDFA.hpp | 2 +- include/converters/NFAToDFA.hpp | 12 +- include/converters/RegularToNFA.hpp | 4 +- include/regular/RegularTree.hpp | 1 - src/DFA/DFAGraphVertex.cpp | 1 - src/FDFA/FDFAGraph.cpp | 98 ----------- src/FDFA/FDFAGraphVertex.cpp | 58 ------ src/NFA/{NFATree.cpp => NFAGraph.cpp} | 36 ++-- src/NFA/NFATreeVertex.cpp | 9 +- src/converters/DFAToFDFA.cpp | 44 ----- src/converters/DFAToMinDFA.cpp | 10 +- src/converters/DFAToRegular.cpp | 2 - src/converters/NFAToDFA.cpp | 205 +++++----------------- src/converters/RegularToNFA.cpp | 9 +- src/main.cpp | 26 +-- tests/DFAToRegular/DFAToRegular.cpp | 84 ++++----- tests/NFAToDFA/check_equivalence.cpp | 10 +- tests/regularToDFA/regularToDFA.cpp | 42 ++--- 22 files changed, 175 insertions(+), 574 deletions(-) delete mode 100644 include/FDFA/FDFAGraph.hpp rename include/NFA/{NFATree.hpp => NFAGraph.hpp} (81%) delete mode 100644 src/FDFA/FDFAGraph.cpp delete mode 100644 src/FDFA/FDFAGraphVertex.cpp rename src/NFA/{NFATree.cpp => NFAGraph.cpp} (82%) diff --git a/CMakeLists.txt b/CMakeLists.txt index 21991db..6ebfd89 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -18,14 +18,12 @@ set(CMAKE_CXX_STANDARD 17) set(SOURCE_FILES src/regular/RegularTree.cpp src/regular/RegularTreeNode.cpp - src/NFA/NFATree.cpp + src/NFA/NFAGraph.cpp src/NFA/NFATreeVertex.cpp src/converters/RegularToNFA.cpp src/converters/NFAToDFA.cpp src/DFA/DFAGraph.cpp src/DFA/DFAGraphVertex.cpp - # src/FDFA/FDFAGraph.cpp - # src/FDFA/FDFAGraphVertex.cpp src/converters/DFAToFDFA.cpp src/converters/DFAToMinDFA.cpp src/converters/DFAToRegular.cpp diff --git a/include/FDFA/FDFAGraph.hpp b/include/FDFA/FDFAGraph.hpp deleted file mode 100644 index 591a50f..0000000 --- a/include/FDFA/FDFAGraph.hpp +++ /dev/null @@ -1,67 +0,0 @@ -#pragma once -#include -#include -#include -#include - -namespace FDFA { -class FDFAGraph { - public: - class Vertex { - public: - Vertex(FDFAGraph* owner); - - bool IsFinal() const; - bool IsStart() const; - size_t GetNumber() const; - - const std::map& GetTransitions() const; - const std::map& GetBackTransitions() const; - - void AddEdge(char, size_t); - void RemoveEdge(char); - void SetOwner(FDFAGraph* owner); - void SetFinal(bool status); - void SetStart(bool status); - private: - FDFAGraph* owner_; - std::map transitions_; - std::map back_transitions_; - - size_t number_; - bool is_final_ = false; - bool is_start_ = false; - - friend class FDFAGraph; - }; - - FDFAGraph() = default; - FDFAGraph(const FDFAGraph&) = delete; - FDFAGraph(FDFAGraph&&) = default; - - FDFAGraph& operator=(const FDFAGraph&) = delete; - FDFAGraph& operator=(FDFAGraph&&) = default; - - size_t AddNewVertex(); - void AddFinalVertex(size_t number); - void AddStartVertex(size_t number); - - void RemoveVertex(size_t number); - void RemoveFinalVertex(size_t number); - void RemoveStartVertex(size_t number); - - std::shared_ptr GetVertex(size_t number); - - size_t GetCountVertexes() const; - const std::vector& GetFinalVertexes() const; - const std::vector& GetStartVertexes() const; - - void Print() const; - bool Accepted(const std::string&) const; - private: - size_t count_vertexes_ = 0; - std::map> vertexes_; - std::vector final_vertexes_; - std::vector start_vertexes_; -}; -} diff --git a/include/NFA/NFATree.hpp b/include/NFA/NFAGraph.hpp similarity index 81% rename from include/NFA/NFATree.hpp rename to include/NFA/NFAGraph.hpp index 02e0d56..abbabaf 100644 --- a/include/NFA/NFATree.hpp +++ b/include/NFA/NFAGraph.hpp @@ -6,11 +6,11 @@ #include namespace NFA { -class NFATree { +class NFAGraph { public: class Vertex { public: - Vertex(NFATree* owner); + Vertex(NFAGraph* owner); bool IsFinal() const; bool IsStart() const; @@ -21,11 +21,11 @@ class NFATree { void AddEdge(char, size_t); void RemoveEdge(char, size_t); - void SetOwner(NFATree* owner); + void SetOwner(NFAGraph* owner); void SetFinal(bool status); void SetStart(bool status); private: - NFATree* owner_; + NFAGraph* owner_; std::map> transitions_; std::map> back_transitions_; @@ -33,15 +33,15 @@ class NFATree { bool is_final_ = false; bool is_start_ = false; - friend class NFATree; + friend class NFAGraph; }; - NFATree() = default; - NFATree(const NFATree&) = delete; - NFATree(NFATree&&); + NFAGraph() = default; + NFAGraph(const NFAGraph&) = delete; + NFAGraph(NFAGraph&&); - NFATree& operator=(const NFATree&) = delete; - NFATree& operator=(NFATree&&); + NFAGraph& operator=(const NFAGraph&) = delete; + NFAGraph& operator=(NFAGraph&&); size_t AddNewVertex(); void AddFinalVertex(size_t number); @@ -51,7 +51,7 @@ class NFATree { void RemoveFinalVertex(size_t number); void RemoveStartVertex(size_t number); - void Composition(NFATree&&, + void Composition(NFAGraph&&, std::vector start_vertexes, std::vector final_vertexes); diff --git a/include/converters/DFAToFDFA.hpp b/include/converters/DFAToFDFA.hpp index bdf1eda..915d51c 100644 --- a/include/converters/DFAToFDFA.hpp +++ b/include/converters/DFAToFDFA.hpp @@ -1,10 +1,7 @@ #pragma once #include "DFA/DFAGraph.hpp" -#include "FDFA/FDFAGraph.hpp" namespace converters { using namespace DFA; -using namespace FDFA; DFAGraph DFAGraphToFDFAGraph(DFAGraph&&, const std::vector& alphabet); -// FDFAGraph DFAGraphToFDFAGraph(DFAGraph&&, const std::vector& alphabet); } diff --git a/include/converters/DFAToMinDFA.hpp b/include/converters/DFAToMinDFA.hpp index dd25402..9791c83 100644 --- a/include/converters/DFAToMinDFA.hpp +++ b/include/converters/DFAToMinDFA.hpp @@ -3,5 +3,5 @@ namespace converters { using namespace DFA; -DFAGraph DFAToMinDFA(DFAGraph&&); +DFAGraph DFAGraphToMinDFAGraph(DFAGraph&&); } diff --git a/include/converters/NFAToDFA.hpp b/include/converters/NFAToDFA.hpp index ecb0669..4dd51eb 100644 --- a/include/converters/NFAToDFA.hpp +++ b/include/converters/NFAToDFA.hpp @@ -1,13 +1,13 @@ #pragma once -#include "NFA/NFATree.hpp" +#include "NFA/NFAGraph.hpp" #include "DFA/DFAGraph.hpp" namespace converters { using namespace NFA; using namespace DFA; -NFATree AddAllEpsilonTransitions(NFATree&&); -NFATree AddAllPossibleStartFilnal(NFATree&&); -NFATree DeleteEpsilonTransitions(NFATree&&); -NFATree DeleteTransitionsByOneLetter(NFATree&&); -DFAGraph NFATreeToDFAGraph(NFATree&&); +NFAGraph AddAllEpsilonTransitions(NFAGraph&&); +NFAGraph AddAllPossibleStartFinal(NFAGraph&&); +NFAGraph DeleteEpsilonTransitions(NFAGraph&&); +NFAGraph DeleteTransitionsByOneLetter(NFAGraph&&); +DFAGraph NFAGraphToDFAGraph(NFAGraph&&); } diff --git a/include/converters/RegularToNFA.hpp b/include/converters/RegularToNFA.hpp index d4dd5f9..dce3ef0 100644 --- a/include/converters/RegularToNFA.hpp +++ b/include/converters/RegularToNFA.hpp @@ -1,10 +1,10 @@ #pragma once #include "regular/RegularTree.hpp" -#include "NFA/NFATree.hpp" +#include "NFA/NFAGraph.hpp" namespace converters { using namespace NFA; using namespace regular; -NFATree RegularToNFA(RegularTree&&); +NFAGraph RegularToNFAGraph(RegularTree&&); } diff --git a/include/regular/RegularTree.hpp b/include/regular/RegularTree.hpp index d6c031e..a564142 100644 --- a/include/regular/RegularTree.hpp +++ b/include/regular/RegularTree.hpp @@ -1,5 +1,4 @@ #pragma once -#include #include #include #include diff --git a/src/DFA/DFAGraphVertex.cpp b/src/DFA/DFAGraphVertex.cpp index a5d0f78..015ba92 100644 --- a/src/DFA/DFAGraphVertex.cpp +++ b/src/DFA/DFAGraphVertex.cpp @@ -1,5 +1,4 @@ #include "DFA/DFAGraph.hpp" -#include using Vertex = DFA::DFAGraph::Vertex; diff --git a/src/FDFA/FDFAGraph.cpp b/src/FDFA/FDFAGraph.cpp deleted file mode 100644 index 310bfec..0000000 --- a/src/FDFA/FDFAGraph.cpp +++ /dev/null @@ -1,98 +0,0 @@ -#include "FDFA/FDFAGraph.hpp" -#include -#include - -namespace FDFA { -size_t FDFAGraph::AddNewVertex() { - vertexes_[count_vertexes_] = std::make_shared(this); - vertexes_[count_vertexes_]->number_ = count_vertexes_; - return count_vertexes_++; -} - -void FDFAGraph::AddFinalVertex(size_t number) { - if (!vertexes_[number]->is_final_) { - vertexes_[number]->is_final_ = true; - final_vertexes_.push_back(number); - } -} - -void FDFAGraph::AddStartVertex(size_t number) { - if (!vertexes_[number]->is_start_) { - vertexes_[number]->is_start_ = true; - start_vertexes_.push_back(number); - } -} - -void FDFAGraph::RemoveVertex(size_t number) { - RemoveFinalVertex(number); - RemoveStartVertex(number); - vertexes_.erase(number); -} - -void FDFAGraph::RemoveFinalVertex(size_t number) { - for (size_t i = 0; i < final_vertexes_.size(); ++i) { - if (final_vertexes_[i] == number) { - vertexes_[number]->is_final_ = false; - std::swap(final_vertexes_[i], final_vertexes_.back()); - final_vertexes_.pop_back(); - break; - } - } -} - -void FDFAGraph::RemoveStartVertex(size_t number) { - for (size_t i = 0; i < start_vertexes_.size(); ++i) { - if (start_vertexes_[i] == number) { - vertexes_[number]->is_start_ = false; - std::swap(start_vertexes_[i], start_vertexes_.back()); - start_vertexes_.pop_back(); - break; - } - } -} - -std::shared_ptr FDFAGraph::GetVertex(size_t number) { - if (vertexes_.count(number)) - return vertexes_[number]; - return nullptr; -} - -size_t FDFAGraph::GetCountVertexes() const { - return count_vertexes_; -} - -const std::vector& FDFAGraph::GetFinalVertexes() const { - return final_vertexes_; -} - -const std::vector& FDFAGraph::GetStartVertexes() const { - return start_vertexes_; -} - -void FDFAGraph::Print() const { - for (auto i: vertexes_) { - std::cout << i.second->number_ << " " << "f-" << i.second->is_final_ << " s-" << - i.second->is_start_ << std::endl; - } - for (auto& i: vertexes_) { - for (auto& j: i.second->transitions_) { - std::cout << i.second->number_ << "->" << j.second << " <" << j.first << ">" << - std::endl; - } - } - std::cout << std::endl; -} - -bool FDFAGraph::Accepted(const std::string& str) const { - std::shared_ptr current = vertexes_.at(start_vertexes_[0]); - for (auto i: str) { - if (current->GetTransitions().count(i)) { - current = vertexes_.at(current->GetTransitions().at(i)); - } else { - return false; - } - } - return current->IsFinal(); -} -} - diff --git a/src/FDFA/FDFAGraphVertex.cpp b/src/FDFA/FDFAGraphVertex.cpp deleted file mode 100644 index 8304387..0000000 --- a/src/FDFA/FDFAGraphVertex.cpp +++ /dev/null @@ -1,58 +0,0 @@ -#include "FDFA/FDFAGraph.hpp" -#include - -using Vertex = FDFA::FDFAGraph::Vertex; - -Vertex::Vertex(FDFAGraph* owner) : owner_(owner) {} - -bool Vertex::IsFinal() const { - return is_final_; -} - -bool Vertex::IsStart() const { - return is_start_; -} - -size_t Vertex::GetNumber() const { - return number_; -} - -const std::map& Vertex::GetTransitions() const { - return transitions_; -} - -const std::map& Vertex::GetBackTransitions() const { - return back_transitions_; -} - -void Vertex::AddEdge(char symbol, size_t number) { - transitions_[symbol] = number; - owner_->GetVertex(number)->back_transitions_[symbol] = number_; -} - -void Vertex::RemoveEdge(char symbol) { - owner_->GetVertex(transitions_[symbol])->back_transitions_.erase(symbol); - transitions_.erase(symbol); -} - -void Vertex::SetOwner(FDFAGraph* owner) { - owner_ = owner; -} - -void Vertex::SetFinal(bool status) { - if (status != is_final_) { - if (status) - owner_->AddFinalVertex(number_); - else - owner_->RemoveFinalVertex(number_); - } -} - -void Vertex::SetStart(bool status) { - if (status != is_start_) { - if (status) - owner_->AddStartVertex(number_); - else - owner_->RemoveStartVertex(number_); - } -} diff --git a/src/NFA/NFATree.cpp b/src/NFA/NFAGraph.cpp similarity index 82% rename from src/NFA/NFATree.cpp rename to src/NFA/NFAGraph.cpp index aa57d47..aefe35a 100644 --- a/src/NFA/NFATree.cpp +++ b/src/NFA/NFAGraph.cpp @@ -1,9 +1,9 @@ -#include "NFA/NFATree.hpp" +#include "NFA/NFAGraph.hpp" #include #include namespace NFA { -NFATree::NFATree(NFATree&& another) { +NFAGraph::NFAGraph(NFAGraph&& another) { std::swap(count_vertexes_, another.count_vertexes_); std::swap(vertexes_, another.vertexes_); std::swap(final_vertexes_, another.final_vertexes_); @@ -15,7 +15,7 @@ NFATree::NFATree(NFATree&& another) { i.second->owner_ = &another; } -NFATree& NFATree::operator=(NFATree&& another) { +NFAGraph& NFAGraph::operator=(NFAGraph&& another) { std::swap(count_vertexes_, another.count_vertexes_); std::swap(vertexes_, another.vertexes_); std::swap(final_vertexes_, another.final_vertexes_); @@ -28,33 +28,33 @@ NFATree& NFATree::operator=(NFATree&& another) { return *this; } -size_t NFATree::AddNewVertex() { +size_t NFAGraph::AddNewVertex() { vertexes_[count_vertexes_] = std::make_shared(this); vertexes_[count_vertexes_]->number_ = count_vertexes_; return count_vertexes_++; } -void NFATree::AddFinalVertex(size_t number) { +void NFAGraph::AddFinalVertex(size_t number) { if (!vertexes_[number]->is_final_) { vertexes_[number]->is_final_ = true; final_vertexes_.push_back(number); } } -void NFATree::AddStartVertex(size_t number) { +void NFAGraph::AddStartVertex(size_t number) { if (!vertexes_[number]->is_start_) { vertexes_[number]->is_start_ = true; start_vertexes_.push_back(number); } } -void NFATree::RemoveVertex(size_t number) { +void NFAGraph::RemoveVertex(size_t number) { RemoveFinalVertex(number); RemoveStartVertex(number); vertexes_.erase(number); } -void NFATree::RemoveFinalVertex(size_t number) { +void NFAGraph::RemoveFinalVertex(size_t number) { for (size_t i = 0; i < final_vertexes_.size(); ++i) { if (final_vertexes_[i] == number) { vertexes_[number]->is_final_ = false; @@ -65,7 +65,7 @@ void NFATree::RemoveFinalVertex(size_t number) { } } -void NFATree::RemoveStartVertex(size_t number) { +void NFAGraph::RemoveStartVertex(size_t number) { for (size_t i = 0; i < start_vertexes_.size(); ++i) { if (start_vertexes_[i] == number) { vertexes_[number]->is_start_ = false; @@ -76,15 +76,15 @@ void NFATree::RemoveStartVertex(size_t number) { } } -void NFATree::Composition(NFATree&& tree, +void NFAGraph::Composition(NFAGraph&& nfa_graph, std::vector start_vertexes, std::vector final_vertexes) { - auto add_final_vertexes = tree.final_vertexes_; - auto add_start_vertexes = tree.start_vertexes_; + auto add_final_vertexes = nfa_graph.final_vertexes_; + auto add_start_vertexes = nfa_graph.start_vertexes_; size_t new_count_vertexes = count_vertexes_; - for (auto& i: tree.vertexes_) { + for (auto& i: nfa_graph.vertexes_) { new_count_vertexes = std::max(new_count_vertexes, i.first + count_vertexes_ + 1); i.second->number_ += count_vertexes_; std::map> new_transitions; @@ -135,25 +135,25 @@ void NFATree::Composition(NFATree&& tree, } } -std::shared_ptr NFATree::GetVertex(size_t number) { +std::shared_ptr NFAGraph::GetVertex(size_t number) { if (vertexes_.count(number)) return vertexes_[number]; return nullptr; } -size_t NFATree::GetCountVertexes() const { +size_t NFAGraph::GetCountVertexes() const { return count_vertexes_; } -const std::vector& NFATree::GetFinalVertexes() const { +const std::vector& NFAGraph::GetFinalVertexes() const { return final_vertexes_; } -const std::vector& NFATree::GetStartVertexes() const { +const std::vector& NFAGraph::GetStartVertexes() const { return start_vertexes_; } -void NFATree::Print() const { +void NFAGraph::Print() const { for (auto i: vertexes_) { std::cout << i.second->number_ << " " << "f-" << i.second->is_final_ << " s-" << i.second->is_start_ << std::endl; diff --git a/src/NFA/NFATreeVertex.cpp b/src/NFA/NFATreeVertex.cpp index 4060d82..a887fae 100644 --- a/src/NFA/NFATreeVertex.cpp +++ b/src/NFA/NFATreeVertex.cpp @@ -1,9 +1,8 @@ -#include "NFA/NFATree.hpp" -#include +#include "NFA/NFAGraph.hpp" -using Vertex = NFA::NFATree::Vertex; +using Vertex = NFA::NFAGraph::Vertex; -Vertex::Vertex(NFATree* owner) : owner_(owner) {} +Vertex::Vertex(NFAGraph* owner) : owner_(owner) {} bool Vertex::IsFinal() const { return is_final_; @@ -40,7 +39,7 @@ void Vertex::RemoveEdge(char symbol, size_t number) { owner_->GetVertex(number)->back_transitions_.erase(symbol); } -void Vertex::SetOwner(NFATree* owner) { +void Vertex::SetOwner(NFAGraph* owner) { owner_ = owner; } diff --git a/src/converters/DFAToFDFA.cpp b/src/converters/DFAToFDFA.cpp index 9d6ec37..8120746 100644 --- a/src/converters/DFAToFDFA.cpp +++ b/src/converters/DFAToFDFA.cpp @@ -43,48 +43,4 @@ DFAGraph DFAGraphToFDFAGraph(DFAGraph&& graph, const std::vector& alphabet return result; } -/* -FDFAGraph DFAGraphToFDFAGraph(DFAGraph&& graph, const std::vector& alphabet) { - FDFAGraph result; - const int n = graph.GetCountVertexes(); - std::map number_vertex_in_DFA; - for (int i = 0; i < n; ++i) { - if (!graph.GetVertex(i)) continue; - number_vertex_in_DFA[i] = result.AddNewVertex(); - } - for (int i = 0; i < n; ++i) { - if (!graph.GetVertex(i)) continue; - if (graph.GetVertex(i)->IsFinal()) - result.GetVertex(number_vertex_in_DFA[i])->SetFinal(true); - if (graph.GetVertex(i)->IsStart()) - result.GetVertex(number_vertex_in_DFA[i])->SetStart(true); - - const auto& transitions = graph.GetVertex(i)->GetTransitions(); - for (const auto& t: transitions) { - result.GetVertex(number_vertex_in_DFA[i])->AddEdge(t.first, t.second); - } - } - - size_t drain = result.AddNewVertex(); - - for (int i = 0; i < n; ++i) { - const auto& transitions = graph.GetVertex(i)->GetTransitions(); - for (char j: alphabet) { - if (!transitions.count(j)) { - result.GetVertex(i)->AddEdge(j, drain); - } - } - } - - if (result.GetVertex(drain)->GetBackTransitions().size() == 0) { - result.RemoveVertex(drain); - } else { - for (char j: alphabet) { - result.GetVertex(drain)->AddEdge(j, drain); - } - } - - return result; -} -*/ } diff --git a/src/converters/DFAToMinDFA.cpp b/src/converters/DFAToMinDFA.cpp index 2cc349c..5912b6d 100644 --- a/src/converters/DFAToMinDFA.cpp +++ b/src/converters/DFAToMinDFA.cpp @@ -1,22 +1,20 @@ #include "converters/DFAToMinDFA.hpp" -#include -#include namespace converters { -DFAGraph DFAToMinDFA(DFAGraph&& graph) { +DFAGraph DFAGraphToMinDFAGraph(DFAGraph&& graph) { const int n = graph.GetCountVertexes(); DFAGraph result; std::vector alphabet; { - std::set salphabet; + std::set set_alphabet; for (int i = 0; i < n; ++i) { for (auto i: graph.GetVertex(i)->GetTransitions()) { - salphabet.insert(i.first); + set_alphabet.insert(i.first); } } - alphabet = std::vector(salphabet.begin(), salphabet.end()); + alphabet = std::vector(set_alphabet.begin(), set_alphabet.end()); } std::vector>> table(n, diff --git a/src/converters/DFAToRegular.cpp b/src/converters/DFAToRegular.cpp index c19834c..4a59507 100644 --- a/src/converters/DFAToRegular.cpp +++ b/src/converters/DFAToRegular.cpp @@ -1,6 +1,4 @@ #include "converters/DFAToRegular.hpp" -#include -#include namespace converters { std::string DFAGraphToRegular(DFAGraph&& graph) { diff --git a/src/converters/NFAToDFA.cpp b/src/converters/NFAToDFA.cpp index c2ac47c..29e2df6 100644 --- a/src/converters/NFAToDFA.cpp +++ b/src/converters/NFAToDFA.cpp @@ -1,135 +1,22 @@ #include "converters/NFAToDFA.hpp" #include -#include #include +#include namespace converters { -/* -OLD version - - -NFATree AddAllEpsilonTransitions(NFATree&& tree) { - // Algorithm from 2-sat - const int n = tree.GetCountVertexes(); - std::vector used(n, false); - std::vector component(n, -1); - std::vector order; - - std::function dfs_order = [&tree, &used, &order, &dfs_order](int v) -> void { - used[v] = true; - const auto& transitions = tree.GetVertex(v)->GetTransitions(); - if (transitions.count(' ')) { - const auto& s = transitions.at(' '); - for (auto i: s) { - if (!used[i]) { - dfs_order(i); - } - } - } - order.push_back(v); - }; - - std::function dfs_component = [&tree, &component, - &dfs_component](int v, int c) -> void { - component[v] = c; - const auto& transitions = tree.GetVertex(v)->GetBackTransitions(); - if (transitions.count(' ')) { - const auto& s = transitions.at(' '); - for (auto i: s) { - if (component[i] == -1) { - dfs_component(i, c); - } - } - } - }; - - for (int i = 0; i < n; ++i) { - if (!used[i] && tree.GetVertex(i)) { - dfs_order(i); - } - } - - int current_component = 0; - for (int i = 0; i < n; ++i) { - int v = order[n - i - 1]; - if (component[v] == -1 && tree.GetVertex(i)) { - dfs_component(v, current_component++); - } - } - - std::set> connectivity_components; - - used.assign(n, false); - std::vector> connectivity_from(current_component); - - std::function dfs_connectivity = [&tree, &component, - &used, &dfs_connectivity, &connectivity_from](int v) -> void { - used[v] = true; - const auto& transitions = tree.GetVertex(v)->GetTransitions(); - if (transitions.count(' ')) { - const auto& s = transitions.at(' '); - for (auto i: s) { - if (!used[i]) { - dfs_connectivity(i); - } - if (component[v] != component[i]) { - connectivity_from[component[v]].insert(connectivity_from[component[i]].begin(), - connectivity_from[component[i]].end()); - connectivity_from[component[v]].insert(component[i]); - } - } - } - }; - - for (int i = 0; i < n; ++i) { - if (!tree.GetVertex(i)) continue; - connectivity_components.emplace(component[i], component[i]); - if (!used[i]) { - dfs_connectivity(i); - } - for (int j: connectivity_from[component[i]]) { - std::cout << i << " " << j << std::endl; - connectivity_components.emplace(component[i], j); - } - } - - for (int i = 0; i < n; ++i) { - std::cout << component[i] << " "; - } - std::cout << std::endl; - for (int i: connectivity_from[1]) { - std::cout << i << " "; - } - std::cout << std::endl; - - - - for (int i = 0; i < n; ++i) { - for (int j = 0; j < n; ++j) { - if (i == j) continue; - if (connectivity_components.count(std::make_pair(component[i], component[j]))) { - tree.GetVertex(i)->AddEdge(' ', j); - } - } - } - - return std::move(tree); -} -*/ - -NFATree AddAllEpsilonTransitions(NFATree&& tree) { - const int n = tree.GetCountVertexes(); +NFAGraph AddAllEpsilonTransitions(NFAGraph&& nfa_graph) { + const int n = nfa_graph.GetCountVertexes(); std::vector used(n, false); - std::function dfs = [&tree, &used, &dfs](int u, int v) -> void { + std::function dfs = [&nfa_graph, &used, &dfs](int u, int v) -> void { used[v] = true; - const auto& transitions = tree.GetVertex(v)->GetTransitions(); + const auto& transitions = nfa_graph.GetVertex(v)->GetTransitions(); if (transitions.count(' ')) { const auto& s = transitions.at(' '); for (auto i: s) { if (!used[i]) { if (u != i) - tree.GetVertex(u)->AddEdge(' ', i); + nfa_graph.GetVertex(u)->AddEdge(' ', i); dfs(u, i); } } @@ -137,62 +24,62 @@ NFATree AddAllEpsilonTransitions(NFATree&& tree) { }; for (int i = 0; i < n; ++i) { - if (!tree.GetVertex(i)) continue; + if (!nfa_graph.GetVertex(i)) continue; used.assign(n, false); dfs(i, i); } - return std::move(tree); + return std::move(nfa_graph); } -NFATree AddAllPossibleStartFilnal(NFATree&& tree) { - if (tree.GetStartVertexes().size() != 1) { - size_t start_vertex = tree.AddNewVertex(); - for (auto v: tree.GetStartVertexes()) { - tree.GetVertex(start_vertex)->AddEdge(' ', v); +NFAGraph AddAllPossibleStartFinal(NFAGraph&& nfa_graph) { + if (nfa_graph.GetStartVertexes().size() != 1) { + size_t start_vertex = nfa_graph.AddNewVertex(); + for (auto v: nfa_graph.GetStartVertexes()) { + nfa_graph.GetVertex(start_vertex)->AddEdge(' ', v); } } - for (const auto& v: tree.GetFinalVertexes()) { - const auto& transitions = tree.GetVertex(v)->GetBackTransitions(); + for (const auto& v: nfa_graph.GetFinalVertexes()) { + const auto& transitions = nfa_graph.GetVertex(v)->GetBackTransitions(); if (transitions.count(' ')) { const auto& s = transitions.at(' '); for (auto i: s) { - tree.GetVertex(i)->SetFinal(true); + nfa_graph.GetVertex(i)->SetFinal(true); } } } - return std::move(tree); + return std::move(nfa_graph); } -NFATree DeleteEpsilonTransitions(NFATree&& tree) { - const int n = tree.GetCountVertexes(); +NFAGraph DeleteEpsilonTransitions(NFAGraph&& nfa_graph) { + const int n = nfa_graph.GetCountVertexes(); for (int v = 0; v < n; ++v) { - if (!tree.GetVertex(v)) continue; + if (!nfa_graph.GetVertex(v)) continue; - const auto& transitions = tree.GetVertex(v)->GetTransitions(); + const auto& transitions = nfa_graph.GetVertex(v)->GetTransitions(); if (transitions.count(' ')) { auto s = transitions.at(' '); for (auto u: s) { - for (auto& i: tree.GetVertex(u)->GetTransitions()) { + for (auto& i: nfa_graph.GetVertex(u)->GetTransitions()) { if (i.first == ' ') continue; for (auto t: i.second) { - tree.GetVertex(v)->AddEdge(i.first, t); + nfa_graph.GetVertex(v)->AddEdge(i.first, t); } } } for (auto u: s) { - tree.GetVertex(v)->RemoveEdge(' ', u); + nfa_graph.GetVertex(v)->RemoveEdge(' ', u); } } } - return std::move(tree); + return std::move(nfa_graph); } -NFATree DeleteTransitionsByOneLetter(NFATree&& tree) { - const int n = tree.GetCountVertexes(); +NFAGraph DeleteTransitionsByOneLetter(NFAGraph&& nfa_graph) { + const int n = nfa_graph.GetCountVertexes(); - NFATree result_tree; + NFAGraph result_tree; std::map, char>, std::set> transitions; std::map, size_t> number_vertex_in_result_tree; @@ -200,14 +87,14 @@ NFATree DeleteTransitionsByOneLetter(NFATree&& tree) { std::set alphabet; for (int i = 0; i < n; ++i) { - if (!tree.GetVertex(i)) continue; - for (const auto& j: tree.GetVertex(i)->GetTransitions()) { + if (!nfa_graph.GetVertex(i)) continue; + for (const auto& j: nfa_graph.GetVertex(i)->GetTransitions()) { if (j.second.size() > 0) alphabet.insert(j.first); } } - for (auto i: tree.GetStartVertexes()) { + for (auto i: nfa_graph.GetStartVertexes()) { queue.push({i}); number_vertex_in_result_tree[{i}] = result_tree.AddNewVertex(); } @@ -219,7 +106,7 @@ NFATree DeleteTransitionsByOneLetter(NFATree&& tree) { for (auto symbol: alphabet) { std::set result; for (auto v: current) { - const auto& transitions = tree.GetVertex(v)->GetTransitions(); + const auto& transitions = nfa_graph.GetVertex(v)->GetTransitions(); if (transitions.count(symbol)) { const auto& s = transitions.at(symbol); result.insert(s.begin(), s.end()); @@ -248,9 +135,9 @@ NFATree DeleteTransitionsByOneLetter(NFATree&& tree) { auto v = i.second; for (auto i: s) { - if (tree.GetVertex(i)->IsFinal()) + if (nfa_graph.GetVertex(i)->IsFinal()) result_tree.GetVertex(v)->SetFinal(true); - if (tree.GetVertex(i)->IsStart()) + if (nfa_graph.GetVertex(i)->IsStart()) result_tree.GetVertex(v)->SetStart(true); } } @@ -258,31 +145,25 @@ NFATree DeleteTransitionsByOneLetter(NFATree&& tree) { return result_tree; } -DFAGraph NFATreeToDFAGraph(NFATree&& tree) { - /* - tree = AddAllEpsilonTransitions(std::move(tree)); - tree = AddAllPossibleStartFilnal(std::move(tree)); - tree = DeleteEpsilonTransitions(std::move(tree)); - tree = DeleteTransitionsByOneLetter(std::move(tree)); - */ - tree = DeleteTransitionsByOneLetter(DeleteEpsilonTransitions(AddAllPossibleStartFilnal( - AddAllEpsilonTransitions(std::move(tree))))); +DFAGraph NFAGraphToDFAGraph(NFAGraph&& nfa_graph) { + nfa_graph = DeleteTransitionsByOneLetter(DeleteEpsilonTransitions(AddAllPossibleStartFinal( + AddAllEpsilonTransitions(std::move(nfa_graph))))); - const int n = tree.GetCountVertexes(); + const int n = nfa_graph.GetCountVertexes(); DFAGraph result; std::map number_vertex_in_DFA; for (int i = 0; i < n; ++i) { - if (!tree.GetVertex(i)) continue; + if (!nfa_graph.GetVertex(i)) continue; number_vertex_in_DFA[i] = result.AddNewVertex(); } for (int i = 0; i < n; ++i) { - if (!tree.GetVertex(i)) continue; - if (tree.GetVertex(i)->IsFinal()) + if (!nfa_graph.GetVertex(i)) continue; + if (nfa_graph.GetVertex(i)->IsFinal()) result.GetVertex(number_vertex_in_DFA[i])->SetFinal(true); - if (tree.GetVertex(i)->IsStart()) + if (nfa_graph.GetVertex(i)->IsStart()) result.GetVertex(number_vertex_in_DFA[i])->SetStart(true); - const auto& transitions = tree.GetVertex(i)->GetTransitions(); + const auto& transitions = nfa_graph.GetVertex(i)->GetTransitions(); for (const auto& t: transitions) { if (t.second.size() != 1) throw std::logic_error(""); result.GetVertex(number_vertex_in_DFA[i])->AddEdge(t.first, *t.second.begin()); diff --git a/src/converters/RegularToNFA.cpp b/src/converters/RegularToNFA.cpp index 54c59b2..c08b686 100644 --- a/src/converters/RegularToNFA.cpp +++ b/src/converters/RegularToNFA.cpp @@ -1,7 +1,6 @@ #include "converters/RegularToNFA.hpp" #include "regular/RegularTree.hpp" -#include "NFA/NFATree.hpp" -#include +#include "NFA/NFAGraph.hpp" using namespace NFA; using namespace regular; @@ -13,8 +12,8 @@ struct do_nothing_deleter{ }; template -NFATree RegularToNFA(std::unique_ptr node) { - NFATree result; +NFAGraph RegularToNFA(std::unique_ptr node) { + NFAGraph result; if (node->type == Node::Type::Word) { auto end = result.AddNewVertex(); auto start = end; @@ -80,7 +79,7 @@ NFATree RegularToNFA(std::unique_ptr node) { } namespace converters { -NFATree RegularToNFA(RegularTree&& tree) { +NFAGraph RegularToNFAGraph(RegularTree&& tree) { const Node& root = tree.GetNode(); return RegularToNFA(std::unique_ptr(&const_cast(tree.GetNode()))); diff --git a/src/main.cpp b/src/main.cpp index 0f1f819..1b71cd0 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -16,17 +16,17 @@ using namespace converters; int main() { { RegularTree r("a*"); - NFATree NFA_tree = RegularToNFA(std::move(r)); - DFAGraph DFA_graph = NFATreeToDFAGraph(std::move(NFA_tree)); - DFA_graph = DFAToMinDFA(std::move(DFA_graph)); + NFAGraph NFA_tree = RegularToNFAGraph(std::move(r)); + DFAGraph DFA_graph = NFAGraphToDFAGraph(std::move(NFA_tree)); + DFA_graph = DFAGraphToMinDFAGraph(std::move(DFA_graph)); DFA_graph.Print(); std::string reg = DFAGraphToRegular(std::move(DFA_graph)); r = RegularTree(reg); - NFA_tree = RegularToNFA(std::move(r)); - DFA_graph = NFATreeToDFAGraph(std::move(NFA_tree)); - DFA_graph = DFAToMinDFA(std::move(DFA_graph)); + NFA_tree = RegularToNFAGraph(std::move(r)); + DFA_graph = NFAGraphToDFAGraph(std::move(NFA_tree)); + DFA_graph = DFAGraphToMinDFAGraph(std::move(DFA_graph)); DFA_graph.Print(); } @@ -36,16 +36,16 @@ int main() { { RegularTree r("a+"); r.Print(); - NFA::NFATree NFA_tree = converters::RegularToNFA(std::move(r)); + NFA::NFAGraph NFA_tree = converters::RegularToNFAGraph(std::move(r)); NFA_tree.Print(); - DFA::DFAGraph DFA_graph = converters::NFATreeToDFAGraph(std::move(NFA_tree)); + DFA::DFAGraph DFA_graph = converters::NFAGraphToDFAGraph(std::move(NFA_tree)); DFA_graph.Print(); - DFA_graph = DFAToMinDFA(std::move(DFA_graph)); + DFA_graph = DFAGraphToMinDFAGraph(std::move(DFA_graph)); DFA_graph.Print(); } return 0; - NFA::NFATree tree; + NFA::NFAGraph tree; const int N = 10; int a[N]; @@ -110,7 +110,7 @@ int main() { tree.GetVertex(a[3])->SetFinal(true); tree.GetVertex(a[4])->SetFinal(true); - DFA::DFAGraph res = converters::NFATreeToDFAGraph(std::move(tree)); + DFA::DFAGraph res = converters::NFAGraphToDFAGraph(std::move(tree)); // FDFA::FDFAGraph res2 = converters::DFAGraphToFDFAGraph(std::move(res), {'a', 'b'}); // res2.Print(); @@ -119,7 +119,7 @@ int main() { // res = converters::DFAGraphToFDFAGraph(std::move(res), {'a', 'b'}); - res = converters::DFAToMinDFA(std::move(res)); + res = converters::DFAGraphToMinDFAGraph(std::move(res)); res.Print(); @@ -163,7 +163,7 @@ int main() { RegularTree reg_tree(str); reg_tree.Print(); - auto NFA_tree = converters::RegularToNFA(std::move(reg_tree)); + auto NFA_tree = converters::RegularToNFAGraph(std::move(reg_tree)); std::cout << std::endl; diff --git a/tests/DFAToRegular/DFAToRegular.cpp b/tests/DFAToRegular/DFAToRegular.cpp index 01c465e..e46e99f 100644 --- a/tests/DFAToRegular/DFAToRegular.cpp +++ b/tests/DFAToRegular/DFAToRegular.cpp @@ -17,16 +17,16 @@ extern std::string GenerateRandomString(std::vector alphabet, size_t len); TEST(DFA_to_regular, a_star) { RegularTree r("a*"); - NFATree NFA_tree = RegularToNFA(std::move(r)); - DFAGraph DFA_graph = NFATreeToDFAGraph(std::move(NFA_tree)); - DFA_graph = DFAToMinDFA(std::move(DFA_graph)); + NFAGraph NFA_tree = RegularToNFAGraph(std::move(r)); + DFAGraph DFA_graph = NFAGraphToDFAGraph(std::move(NFA_tree)); + DFA_graph = DFAGraphToMinDFAGraph(std::move(DFA_graph)); std::string reg = DFAGraphToRegular(std::move(DFA_graph)); r = RegularTree(reg); - NFA_tree = RegularToNFA(std::move(r)); - DFA_graph = NFATreeToDFAGraph(std::move(NFA_tree)); - DFA_graph = DFAToMinDFA(std::move(DFA_graph)); + NFA_tree = RegularToNFAGraph(std::move(r)); + DFA_graph = NFAGraphToDFAGraph(std::move(NFA_tree)); + DFA_graph = DFAGraphToMinDFAGraph(std::move(DFA_graph)); std::string s = ""; @@ -40,16 +40,16 @@ TEST(DFA_to_regular, a_plus) { std::string regulars[] = {"a+", "(a)+", "(a+)"}; for (const auto& regular: regulars) { RegularTree r(regular); - NFATree NFA_tree = RegularToNFA(std::move(r)); - DFAGraph DFA_graph = NFATreeToDFAGraph(std::move(NFA_tree)); - DFA_graph = DFAToMinDFA(std::move(DFA_graph)); + NFAGraph NFA_tree = RegularToNFAGraph(std::move(r)); + DFAGraph DFA_graph = NFAGraphToDFAGraph(std::move(NFA_tree)); + DFA_graph = DFAGraphToMinDFAGraph(std::move(DFA_graph)); std::string reg = DFAGraphToRegular(std::move(DFA_graph)); r = RegularTree(reg); - NFA_tree = RegularToNFA(std::move(r)); - DFA_graph = NFATreeToDFAGraph(std::move(NFA_tree)); - DFA_graph = DFAToMinDFA(std::move(DFA_graph)); + NFA_tree = RegularToNFAGraph(std::move(r)); + DFA_graph = NFAGraphToDFAGraph(std::move(NFA_tree)); + DFA_graph = DFAGraphToMinDFAGraph(std::move(DFA_graph)); std::string s = ""; ASSERT_EQ(DFA_graph.Accepted(s), false); @@ -65,16 +65,16 @@ TEST(DFA_to_regular, abc) { std::string regulars[] = {"abc"}; for (const auto& regular: regulars) { RegularTree r(regular); - NFATree NFA_tree = RegularToNFA(std::move(r)); - DFAGraph DFA_graph = NFATreeToDFAGraph(std::move(NFA_tree)); - DFA_graph = DFAToMinDFA(std::move(DFA_graph)); + NFAGraph NFA_tree = RegularToNFAGraph(std::move(r)); + DFAGraph DFA_graph = NFAGraphToDFAGraph(std::move(NFA_tree)); + DFA_graph = DFAGraphToMinDFAGraph(std::move(DFA_graph)); std::string reg = DFAGraphToRegular(std::move(DFA_graph)); r = RegularTree(reg); - NFA_tree = RegularToNFA(std::move(r)); - DFA_graph = NFATreeToDFAGraph(std::move(NFA_tree)); - DFA_graph = DFAToMinDFA(std::move(DFA_graph)); + NFA_tree = RegularToNFAGraph(std::move(r)); + DFA_graph = NFAGraphToDFAGraph(std::move(NFA_tree)); + DFA_graph = DFAGraphToMinDFAGraph(std::move(DFA_graph)); ASSERT_EQ(DFA_graph.Accepted("abc"), true); for (int i = 0; i < 1000; ++i) { @@ -89,16 +89,16 @@ TEST(DFA_to_regular, a_or_b_or_c) { std::string regulars[] = {}; for (const auto& regular: regulars) { RegularTree r("a|b|c"); - NFATree NFA_tree = RegularToNFA(std::move(r)); - DFAGraph DFA_graph = NFATreeToDFAGraph(std::move(NFA_tree)); - DFA_graph = DFAToMinDFA(std::move(DFA_graph)); + NFAGraph NFA_tree = RegularToNFAGraph(std::move(r)); + DFAGraph DFA_graph = NFAGraphToDFAGraph(std::move(NFA_tree)); + DFA_graph = DFAGraphToMinDFAGraph(std::move(DFA_graph)); std::string reg = DFAGraphToRegular(std::move(DFA_graph)); r = RegularTree(reg); - NFA_tree = RegularToNFA(std::move(r)); - DFA_graph = NFATreeToDFAGraph(std::move(NFA_tree)); - DFA_graph = DFAToMinDFA(std::move(DFA_graph)); + NFA_tree = RegularToNFAGraph(std::move(r)); + DFA_graph = NFAGraphToDFAGraph(std::move(NFA_tree)); + DFA_graph = DFAGraphToMinDFAGraph(std::move(DFA_graph)); ASSERT_EQ(DFA_graph.Accepted("a"), true); ASSERT_EQ(DFA_graph.Accepted("b"), true); @@ -117,16 +117,16 @@ TEST(DFA_to_regular, 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); - NFATree NFA_tree = RegularToNFA(std::move(r)); - DFAGraph DFA_graph = NFATreeToDFAGraph(std::move(NFA_tree)); - DFA_graph = DFAToMinDFA(std::move(DFA_graph)); + NFAGraph NFA_tree = RegularToNFAGraph(std::move(r)); + DFAGraph DFA_graph = NFAGraphToDFAGraph(std::move(NFA_tree)); + DFA_graph = DFAGraphToMinDFAGraph(std::move(DFA_graph)); std::string reg = DFAGraphToRegular(std::move(DFA_graph)); r = RegularTree(reg); - NFA_tree = RegularToNFA(std::move(r)); - DFA_graph = NFATreeToDFAGraph(std::move(NFA_tree)); - DFA_graph = DFAToMinDFA(std::move(DFA_graph)); + NFA_tree = RegularToNFAGraph(std::move(r)); + DFA_graph = NFAGraphToDFAGraph(std::move(NFA_tree)); + DFA_graph = DFAGraphToMinDFAGraph(std::move(DFA_graph)); auto check = [](const std::string str) { std::set s(str.begin(), str.end()); @@ -151,16 +151,16 @@ TEST(DFA_to_regular, a_star_or_b_star_or_c_star) { TEST(DFA_to_regular, _a_star_or_b_star_or_c_star_plus) { RegularTree r("(a*|b*|c*)+"); - NFATree NFA_tree = RegularToNFA(std::move(r)); - DFAGraph DFA_graph = NFATreeToDFAGraph(std::move(NFA_tree)); - DFA_graph = DFAToMinDFA(std::move(DFA_graph)); + NFAGraph NFA_tree = RegularToNFAGraph(std::move(r)); + DFAGraph DFA_graph = NFAGraphToDFAGraph(std::move(NFA_tree)); + DFA_graph = DFAGraphToMinDFAGraph(std::move(DFA_graph)); std::string reg = DFAGraphToRegular(std::move(DFA_graph)); r = RegularTree(reg); - NFA_tree = RegularToNFA(std::move(r)); - DFA_graph = NFATreeToDFAGraph(std::move(NFA_tree)); - DFA_graph = DFAToMinDFA(std::move(DFA_graph)); + NFA_tree = RegularToNFAGraph(std::move(r)); + DFA_graph = NFAGraphToDFAGraph(std::move(NFA_tree)); + DFA_graph = DFAGraphToMinDFAGraph(std::move(DFA_graph)); auto check = [](const std::string str) { std::set s(str.begin(), str.end()); @@ -177,16 +177,16 @@ TEST(DFA_to_regular, _a_star_or_b_star_or_c_star_plus) { TEST(DFA_to_regular, _a_or_b_or_c_star_plus) { RegularTree r("(a|b|c*)+"); - NFATree NFA_tree = RegularToNFA(std::move(r)); - DFAGraph DFA_graph = NFATreeToDFAGraph(std::move(NFA_tree)); - DFA_graph = DFAToMinDFA(std::move(DFA_graph)); + NFAGraph NFA_tree = RegularToNFAGraph(std::move(r)); + DFAGraph DFA_graph = NFAGraphToDFAGraph(std::move(NFA_tree)); + DFA_graph = DFAGraphToMinDFAGraph(std::move(DFA_graph)); std::string reg = DFAGraphToRegular(std::move(DFA_graph)); r = RegularTree(reg); - NFA_tree = RegularToNFA(std::move(r)); - DFA_graph = NFATreeToDFAGraph(std::move(NFA_tree)); - DFA_graph = DFAToMinDFA(std::move(DFA_graph)); + NFA_tree = RegularToNFAGraph(std::move(r)); + DFA_graph = NFAGraphToDFAGraph(std::move(NFA_tree)); + DFA_graph = DFAGraphToMinDFAGraph(std::move(DFA_graph)); auto check = [](const std::string str) { std::set s(str.begin(), str.end()); diff --git a/tests/NFAToDFA/check_equivalence.cpp b/tests/NFAToDFA/check_equivalence.cpp index 579632c..2594763 100644 --- a/tests/NFAToDFA/check_equivalence.cpp +++ b/tests/NFAToDFA/check_equivalence.cpp @@ -1,7 +1,7 @@ #include #include #include "DFA/DFAGraph.hpp" -#include "NFA/NFATree.hpp" +#include "NFA/NFAGraph.hpp" #include "converters/NFAToDFA.hpp" using namespace NFA; @@ -19,7 +19,7 @@ std::string GenerateRandomString(std::vector alphabet, size_t len) { } TEST(check_equivalence_NFA_to_DFA, 1) { - NFA::NFATree tree; + NFA::NFAGraph tree; const int N = 10; int a[N]; @@ -34,7 +34,7 @@ TEST(check_equivalence_NFA_to_DFA, 1) { tree.GetVertex(a[2])->SetFinal(true); tree.GetVertex(a[3])->SetFinal(true); - DFA::DFAGraph res = converters::NFATreeToDFAGraph(std::move(tree)); + DFA::DFAGraph res = converters::NFAGraphToDFAGraph(std::move(tree)); EXPECT_FALSE(res.Accepted("")); EXPECT_TRUE(res.Accepted("a")); @@ -46,7 +46,7 @@ TEST(check_equivalence_NFA_to_DFA, 1) { } TEST(check_equivalence_NFA_to_DFA, 2) { - NFA::NFATree tree; + NFA::NFAGraph tree; const int N = 10; int a[N]; @@ -62,7 +62,7 @@ TEST(check_equivalence_NFA_to_DFA, 2) { tree.GetVertex(a[1])->SetFinal(true); tree.GetVertex(a[2])->SetFinal(true); - DFA::DFAGraph res = converters::NFATreeToDFAGraph(std::move(tree)); + DFA::DFAGraph res = converters::NFAGraphToDFAGraph(std::move(tree)); auto check = [](const std::string& str) { if (str.size() > 0) { diff --git a/tests/regularToDFA/regularToDFA.cpp b/tests/regularToDFA/regularToDFA.cpp index 3d157a1..6087923 100644 --- a/tests/regularToDFA/regularToDFA.cpp +++ b/tests/regularToDFA/regularToDFA.cpp @@ -16,9 +16,9 @@ extern std::string GenerateRandomString(std::vector alphabet, size_t len); TEST(regular_to_DFA, a_star) { RegularTree r("a*"); - NFATree NFA_tree = RegularToNFA(std::move(r)); - DFAGraph DFA_graph = NFATreeToDFAGraph(std::move(NFA_tree)); - DFA_graph = DFAToMinDFA(std::move(DFA_graph)); + NFAGraph NFA_tree = RegularToNFAGraph(std::move(r)); + DFAGraph DFA_graph = NFAGraphToDFAGraph(std::move(NFA_tree)); + DFA_graph = DFAGraphToMinDFAGraph(std::move(DFA_graph)); std::string s = ""; for (int i = 0; i < 100; ++i) { @@ -31,9 +31,9 @@ TEST(regular_to_DFA, a_plus) { std::string regulars[] = {"a+", "(a)+", "(a+)"}; for (const auto& regular: regulars) { RegularTree r(regular); - NFATree NFA_tree = RegularToNFA(std::move(r)); - DFAGraph DFA_graph = NFATreeToDFAGraph(std::move(NFA_tree)); - DFA_graph = DFAToMinDFA(std::move(DFA_graph)); + NFAGraph NFA_tree = RegularToNFAGraph(std::move(r)); + DFAGraph DFA_graph = NFAGraphToDFAGraph(std::move(NFA_tree)); + DFA_graph = DFAGraphToMinDFAGraph(std::move(DFA_graph)); std::string s = ""; ASSERT_EQ(DFA_graph.Accepted(s), false); @@ -49,9 +49,9 @@ TEST(regular_to_DFA, abc) { std::string regulars[] = {"abc"}; for (const auto& regular: regulars) { RegularTree r(regular); - NFATree NFA_tree = RegularToNFA(std::move(r)); - DFAGraph DFA_graph = NFATreeToDFAGraph(std::move(NFA_tree)); - DFA_graph = DFAToMinDFA(std::move(DFA_graph)); + NFAGraph NFA_tree = RegularToNFAGraph(std::move(r)); + DFAGraph DFA_graph = NFAGraphToDFAGraph(std::move(NFA_tree)); + DFA_graph = DFAGraphToMinDFAGraph(std::move(DFA_graph)); ASSERT_EQ(DFA_graph.Accepted("abc"), true); for (int i = 0; i < 1000; ++i) { @@ -66,9 +66,9 @@ TEST(regular_to_DFA, a_or_b_or_c) { std::string regulars[] = {}; for (const auto& regular: regulars) { RegularTree r("a|b|c"); - NFATree NFA_tree = RegularToNFA(std::move(r)); - DFAGraph DFA_graph = NFATreeToDFAGraph(std::move(NFA_tree)); - DFA_graph = DFAToMinDFA(std::move(DFA_graph)); + NFAGraph NFA_tree = RegularToNFAGraph(std::move(r)); + DFAGraph DFA_graph = NFAGraphToDFAGraph(std::move(NFA_tree)); + DFA_graph = DFAGraphToMinDFAGraph(std::move(DFA_graph)); ASSERT_EQ(DFA_graph.Accepted("a"), true); ASSERT_EQ(DFA_graph.Accepted("b"), true); @@ -87,9 +87,9 @@ TEST(regular_to_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); - NFATree NFA_tree = RegularToNFA(std::move(r)); - DFAGraph DFA_graph = NFATreeToDFAGraph(std::move(NFA_tree)); - DFA_graph = DFAToMinDFA(std::move(DFA_graph)); + NFAGraph NFA_tree = RegularToNFAGraph(std::move(r)); + DFAGraph DFA_graph = NFAGraphToDFAGraph(std::move(NFA_tree)); + DFA_graph = DFAGraphToMinDFAGraph(std::move(DFA_graph)); auto check = [](const std::string str) { std::set s(str.begin(), str.end()); @@ -114,9 +114,9 @@ TEST(regular_to_DFA, a_star_or_b_star_or_c_star) { TEST(regular_to_DFA, _a_star_or_b_star_or_c_star_plus) { RegularTree r("(a*|b*|c*)+"); - NFATree NFA_tree = RegularToNFA(std::move(r)); - DFAGraph DFA_graph = NFATreeToDFAGraph(std::move(NFA_tree)); - DFA_graph = DFAToMinDFA(std::move(DFA_graph)); + NFAGraph NFA_tree = RegularToNFAGraph(std::move(r)); + DFAGraph DFA_graph = NFAGraphToDFAGraph(std::move(NFA_tree)); + DFA_graph = DFAGraphToMinDFAGraph(std::move(DFA_graph)); auto check = [](const std::string str) { std::set s(str.begin(), str.end()); @@ -133,9 +133,9 @@ TEST(regular_to_DFA, _a_star_or_b_star_or_c_star_plus) { TEST(regular_to_DFA, _a_or_b_or_c_star_plus) { RegularTree r("(a|b|c*)+"); - NFATree NFA_tree = RegularToNFA(std::move(r)); - DFAGraph DFA_graph = NFATreeToDFAGraph(std::move(NFA_tree)); - DFA_graph = DFAToMinDFA(std::move(DFA_graph)); + NFAGraph NFA_tree = RegularToNFAGraph(std::move(r)); + DFAGraph DFA_graph = NFAGraphToDFAGraph(std::move(NFA_tree)); + DFA_graph = DFAGraphToMinDFAGraph(std::move(DFA_graph)); auto check = [](const std::string str) { std::set s(str.begin(), str.end()); From aad17d8c8c0023a2538c7b318972ac51583db2a4 Mon Sep 17 00:00:00 2001 From: MaxanRus Date: Tue, 5 Oct 2021 17:03:03 +0300 Subject: [PATCH 09/17] refactoring & add invertion --- CMakeLists.txt | 14 +- include/DFA/DFAGraph.hpp | 4 +- include/converters/InvertFDFA.hpp | 7 + src/DFA/DFAGraph.cpp | 24 +++ .../{NFATreeVertex.cpp => NFAGraphVertex.cpp} | 0 src/converters/InvertFDFA.cpp | 12 ++ src/main.cpp | 198 +++++------------- tests/{test_main.cpp => MainTest.cpp} | 0 ...k_equivalence.cpp => CheckEquivalence.cpp} | 0 tests/invertFDFA/InvertFDFA.cpp | 181 ++++++++++++++++ .../{parse_regular.cpp => ParseRegular.cpp} | 0 .../{regularToDFA.cpp => RegularToDFA.cpp} | 0 12 files changed, 286 insertions(+), 154 deletions(-) create mode 100644 include/converters/InvertFDFA.hpp rename src/NFA/{NFATreeVertex.cpp => NFAGraphVertex.cpp} (100%) create mode 100644 src/converters/InvertFDFA.cpp rename tests/{test_main.cpp => MainTest.cpp} (100%) rename tests/NFAToDFA/{check_equivalence.cpp => CheckEquivalence.cpp} (100%) create mode 100644 tests/invertFDFA/InvertFDFA.cpp rename tests/regular/{parse_regular.cpp => ParseRegular.cpp} (100%) rename tests/regularToDFA/{regularToDFA.cpp => RegularToDFA.cpp} (100%) diff --git a/CMakeLists.txt b/CMakeLists.txt index 6ebfd89..bd98941 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -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) diff --git a/include/DFA/DFAGraph.hpp b/include/DFA/DFAGraph.hpp index af1f100..a04c796 100644 --- a/include/DFA/DFAGraph.hpp +++ b/include/DFA/DFAGraph.hpp @@ -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); diff --git a/include/converters/InvertFDFA.hpp b/include/converters/InvertFDFA.hpp new file mode 100644 index 0000000..e5dce0e --- /dev/null +++ b/include/converters/InvertFDFA.hpp @@ -0,0 +1,7 @@ +#pragma once +#include "DFA/DFAGraph.hpp" + +namespace converters { +using namespace DFA; +DFAGraph InvertFDFAGraph(DFAGraph&&); +} diff --git a/src/DFA/DFAGraph.cpp b/src/DFA/DFAGraph.cpp index 01882a3..90f8c40 100644 --- a/src/DFA/DFAGraph.cpp +++ b/src/DFA/DFAGraph.cpp @@ -3,6 +3,30 @@ #include 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(this); vertexes_[count_vertexes_]->number_ = count_vertexes_; diff --git a/src/NFA/NFATreeVertex.cpp b/src/NFA/NFAGraphVertex.cpp similarity index 100% rename from src/NFA/NFATreeVertex.cpp rename to src/NFA/NFAGraphVertex.cpp diff --git a/src/converters/InvertFDFA.cpp b/src/converters/InvertFDFA.cpp new file mode 100644 index 0000000..4d3c5e0 --- /dev/null +++ b/src/converters/InvertFDFA.cpp @@ -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); +} +} diff --git a/src/main.cpp b/src/main.cpp index 1b71cd0..1792d0f 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -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; } diff --git a/tests/test_main.cpp b/tests/MainTest.cpp similarity index 100% rename from tests/test_main.cpp rename to tests/MainTest.cpp diff --git a/tests/NFAToDFA/check_equivalence.cpp b/tests/NFAToDFA/CheckEquivalence.cpp similarity index 100% rename from tests/NFAToDFA/check_equivalence.cpp rename to tests/NFAToDFA/CheckEquivalence.cpp diff --git a/tests/invertFDFA/InvertFDFA.cpp b/tests/invertFDFA/InvertFDFA.cpp new file mode 100644 index 0000000..cc1efb2 --- /dev/null +++ b/tests/invertFDFA/InvertFDFA.cpp @@ -0,0 +1,181 @@ +#include +#include +#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 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 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 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 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)); + } +} diff --git a/tests/regular/parse_regular.cpp b/tests/regular/ParseRegular.cpp similarity index 100% rename from tests/regular/parse_regular.cpp rename to tests/regular/ParseRegular.cpp diff --git a/tests/regularToDFA/regularToDFA.cpp b/tests/regularToDFA/RegularToDFA.cpp similarity index 100% rename from tests/regularToDFA/regularToDFA.cpp rename to tests/regularToDFA/RegularToDFA.cpp From 0947eeac5d1ae974b702d4eedba3d9d9d1b0d96f Mon Sep 17 00:00:00 2001 From: MaxanRus Date: Tue, 5 Oct 2021 17:12:00 +0300 Subject: [PATCH 10/17] some fix bugs --- src/DFA/DFAGraph.cpp | 1 + src/converters/DFAToMinDFA.cpp | 1 + src/main.cpp | 18 ++++++++++++------ 3 files changed, 14 insertions(+), 6 deletions(-) diff --git a/src/DFA/DFAGraph.cpp b/src/DFA/DFAGraph.cpp index 90f8c40..1024151 100644 --- a/src/DFA/DFAGraph.cpp +++ b/src/DFA/DFAGraph.cpp @@ -51,6 +51,7 @@ void DFAGraph::RemoveVertex(size_t number) { RemoveFinalVertex(number); RemoveStartVertex(number); vertexes_.erase(number); + if (number == count_vertexes_ - 1) count_vertexes_--; } void DFAGraph::RemoveFinalVertex(size_t number) { diff --git a/src/converters/DFAToMinDFA.cpp b/src/converters/DFAToMinDFA.cpp index 5912b6d..4a67245 100644 --- a/src/converters/DFAToMinDFA.cpp +++ b/src/converters/DFAToMinDFA.cpp @@ -10,6 +10,7 @@ DFAGraph DFAGraphToMinDFAGraph(DFAGraph&& graph) { { std::set set_alphabet; for (int i = 0; i < n; ++i) { + if (!graph.GetVertex(i)) continue; for (auto i: graph.GetVertex(i)->GetTransitions()) { set_alphabet.insert(i.first); } diff --git a/src/main.cpp b/src/main.cpp index 1792d0f..47887ed 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -50,17 +50,21 @@ void example2() { } int main() { + { - RegularTree r("a*"); + RegularTree r("(a|b)+bab(a|b)+"); 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(); + DFA_graph = DFAGraphToFDFAGraph(std::move(DFA_graph), {'a', 'b'}); DFA_graph = InvertFDFAGraph(std::move(DFA_graph)); - return 0; DFA_graph = DFAGraphToMinDFAGraph(std::move(DFA_graph)); + DFA_graph.Print(); + auto s = DFAGraphToRegular(std::move(DFA_graph)); + std::cout << s << std::endl; + r = RegularTree(s); + r.Print(); } return 0; RegularTree r("a*"); @@ -74,6 +78,8 @@ int main() { dfa = DFAGraphToMinDFAGraph(std::move(fdfa)); auto s = DFAGraphToRegular(std::move(dfa)); - // RegularTree r("(a|b)+bab(a|b)+"); - // std::cout << DFAGraphToRegular(DFAGraphToMinDFAGraph(InvertFDFAGraph(DFAGraphToFDFAGraph(DFAGraphToMinDFAGraph(NFAGraphToDFAGraph(RegularToNFAGraph(std::move(r)))), {'a', 'b'})))) << std::endl; + /* + RegularTree r("(a|b)+bab(a|b)+"); + std::cout << DFAGraphToRegular(DFAGraphToMinDFAGraph(InvertFDFAGraph(DFAGraphToFDFAGraph(DFAGraphToMinDFAGraph(NFAGraphToDFAGraph(RegularToNFAGraph(std::move(r)))), {'a', 'b'})))) << std::endl; + */ } From 124a6c17b1d3399874f87a6f76b2ee03d8d6bb19 Mon Sep 17 00:00:00 2001 From: MaxanRus Date: Tue, 5 Oct 2021 18:13:31 +0300 Subject: [PATCH 11/17] regular to string --- CMakeLists.txt | 1 + include/regular/RegularTree.hpp | 3 + src/main.cpp | 3 +- src/regular/RegularTree.cpp | 4 + src/regular/RegularTreeNode.cpp | 56 ++++++- tests/DFAToRegular/DFAToRegular2.cpp | 209 +++++++++++++++++++++++++++ 6 files changed, 274 insertions(+), 2 deletions(-) create mode 100644 tests/DFAToRegular/DFAToRegular2.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index bd98941..6395d82 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -36,6 +36,7 @@ set(TEST_FILES tests/regularToDFA/RegularToDFA.cpp tests/DFAToRegular/DFAToRegular.cpp tests/invertFDFA/InvertFDFA.cpp + tests/DFAToRegular/DFAToRegular2.cpp ) add_executable(Formalang src/main.cpp ${SOURCE_FILES}) diff --git a/include/regular/RegularTree.hpp b/include/regular/RegularTree.hpp index a564142..3863b3d 100644 --- a/include/regular/RegularTree.hpp +++ b/include/regular/RegularTree.hpp @@ -25,15 +25,18 @@ class RegularTree { std::string word; Type type; Modifier modifier = Modifier::None; + std::string ToString() const; private: void ParseCurrentType(const std::string_view); void Compression(); + void Compression2(); void Print(int nesting_level) const; }; RegularTree(const std::string&); const Node& GetNode() const; void Print() const; + std::string ToString() const; private: Node node_; diff --git a/src/main.cpp b/src/main.cpp index 47887ed..d4946b5 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -64,7 +64,8 @@ int main() { auto s = DFAGraphToRegular(std::move(DFA_graph)); std::cout << s << std::endl; r = RegularTree(s); - r.Print(); + // r.Print(); + std::cout << r.ToString() << std::endl; } return 0; RegularTree r("a*"); diff --git a/src/regular/RegularTree.cpp b/src/regular/RegularTree.cpp index 3cde403..70285b7 100644 --- a/src/regular/RegularTree.cpp +++ b/src/regular/RegularTree.cpp @@ -12,4 +12,8 @@ const RegularTree::Node& RegularTree::GetNode() const { void RegularTree::Print() const { node_.Print(); } + +std::string RegularTree::ToString() const { + return node_.ToString(); +} } diff --git a/src/regular/RegularTreeNode.cpp b/src/regular/RegularTreeNode.cpp index f103293..ac297ae 100644 --- a/src/regular/RegularTreeNode.cpp +++ b/src/regular/RegularTreeNode.cpp @@ -8,7 +8,10 @@ Node::Node(Type type) : type(type) {} void Node::Parse(const std::string& regular) { type = Type::Addition; ParseCurrentType(std::string_view(regular.c_str(), regular.size())); - Compression(); + for (int i = 0; i < 10; ++i) { + Compression(); + Compression2(); + } } void Node::Print() const { @@ -160,6 +163,25 @@ void Node::Compression() { } } +void Node::Compression2() { + for (auto& i: children) { + i->Compression2(); + } + bool f = type == Type::Concatenation; + for (auto& i: children) { + f &= i->modifier == Modifier::None; + f &= i->type == Type::Word; + } + if (f) { + auto tmp = std::move(*children[0]); + tmp.modifier = modifier; + for (int i = 1; i < children.size(); ++i) { + tmp.word += children[i]->word; + } + *this = std::move(tmp); + } +} + void Node::Print(int nesting_level) const { auto PrintNesingLevel = [](int nesting_level) { for (int i = 0; i < nesting_level; ++i) { @@ -198,3 +220,35 @@ void Node::Print(int nesting_level) const { i->Print(nesting_level + 1); } } + +std::string regular::RegularTree::Node::ToString() const { + std::string res; + if (type == Type::Word) { + res = word; + if (modifier == Modifier::Plus) + res = "(" + res + ")+"; + else if (modifier == Modifier::Star) + res = "(" + res + ")*"; + } else if (type == Type::Concatenation) { + for (auto& i: children) { + res += i->ToString(); + } + if (modifier == Modifier::Plus) + res = "(" + res + ")+"; + else if (modifier == Modifier::Star) + res = "(" + res + ")*"; + } else if (type == Type::Addition) { + for (auto& i: children) { + res += i->ToString(); + res += "|"; + } + if (res.size()) + res.pop_back(); + res = "(" + res + ")"; + if (modifier == Modifier::Plus) + res += "+"; + else if (modifier == Modifier::Star) + res += "*"; + } + return res; +} diff --git a/tests/DFAToRegular/DFAToRegular2.cpp b/tests/DFAToRegular/DFAToRegular2.cpp new file mode 100644 index 0000000..17603ab --- /dev/null +++ b/tests/DFAToRegular/DFAToRegular2.cpp @@ -0,0 +1,209 @@ +#include +#include +#include "regular/RegularTree.hpp" +#include "converters/RegularToNFA.hpp" +#include "converters/NFAToDFA.hpp" +#include "converters/DFAToMinDFA.hpp" +#include "converters/DFAToRegular.hpp" + +using namespace regular; +using namespace NFA; +using namespace DFA; +using namespace converters; + +extern std::mt19937 rnd; + +extern std::string GenerateRandomString(std::vector alphabet, size_t len); + +TEST(DFA_to_regular2, 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)); + + std::string reg = DFAGraphToRegular(std::move(DFA_graph)); + reg = RegularTree(reg).ToString(); + + r = RegularTree(reg); + NFA_tree = RegularToNFAGraph(std::move(r)); + DFA_graph = NFAGraphToDFAGraph(std::move(NFA_tree)); + DFA_graph = DFAGraphToMinDFAGraph(std::move(DFA_graph)); + + + std::string s = ""; + for (int i = 0; i < 100; ++i) { + ASSERT_EQ(DFA_graph.Accepted(s), true); + s += "a"; + } +} + +TEST(DFA_to_regular2, 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)); + + std::string reg = DFAGraphToRegular(std::move(DFA_graph)); + reg = RegularTree(reg).ToString(); + + r = RegularTree(reg); + NFA_tree = RegularToNFAGraph(std::move(r)); + DFA_graph = NFAGraphToDFAGraph(std::move(NFA_tree)); + DFA_graph = DFAGraphToMinDFAGraph(std::move(DFA_graph)); + + std::string s = ""; + ASSERT_EQ(DFA_graph.Accepted(s), false); + s += "a"; + for (int i = 0; i < 100; ++i) { + ASSERT_EQ(DFA_graph.Accepted(s), true); + s += "a"; + } + } +} + +TEST(DFA_to_regular2, 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)); + + std::string reg = DFAGraphToRegular(std::move(DFA_graph)); + reg = RegularTree(reg).ToString(); + + r = RegularTree(reg); + NFA_tree = RegularToNFAGraph(std::move(r)); + DFA_graph = NFAGraphToDFAGraph(std::move(NFA_tree)); + DFA_graph = DFAGraphToMinDFAGraph(std::move(DFA_graph)); + + ASSERT_EQ(DFA_graph.Accepted("abc"), true); + 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), false); + } + } +} + +TEST(DFA_to_regular2, 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)); + + std::string reg = DFAGraphToRegular(std::move(DFA_graph)); + reg = RegularTree(reg).ToString(); + + r = RegularTree(reg); + NFA_tree = RegularToNFAGraph(std::move(r)); + DFA_graph = NFAGraphToDFAGraph(std::move(NFA_tree)); + DFA_graph = DFAGraphToMinDFAGraph(std::move(DFA_graph)); + + ASSERT_EQ(DFA_graph.Accepted("a"), true); + ASSERT_EQ(DFA_graph.Accepted("b"), true); + ASSERT_EQ(DFA_graph.Accepted("c"), true); + 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), false); + } + } +} + +TEST(DFA_to_regular2, 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)); + + std::string reg = DFAGraphToRegular(std::move(DFA_graph)); + reg = RegularTree(reg).ToString(); + + r = RegularTree(reg); + NFA_tree = RegularToNFAGraph(std::move(r)); + DFA_graph = NFAGraphToDFAGraph(std::move(NFA_tree)); + DFA_graph = DFAGraphToMinDFAGraph(std::move(DFA_graph)); + + auto check = [](const std::string str) { + std::set 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(""), true); + 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(DFA_to_regular2, _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)); + + std::string reg = DFAGraphToRegular(std::move(DFA_graph)); + reg = RegularTree(reg).ToString(); + + r = RegularTree(reg); + NFA_tree = RegularToNFAGraph(std::move(r)); + DFA_graph = NFAGraphToDFAGraph(std::move(NFA_tree)); + DFA_graph = DFAGraphToMinDFAGraph(std::move(DFA_graph)); + + auto check = [](const std::string str) { + std::set s(str.begin(), str.end()); + return s.find('d') == s.end(); + }; + + ASSERT_EQ(DFA_graph.Accepted(""), true); + 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(DFA_to_regular2, _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)); + + std::string reg = DFAGraphToRegular(std::move(DFA_graph)); + reg = RegularTree(reg).ToString(); + + r = RegularTree(reg); + NFA_tree = RegularToNFAGraph(std::move(r)); + DFA_graph = NFAGraphToDFAGraph(std::move(NFA_tree)); + DFA_graph = DFAGraphToMinDFAGraph(std::move(DFA_graph)); + + auto check = [](const std::string str) { + std::set s(str.begin(), str.end()); + return s.find('d') == s.end(); + }; + + ASSERT_EQ(DFA_graph.Accepted(""), true); + for (int i = 0; i < 1000; ++i) { + auto s = GenerateRandomString({'a', 'b', 'c', 'd'}, rnd() % 10); + + ASSERT_EQ(DFA_graph.Accepted(s), check(s)); + } +} From f715234f41707d91047c7ca7e1b959e11de8ef08 Mon Sep 17 00:00:00 2001 From: MaxanRus Date: Tue, 5 Oct 2021 20:41:05 +0300 Subject: [PATCH 12/17] dot files --- CMakeLists.txt | 5 ++--- include/DFA/DFAGraph.hpp | 1 + include/NFA/NFAGraph.hpp | 1 + src/DFA/DFAGraph.cpp | 21 +++++++++++++++++++++ src/NFA/NFAGraph.cpp | 23 +++++++++++++++++++++++ src/converters/DFAToMinDFA.cpp | 3 +-- src/main.cpp | 16 ++++++++++++---- 7 files changed, 61 insertions(+), 9 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 6395d82..d479af6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3,6 +3,7 @@ cmake_minimum_required(VERSION 3.10) project("Formalang") # set(CMAKE_CXX_FLAGS "-O3") +# set(CMAKE_CXX_FLAGS "-O0 --coverage -ftest-coverage -fprofile-arcs") find_package(GTest REQUIRED) find_package(Threads REQUIRED) @@ -19,7 +20,7 @@ set(SOURCE_FILES src/regular/RegularTree.cpp src/regular/RegularTreeNode.cpp src/NFA/NFAGraph.cpp - src/NFA/NFAGraphVertex.cpp + src/NFA/NFAGraphVertex.cpp src/converters/RegularToNFA.cpp src/converters/NFAToDFA.cpp src/DFA/DFAGraph.cpp @@ -44,5 +45,3 @@ add_executable(Formalang src/main.cpp ${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) - diff --git a/include/DFA/DFAGraph.hpp b/include/DFA/DFAGraph.hpp index a04c796..82b5c5a 100644 --- a/include/DFA/DFAGraph.hpp +++ b/include/DFA/DFAGraph.hpp @@ -59,6 +59,7 @@ class DFAGraph { void Print() const; bool Accepted(const std::string&) const; + void CreateDotFile(const std::string& filename) const; private: size_t count_vertexes_ = 0; std::map> vertexes_; diff --git a/include/NFA/NFAGraph.hpp b/include/NFA/NFAGraph.hpp index abbabaf..69e1d45 100644 --- a/include/NFA/NFAGraph.hpp +++ b/include/NFA/NFAGraph.hpp @@ -61,6 +61,7 @@ class NFAGraph { const std::vector& GetStartVertexes() const; void Print() const; + void CreateDotFile(const std::string& filename) const; private: size_t count_vertexes_ = 0; std::map> vertexes_; diff --git a/src/DFA/DFAGraph.cpp b/src/DFA/DFAGraph.cpp index 1024151..05378b3 100644 --- a/src/DFA/DFAGraph.cpp +++ b/src/DFA/DFAGraph.cpp @@ -1,6 +1,7 @@ #include "DFA/DFAGraph.hpp" #include #include +#include namespace DFA { DFAGraph::DFAGraph(DFAGraph&& another) { @@ -119,5 +120,25 @@ bool DFAGraph::Accepted(const std::string& str) const { } return current->IsFinal(); } +void DFAGraph::CreateDotFile(const std::string& filename) const { + std::ofstream out(filename); + out << "digraph G {\n"; + + for (auto& i: vertexes_) { + for (auto& j: i.second->transitions_) { + out << i.first << "->" << j.second << "[label=" << j.first << "]\n"; + } + if (i.second->IsStart() && i.second->IsFinal()) { + out << " " << i.first << " [shape=star];\n"; + } else if (i.second->IsStart()) { + out << " " << i.first << " [shape=rarrow];\n"; + } else if (i.second->IsFinal()) { + out << " " << i.first << " [shape=Msquare];\n"; + } + } + + out << "}\n"; + +} } diff --git a/src/NFA/NFAGraph.cpp b/src/NFA/NFAGraph.cpp index aefe35a..ade1e57 100644 --- a/src/NFA/NFAGraph.cpp +++ b/src/NFA/NFAGraph.cpp @@ -1,6 +1,7 @@ #include "NFA/NFAGraph.hpp" #include #include +#include namespace NFA { NFAGraph::NFAGraph(NFAGraph&& another) { @@ -168,4 +169,26 @@ void NFAGraph::Print() const { } std::cout << std::endl; } + +void NFAGraph::CreateDotFile(const std::string& filename) const { + std::ofstream out(filename); + out << "digraph G {\n"; + + for (auto& i: vertexes_) { + for (auto& j: i.second->transitions_) { + for (auto& k: j.second) { + out << i.first << "->" << k << "[label=" << j.first << "]\n"; + } + } + if (i.second->IsStart() && i.second->IsFinal()) { + out << " " << i.first << " [shape=Mstar];\n"; + } else if (i.second->IsStart()) { + out << " " << i.first << " [shape=Mdiamond];\n"; + } else if (i.second->IsFinal()) { + out << " " << i.first << " [shape=Msquare];\n"; + } + } + + out << "}\n"; +} } diff --git a/src/converters/DFAToMinDFA.cpp b/src/converters/DFAToMinDFA.cpp index 4a67245..5372265 100644 --- a/src/converters/DFAToMinDFA.cpp +++ b/src/converters/DFAToMinDFA.cpp @@ -1,4 +1,5 @@ #include "converters/DFAToMinDFA.hpp" +#include namespace converters { DFAGraph DFAGraphToMinDFAGraph(DFAGraph&& graph) { @@ -65,7 +66,6 @@ DFAGraph DFAGraphToMinDFAGraph(DFAGraph&& graph) { } } - /* for (int i = 0; i < n; ++i) { for (int k = 0; k < n; ++k) { for (int j = 0; j < alphabet.size() + 1; ++j) { @@ -75,7 +75,6 @@ DFAGraph DFAGraphToMinDFAGraph(DFAGraph&& graph) { } std::cout << std::endl; } - */ std::vector>& last_layer(table.back()); size_t count_vertex = 0; diff --git a/src/main.cpp b/src/main.cpp index d4946b5..30193c9 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,5 +1,4 @@ #include -#include #include "regular/RegularTree.hpp" #include "converters/RegularToNFA.hpp" #include "converters/NFAToDFA.hpp" @@ -52,13 +51,22 @@ void example2() { int main() { { - RegularTree r("(a|b)+bab(a|b)+"); + RegularTree r("((ab|ba)*( |a|ba))"); NFAGraph NFA_tree = RegularToNFAGraph(std::move(r)); DFAGraph DFA_graph = NFAGraphToDFAGraph(std::move(NFA_tree)); - DFA_graph = DFAGraphToMinDFAGraph(std::move(DFA_graph)); - + // DFA_graph.CreateDotFile("1.dot"); + // DFA_graph = DFAGraphToMinDFAGraph(std::move(DFA_graph)); DFA_graph = DFAGraphToFDFAGraph(std::move(DFA_graph), {'a', 'b'}); DFA_graph = InvertFDFAGraph(std::move(DFA_graph)); + // DFA_graph.CreateDotFile("2.dot"); + auto ss = DFAGraphToRegular(std::move(DFA_graph)); + std::cout << ss << std::endl; + r = RegularTree(ss); + // r.Print(); + std::cout << r.ToString() << std::endl; + // DFA_graph.Print(); + return 0; + DFA_graph = DFAGraphToMinDFAGraph(std::move(DFA_graph)); DFA_graph.Print(); auto s = DFAGraphToRegular(std::move(DFA_graph)); From 7023d46c56c106e2a2640b90c62e6c2777b87f8a Mon Sep 17 00:00:00 2001 From: MaxanRus Date: Wed, 6 Oct 2021 11:11:51 +0300 Subject: [PATCH 13/17] add readme --- README.md | 41 +++++++++++++++++++++++++++++++++++++++++ src/main.cpp | 3 ++- 2 files changed, 43 insertions(+), 1 deletion(-) create mode 100644 README.md diff --git a/README.md b/README.md new file mode 100644 index 0000000..c18d217 --- /dev/null +++ b/README.md @@ -0,0 +1,41 @@ +# Formalang +```c++ +#include "regular/RegularTree.hpp" +#include "NFA/NFAGraph.hpp" +#include "DFA/DFAGraph.hpp" +#include "converters/RegularToNFA.hpp" +#include "converters/NFAToDFA.hpp" +#include "converters/DFAToFDFA.hpp" +#include "converters/DFAToMinDFA.hpp" +#include "converters/DFAToRegular.hpp" +#include "converters/InvertFDFA.hpp" + +using namespace regular; +using namespace NFA; +using namespace DFA; +using namespace converters; +``` +так можно подключить все что есть в моей программе. +```c++ +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.Print(); // Мой вывод +DFA_graph.CreateDotFile("2.dot"); // Вывод в dot файл +std::string reg = DFAGraphToRegular(std::move(DFA_graph)); // В регулярку +``` +Такой вывод в регулярку как показано в прошлом примере сделает много лишних скобок, если мы хотим привести к более нормальному виду, то можно сделать так +```c++ +RegularTree(reg).ToString() // Получится более красивая регулярка +``` +Про сами регулярки + * - это плюс и звезда Клини. Их можно писать после слов, или после скобок. +abacaba* ~ (abacaba)\*. a(b)a\* ~ a(b)(a)\*. Для сложения языков используется |. Символом пустого слова является пробел. + +Примеры регулярок + +a* + +a(b)+a + +(a|b)* diff --git a/src/main.cpp b/src/main.cpp index 30193c9..701fd02 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,5 +1,7 @@ #include #include "regular/RegularTree.hpp" +#include "NFA/NFAGraph.hpp" +#include "DFA/DFAGraph.hpp" #include "converters/RegularToNFA.hpp" #include "converters/NFAToDFA.hpp" #include "converters/DFAToFDFA.hpp" @@ -7,7 +9,6 @@ #include "converters/DFAToRegular.hpp" #include "converters/InvertFDFA.hpp" -using namespace regular; using namespace regular; using namespace NFA; using namespace DFA; From 1aed271643ffd84543b5922d9a2f30e4364695b3 Mon Sep 17 00:00:00 2001 From: MaxanRus Date: Sun, 10 Oct 2021 21:08:13 +0300 Subject: [PATCH 14/17] Delete unnecessary shared pointer --- include/DFA/DFAGraph.hpp | 5 ++- include/NFA/NFAGraph.hpp | 6 ++- src/DFA/DFAGraph.cpp | 64 +++++++++++++------------- src/DFA/DFAGraphVertex.cpp | 4 +- src/NFA/NFAGraph.cpp | 80 +++++++++++++++++---------------- src/NFA/NFAGraphVertex.cpp | 10 ++--- src/converters/DFAToFDFA.cpp | 24 +++++----- src/converters/DFAToMinDFA.cpp | 18 ++++---- src/converters/DFAToRegular.cpp | 14 +++--- src/converters/InvertFDFA.cpp | 4 +- src/converters/NFAToDFA.cpp | 55 ++++++++++++----------- src/converters/RegularToNFA.cpp | 20 ++++----- src/main.cpp | 2 +- 13 files changed, 159 insertions(+), 147 deletions(-) diff --git a/include/DFA/DFAGraph.hpp b/include/DFA/DFAGraph.hpp index 82b5c5a..d410e9a 100644 --- a/include/DFA/DFAGraph.hpp +++ b/include/DFA/DFAGraph.hpp @@ -51,7 +51,8 @@ class DFAGraph { void RemoveFinalVertex(size_t number); void RemoveStartVertex(size_t number); - std::shared_ptr GetVertex(size_t number); + Vertex& GetVertex(size_t number); + bool NotExistVertex(size_t number); size_t GetCountVertexes() const; const std::vector& GetFinalVertexes() const; @@ -62,7 +63,7 @@ class DFAGraph { void CreateDotFile(const std::string& filename) const; private: size_t count_vertexes_ = 0; - std::map> vertexes_; + std::map vertexes_; std::vector final_vertexes_; std::vector start_vertexes_; }; diff --git a/include/NFA/NFAGraph.hpp b/include/NFA/NFAGraph.hpp index 69e1d45..6fd1738 100644 --- a/include/NFA/NFAGraph.hpp +++ b/include/NFA/NFAGraph.hpp @@ -55,7 +55,9 @@ class NFAGraph { std::vector start_vertexes, std::vector final_vertexes); - std::shared_ptr GetVertex(size_t number); + Vertex& GetVertex(size_t number); + bool NotExistVertex(size_t number); + size_t GetCountVertexes() const; const std::vector& GetFinalVertexes() const; const std::vector& GetStartVertexes() const; @@ -64,7 +66,7 @@ class NFAGraph { void CreateDotFile(const std::string& filename) const; private: size_t count_vertexes_ = 0; - std::map> vertexes_; + std::map vertexes_; std::vector final_vertexes_; std::vector start_vertexes_; }; diff --git a/src/DFA/DFAGraph.cpp b/src/DFA/DFAGraph.cpp index 05378b3..3742ec0 100644 --- a/src/DFA/DFAGraph.cpp +++ b/src/DFA/DFAGraph.cpp @@ -11,9 +11,9 @@ DFAGraph::DFAGraph(DFAGraph&& another) { std::swap(start_vertexes_, another.start_vertexes_); for (auto& i: vertexes_) - i.second->owner_ = this; + i.second.owner_ = this; for (auto& i: another.vertexes_) - i.second->owner_ = &another; + i.second.owner_ = &another; } DFAGraph& DFAGraph::operator=(DFAGraph&& another) { @@ -23,27 +23,27 @@ DFAGraph& DFAGraph::operator=(DFAGraph&& another) { std::swap(start_vertexes_, another.start_vertexes_); for (auto& i: vertexes_) - i.second->owner_ = this; + i.second.owner_ = this; for (auto& i: another.vertexes_) - i.second->owner_ = &another; + i.second.owner_ = &another; return *this; } size_t DFAGraph::AddNewVertex() { - vertexes_[count_vertexes_] = std::make_shared(this); - vertexes_[count_vertexes_]->number_ = count_vertexes_; + vertexes_.emplace(count_vertexes_, this); + GetVertex(count_vertexes_).number_ = count_vertexes_; return count_vertexes_++; } void DFAGraph::AddFinalVertex(size_t number) { - if (!vertexes_[number]->is_final_) { - vertexes_[number]->is_final_ = true; + if (!GetVertex(number).is_final_) { + GetVertex(number).is_final_ = true; final_vertexes_.push_back(number); } } void DFAGraph::AddStartVertex(size_t number) { - if (!vertexes_[number]->is_start_) { - vertexes_[number]->is_start_ = true; + if (!GetVertex(number).is_start_) { + GetVertex(number).is_start_ = true; start_vertexes_.push_back(number); } } @@ -58,7 +58,7 @@ void DFAGraph::RemoveVertex(size_t number) { void DFAGraph::RemoveFinalVertex(size_t number) { for (size_t i = 0; i < final_vertexes_.size(); ++i) { if (final_vertexes_[i] == number) { - vertexes_[number]->is_final_ = false; + GetVertex(number).is_final_ = false; std::swap(final_vertexes_[i], final_vertexes_.back()); final_vertexes_.pop_back(); break; @@ -69,7 +69,7 @@ void DFAGraph::RemoveFinalVertex(size_t number) { void DFAGraph::RemoveStartVertex(size_t number) { for (size_t i = 0; i < start_vertexes_.size(); ++i) { if (start_vertexes_[i] == number) { - vertexes_[number]->is_start_ = false; + GetVertex(number).is_start_ = false; std::swap(start_vertexes_[i], start_vertexes_.back()); start_vertexes_.pop_back(); break; @@ -77,10 +77,14 @@ void DFAGraph::RemoveStartVertex(size_t number) { } } -std::shared_ptr DFAGraph::GetVertex(size_t number) { - if (vertexes_.count(number)) - return vertexes_[number]; - return nullptr; +DFAGraph::Vertex& DFAGraph::GetVertex(size_t number) { + if (!NotExistVertex(number)) + return vertexes_.at(number); + throw std::out_of_range("This vertex don't exist"); +} + +bool DFAGraph::NotExistVertex(size_t number) { + return !vertexes_.count(number); } size_t DFAGraph::GetCountVertexes() const { @@ -97,12 +101,12 @@ const std::vector& DFAGraph::GetStartVertexes() const { void DFAGraph::Print() const { for (auto i: vertexes_) { - std::cout << i.second->number_ << " " << "f-" << i.second->is_final_ << " s-" << - i.second->is_start_ << std::endl; + std::cout << i.second.number_ << " " << "f-" << i.second.is_final_ << " s-" << + i.second.is_start_ << std::endl; } for (auto& i: vertexes_) { - for (auto& j: i.second->transitions_) { - std::cout << i.second->number_ << "->" << j.second << " <" << j.first << ">" << + for (auto& j: i.second.transitions_) { + std::cout << i.second.number_ << "->" << j.second << " <" << j.first << ">" << std::endl; } } @@ -110,35 +114,35 @@ void DFAGraph::Print() const { } bool DFAGraph::Accepted(const std::string& str) const { - std::shared_ptr current = vertexes_.at(start_vertexes_[0]); + size_t current = vertexes_.at(start_vertexes_[0]).GetNumber(); for (auto i: str) { - if (current->GetTransitions().count(i)) { - current = vertexes_.at(current->GetTransitions().at(i)); + if (vertexes_.at(current).GetTransitions().count(i)) { + current = vertexes_.at(vertexes_.at(current).GetTransitions().at(i)).GetNumber(); } else { return false; } } - return current->IsFinal(); + return vertexes_.at(current).IsFinal(); } + void DFAGraph::CreateDotFile(const std::string& filename) const { std::ofstream out(filename); out << "digraph G {\n"; for (auto& i: vertexes_) { - for (auto& j: i.second->transitions_) { - out << i.first << "->" << j.second << "[label=" << j.first << "]\n"; + for (auto& j: i.second.transitions_) { + out << i.first << "." << j.second << "[label=" << j.first << "]\n"; } - if (i.second->IsStart() && i.second->IsFinal()) { + if (i.second.IsStart() && i.second.IsFinal()) { out << " " << i.first << " [shape=star];\n"; - } else if (i.second->IsStart()) { + } else if (i.second.IsStart()) { out << " " << i.first << " [shape=rarrow];\n"; - } else if (i.second->IsFinal()) { + } else if (i.second.IsFinal()) { out << " " << i.first << " [shape=Msquare];\n"; } } out << "}\n"; - } } diff --git a/src/DFA/DFAGraphVertex.cpp b/src/DFA/DFAGraphVertex.cpp index 015ba92..b1602c8 100644 --- a/src/DFA/DFAGraphVertex.cpp +++ b/src/DFA/DFAGraphVertex.cpp @@ -26,11 +26,11 @@ const std::map& Vertex::GetBackTransitions() const { void Vertex::AddEdge(char symbol, size_t number) { transitions_[symbol] = number; - owner_->GetVertex(number)->back_transitions_[symbol] = number_; + owner_->GetVertex(number).back_transitions_[symbol] = number_; } void Vertex::RemoveEdge(char symbol) { - owner_->GetVertex(transitions_[symbol])->back_transitions_.erase(symbol); + owner_->GetVertex(transitions_[symbol]).back_transitions_.erase(symbol); transitions_.erase(symbol); } diff --git a/src/NFA/NFAGraph.cpp b/src/NFA/NFAGraph.cpp index ade1e57..b27bb21 100644 --- a/src/NFA/NFAGraph.cpp +++ b/src/NFA/NFAGraph.cpp @@ -11,9 +11,9 @@ NFAGraph::NFAGraph(NFAGraph&& another) { std::swap(start_vertexes_, another.start_vertexes_); for (auto& i: vertexes_) - i.second->owner_ = this; + i.second.owner_ = this; for (auto& i: another.vertexes_) - i.second->owner_ = &another; + i.second.owner_ = &another; } NFAGraph& NFAGraph::operator=(NFAGraph&& another) { @@ -23,28 +23,28 @@ NFAGraph& NFAGraph::operator=(NFAGraph&& another) { std::swap(start_vertexes_, another.start_vertexes_); for (auto& i: vertexes_) - i.second->owner_ = this; + i.second.owner_ = this; for (auto& i: another.vertexes_) - i.second->owner_ = &another; + i.second.owner_ = &another; return *this; } size_t NFAGraph::AddNewVertex() { - vertexes_[count_vertexes_] = std::make_shared(this); - vertexes_[count_vertexes_]->number_ = count_vertexes_; + vertexes_.emplace(count_vertexes_, this); + GetVertex(count_vertexes_).number_ = count_vertexes_; return count_vertexes_++; } void NFAGraph::AddFinalVertex(size_t number) { - if (!vertexes_[number]->is_final_) { - vertexes_[number]->is_final_ = true; + if (!GetVertex(number).is_final_) { + GetVertex(number).is_final_ = true; final_vertexes_.push_back(number); } } void NFAGraph::AddStartVertex(size_t number) { - if (!vertexes_[number]->is_start_) { - vertexes_[number]->is_start_ = true; + if (!GetVertex(number).is_start_) { + GetVertex(number).is_start_ = true; start_vertexes_.push_back(number); } } @@ -58,7 +58,7 @@ void NFAGraph::RemoveVertex(size_t number) { void NFAGraph::RemoveFinalVertex(size_t number) { for (size_t i = 0; i < final_vertexes_.size(); ++i) { if (final_vertexes_[i] == number) { - vertexes_[number]->is_final_ = false; + GetVertex(number).is_final_ = false; std::swap(final_vertexes_[i], final_vertexes_.back()); final_vertexes_.pop_back(); break; @@ -69,7 +69,7 @@ void NFAGraph::RemoveFinalVertex(size_t number) { void NFAGraph::RemoveStartVertex(size_t number) { for (size_t i = 0; i < start_vertexes_.size(); ++i) { if (start_vertexes_[i] == number) { - vertexes_[number]->is_start_ = false; + GetVertex(number).is_start_ = false; std::swap(start_vertexes_[i], start_vertexes_.back()); start_vertexes_.pop_back(); break; @@ -87,24 +87,24 @@ void NFAGraph::Composition(NFAGraph&& nfa_graph, for (auto& i: nfa_graph.vertexes_) { new_count_vertexes = std::max(new_count_vertexes, i.first + count_vertexes_ + 1); - i.second->number_ += count_vertexes_; + i.second.number_ += count_vertexes_; std::map> new_transitions; - for (auto& j: i.second->transitions_) { + for (auto& j: i.second.transitions_) { for (auto& k: j.second) { new_transitions[j.first].insert(k + count_vertexes_); } } std::map> new_back_transitions; - for (auto& j: i.second->back_transitions_) { + for (auto& j: i.second.back_transitions_) { for (auto& k: j.second) { new_back_transitions[j.first].insert(k + count_vertexes_); } } - i.second->transitions_ = std::move(new_transitions); - i.second->back_transitions_ = std::move(new_back_transitions); + i.second.transitions_ = std::move(new_transitions); + i.second.back_transitions_ = std::move(new_back_transitions); - i.second->SetOwner(this); - vertexes_[i.second->number_] = std::move(i.second); + i.second.SetOwner(this); + vertexes_.emplace(i.second.number_, std::move(i.second)); } for (auto& i: add_start_vertexes) { @@ -118,28 +118,32 @@ void NFAGraph::Composition(NFAGraph&& nfa_graph, for (auto& i: start_vertexes) { for (auto& j: add_start_vertexes) { - vertexes_[i]->transitions_[' '].insert(j); - vertexes_[j]->back_transitions_[' '].insert(i); + GetVertex(i).transitions_[' '].insert(j); + GetVertex(j).back_transitions_[' '].insert(i); } } for (auto& i: add_final_vertexes) { for (auto& j: final_vertexes) { - vertexes_[i]->transitions_[' '].insert(j); - vertexes_[j]->back_transitions_[' '].insert(i); + GetVertex(i).transitions_[' '].insert(j); + GetVertex(j).back_transitions_[' '].insert(i); } } for (auto& i: add_final_vertexes) { - vertexes_[i]->is_final_ = false; + GetVertex(i).is_final_ = false; } for (auto& i: add_start_vertexes) { - vertexes_[i]->is_start_ = false; + GetVertex(i).is_start_ = false; } } -std::shared_ptr NFAGraph::GetVertex(size_t number) { - if (vertexes_.count(number)) - return vertexes_[number]; - return nullptr; +NFAGraph::Vertex& NFAGraph::GetVertex(size_t number) { + if (!NotExistVertex(number)) + return vertexes_.at(number); + throw std::out_of_range("This vertex don't exist"); +} + +bool NFAGraph::NotExistVertex(size_t number) { + return !vertexes_.count(number); } size_t NFAGraph::GetCountVertexes() const { @@ -156,13 +160,13 @@ const std::vector& NFAGraph::GetStartVertexes() const { void NFAGraph::Print() const { for (auto i: vertexes_) { - std::cout << i.second->number_ << " " << "f-" << i.second->is_final_ << " s-" << - i.second->is_start_ << std::endl; + std::cout << i.second.number_ << " " << "f-" << i.second.is_final_ << " s-" << + i.second.is_start_ << std::endl; } for (auto& i: vertexes_) { - for (auto& j: i.second->transitions_) { + for (auto& j: i.second.transitions_) { for (auto k: j.second) { - std::cout << i.second->number_ << "->" << k << " <" << j.first << ">" << + std::cout << i.second.number_ << "." << k << " <" << j.first << ">" << std::endl; } } @@ -175,16 +179,16 @@ void NFAGraph::CreateDotFile(const std::string& filename) const { out << "digraph G {\n"; for (auto& i: vertexes_) { - for (auto& j: i.second->transitions_) { + for (auto& j: i.second.transitions_) { for (auto& k: j.second) { - out << i.first << "->" << k << "[label=" << j.first << "]\n"; + out << i.first << "." << k << "[label=" << j.first << "]\n"; } } - if (i.second->IsStart() && i.second->IsFinal()) { + if (i.second.IsStart() && i.second.IsFinal()) { out << " " << i.first << " [shape=Mstar];\n"; - } else if (i.second->IsStart()) { + } else if (i.second.IsStart()) { out << " " << i.first << " [shape=Mdiamond];\n"; - } else if (i.second->IsFinal()) { + } else if (i.second.IsFinal()) { out << " " << i.first << " [shape=Msquare];\n"; } } diff --git a/src/NFA/NFAGraphVertex.cpp b/src/NFA/NFAGraphVertex.cpp index a887fae..32610a9 100644 --- a/src/NFA/NFAGraphVertex.cpp +++ b/src/NFA/NFAGraphVertex.cpp @@ -26,17 +26,17 @@ const std::map>& Vertex::GetBackTransitions() const { void Vertex::AddEdge(char symbol, size_t number) { transitions_[symbol].insert(number); - owner_->GetVertex(number)->back_transitions_[symbol]; - owner_->GetVertex(number)->back_transitions_[symbol].insert(number_); + owner_->GetVertex(number).back_transitions_[symbol]; + owner_->GetVertex(number).back_transitions_[symbol].insert(number_); } void Vertex::RemoveEdge(char symbol, size_t number) { transitions_[symbol].erase(number); if (transitions_[symbol].size() == 0) transitions_.erase(symbol); - owner_->GetVertex(number)->back_transitions_[symbol].erase(number_); - if (owner_->GetVertex(number)->back_transitions_[symbol].size() == 0) - owner_->GetVertex(number)->back_transitions_.erase(symbol); + owner_->GetVertex(number).back_transitions_[symbol].erase(number_); + if (owner_->GetVertex(number).back_transitions_[symbol].size() == 0) + owner_->GetVertex(number).back_transitions_.erase(symbol); } void Vertex::SetOwner(NFAGraph* owner) { diff --git a/src/converters/DFAToFDFA.cpp b/src/converters/DFAToFDFA.cpp index 8120746..6b7245d 100644 --- a/src/converters/DFAToFDFA.cpp +++ b/src/converters/DFAToFDFA.cpp @@ -6,38 +6,38 @@ DFAGraph DFAGraphToFDFAGraph(DFAGraph&& graph, const std::vector& alphabet const int n = graph.GetCountVertexes(); std::map number_vertex_in_DFA; for (int i = 0; i < n; ++i) { - if (!graph.GetVertex(i)) continue; + if (graph.NotExistVertex(i)) continue; number_vertex_in_DFA[i] = result.AddNewVertex(); } for (int i = 0; i < n; ++i) { - if (!graph.GetVertex(i)) continue; - if (graph.GetVertex(i)->IsFinal()) - result.GetVertex(number_vertex_in_DFA[i])->SetFinal(true); - if (graph.GetVertex(i)->IsStart()) - result.GetVertex(number_vertex_in_DFA[i])->SetStart(true); + if (graph.NotExistVertex(i)) continue; + if (graph.GetVertex(i).IsFinal()) + result.GetVertex(number_vertex_in_DFA[i]).SetFinal(true); + if (graph.GetVertex(i).IsStart()) + result.GetVertex(number_vertex_in_DFA[i]).SetStart(true); - const auto& transitions = graph.GetVertex(i)->GetTransitions(); + const auto& transitions = graph.GetVertex(i).GetTransitions(); for (const auto& t: transitions) { - result.GetVertex(number_vertex_in_DFA[i])->AddEdge(t.first, t.second); + result.GetVertex(number_vertex_in_DFA[i]).AddEdge(t.first, t.second); } } size_t drain = result.AddNewVertex(); for (int i = 0; i < n; ++i) { - const auto& transitions = graph.GetVertex(i)->GetTransitions(); + const auto& transitions = graph.GetVertex(i).GetTransitions(); for (char j: alphabet) { if (!transitions.count(j)) { - result.GetVertex(i)->AddEdge(j, drain); + result.GetVertex(i).AddEdge(j, drain); } } } - if (result.GetVertex(drain)->GetBackTransitions().size() == 0) { + if (result.GetVertex(drain).GetBackTransitions().size() == 0) { result.RemoveVertex(drain); } else { for (char j: alphabet) { - result.GetVertex(drain)->AddEdge(j, drain); + result.GetVertex(drain).AddEdge(j, drain); } } diff --git a/src/converters/DFAToMinDFA.cpp b/src/converters/DFAToMinDFA.cpp index 5372265..591e49e 100644 --- a/src/converters/DFAToMinDFA.cpp +++ b/src/converters/DFAToMinDFA.cpp @@ -11,8 +11,8 @@ DFAGraph DFAGraphToMinDFAGraph(DFAGraph&& graph) { { std::set set_alphabet; for (int i = 0; i < n; ++i) { - if (!graph.GetVertex(i)) continue; - for (auto i: graph.GetVertex(i)->GetTransitions()) { + if (graph.NotExistVertex(i)) continue; + for (auto i: graph.GetVertex(i).GetTransitions()) { set_alphabet.insert(i.first); } } @@ -25,11 +25,11 @@ DFAGraph DFAGraphToMinDFAGraph(DFAGraph&& graph) { { std::vector>& layer(table[0]); for (int i = 0; i < n; ++i) { - layer[i][0] = graph.GetVertex(i)->IsFinal(); + layer[i][0] = graph.GetVertex(i).IsFinal(); } for (int i = 0; i < n; ++i) { for (int j = 0; j < alphabet.size(); ++j) { - const auto& transitions = graph.GetVertex(i)->GetTransitions(); + const auto& transitions = graph.GetVertex(i).GetTransitions(); if (transitions.count(alphabet[j])) layer[i][j + 1] = layer[transitions.at(alphabet[j])][0]; else @@ -57,7 +57,7 @@ DFAGraph DFAGraphToMinDFAGraph(DFAGraph&& graph) { } for (int i = 0; i < n; ++i) { for (int j = 0; j < alphabet.size(); ++j) { - const auto& transitions = graph.GetVertex(i)->GetTransitions(); + const auto& transitions = graph.GetVertex(i).GetTransitions(); if (transitions.count(alphabet[j])) layer[i][j + 1] = layer[transitions.at(alphabet[j])][0]; else @@ -92,16 +92,16 @@ DFAGraph DFAGraphToMinDFAGraph(DFAGraph&& graph) { for (int i = 0; i < n; ++i) { size_t v = number_vertex_in_DFA[last_layer[i][0]]; - const auto& transitions = graph.GetVertex(i)->GetTransitions(); + const auto& transitions = graph.GetVertex(i).GetTransitions(); for (const auto& t: transitions) { if (last_layer[t.second][0] != -1LL) { size_t u = number_vertex_in_DFA[last_layer[t.second][0]]; - result.GetVertex(v)->AddEdge(t.first, u); + result.GetVertex(v).AddEdge(t.first, u); } } - if (graph.GetVertex(i)->IsStart()) result.GetVertex(v)->SetStart(true); - if (graph.GetVertex(i)->IsFinal()) result.GetVertex(v)->SetFinal(true); + if (graph.GetVertex(i).IsStart()) result.GetVertex(v).SetStart(true); + if (graph.GetVertex(i).IsFinal()) result.GetVertex(v).SetFinal(true); } return result; diff --git a/src/converters/DFAToRegular.cpp b/src/converters/DFAToRegular.cpp index 4a59507..ffd6f0c 100644 --- a/src/converters/DFAToRegular.cpp +++ b/src/converters/DFAToRegular.cpp @@ -12,8 +12,8 @@ std::string DFAGraphToRegular(DFAGraph&& graph) { size_t start = -1; for (int i = 0; i < n - 1; ++i) { - if (!graph.GetVertex(i)) continue; - if (graph.GetVertex(i)->IsStart()) start = i; + if (graph.NotExistVertex(i)) continue; + if (graph.GetVertex(i).IsStart()) start = i; } rename[start] = 1; @@ -26,13 +26,13 @@ std::string DFAGraphToRegular(DFAGraph&& graph) { for (int i = 0; i < n - 1; ++i) { - if (!graph.GetVertex(i)) continue; - const auto& vertex_transitions = graph.GetVertex(i)->GetTransitions(); + if (graph.NotExistVertex(i)) continue; + const auto& vertex_transitions = graph.GetVertex(i).GetTransitions(); for (auto j: vertex_transitions) { transitions[rename[i]][rename[j.second]].insert(std::string(1, j.first)); } - if (graph.GetVertex(i)->IsFinal()) { + if (graph.GetVertex(i).IsFinal()) { transitions[rename[i]][0].insert("( )"); } } @@ -99,7 +99,7 @@ std::string DFAGraphToRegular(DFAGraph&& graph) { std::string begin_to_end; if (transitions[1][1].size() != 0) { - for (const std::string s: transitions[1][1]) { + for (const std::string& s: transitions[1][1]) { loop += "("; loop += s; loop += ")"; @@ -109,7 +109,7 @@ std::string DFAGraphToRegular(DFAGraph&& graph) { loop.pop_back(); loop = "(" + loop + ")*"; } - for (const std::string s: transitions[1][0]) { + for (const std::string& s: transitions[1][0]) { begin_to_end += "("; begin_to_end += s; begin_to_end += ")"; diff --git a/src/converters/InvertFDFA.cpp b/src/converters/InvertFDFA.cpp index 4d3c5e0..61ad9e2 100644 --- a/src/converters/InvertFDFA.cpp +++ b/src/converters/InvertFDFA.cpp @@ -4,8 +4,8 @@ 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()); + if (fdfa_graph.NotExistVertex(i)) continue; + fdfa_graph.GetVertex(i).SetFinal(fdfa_graph.GetVertex(i).IsFinal()); } return std::move(fdfa_graph); } diff --git a/src/converters/NFAToDFA.cpp b/src/converters/NFAToDFA.cpp index 29e2df6..fe24976 100644 --- a/src/converters/NFAToDFA.cpp +++ b/src/converters/NFAToDFA.cpp @@ -10,13 +10,13 @@ NFAGraph AddAllEpsilonTransitions(NFAGraph&& nfa_graph) { std::function dfs = [&nfa_graph, &used, &dfs](int u, int v) -> void { used[v] = true; - const auto& transitions = nfa_graph.GetVertex(v)->GetTransitions(); + const auto& transitions = nfa_graph.GetVertex(v).GetTransitions(); if (transitions.count(' ')) { const auto& s = transitions.at(' '); for (auto i: s) { if (!used[i]) { if (u != i) - nfa_graph.GetVertex(u)->AddEdge(' ', i); + nfa_graph.GetVertex(u).AddEdge(' ', i); dfs(u, i); } } @@ -24,7 +24,7 @@ NFAGraph AddAllEpsilonTransitions(NFAGraph&& nfa_graph) { }; for (int i = 0; i < n; ++i) { - if (!nfa_graph.GetVertex(i)) continue; + if (nfa_graph.NotExistVertex(i)) continue; used.assign(n, false); dfs(i, i); @@ -36,15 +36,15 @@ NFAGraph AddAllPossibleStartFinal(NFAGraph&& nfa_graph) { if (nfa_graph.GetStartVertexes().size() != 1) { size_t start_vertex = nfa_graph.AddNewVertex(); for (auto v: nfa_graph.GetStartVertexes()) { - nfa_graph.GetVertex(start_vertex)->AddEdge(' ', v); + nfa_graph.GetVertex(start_vertex).AddEdge(' ', v); } } for (const auto& v: nfa_graph.GetFinalVertexes()) { - const auto& transitions = nfa_graph.GetVertex(v)->GetBackTransitions(); + const auto& transitions = nfa_graph.GetVertex(v).GetBackTransitions(); if (transitions.count(' ')) { const auto& s = transitions.at(' '); for (auto i: s) { - nfa_graph.GetVertex(i)->SetFinal(true); + nfa_graph.GetVertex(i).SetFinal(true); } } } @@ -55,21 +55,21 @@ NFAGraph DeleteEpsilonTransitions(NFAGraph&& nfa_graph) { const int n = nfa_graph.GetCountVertexes(); for (int v = 0; v < n; ++v) { - if (!nfa_graph.GetVertex(v)) continue; + if (nfa_graph.NotExistVertex(v)) continue; - const auto& transitions = nfa_graph.GetVertex(v)->GetTransitions(); + const auto& transitions = nfa_graph.GetVertex(v).GetTransitions(); if (transitions.count(' ')) { auto s = transitions.at(' '); for (auto u: s) { - for (auto& i: nfa_graph.GetVertex(u)->GetTransitions()) { + for (auto& i: nfa_graph.GetVertex(u).GetTransitions()) { if (i.first == ' ') continue; for (auto t: i.second) { - nfa_graph.GetVertex(v)->AddEdge(i.first, t); + nfa_graph.GetVertex(v).AddEdge(i.first, t); } } } for (auto u: s) { - nfa_graph.GetVertex(v)->RemoveEdge(' ', u); + nfa_graph.GetVertex(v).RemoveEdge(' ', u); } } } @@ -87,8 +87,8 @@ NFAGraph DeleteTransitionsByOneLetter(NFAGraph&& nfa_graph) { std::set alphabet; for (int i = 0; i < n; ++i) { - if (!nfa_graph.GetVertex(i)) continue; - for (const auto& j: nfa_graph.GetVertex(i)->GetTransitions()) { + if (nfa_graph.NotExistVertex(i)) continue; + for (const auto& j: nfa_graph.GetVertex(i).GetTransitions()) { if (j.second.size() > 0) alphabet.insert(j.first); } @@ -106,7 +106,7 @@ NFAGraph DeleteTransitionsByOneLetter(NFAGraph&& nfa_graph) { for (auto symbol: alphabet) { std::set result; for (auto v: current) { - const auto& transitions = nfa_graph.GetVertex(v)->GetTransitions(); + const auto& transitions = nfa_graph.GetVertex(v).GetTransitions(); if (transitions.count(symbol)) { const auto& s = transitions.at(symbol); result.insert(s.begin(), s.end()); @@ -127,7 +127,7 @@ NFAGraph DeleteTransitionsByOneLetter(NFAGraph&& nfa_graph) { int v = number_vertex_in_result_tree[i.first.first]; int u = number_vertex_in_result_tree[i.second]; char symbol = i.first.second; - result_tree.GetVertex(v)->AddEdge(symbol, u); + result_tree.GetVertex(v).AddEdge(symbol, u); } for (auto i: number_vertex_in_result_tree) { @@ -135,10 +135,10 @@ NFAGraph DeleteTransitionsByOneLetter(NFAGraph&& nfa_graph) { auto v = i.second; for (auto i: s) { - if (nfa_graph.GetVertex(i)->IsFinal()) - result_tree.GetVertex(v)->SetFinal(true); - if (nfa_graph.GetVertex(i)->IsStart()) - result_tree.GetVertex(v)->SetStart(true); + if (nfa_graph.GetVertex(i).IsFinal()) + result_tree.GetVertex(v).SetFinal(true); + if (nfa_graph.GetVertex(i).IsStart()) + result_tree.GetVertex(v).SetStart(true); } } @@ -146,6 +146,7 @@ NFAGraph DeleteTransitionsByOneLetter(NFAGraph&& nfa_graph) { } DFAGraph NFAGraphToDFAGraph(NFAGraph&& nfa_graph) { + nfa_graph = AddAllEpsilonTransitions(std::move(nfa_graph)); nfa_graph = DeleteTransitionsByOneLetter(DeleteEpsilonTransitions(AddAllPossibleStartFinal( AddAllEpsilonTransitions(std::move(nfa_graph))))); @@ -153,20 +154,20 @@ DFAGraph NFAGraphToDFAGraph(NFAGraph&& nfa_graph) { DFAGraph result; std::map number_vertex_in_DFA; for (int i = 0; i < n; ++i) { - if (!nfa_graph.GetVertex(i)) continue; + if (nfa_graph.NotExistVertex(i)) continue; number_vertex_in_DFA[i] = result.AddNewVertex(); } for (int i = 0; i < n; ++i) { - if (!nfa_graph.GetVertex(i)) continue; - if (nfa_graph.GetVertex(i)->IsFinal()) - result.GetVertex(number_vertex_in_DFA[i])->SetFinal(true); - if (nfa_graph.GetVertex(i)->IsStart()) - result.GetVertex(number_vertex_in_DFA[i])->SetStart(true); + if (nfa_graph.NotExistVertex(i)) continue; + if (nfa_graph.GetVertex(i).IsFinal()) + result.GetVertex(number_vertex_in_DFA[i]).SetFinal(true); + if (nfa_graph.GetVertex(i).IsStart()) + result.GetVertex(number_vertex_in_DFA[i]).SetStart(true); - const auto& transitions = nfa_graph.GetVertex(i)->GetTransitions(); + const auto& transitions = nfa_graph.GetVertex(i).GetTransitions(); for (const auto& t: transitions) { if (t.second.size() != 1) throw std::logic_error(""); - result.GetVertex(number_vertex_in_DFA[i])->AddEdge(t.first, *t.second.begin()); + result.GetVertex(number_vertex_in_DFA[i]).AddEdge(t.first, *t.second.begin()); } } return result; diff --git a/src/converters/RegularToNFA.cpp b/src/converters/RegularToNFA.cpp index c08b686..acae0a6 100644 --- a/src/converters/RegularToNFA.cpp +++ b/src/converters/RegularToNFA.cpp @@ -20,14 +20,14 @@ NFAGraph RegularToNFA(std::unique_ptr node) { result.AddStartVertex(end); for (char i: node->word) { auto tmp = result.AddNewVertex(); - result.GetVertex(end)->AddEdge(i, tmp); + result.GetVertex(end).AddEdge(i, tmp); end = tmp; } if (node->modifier == Node::Modifier::Plus) { - result.GetVertex(end)->AddEdge(' ', start); + result.GetVertex(end).AddEdge(' ', start); } else if (node->modifier == Node::Modifier::Star) { - result.GetVertex(end)->AddEdge(' ', start); - result.GetVertex(start)->AddEdge(' ', end); + result.GetVertex(end).AddEdge(' ', start); + result.GetVertex(start).AddEdge(' ', end); } result.AddFinalVertex(end); } else if (node->type == Node::Type::Concatenation) { @@ -47,14 +47,14 @@ NFAGraph RegularToNFA(std::unique_ptr node) { if (node->modifier == Node::Modifier::Plus) { for (auto start: start_vertexes) { for (auto end: end_vertexes) { - result.GetVertex(end)->AddEdge(' ', start); + result.GetVertex(end).AddEdge(' ', start); } } } else if (node->modifier == Node::Modifier::Star) { for (auto start: start_vertexes) { for (auto end: end_vertexes) { - result.GetVertex(end)->AddEdge(' ', start); - result.GetVertex(start)->AddEdge(' ', end); + result.GetVertex(end).AddEdge(' ', start); + result.GetVertex(start).AddEdge(' ', end); } } } @@ -69,10 +69,10 @@ NFAGraph RegularToNFA(std::unique_ptr node) { result.Composition(std::move(tmp), {start}, {end}); } if (node->modifier == Node::Modifier::Plus) { - result.GetVertex(end)->AddEdge(' ', start); + result.GetVertex(end).AddEdge(' ', start); } else if (node->modifier == Node::Modifier::Star) { - result.GetVertex(end)->AddEdge(' ', start); - result.GetVertex(start)->AddEdge(' ', end); + result.GetVertex(end).AddEdge(' ', start); + result.GetVertex(start).AddEdge(' ', end); } } return result; diff --git a/src/main.cpp b/src/main.cpp index 701fd02..6cd9217 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -36,7 +36,7 @@ void example2() { 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]); + nfa_graph.GetVertex(a[u]).AddEdge(symbol, a[v]); }; AddEdge('a', 0, 1); From 40b634b7223aeb276d9bba37c37fefd8b7dc85d4 Mon Sep 17 00:00:00 2001 From: MaxanRus Date: Sun, 10 Oct 2021 21:28:19 +0300 Subject: [PATCH 15/17] Fix some bugs --- src/DFA/DFAGraph.cpp | 2 +- src/converters/DFAToMinDFA.cpp | 2 ++ src/converters/InvertFDFA.cpp | 2 +- src/main.cpp | 13 +++++++++++++ tests/NFAToDFA/CheckEquivalence.cpp | 26 +++++++++++++------------- 5 files changed, 30 insertions(+), 15 deletions(-) diff --git a/src/DFA/DFAGraph.cpp b/src/DFA/DFAGraph.cpp index 3742ec0..ad280b7 100644 --- a/src/DFA/DFAGraph.cpp +++ b/src/DFA/DFAGraph.cpp @@ -131,7 +131,7 @@ void DFAGraph::CreateDotFile(const std::string& filename) const { for (auto& i: vertexes_) { for (auto& j: i.second.transitions_) { - out << i.first << "." << j.second << "[label=" << j.first << "]\n"; + out << i.first << "->" << j.second << "[label=" << j.first << "]\n"; } if (i.second.IsStart() && i.second.IsFinal()) { out << " " << i.first << " [shape=star];\n"; diff --git a/src/converters/DFAToMinDFA.cpp b/src/converters/DFAToMinDFA.cpp index 591e49e..af52be9 100644 --- a/src/converters/DFAToMinDFA.cpp +++ b/src/converters/DFAToMinDFA.cpp @@ -66,6 +66,7 @@ DFAGraph DFAGraphToMinDFAGraph(DFAGraph&& graph) { } } + /* for (int i = 0; i < n; ++i) { for (int k = 0; k < n; ++k) { for (int j = 0; j < alphabet.size() + 1; ++j) { @@ -75,6 +76,7 @@ DFAGraph DFAGraphToMinDFAGraph(DFAGraph&& graph) { } std::cout << std::endl; } + */ std::vector>& last_layer(table.back()); size_t count_vertex = 0; diff --git a/src/converters/InvertFDFA.cpp b/src/converters/InvertFDFA.cpp index 61ad9e2..429060b 100644 --- a/src/converters/InvertFDFA.cpp +++ b/src/converters/InvertFDFA.cpp @@ -5,7 +5,7 @@ DFAGraph InvertFDFAGraph(DFAGraph&& fdfa_graph) { const size_t n = fdfa_graph.GetCountVertexes(); for (int i = 0; i < n; ++i) { if (fdfa_graph.NotExistVertex(i)) continue; - fdfa_graph.GetVertex(i).SetFinal(fdfa_graph.GetVertex(i).IsFinal()); + fdfa_graph.GetVertex(i).SetFinal(!fdfa_graph.GetVertex(i).IsFinal()); } return std::move(fdfa_graph); } diff --git a/src/main.cpp b/src/main.cpp index 6cd9217..9187628 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -50,7 +50,20 @@ void example2() { } int main() { + { + RegularTree r("a*"); + NFAGraph NFA_graph = RegularToNFAGraph(std::move(r)); + DFAGraph DFA_graph = NFAGraphToDFAGraph(std::move(NFA_graph)); + DFA_graph = DFAGraphToMinDFAGraph(std::move(DFA_graph)); + DFA_graph = DFAGraphToFDFAGraph(std::move(DFA_graph), {'a', 'b'}); + DFA_graph.Print(); + DFA_graph.CreateDotFile("1.dot"); + DFA_graph = InvertFDFAGraph(std::move(DFA_graph)); + DFA_graph.CreateDotFile("2.dot"); + DFA_graph = DFAGraphToMinDFAGraph(std::move(DFA_graph)); + } + return 0; { RegularTree r("((ab|ba)*( |a|ba))"); NFAGraph NFA_tree = RegularToNFAGraph(std::move(r)); diff --git a/tests/NFAToDFA/CheckEquivalence.cpp b/tests/NFAToDFA/CheckEquivalence.cpp index 2594763..2b84cfa 100644 --- a/tests/NFAToDFA/CheckEquivalence.cpp +++ b/tests/NFAToDFA/CheckEquivalence.cpp @@ -26,13 +26,13 @@ TEST(check_equivalence_NFA_to_DFA, 1) { for (int i = 0; i < N; ++i) a[i] = tree.AddNewVertex(); - tree.GetVertex(a[0])->AddEdge('a', a[1]); - tree.GetVertex(a[1])->AddEdge('a', a[2]); - tree.GetVertex(a[0])->AddEdge('a', a[3]); + tree.GetVertex(a[0]).AddEdge('a', a[1]); + tree.GetVertex(a[1]).AddEdge('a', a[2]); + tree.GetVertex(a[0]).AddEdge('a', a[3]); - tree.GetVertex(a[0])->SetStart(true); - tree.GetVertex(a[2])->SetFinal(true); - tree.GetVertex(a[3])->SetFinal(true); + tree.GetVertex(a[0]).SetStart(true); + tree.GetVertex(a[2]).SetFinal(true); + tree.GetVertex(a[3]).SetFinal(true); DFA::DFAGraph res = converters::NFAGraphToDFAGraph(std::move(tree)); @@ -53,14 +53,14 @@ TEST(check_equivalence_NFA_to_DFA, 2) { for (int i = 0; i < N; ++i) a[i] = tree.AddNewVertex(); - 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]).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]).SetStart(true); + tree.GetVertex(a[1]).SetFinal(true); + tree.GetVertex(a[2]).SetFinal(true); DFA::DFAGraph res = converters::NFAGraphToDFAGraph(std::move(tree)); From 346f0016a5a16ccac578a8ddfefdf1283527c389 Mon Sep 17 00:00:00 2001 From: MaxanRus Date: Mon, 11 Oct 2021 00:32:47 +0300 Subject: [PATCH 16/17] Some refactor --- include/DFA/DFAGraph.hpp | 6 +++--- include/converters/NFAToDFA.hpp | 2 +- src/DFA/DFAGraph.cpp | 25 +++++++++++-------------- src/DFA/DFAGraphVertex.cpp | 2 +- src/converters/NFAToDFA.cpp | 16 ++++++++++++---- 5 files changed, 28 insertions(+), 23 deletions(-) diff --git a/include/DFA/DFAGraph.hpp b/include/DFA/DFAGraph.hpp index d410e9a..606a166 100644 --- a/include/DFA/DFAGraph.hpp +++ b/include/DFA/DFAGraph.hpp @@ -45,7 +45,7 @@ class DFAGraph { size_t AddNewVertex(); void AddFinalVertex(size_t number); - void AddStartVertex(size_t number); + void SetStartVertex(size_t number); void RemoveVertex(size_t number); void RemoveFinalVertex(size_t number); @@ -56,7 +56,7 @@ class DFAGraph { size_t GetCountVertexes() const; const std::vector& GetFinalVertexes() const; - const std::vector& GetStartVertexes() const; + size_t GetStartVertex() const; void Print() const; bool Accepted(const std::string&) const; @@ -65,6 +65,6 @@ class DFAGraph { size_t count_vertexes_ = 0; std::map vertexes_; std::vector final_vertexes_; - std::vector start_vertexes_; + size_t start_vertex_ = -1; }; } diff --git a/include/converters/NFAToDFA.hpp b/include/converters/NFAToDFA.hpp index 4dd51eb..66eb908 100644 --- a/include/converters/NFAToDFA.hpp +++ b/include/converters/NFAToDFA.hpp @@ -6,7 +6,7 @@ namespace converters { using namespace NFA; using namespace DFA; NFAGraph AddAllEpsilonTransitions(NFAGraph&&); -NFAGraph AddAllPossibleStartFinal(NFAGraph&&); +NFAGraph AddAllPossibleFinalVertexes(NFAGraph&&); NFAGraph DeleteEpsilonTransitions(NFAGraph&&); NFAGraph DeleteTransitionsByOneLetter(NFAGraph&&); DFAGraph NFAGraphToDFAGraph(NFAGraph&&); diff --git a/src/DFA/DFAGraph.cpp b/src/DFA/DFAGraph.cpp index ad280b7..f6f2388 100644 --- a/src/DFA/DFAGraph.cpp +++ b/src/DFA/DFAGraph.cpp @@ -8,7 +8,8 @@ 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_); + // TODO + // std::swap(start_vertexes_, another.start_vertexes_); for (auto& i: vertexes_) i.second.owner_ = this; @@ -20,7 +21,8 @@ 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_); + // TODO + // std::swap(start_vertexes_, another.start_vertexes_); for (auto& i: vertexes_) i.second.owner_ = this; @@ -41,10 +43,10 @@ void DFAGraph::AddFinalVertex(size_t number) { } } -void DFAGraph::AddStartVertex(size_t number) { +void DFAGraph::SetStartVertex(size_t number) { if (!GetVertex(number).is_start_) { GetVertex(number).is_start_ = true; - start_vertexes_.push_back(number); + start_vertex_ = number; } } @@ -67,13 +69,8 @@ void DFAGraph::RemoveFinalVertex(size_t number) { } void DFAGraph::RemoveStartVertex(size_t number) { - for (size_t i = 0; i < start_vertexes_.size(); ++i) { - if (start_vertexes_[i] == number) { - GetVertex(number).is_start_ = false; - std::swap(start_vertexes_[i], start_vertexes_.back()); - start_vertexes_.pop_back(); - break; - } + if (start_vertex_ == number) { + start_vertex_ = -1; } } @@ -95,8 +92,8 @@ const std::vector& DFAGraph::GetFinalVertexes() const { return final_vertexes_; } -const std::vector& DFAGraph::GetStartVertexes() const { - return start_vertexes_; +size_t DFAGraph::GetStartVertex() const { + return start_vertex_; } void DFAGraph::Print() const { @@ -114,7 +111,7 @@ void DFAGraph::Print() const { } bool DFAGraph::Accepted(const std::string& str) const { - size_t current = vertexes_.at(start_vertexes_[0]).GetNumber(); + size_t current = start_vertex_; for (auto i: str) { if (vertexes_.at(current).GetTransitions().count(i)) { current = vertexes_.at(vertexes_.at(current).GetTransitions().at(i)).GetNumber(); diff --git a/src/DFA/DFAGraphVertex.cpp b/src/DFA/DFAGraphVertex.cpp index b1602c8..ddad254 100644 --- a/src/DFA/DFAGraphVertex.cpp +++ b/src/DFA/DFAGraphVertex.cpp @@ -50,7 +50,7 @@ void Vertex::SetFinal(bool status) { void Vertex::SetStart(bool status) { if (status != is_start_) { if (status) - owner_->AddStartVertex(number_); + owner_->SetStartVertex(number_); else owner_->RemoveStartVertex(number_); } diff --git a/src/converters/NFAToDFA.cpp b/src/converters/NFAToDFA.cpp index fe24976..843fc06 100644 --- a/src/converters/NFAToDFA.cpp +++ b/src/converters/NFAToDFA.cpp @@ -32,7 +32,7 @@ NFAGraph AddAllEpsilonTransitions(NFAGraph&& nfa_graph) { return std::move(nfa_graph); } -NFAGraph AddAllPossibleStartFinal(NFAGraph&& nfa_graph) { +NFAGraph AddAllPossibleFinalVertexes(NFAGraph&& nfa_graph) { if (nfa_graph.GetStartVertexes().size() != 1) { size_t start_vertex = nfa_graph.AddNewVertex(); for (auto v: nfa_graph.GetStartVertexes()) { @@ -146,8 +146,7 @@ NFAGraph DeleteTransitionsByOneLetter(NFAGraph&& nfa_graph) { } DFAGraph NFAGraphToDFAGraph(NFAGraph&& nfa_graph) { - nfa_graph = AddAllEpsilonTransitions(std::move(nfa_graph)); - nfa_graph = DeleteTransitionsByOneLetter(DeleteEpsilonTransitions(AddAllPossibleStartFinal( + nfa_graph = DeleteTransitionsByOneLetter(DeleteEpsilonTransitions(AddAllPossibleFinalVertexes( AddAllEpsilonTransitions(std::move(nfa_graph))))); const int n = nfa_graph.GetCountVertexes(); @@ -157,12 +156,18 @@ DFAGraph NFAGraphToDFAGraph(NFAGraph&& nfa_graph) { if (nfa_graph.NotExistVertex(i)) continue; number_vertex_in_DFA[i] = result.AddNewVertex(); } + bool exists_start_vertex = false; for (int i = 0; i < n; ++i) { if (nfa_graph.NotExistVertex(i)) continue; if (nfa_graph.GetVertex(i).IsFinal()) result.GetVertex(number_vertex_in_DFA[i]).SetFinal(true); - if (nfa_graph.GetVertex(i).IsStart()) + if (nfa_graph.GetVertex(i).IsStart()) { + if (exists_start_vertex) { + throw std::runtime_error("I can't delete starts vertex"); + } result.GetVertex(number_vertex_in_DFA[i]).SetStart(true); + exists_start_vertex = true; + } const auto& transitions = nfa_graph.GetVertex(i).GetTransitions(); for (const auto& t: transitions) { @@ -170,6 +175,9 @@ DFAGraph NFAGraphToDFAGraph(NFAGraph&& nfa_graph) { result.GetVertex(number_vertex_in_DFA[i]).AddEdge(t.first, *t.second.begin()); } } + if (!exists_start_vertex) { + throw std::runtime_error("I can't find start vertex"); + } return result; } } From 04109bd54b066bcd2c6f4f44f41e37c36ca8bac9 Mon Sep 17 00:00:00 2001 From: MaxanRus Date: Mon, 11 Oct 2021 01:13:50 +0300 Subject: [PATCH 17/17] Add testing minimization --- CMakeLists.txt | 1 + include/DFA/DFAGraph.hpp | 1 + include/NFA/NFAGraph.hpp | 1 + src/DFA/DFAGraph.cpp | 4 +++ src/NFA/NFAGraph.cpp | 4 +++ tests/DFAToMinDFA/CountSizesMinDFA.cpp | 40 ++++++++++++++++++++++++++ 6 files changed, 51 insertions(+) create mode 100644 tests/DFAToMinDFA/CountSizesMinDFA.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index d479af6..703bedc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -38,6 +38,7 @@ set(TEST_FILES tests/DFAToRegular/DFAToRegular.cpp tests/invertFDFA/InvertFDFA.cpp tests/DFAToRegular/DFAToRegular2.cpp + tests/DFAToMinDFA/CountSizesMinDFA.cpp ) add_executable(Formalang src/main.cpp ${SOURCE_FILES}) diff --git a/include/DFA/DFAGraph.hpp b/include/DFA/DFAGraph.hpp index 606a166..f1cb616 100644 --- a/include/DFA/DFAGraph.hpp +++ b/include/DFA/DFAGraph.hpp @@ -55,6 +55,7 @@ class DFAGraph { bool NotExistVertex(size_t number); size_t GetCountVertexes() const; + size_t GetReallyCountVertexes() const; const std::vector& GetFinalVertexes() const; size_t GetStartVertex() const; diff --git a/include/NFA/NFAGraph.hpp b/include/NFA/NFAGraph.hpp index 6fd1738..db389af 100644 --- a/include/NFA/NFAGraph.hpp +++ b/include/NFA/NFAGraph.hpp @@ -59,6 +59,7 @@ class NFAGraph { bool NotExistVertex(size_t number); size_t GetCountVertexes() const; + size_t GetReallyCountVertexes() const; const std::vector& GetFinalVertexes() const; const std::vector& GetStartVertexes() const; diff --git a/src/DFA/DFAGraph.cpp b/src/DFA/DFAGraph.cpp index f6f2388..011df6e 100644 --- a/src/DFA/DFAGraph.cpp +++ b/src/DFA/DFAGraph.cpp @@ -88,6 +88,10 @@ size_t DFAGraph::GetCountVertexes() const { return count_vertexes_; } +size_t DFAGraph::GetReallyCountVertexes() const { + return vertexes_.size(); +} + const std::vector& DFAGraph::GetFinalVertexes() const { return final_vertexes_; } diff --git a/src/NFA/NFAGraph.cpp b/src/NFA/NFAGraph.cpp index b27bb21..2d31831 100644 --- a/src/NFA/NFAGraph.cpp +++ b/src/NFA/NFAGraph.cpp @@ -150,6 +150,10 @@ size_t NFAGraph::GetCountVertexes() const { return count_vertexes_; } +size_t NFAGraph::GetReallyCountVertexes() const { + return vertexes_.size(); +} + const std::vector& NFAGraph::GetFinalVertexes() const { return final_vertexes_; } diff --git a/tests/DFAToMinDFA/CountSizesMinDFA.cpp b/tests/DFAToMinDFA/CountSizesMinDFA.cpp new file mode 100644 index 0000000..66a1cf5 --- /dev/null +++ b/tests/DFAToMinDFA/CountSizesMinDFA.cpp @@ -0,0 +1,40 @@ +#include +#include "regular/RegularTree.hpp" +#include "converters/RegularToNFA.hpp" +#include "converters/NFAToDFA.hpp" +#include "converters/DFAToMinDFA.hpp" +#include "converters/DFAToRegular.hpp" + +using namespace regular; +using namespace NFA; +using namespace DFA; +using namespace converters; + +size_t GetCountVertexes(const std::string& regular) { + 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)); + + return DFA_graph.GetReallyCountVertexes(); +} + +TEST(DFA_to_min_DFA, a_start) { + EXPECT_EQ(GetCountVertexes("a*"), GetCountVertexes("( a | )*| | | aaa a a")); +} + +TEST(DFA_to_min_DFA, a_plus) { + EXPECT_EQ(GetCountVertexes("a+"), GetCountVertexes("( a | a a )+|a | a |a ")); +} + +TEST(DFA_to_min_DFA, a_star_or_b_star) { + EXPECT_EQ(GetCountVertexes("a*|b*"), GetCountVertexes("a|b|a*|a+|b*|b+|bbb b b b| a a aa a aa | a+")); +} + +TEST(DFA_to_min_DFA, epsilon) { + EXPECT_EQ(GetCountVertexes(" "), GetCountVertexes(" | | | ")); +} + +TEST(DFA_to_min_DFA, a_or_b_star) { + EXPECT_EQ(GetCountVertexes("(a|b)*"), GetCountVertexes("a+|b+|a*|b*|a*b*a*|a|b(a|b)*|b| |(a|b)*")); +}