Compare commits

..

No commits in common. "59521e3be244c455726263662e64561fb4ad7dad" and "aad17d8c8c0023a2538c7b318972ac51583db2a4" have entirely different histories.

23 changed files with 234 additions and 808 deletions

View file

@ -3,7 +3,6 @@ cmake_minimum_required(VERSION 3.10)
project("Formalang") project("Formalang")
# set(CMAKE_CXX_FLAGS "-O3") # set(CMAKE_CXX_FLAGS "-O3")
# set(CMAKE_CXX_FLAGS "-O0 --coverage -ftest-coverage -fprofile-arcs")
find_package(GTest REQUIRED) find_package(GTest REQUIRED)
find_package(Threads REQUIRED) find_package(Threads REQUIRED)
@ -11,6 +10,7 @@ find_package(Threads REQUIRED)
include_directories( include_directories(
"include" "include"
${GTEST_INCLUDE_DIRS} ${GTEST_INCLUDE_DIRS}
${Boost_INCLUDE_DIR}
) )
set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD 17)
@ -19,7 +19,7 @@ set(SOURCE_FILES
src/regular/RegularTree.cpp src/regular/RegularTree.cpp
src/regular/RegularTreeNode.cpp src/regular/RegularTreeNode.cpp
src/NFA/NFAGraph.cpp src/NFA/NFAGraph.cpp
src/NFA/NFAGraphVertex.cpp src/NFA/NFAGraphVertex.cpp
src/converters/RegularToNFA.cpp src/converters/RegularToNFA.cpp
src/converters/NFAToDFA.cpp src/converters/NFAToDFA.cpp
src/DFA/DFAGraph.cpp src/DFA/DFAGraph.cpp
@ -36,9 +36,6 @@ set(TEST_FILES
tests/regularToDFA/RegularToDFA.cpp tests/regularToDFA/RegularToDFA.cpp
tests/DFAToRegular/DFAToRegular.cpp tests/DFAToRegular/DFAToRegular.cpp
tests/invertFDFA/InvertFDFA.cpp tests/invertFDFA/InvertFDFA.cpp
tests/DFAToRegular/DFAToRegular2.cpp
tests/DFAToMinDFA/CountSizesMinDFA.cpp
tests/GenericTest/GenericTest1.cpp
) )
add_executable(Formalang src/main.cpp ${SOURCE_FILES}) add_executable(Formalang src/main.cpp ${SOURCE_FILES})
@ -46,3 +43,5 @@ add_executable(Formalang src/main.cpp ${SOURCE_FILES})
add_executable(Tests tests/MainTest.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(Tests ${GTEST_LIBRARIES} Threads::Threads)
target_link_libraries(Formalang Threads::Threads)

View file

@ -1,43 +0,0 @@
# 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)\*. Для сложения языков используется |. Символом пустого слова является пробел.
Очень важное отличие, что у меня + \* привязываются не к букве, а к слову(например aba* это (aba)\*, а не ab(a)\* как вы ожидаете), это значительное отличие от существующих регулярок, но .ToString у RegularTree всегда + \* выдаст строку у которой перед + \* будет стоять скобочка
Примеры регулярок
a*
a(b)+a
(a|b)*

View file

@ -45,27 +45,24 @@ class DFAGraph {
size_t AddNewVertex(); size_t AddNewVertex();
void AddFinalVertex(size_t number); void AddFinalVertex(size_t number);
void SetStartVertex(size_t number); void AddStartVertex(size_t number);
void RemoveVertex(size_t number); void RemoveVertex(size_t number);
void RemoveFinalVertex(size_t number); void RemoveFinalVertex(size_t number);
void RemoveStartVertex(size_t number); void RemoveStartVertex(size_t number);
Vertex& GetVertex(size_t number); std::shared_ptr<Vertex> GetVertex(size_t number);
bool NotExistVertex(size_t number);
size_t GetCountVertexes() const; size_t GetCountVertexes() const;
size_t GetReallyCountVertexes() const;
const std::vector<size_t>& GetFinalVertexes() const; const std::vector<size_t>& GetFinalVertexes() const;
size_t GetStartVertex() const; const std::vector<size_t>& GetStartVertexes() const;
void Print() const; void Print() const;
bool Accepted(const std::string&) const; bool Accepted(const std::string&) const;
void CreateDotFile(const std::string& filename) const;
private: private:
size_t count_vertexes_ = 0; size_t count_vertexes_ = 0;
std::map<size_t, Vertex> vertexes_; std::map<size_t, std::shared_ptr<Vertex>> vertexes_;
std::vector<size_t> final_vertexes_; std::vector<size_t> final_vertexes_;
size_t start_vertex_ = -1; std::vector<size_t> start_vertexes_;
}; };
} }

View file

@ -55,19 +55,15 @@ class NFAGraph {
std::vector<size_t> start_vertexes, std::vector<size_t> start_vertexes,
std::vector<size_t> final_vertexes); std::vector<size_t> final_vertexes);
Vertex& GetVertex(size_t number); std::shared_ptr<Vertex> GetVertex(size_t number);
bool NotExistVertex(size_t number);
size_t GetCountVertexes() const; size_t GetCountVertexes() const;
size_t GetReallyCountVertexes() const;
const std::vector<size_t>& GetFinalVertexes() const; const std::vector<size_t>& GetFinalVertexes() const;
const std::vector<size_t>& GetStartVertexes() const; const std::vector<size_t>& GetStartVertexes() const;
void Print() const; void Print() const;
void CreateDotFile(const std::string& filename) const;
private: private:
size_t count_vertexes_ = 0; size_t count_vertexes_ = 0;
std::map<size_t, Vertex> vertexes_; std::map<size_t, std::shared_ptr<Vertex>> vertexes_;
std::vector<size_t> final_vertexes_; std::vector<size_t> final_vertexes_;
std::vector<size_t> start_vertexes_; std::vector<size_t> start_vertexes_;
}; };

View file

@ -6,7 +6,7 @@ namespace converters {
using namespace NFA; using namespace NFA;
using namespace DFA; using namespace DFA;
NFAGraph AddAllEpsilonTransitions(NFAGraph&&); NFAGraph AddAllEpsilonTransitions(NFAGraph&&);
NFAGraph AddAllPossibleFinalVertexes(NFAGraph&&); NFAGraph AddAllPossibleStartFinal(NFAGraph&&);
NFAGraph DeleteEpsilonTransitions(NFAGraph&&); NFAGraph DeleteEpsilonTransitions(NFAGraph&&);
NFAGraph DeleteTransitionsByOneLetter(NFAGraph&&); NFAGraph DeleteTransitionsByOneLetter(NFAGraph&&);
DFAGraph NFAGraphToDFAGraph(NFAGraph&&); DFAGraph NFAGraphToDFAGraph(NFAGraph&&);

View file

@ -25,18 +25,15 @@ class RegularTree {
std::string word; std::string word;
Type type; Type type;
Modifier modifier = Modifier::None; Modifier modifier = Modifier::None;
std::string ToString() const;
private: private:
void ParseCurrentType(const std::string_view); void ParseCurrentType(const std::string_view);
void Compression(); void Compression();
void Compression2();
void Print(int nesting_level) const; void Print(int nesting_level) const;
}; };
RegularTree(const std::string&); RegularTree(const std::string&);
const Node& GetNode() const; const Node& GetNode() const;
void Print() const; void Print() const;
std::string ToString() const;
private: private:
Node node_; Node node_;

View file

@ -1,50 +1,49 @@
#include "DFA/DFAGraph.hpp" #include "DFA/DFAGraph.hpp"
#include <algorithm> #include <algorithm>
#include <iostream> #include <iostream>
#include <fstream>
namespace DFA { namespace DFA {
DFAGraph::DFAGraph(DFAGraph&& another) { DFAGraph::DFAGraph(DFAGraph&& another) {
std::swap(count_vertexes_, another.count_vertexes_); std::swap(count_vertexes_, another.count_vertexes_);
std::swap(vertexes_, another.vertexes_); std::swap(vertexes_, another.vertexes_);
std::swap(final_vertexes_, another.final_vertexes_); std::swap(final_vertexes_, another.final_vertexes_);
std::swap(start_vertex_, another.start_vertex_); std::swap(start_vertexes_, another.start_vertexes_);
for (auto& i: vertexes_) for (auto& i: vertexes_)
i.second.owner_ = this; i.second->owner_ = this;
for (auto& i: another.vertexes_) for (auto& i: another.vertexes_)
i.second.owner_ = &another; i.second->owner_ = &another;
} }
DFAGraph& DFAGraph::operator=(DFAGraph&& another) { DFAGraph& DFAGraph::operator=(DFAGraph&& another) {
std::swap(count_vertexes_, another.count_vertexes_); std::swap(count_vertexes_, another.count_vertexes_);
std::swap(vertexes_, another.vertexes_); std::swap(vertexes_, another.vertexes_);
std::swap(final_vertexes_, another.final_vertexes_); std::swap(final_vertexes_, another.final_vertexes_);
std::swap(start_vertex_, another.start_vertex_); std::swap(start_vertexes_, another.start_vertexes_);
for (auto& i: vertexes_) for (auto& i: vertexes_)
i.second.owner_ = this; i.second->owner_ = this;
for (auto& i: another.vertexes_) for (auto& i: another.vertexes_)
i.second.owner_ = &another; i.second->owner_ = &another;
return *this; return *this;
} }
size_t DFAGraph::AddNewVertex() { size_t DFAGraph::AddNewVertex() {
vertexes_.emplace(count_vertexes_, this); vertexes_[count_vertexes_] = std::make_shared<Vertex>(this);
GetVertex(count_vertexes_).number_ = count_vertexes_; vertexes_[count_vertexes_]->number_ = count_vertexes_;
return count_vertexes_++; return count_vertexes_++;
} }
void DFAGraph::AddFinalVertex(size_t number) { void DFAGraph::AddFinalVertex(size_t number) {
if (!GetVertex(number).is_final_) { if (!vertexes_[number]->is_final_) {
GetVertex(number).is_final_ = true; vertexes_[number]->is_final_ = true;
final_vertexes_.push_back(number); final_vertexes_.push_back(number);
} }
} }
void DFAGraph::SetStartVertex(size_t number) { void DFAGraph::AddStartVertex(size_t number) {
if (!GetVertex(number).is_start_) { if (!vertexes_[number]->is_start_) {
GetVertex(number).is_start_ = true; vertexes_[number]->is_start_ = true;
start_vertex_ = number; start_vertexes_.push_back(number);
} }
} }
@ -52,13 +51,12 @@ void DFAGraph::RemoveVertex(size_t number) {
RemoveFinalVertex(number); RemoveFinalVertex(number);
RemoveStartVertex(number); RemoveStartVertex(number);
vertexes_.erase(number); vertexes_.erase(number);
if (number == count_vertexes_ - 1) count_vertexes_--;
} }
void DFAGraph::RemoveFinalVertex(size_t number) { void DFAGraph::RemoveFinalVertex(size_t number) {
for (size_t i = 0; i < final_vertexes_.size(); ++i) { for (size_t i = 0; i < final_vertexes_.size(); ++i) {
if (final_vertexes_[i] == number) { if (final_vertexes_[i] == number) {
GetVertex(number).is_final_ = false; vertexes_[number]->is_final_ = false;
std::swap(final_vertexes_[i], final_vertexes_.back()); std::swap(final_vertexes_[i], final_vertexes_.back());
final_vertexes_.pop_back(); final_vertexes_.pop_back();
break; break;
@ -67,46 +65,42 @@ void DFAGraph::RemoveFinalVertex(size_t number) {
} }
void DFAGraph::RemoveStartVertex(size_t number) { void DFAGraph::RemoveStartVertex(size_t number) {
if (start_vertex_ == number) { for (size_t i = 0; i < start_vertexes_.size(); ++i) {
start_vertex_ = -1; if (start_vertexes_[i] == number) {
GetVertex(number).is_start_ = false; vertexes_[number]->is_start_ = false;
std::swap(start_vertexes_[i], start_vertexes_.back());
start_vertexes_.pop_back();
break;
}
} }
} }
DFAGraph::Vertex& DFAGraph::GetVertex(size_t number) { std::shared_ptr<DFAGraph::Vertex> DFAGraph::GetVertex(size_t number) {
if (!NotExistVertex(number)) if (vertexes_.count(number))
return vertexes_.at(number); return vertexes_[number];
throw std::out_of_range("This vertex don't exist"); return nullptr;
}
bool DFAGraph::NotExistVertex(size_t number) {
return !vertexes_.count(number);
} }
size_t DFAGraph::GetCountVertexes() const { size_t DFAGraph::GetCountVertexes() const {
return count_vertexes_; return count_vertexes_;
} }
size_t DFAGraph::GetReallyCountVertexes() const {
return vertexes_.size();
}
const std::vector<size_t>& DFAGraph::GetFinalVertexes() const { const std::vector<size_t>& DFAGraph::GetFinalVertexes() const {
return final_vertexes_; return final_vertexes_;
} }
size_t DFAGraph::GetStartVertex() const { const std::vector<size_t>& DFAGraph::GetStartVertexes() const {
return start_vertex_; return start_vertexes_;
} }
void DFAGraph::Print() const { void DFAGraph::Print() const {
for (auto i: vertexes_) { for (auto i: vertexes_) {
std::cout << i.second.number_ << " " << "f-" << i.second.is_final_ << " s-" << std::cout << i.second->number_ << " " << "f-" << i.second->is_final_ << " s-" <<
i.second.is_start_ << std::endl; i.second->is_start_ << std::endl;
} }
for (auto& i: vertexes_) { for (auto& i: vertexes_) {
for (auto& j: i.second.transitions_) { for (auto& j: i.second->transitions_) {
std::cout << i.second.number_ << "->" << j.second << " <" << j.first << ">" << std::cout << i.second->number_ << "->" << j.second << " <" << j.first << ">" <<
std::endl; std::endl;
} }
} }
@ -114,35 +108,15 @@ void DFAGraph::Print() const {
} }
bool DFAGraph::Accepted(const std::string& str) const { bool DFAGraph::Accepted(const std::string& str) const {
size_t current = start_vertex_; std::shared_ptr<const Vertex> current = vertexes_.at(start_vertexes_[0]);
for (auto i: str) { for (auto i: str) {
if (vertexes_.at(current).GetTransitions().count(i)) { if (current->GetTransitions().count(i)) {
current = vertexes_.at(vertexes_.at(current).GetTransitions().at(i)).GetNumber(); current = vertexes_.at(current->GetTransitions().at(i));
} else { } else {
return false; return false;
} }
} }
return vertexes_.at(current).IsFinal(); 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";
} }
} }

View file

@ -26,11 +26,11 @@ const std::map<char, size_t>& Vertex::GetBackTransitions() const {
void Vertex::AddEdge(char symbol, size_t number) { void Vertex::AddEdge(char symbol, size_t number) {
transitions_[symbol] = number; transitions_[symbol] = number;
owner_->GetVertex(number).back_transitions_[symbol] = number_; owner_->GetVertex(number)->back_transitions_[symbol] = number_;
} }
void Vertex::RemoveEdge(char symbol) { void Vertex::RemoveEdge(char symbol) {
owner_->GetVertex(transitions_[symbol]).back_transitions_.erase(symbol); owner_->GetVertex(transitions_[symbol])->back_transitions_.erase(symbol);
transitions_.erase(symbol); transitions_.erase(symbol);
} }
@ -50,7 +50,7 @@ void Vertex::SetFinal(bool status) {
void Vertex::SetStart(bool status) { void Vertex::SetStart(bool status) {
if (status != is_start_) { if (status != is_start_) {
if (status) if (status)
owner_->SetStartVertex(number_); owner_->AddStartVertex(number_);
else else
owner_->RemoveStartVertex(number_); owner_->RemoveStartVertex(number_);
} }

View file

@ -1,7 +1,6 @@
#include "NFA/NFAGraph.hpp" #include "NFA/NFAGraph.hpp"
#include <algorithm> #include <algorithm>
#include <iostream> #include <iostream>
#include <fstream>
namespace NFA { namespace NFA {
NFAGraph::NFAGraph(NFAGraph&& another) { NFAGraph::NFAGraph(NFAGraph&& another) {
@ -11,9 +10,9 @@ NFAGraph::NFAGraph(NFAGraph&& another) {
std::swap(start_vertexes_, another.start_vertexes_); std::swap(start_vertexes_, another.start_vertexes_);
for (auto& i: vertexes_) for (auto& i: vertexes_)
i.second.owner_ = this; i.second->owner_ = this;
for (auto& i: another.vertexes_) for (auto& i: another.vertexes_)
i.second.owner_ = &another; i.second->owner_ = &another;
} }
NFAGraph& NFAGraph::operator=(NFAGraph&& another) { NFAGraph& NFAGraph::operator=(NFAGraph&& another) {
@ -23,28 +22,28 @@ NFAGraph& NFAGraph::operator=(NFAGraph&& another) {
std::swap(start_vertexes_, another.start_vertexes_); std::swap(start_vertexes_, another.start_vertexes_);
for (auto& i: vertexes_) for (auto& i: vertexes_)
i.second.owner_ = this; i.second->owner_ = this;
for (auto& i: another.vertexes_) for (auto& i: another.vertexes_)
i.second.owner_ = &another; i.second->owner_ = &another;
return *this; return *this;
} }
size_t NFAGraph::AddNewVertex() { size_t NFAGraph::AddNewVertex() {
vertexes_.emplace(count_vertexes_, this); vertexes_[count_vertexes_] = std::make_shared<Vertex>(this);
GetVertex(count_vertexes_).number_ = count_vertexes_; vertexes_[count_vertexes_]->number_ = count_vertexes_;
return count_vertexes_++; return count_vertexes_++;
} }
void NFAGraph::AddFinalVertex(size_t number) { void NFAGraph::AddFinalVertex(size_t number) {
if (!GetVertex(number).is_final_) { if (!vertexes_[number]->is_final_) {
GetVertex(number).is_final_ = true; vertexes_[number]->is_final_ = true;
final_vertexes_.push_back(number); final_vertexes_.push_back(number);
} }
} }
void NFAGraph::AddStartVertex(size_t number) { void NFAGraph::AddStartVertex(size_t number) {
if (!GetVertex(number).is_start_) { if (!vertexes_[number]->is_start_) {
GetVertex(number).is_start_ = true; vertexes_[number]->is_start_ = true;
start_vertexes_.push_back(number); start_vertexes_.push_back(number);
} }
} }
@ -58,7 +57,7 @@ void NFAGraph::RemoveVertex(size_t number) {
void NFAGraph::RemoveFinalVertex(size_t number) { void NFAGraph::RemoveFinalVertex(size_t number) {
for (size_t i = 0; i < final_vertexes_.size(); ++i) { for (size_t i = 0; i < final_vertexes_.size(); ++i) {
if (final_vertexes_[i] == number) { if (final_vertexes_[i] == number) {
GetVertex(number).is_final_ = false; vertexes_[number]->is_final_ = false;
std::swap(final_vertexes_[i], final_vertexes_.back()); std::swap(final_vertexes_[i], final_vertexes_.back());
final_vertexes_.pop_back(); final_vertexes_.pop_back();
break; break;
@ -69,7 +68,7 @@ void NFAGraph::RemoveFinalVertex(size_t number) {
void NFAGraph::RemoveStartVertex(size_t number) { void NFAGraph::RemoveStartVertex(size_t number) {
for (size_t i = 0; i < start_vertexes_.size(); ++i) { for (size_t i = 0; i < start_vertexes_.size(); ++i) {
if (start_vertexes_[i] == number) { if (start_vertexes_[i] == number) {
GetVertex(number).is_start_ = false; vertexes_[number]->is_start_ = false;
std::swap(start_vertexes_[i], start_vertexes_.back()); std::swap(start_vertexes_[i], start_vertexes_.back());
start_vertexes_.pop_back(); start_vertexes_.pop_back();
break; break;
@ -87,24 +86,24 @@ void NFAGraph::Composition(NFAGraph&& nfa_graph,
for (auto& i: nfa_graph.vertexes_) { for (auto& i: nfa_graph.vertexes_) {
new_count_vertexes = std::max(new_count_vertexes, i.first + count_vertexes_ + 1); 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<char, std::set<size_t>> new_transitions; std::map<char, std::set<size_t>> new_transitions;
for (auto& j: i.second.transitions_) { for (auto& j: i.second->transitions_) {
for (auto& k: j.second) { for (auto& k: j.second) {
new_transitions[j.first].insert(k + count_vertexes_); new_transitions[j.first].insert(k + count_vertexes_);
} }
} }
std::map<char, std::set<size_t>> new_back_transitions; std::map<char, std::set<size_t>> new_back_transitions;
for (auto& j: i.second.back_transitions_) { for (auto& j: i.second->back_transitions_) {
for (auto& k: j.second) { for (auto& k: j.second) {
new_back_transitions[j.first].insert(k + count_vertexes_); new_back_transitions[j.first].insert(k + count_vertexes_);
} }
} }
i.second.transitions_ = std::move(new_transitions); i.second->transitions_ = std::move(new_transitions);
i.second.back_transitions_ = std::move(new_back_transitions); i.second->back_transitions_ = std::move(new_back_transitions);
i.second.SetOwner(this); i.second->SetOwner(this);
vertexes_.emplace(i.second.number_, std::move(i.second)); vertexes_[i.second->number_] = std::move(i.second);
} }
for (auto& i: add_start_vertexes) { for (auto& i: add_start_vertexes) {
@ -118,42 +117,34 @@ void NFAGraph::Composition(NFAGraph&& nfa_graph,
for (auto& i: start_vertexes) { for (auto& i: start_vertexes) {
for (auto& j: add_start_vertexes) { for (auto& j: add_start_vertexes) {
GetVertex(i).transitions_[' '].insert(j); vertexes_[i]->transitions_[' '].insert(j);
GetVertex(j).back_transitions_[' '].insert(i); vertexes_[j]->back_transitions_[' '].insert(i);
} }
} }
for (auto& i: add_final_vertexes) { for (auto& i: add_final_vertexes) {
for (auto& j: final_vertexes) { for (auto& j: final_vertexes) {
GetVertex(i).transitions_[' '].insert(j); vertexes_[i]->transitions_[' '].insert(j);
GetVertex(j).back_transitions_[' '].insert(i); vertexes_[j]->back_transitions_[' '].insert(i);
} }
} }
for (auto& i: add_final_vertexes) { for (auto& i: add_final_vertexes) {
GetVertex(i).is_final_ = false; vertexes_[i]->is_final_ = false;
} }
for (auto& i: add_start_vertexes) { for (auto& i: add_start_vertexes) {
GetVertex(i).is_start_ = false; vertexes_[i]->is_start_ = false;
} }
} }
NFAGraph::Vertex& NFAGraph::GetVertex(size_t number) { std::shared_ptr<NFAGraph::Vertex> NFAGraph::GetVertex(size_t number) {
if (!NotExistVertex(number)) if (vertexes_.count(number))
return vertexes_.at(number); return vertexes_[number];
throw std::out_of_range("This vertex don't exist"); return nullptr;
}
bool NFAGraph::NotExistVertex(size_t number) {
return !vertexes_.count(number);
} }
size_t NFAGraph::GetCountVertexes() const { size_t NFAGraph::GetCountVertexes() const {
return count_vertexes_; return count_vertexes_;
} }
size_t NFAGraph::GetReallyCountVertexes() const {
return vertexes_.size();
}
const std::vector<size_t>& NFAGraph::GetFinalVertexes() const { const std::vector<size_t>& NFAGraph::GetFinalVertexes() const {
return final_vertexes_; return final_vertexes_;
} }
@ -164,42 +155,17 @@ const std::vector<size_t>& NFAGraph::GetStartVertexes() const {
void NFAGraph::Print() const { void NFAGraph::Print() const {
for (auto i: vertexes_) { for (auto i: vertexes_) {
std::cout << i.second.number_ << " " << "f-" << i.second.is_final_ << " s-" << std::cout << i.second->number_ << " " << "f-" << i.second->is_final_ << " s-" <<
i.second.is_start_ << std::endl; i.second->is_start_ << std::endl;
} }
for (auto& i: vertexes_) { for (auto& i: vertexes_) {
for (auto& j: i.second.transitions_) { for (auto& j: i.second->transitions_) {
for (auto k: j.second) { for (auto k: j.second) {
std::cout << i.second.number_ << "." << k << " <" << j.first << ">" << std::cout << i.second->number_ << "->" << k << " <" << j.first << ">" <<
std::endl; std::endl;
} }
} }
} }
std::cout << std::endl; 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) {
if (j.first == ' ')
out << i.first << "->" << k << "[label=" << "EPS" << "]\n";
else
out << i.first << "->" << k << "[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";
}
} }

View file

@ -26,17 +26,17 @@ const std::map<char, std::set<size_t>>& Vertex::GetBackTransitions() const {
void Vertex::AddEdge(char symbol, size_t number) { void Vertex::AddEdge(char symbol, size_t number) {
transitions_[symbol].insert(number); transitions_[symbol].insert(number);
owner_->GetVertex(number).back_transitions_[symbol]; owner_->GetVertex(number)->back_transitions_[symbol];
owner_->GetVertex(number).back_transitions_[symbol].insert(number_); owner_->GetVertex(number)->back_transitions_[symbol].insert(number_);
} }
void Vertex::RemoveEdge(char symbol, size_t number) { void Vertex::RemoveEdge(char symbol, size_t number) {
transitions_[symbol].erase(number); transitions_[symbol].erase(number);
if (transitions_[symbol].size() == 0) if (transitions_[symbol].size() == 0)
transitions_.erase(symbol); transitions_.erase(symbol);
owner_->GetVertex(number).back_transitions_[symbol].erase(number_); owner_->GetVertex(number)->back_transitions_[symbol].erase(number_);
if (owner_->GetVertex(number).back_transitions_[symbol].size() == 0) if (owner_->GetVertex(number)->back_transitions_[symbol].size() == 0)
owner_->GetVertex(number).back_transitions_.erase(symbol); owner_->GetVertex(number)->back_transitions_.erase(symbol);
} }
void Vertex::SetOwner(NFAGraph* owner) { void Vertex::SetOwner(NFAGraph* owner) {

View file

@ -6,38 +6,38 @@ DFAGraph DFAGraphToFDFAGraph(DFAGraph&& graph, const std::vector<char>& alphabet
const int n = graph.GetCountVertexes(); const int n = graph.GetCountVertexes();
std::map<size_t, size_t> number_vertex_in_DFA; std::map<size_t, size_t> number_vertex_in_DFA;
for (int i = 0; i < n; ++i) { for (int i = 0; i < n; ++i) {
if (graph.NotExistVertex(i)) continue; if (!graph.GetVertex(i)) continue;
number_vertex_in_DFA[i] = result.AddNewVertex(); number_vertex_in_DFA[i] = result.AddNewVertex();
} }
for (int i = 0; i < n; ++i) { for (int i = 0; i < n; ++i) {
if (graph.NotExistVertex(i)) continue; if (!graph.GetVertex(i)) continue;
if (graph.GetVertex(i).IsFinal()) if (graph.GetVertex(i)->IsFinal())
result.GetVertex(number_vertex_in_DFA[i]).SetFinal(true); result.GetVertex(number_vertex_in_DFA[i])->SetFinal(true);
if (graph.GetVertex(i).IsStart()) if (graph.GetVertex(i)->IsStart())
result.GetVertex(number_vertex_in_DFA[i]).SetStart(true); 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) { 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(); size_t drain = result.AddNewVertex();
for (int i = 0; i < n; ++i) { 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) { for (char j: alphabet) {
if (!transitions.count(j)) { 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); result.RemoveVertex(drain);
} else { } else {
for (char j: alphabet) { for (char j: alphabet) {
result.GetVertex(drain).AddEdge(j, drain); result.GetVertex(drain)->AddEdge(j, drain);
} }
} }

View file

@ -1,5 +1,4 @@
#include "converters/DFAToMinDFA.hpp" #include "converters/DFAToMinDFA.hpp"
#include <iostream>
namespace converters { namespace converters {
DFAGraph DFAGraphToMinDFAGraph(DFAGraph&& graph) { DFAGraph DFAGraphToMinDFAGraph(DFAGraph&& graph) {
@ -11,8 +10,7 @@ DFAGraph DFAGraphToMinDFAGraph(DFAGraph&& graph) {
{ {
std::set<char> set_alphabet; std::set<char> set_alphabet;
for (int i = 0; i < n; ++i) { for (int i = 0; i < n; ++i) {
if (graph.NotExistVertex(i)) continue; for (auto i: graph.GetVertex(i)->GetTransitions()) {
for (auto i: graph.GetVertex(i).GetTransitions()) {
set_alphabet.insert(i.first); set_alphabet.insert(i.first);
} }
} }
@ -25,11 +23,11 @@ DFAGraph DFAGraphToMinDFAGraph(DFAGraph&& graph) {
{ {
std::vector<std::vector<size_t>>& layer(table[0]); std::vector<std::vector<size_t>>& layer(table[0]);
for (int i = 0; i < n; ++i) { 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 i = 0; i < n; ++i) {
for (int j = 0; j < alphabet.size(); ++j) { 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])) if (transitions.count(alphabet[j]))
layer[i][j + 1] = layer[transitions.at(alphabet[j])][0]; layer[i][j + 1] = layer[transitions.at(alphabet[j])][0];
else else
@ -57,7 +55,7 @@ DFAGraph DFAGraphToMinDFAGraph(DFAGraph&& graph) {
} }
for (int i = 0; i < n; ++i) { for (int i = 0; i < n; ++i) {
for (int j = 0; j < alphabet.size(); ++j) { 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])) if (transitions.count(alphabet[j]))
layer[i][j + 1] = layer[transitions.at(alphabet[j])][0]; layer[i][j + 1] = layer[transitions.at(alphabet[j])][0];
else else
@ -76,7 +74,7 @@ DFAGraph DFAGraphToMinDFAGraph(DFAGraph&& graph) {
} }
std::cout << std::endl; std::cout << std::endl;
} }
*/ */
std::vector<std::vector<size_t>>& last_layer(table.back()); std::vector<std::vector<size_t>>& last_layer(table.back());
size_t count_vertex = 0; size_t count_vertex = 0;
@ -94,16 +92,16 @@ DFAGraph DFAGraphToMinDFAGraph(DFAGraph&& graph) {
for (int i = 0; i < n; ++i) { for (int i = 0; i < n; ++i) {
size_t v = number_vertex_in_DFA[last_layer[i][0]]; 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) { for (const auto& t: transitions) {
if (last_layer[t.second][0] != -1LL) { if (last_layer[t.second][0] != -1LL) {
size_t u = number_vertex_in_DFA[last_layer[t.second][0]]; 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)->IsStart()) result.GetVertex(v)->SetStart(true);
if (graph.GetVertex(i).IsFinal()) result.GetVertex(v).SetFinal(true); if (graph.GetVertex(i)->IsFinal()) result.GetVertex(v)->SetFinal(true);
} }
return result; return result;

View file

@ -1,20 +1,19 @@
#include "converters/DFAToRegular.hpp" #include "converters/DFAToRegular.hpp"
#include "regular/RegularTree.hpp"
#include <iostream>
#include <fstream>
namespace converters { namespace converters {
std::string DFAGraphToRegular(DFAGraph&& graph) { std::string DFAGraphToRegular(DFAGraph&& graph) {
const size_t n = graph.GetCountVertexes() + 1; const size_t n = graph.GetCountVertexes() + 1;
std::string result = "";
std::vector<std::vector<std::set<std::string>>> transitions(n,
std::vector<std::set<std::string>>(n));
std::map<size_t, size_t> rename; std::map<size_t, size_t> rename;
size_t start = -1; size_t start = -1;
for (int i = 0; i < n - 1; ++i) { for (int i = 0; i < n - 1; ++i) {
if (graph.NotExistVertex(i)) continue; if (!graph.GetVertex(i)) continue;
if (graph.GetVertex(i).IsStart()) { if (graph.GetVertex(i)->IsStart()) start = i;
start = i;
}
} }
rename[start] = 1; rename[start] = 1;
@ -24,72 +23,42 @@ std::string DFAGraphToRegular(DFAGraph&& graph) {
if (i == start) continue; if (i == start) continue;
rename[i] = cnt++; rename[i] = cnt++;
} }
std::vector<std::vector<std::set<std::string>>> transitions(cnt,
std::vector<std::set<std::string>>(cnt));
for (int i = 0; i < n - 1; ++i) { for (int i = 0; i < n - 1; ++i) {
if (graph.NotExistVertex(i)) continue; if (!graph.GetVertex(i)) continue;
const auto& vertex_transitions = graph.GetVertex(i).GetTransitions(); const auto& vertex_transitions = graph.GetVertex(i)->GetTransitions();
for (auto j: vertex_transitions) { for (auto j: vertex_transitions) {
transitions[rename[i]][rename[j.second]].insert(std::string(1, j.first)); 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("( )"); transitions[rename[i]][0].insert("( )");
} }
} }
for (int i = n - 1; i > 1; --i) {
const bool print_table = true; std::vector<std::vector<std::set<std::string>>> new_transitions(n,
auto PrintTable = [n, &transitions](int i) { std::vector<std::set<std::string>>(n));
std::ofstream out("ConvertToRegular/" + std::to_string(n - i) + ".dot"); std::string loop = "";
out << "digraph G {\n";
for (int j = 0; j < i; ++j) {
for (int k = 0; k < i; ++k) {
std::string j_to_k = "";
for (const std::string& s: transitions[j][k]) {
j_to_k += "(";
j_to_k += s;
j_to_k += ")";
j_to_k += "|";
}
if (j_to_k.size())
j_to_k.pop_back();
else
continue;
out << j << "->" << k << "[label=\"" << regular::RegularTree(j_to_k).ToString() << "\"]\n";
}
}
out << " " << 1 << " [shape=rarrow];\n";
out << " " << 0 << " [shape=Msquare];\n";
out << "}\n";
};
if (print_table) {
PrintTable(cnt);
}
for (int i = cnt - 1; i > 1; --i) {
std::vector<std::vector<std::set<std::string>>> new_transitions(cnt,
std::vector<std::set<std::string>>(cnt));
std::string loop;
if (transitions[i][i].size() != 0) { if (transitions[i][i].size() != 0) {
for (const std::string& s: transitions[i][i]) { for (const std::string s: transitions[i][i]) {
loop += "("; loop += "(";
loop += s; loop += s;
loop += ")"; loop += ")";
loop += "|"; loop += "|";
} }
if (loop.size()) { if (loop.size())
loop.pop_back(); loop.pop_back();
if (transitions[i][i].size() > 1)
loop = "(" + loop + ")*"; loop = "(" + loop + ")*";
} else { else
loop = ""; loop += "*";
}
} }
for (int j = 0; j < i; ++j) { for (int j = 0; j < i; ++j) {
if (transitions[j][i].size() == 0) continue; if (transitions[j][i].size() == 0) continue;
std::string j_to_i; std::string j_to_i = "";
for (const std::string s: transitions[j][i]) { for (const std::string s: transitions[j][i]) {
j_to_i += "("; j_to_i += "(";
j_to_i += s; j_to_i += s;
@ -98,14 +67,13 @@ std::string DFAGraphToRegular(DFAGraph&& graph) {
} }
if (j_to_i.size()) if (j_to_i.size())
j_to_i.pop_back(); j_to_i.pop_back();
else if (transitions[j][i].size() > 1)
continue; j_to_i = "(" + j_to_i + ")";
j_to_i = "(" + j_to_i + ")";
for (int k = 0; k < i; ++k) { for (int k = 0; k < i; ++k) {
if (transitions[i][k].size() == 0) continue; if (transitions[i][k].size() == 0) continue;
std::string i_to_k = ""; std::string i_to_k = "";
for (const std::string& s: transitions[i][k]) { for (const std::string s: transitions[i][k]) {
i_to_k += "("; i_to_k += "(";
i_to_k += s; i_to_k += s;
i_to_k += ")"; i_to_k += ")";
@ -113,10 +81,8 @@ std::string DFAGraphToRegular(DFAGraph&& graph) {
} }
if (i_to_k.size()) if (i_to_k.size())
i_to_k.pop_back(); i_to_k.pop_back();
else if (transitions[i][k].size() > 1)
continue; i_to_k = "(" + j_to_i + ")";
i_to_k = "(" + i_to_k + ")";
new_transitions[j][k].insert(j_to_i + loop + i_to_k); new_transitions[j][k].insert(j_to_i + loop + i_to_k);
} }
@ -127,38 +93,32 @@ std::string DFAGraphToRegular(DFAGraph&& graph) {
transitions[j][k].insert(new_transitions[j][k].begin(), new_transitions[j][k].end()); transitions[j][k].insert(new_transitions[j][k].begin(), new_transitions[j][k].end());
} }
} }
if (print_table) {
PrintTable(i);
}
} }
std::string loop; std::string loop;
std::string start_to_end; std::string begin_to_end;
if (transitions[1][1].size() != 0) { if (transitions[1][1].size() != 0) {
for (const std::string& s: transitions[1][1]) { for (const std::string s: transitions[1][1]) {
loop += "("; loop += "(";
loop += s; loop += s;
loop += ")"; loop += ")";
loop += "|"; loop += "|";
} }
if (loop.size()) { if (loop.size())
loop.pop_back(); loop.pop_back();
loop = "(" + loop + ")*"; loop = "(" + loop + ")*";
} else {
loop = "";
}
} }
for (const std::string& s: transitions[1][0]) { for (const std::string s: transitions[1][0]) {
start_to_end += "("; begin_to_end += "(";
start_to_end += s; begin_to_end += s;
start_to_end += ")"; begin_to_end += ")";
start_to_end += "|"; begin_to_end += "|";
} }
if (start_to_end.size()) if (begin_to_end.size())
start_to_end.pop_back(); begin_to_end.pop_back();
return loop + "(" + start_to_end + ")"; std::string res(loop + "(" + begin_to_end + ")");
return res;
} }
} }

View file

@ -4,8 +4,8 @@ namespace converters {
DFAGraph InvertFDFAGraph(DFAGraph&& fdfa_graph) { DFAGraph InvertFDFAGraph(DFAGraph&& fdfa_graph) {
const size_t n = fdfa_graph.GetCountVertexes(); const size_t n = fdfa_graph.GetCountVertexes();
for (int i = 0; i < n; ++i) { for (int i = 0; i < n; ++i) {
if (fdfa_graph.NotExistVertex(i)) continue; if (!fdfa_graph.GetVertex(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); return std::move(fdfa_graph);
} }

View file

@ -2,8 +2,6 @@
#include <functional> #include <functional>
#include <queue> #include <queue>
#include <stdexcept> #include <stdexcept>
#include <iostream>
#include <iomanip>
namespace converters { namespace converters {
NFAGraph AddAllEpsilonTransitions(NFAGraph&& nfa_graph) { NFAGraph AddAllEpsilonTransitions(NFAGraph&& nfa_graph) {
@ -12,13 +10,13 @@ NFAGraph AddAllEpsilonTransitions(NFAGraph&& nfa_graph) {
std::function<void(int, int)> dfs = [&nfa_graph, &used, &dfs](int u, int v) -> void { std::function<void(int, int)> dfs = [&nfa_graph, &used, &dfs](int u, int v) -> void {
used[v] = true; used[v] = true;
const auto& transitions = nfa_graph.GetVertex(v).GetTransitions(); const auto& transitions = nfa_graph.GetVertex(v)->GetTransitions();
if (transitions.count(' ')) { if (transitions.count(' ')) {
const auto& s = transitions.at(' '); const auto& s = transitions.at(' ');
for (auto i: s) { for (auto i: s) {
if (!used[i]) { if (!used[i]) {
if (u != i) if (u != i)
nfa_graph.GetVertex(u).AddEdge(' ', i); nfa_graph.GetVertex(u)->AddEdge(' ', i);
dfs(u, i); dfs(u, i);
} }
} }
@ -26,7 +24,7 @@ NFAGraph AddAllEpsilonTransitions(NFAGraph&& nfa_graph) {
}; };
for (int i = 0; i < n; ++i) { for (int i = 0; i < n; ++i) {
if (nfa_graph.NotExistVertex(i)) continue; if (!nfa_graph.GetVertex(i)) continue;
used.assign(n, false); used.assign(n, false);
dfs(i, i); dfs(i, i);
@ -34,19 +32,19 @@ NFAGraph AddAllEpsilonTransitions(NFAGraph&& nfa_graph) {
return std::move(nfa_graph); return std::move(nfa_graph);
} }
NFAGraph AddAllPossibleFinalVertexes(NFAGraph&& nfa_graph) { NFAGraph AddAllPossibleStartFinal(NFAGraph&& nfa_graph) {
if (nfa_graph.GetStartVertexes().size() != 1) { if (nfa_graph.GetStartVertexes().size() != 1) {
size_t start_vertex = nfa_graph.AddNewVertex(); size_t start_vertex = nfa_graph.AddNewVertex();
for (auto v: nfa_graph.GetStartVertexes()) { 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()) { 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(' ')) { if (transitions.count(' ')) {
const auto& s = transitions.at(' '); const auto& s = transitions.at(' ');
for (auto i: s) { for (auto i: s) {
nfa_graph.GetVertex(i).SetFinal(true); nfa_graph.GetVertex(i)->SetFinal(true);
} }
} }
} }
@ -57,21 +55,21 @@ NFAGraph DeleteEpsilonTransitions(NFAGraph&& nfa_graph) {
const int n = nfa_graph.GetCountVertexes(); const int n = nfa_graph.GetCountVertexes();
for (int v = 0; v < n; ++v) { for (int v = 0; v < n; ++v) {
if (nfa_graph.NotExistVertex(v)) continue; if (!nfa_graph.GetVertex(v)) continue;
const auto& transitions = nfa_graph.GetVertex(v).GetTransitions(); const auto& transitions = nfa_graph.GetVertex(v)->GetTransitions();
if (transitions.count(' ')) { if (transitions.count(' ')) {
auto s = transitions.at(' '); auto s = transitions.at(' ');
for (auto u: s) { for (auto u: s) {
for (auto& i: nfa_graph.GetVertex(u).GetTransitions()) { for (auto& i: nfa_graph.GetVertex(u)->GetTransitions()) {
if (i.first == ' ') continue; if (i.first == ' ') continue;
for (auto t: i.second) { 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) { for (auto u: s) {
nfa_graph.GetVertex(v).RemoveEdge(' ', u); nfa_graph.GetVertex(v)->RemoveEdge(' ', u);
} }
} }
} }
@ -89,8 +87,8 @@ NFAGraph DeleteTransitionsByOneLetter(NFAGraph&& nfa_graph) {
std::set<char> alphabet; std::set<char> alphabet;
for (int i = 0; i < n; ++i) { for (int i = 0; i < n; ++i) {
if (nfa_graph.NotExistVertex(i)) continue; if (!nfa_graph.GetVertex(i)) continue;
for (const auto& j: nfa_graph.GetVertex(i).GetTransitions()) { for (const auto& j: nfa_graph.GetVertex(i)->GetTransitions()) {
if (j.second.size() > 0) if (j.second.size() > 0)
alphabet.insert(j.first); alphabet.insert(j.first);
} }
@ -101,54 +99,20 @@ NFAGraph DeleteTransitionsByOneLetter(NFAGraph&& nfa_graph) {
number_vertex_in_result_tree[{i}] = result_tree.AddNewVertex(); number_vertex_in_result_tree[{i}] = result_tree.AddNewVertex();
} }
const bool print_table = false;
const size_t length_set = 10;
if (print_table) {
std::cout << std::setw(length_set) << "vertex" << " | ";
for (auto i: alphabet) {
std::cout << std::string(length_set / 2, ' ') << i << std::string(length_set - length_set / 2 - 1, ' ') << " | ";
}
std::cout << std::setw(length_set) << "new number" << " | ";
std::cout << std::endl;
std::cout << std::string((length_set + 3) * (alphabet.size() + 2) - 1, '-') << std::endl;
}
while (!queue.empty()) { while (!queue.empty()) {
auto current = queue.front(); auto current = queue.front();
queue.pop(); queue.pop();
if (print_table) {
std::string res;
for (int v: current) {
res += std::to_string(v) + ",";
}
if (res.length())
res.pop_back();
std::cout << std::setw(length_set) << res << " | ";
}
for (auto symbol: alphabet) { for (auto symbol: alphabet) {
std::set<size_t> result; std::set<size_t> result;
for (auto v: current) { for (auto v: current) {
const auto& transitions = nfa_graph.GetVertex(v).GetTransitions(); const auto& transitions = nfa_graph.GetVertex(v)->GetTransitions();
if (transitions.count(symbol)) { if (transitions.count(symbol)) {
const auto& s = transitions.at(symbol); const auto& s = transitions.at(symbol);
result.insert(s.begin(), s.end()); result.insert(s.begin(), s.end());
} }
} }
if (print_table) {
std::string res;
if (result.size() == 0) {
std::cout << std::setw(length_set) << '-' << " | ";
} else {
for (int v: result) {
res += std::to_string(v) + ",";
}
if (res.length())
res.pop_back();
std::cout << std::setw(length_set) << res << " | ";
}
}
if (result.size() == 0) continue; if (result.size() == 0) continue;
transitions[std::make_pair(current, symbol)] = result; transitions[std::make_pair(current, symbol)] = result;
@ -156,11 +120,6 @@ NFAGraph DeleteTransitionsByOneLetter(NFAGraph&& nfa_graph) {
queue.push(result); queue.push(result);
number_vertex_in_result_tree[result] = result_tree.AddNewVertex(); number_vertex_in_result_tree[result] = result_tree.AddNewVertex();
} }
}
if (print_table) {
std::cout << std::setw(length_set) << number_vertex_in_result_tree[current] << "|";
std::cout << std::endl;
} }
} }
@ -168,7 +127,7 @@ NFAGraph DeleteTransitionsByOneLetter(NFAGraph&& nfa_graph) {
int v = number_vertex_in_result_tree[i.first.first]; int v = number_vertex_in_result_tree[i.first.first];
int u = number_vertex_in_result_tree[i.second]; int u = number_vertex_in_result_tree[i.second];
char symbol = i.first.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) { for (auto i: number_vertex_in_result_tree) {
@ -176,52 +135,40 @@ NFAGraph DeleteTransitionsByOneLetter(NFAGraph&& nfa_graph) {
auto v = i.second; auto v = i.second;
for (auto i: s) { for (auto i: s) {
if (nfa_graph.GetVertex(i).IsFinal()) if (nfa_graph.GetVertex(i)->IsFinal())
result_tree.GetVertex(v).SetFinal(true); result_tree.GetVertex(v)->SetFinal(true);
if (nfa_graph.GetVertex(i).IsStart()) if (nfa_graph.GetVertex(i)->IsStart())
result_tree.GetVertex(v).SetStart(true); result_tree.GetVertex(v)->SetStart(true);
} }
} }
return result_tree; return result_tree;
} }
DFAGraph NFAGraphToDFAGraph(NFAGraph&& nfa_graph) { DFAGraph NFAGraphToDFAGraph(NFAGraph&& nfa_graph) {
nfa_graph = AddAllEpsilonTransitions(std::move(nfa_graph)); nfa_graph = DeleteTransitionsByOneLetter(DeleteEpsilonTransitions(AddAllPossibleStartFinal(
nfa_graph = AddAllPossibleFinalVertexes(std::move(nfa_graph)); AddAllEpsilonTransitions(std::move(nfa_graph)))));
nfa_graph = DeleteEpsilonTransitions(std::move(nfa_graph));
nfa_graph = DeleteTransitionsByOneLetter(std::move(nfa_graph));
const int n = nfa_graph.GetCountVertexes(); const int n = nfa_graph.GetCountVertexes();
DFAGraph result; DFAGraph result;
std::map<int, int> number_vertex_in_DFA; std::map<int, int> number_vertex_in_DFA;
for (int i = 0; i < n; ++i) { for (int i = 0; i < n; ++i) {
if (nfa_graph.NotExistVertex(i)) continue; if (!nfa_graph.GetVertex(i)) continue;
number_vertex_in_DFA[i] = result.AddNewVertex(); number_vertex_in_DFA[i] = result.AddNewVertex();
} }
bool exists_start_vertex = false;
for (int i = 0; i < n; ++i) { for (int i = 0; i < n; ++i) {
if (nfa_graph.NotExistVertex(i)) continue; if (!nfa_graph.GetVertex(i)) continue;
if (nfa_graph.GetVertex(i).IsFinal()) if (nfa_graph.GetVertex(i)->IsFinal())
result.GetVertex(number_vertex_in_DFA[i]).SetFinal(true); 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) { result.GetVertex(number_vertex_in_DFA[i])->SetStart(true);
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(); const auto& transitions = nfa_graph.GetVertex(i)->GetTransitions();
for (const auto& t: transitions) { for (const auto& t: transitions) {
if (t.second.size() != 1) throw std::logic_error(""); 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());
} }
} }
if (!exists_start_vertex) {
throw std::runtime_error("I can't find start vertex");
}
return result; return result;
} }
} }

View file

@ -20,14 +20,14 @@ NFAGraph RegularToNFA(std::unique_ptr<Node, deleter> node) {
result.AddStartVertex(end); result.AddStartVertex(end);
for (char i: node->word) { for (char i: node->word) {
auto tmp = result.AddNewVertex(); auto tmp = result.AddNewVertex();
result.GetVertex(end).AddEdge(i, tmp); result.GetVertex(end)->AddEdge(i, tmp);
end = tmp; end = tmp;
} }
if (node->modifier == Node::Modifier::Plus) { if (node->modifier == Node::Modifier::Plus) {
result.GetVertex(end).AddEdge(' ', start); result.GetVertex(end)->AddEdge(' ', start);
} else if (node->modifier == Node::Modifier::Star) { } else if (node->modifier == Node::Modifier::Star) {
result.GetVertex(end).AddEdge(' ', start); result.GetVertex(end)->AddEdge(' ', start);
result.GetVertex(start).AddEdge(' ', end); result.GetVertex(start)->AddEdge(' ', end);
} }
result.AddFinalVertex(end); result.AddFinalVertex(end);
} else if (node->type == Node::Type::Concatenation) { } else if (node->type == Node::Type::Concatenation) {
@ -47,14 +47,14 @@ NFAGraph RegularToNFA(std::unique_ptr<Node, deleter> node) {
if (node->modifier == Node::Modifier::Plus) { if (node->modifier == Node::Modifier::Plus) {
for (auto start: start_vertexes) { for (auto start: start_vertexes) {
for (auto end: end_vertexes) { for (auto end: end_vertexes) {
result.GetVertex(end).AddEdge(' ', start); result.GetVertex(end)->AddEdge(' ', start);
} }
} }
} else if (node->modifier == Node::Modifier::Star) { } else if (node->modifier == Node::Modifier::Star) {
for (auto start: start_vertexes) { for (auto start: start_vertexes) {
for (auto end: end_vertexes) { for (auto end: end_vertexes) {
result.GetVertex(end).AddEdge(' ', start); result.GetVertex(end)->AddEdge(' ', start);
result.GetVertex(start).AddEdge(' ', end); result.GetVertex(start)->AddEdge(' ', end);
} }
} }
} }
@ -69,10 +69,10 @@ NFAGraph RegularToNFA(std::unique_ptr<Node, deleter> node) {
result.Composition(std::move(tmp), {start}, {end}); result.Composition(std::move(tmp), {start}, {end});
} }
if (node->modifier == Node::Modifier::Plus) { if (node->modifier == Node::Modifier::Plus) {
result.GetVertex(end).AddEdge(' ', start); result.GetVertex(end)->AddEdge(' ', start);
} else if (node->modifier == Node::Modifier::Star) { } else if (node->modifier == Node::Modifier::Star) {
result.GetVertex(end).AddEdge(' ', start); result.GetVertex(end)->AddEdge(' ', start);
result.GetVertex(start).AddEdge(' ', end); result.GetVertex(start)->AddEdge(' ', end);
} }
} }
return result; return result;

View file

@ -1,19 +1,14 @@
#include <iostream> #include <iostream>
#include <cassert>
#include "regular/RegularTree.hpp" #include "regular/RegularTree.hpp"
#include "NFA/NFAGraph.hpp"
#include "DFA/DFAGraph.hpp"
#include "converters/RegularToNFA.hpp" #include "converters/RegularToNFA.hpp"
#include "converters/NFAToDFA.hpp" #include "converters/NFAToDFA.hpp"
#include "converters/DFAToFDFA.hpp" #include "converters/DFAToFDFA.hpp"
#include "converters/DFAToMinDFA.hpp" #include "converters/DFAToMinDFA.hpp"
#include "converters/DFAToRegular.hpp" #include "converters/DFAToRegular.hpp"
#include "converters/InvertFDFA.hpp" #include "converters/InvertFDFA.hpp"
#include <random>
#define RegularStringToDFAGraph(s) NFAGraphToDFAGraph(RegularToNFAGraph(RegularTree(s)))
#define RegularStringToMinDFAGraph(s) DFAGraphToMinDFAGraph(NFAGraphToDFAGraph(RegularToNFAGraph(RegularTree(s))))
#define InvertRegularString(v, s) RegularTree(DFAGraphToRegular(DFAGraphToMinDFAGraph(InvertFDFAGraph(DFAGraphToMinDFAGraph(DFAGraphToFDFAGraph(NFAGraphToDFAGraph(RegularToNFAGraph(RegularTree(s))), v)))))).ToString()
using namespace regular;
using namespace regular; using namespace regular;
using namespace NFA; using namespace NFA;
using namespace DFA; using namespace DFA;
@ -41,7 +36,7 @@ void example2() {
a[i] = nfa_graph.AddNewVertex(); a[i] = nfa_graph.AddNewVertex();
auto AddEdge = [&nfa_graph, &a](char symbol, int u, int v) { 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); AddEdge('a', 0, 1);
@ -54,15 +49,31 @@ void example2() {
dfa_graph.Print(); dfa_graph.Print();
} }
std::mt19937 rnd(1337);
std::string GenerateRandomString(std::vector<char> alphabet, size_t len) {
std::string res(len, ' ');
for (auto& i: res) {
i = alphabet[rnd() % alphabet.size()];
}
return res;
}
int main() { 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();
DFA_graph = InvertFDFAGraph(std::move(DFA_graph));
return 0;
DFA_graph = DFAGraphToMinDFAGraph(std::move(DFA_graph));
}
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|b)+bab(a|b)+");
// std::cout << DFAGraphToRegular(DFAGraphToMinDFAGraph(InvertFDFAGraph(DFAGraphToFDFAGraph(DFAGraphToMinDFAGraph(NFAGraphToDFAGraph(RegularToNFAGraph(std::move(r)))), {'a', 'b'})))) << std::endl;
} }

View file

@ -12,8 +12,4 @@ const RegularTree::Node& RegularTree::GetNode() const {
void RegularTree::Print() const { void RegularTree::Print() const {
node_.Print(); node_.Print();
} }
std::string RegularTree::ToString() const {
return node_.ToString();
}
} }

View file

@ -8,10 +8,7 @@ Node::Node(Type type) : type(type) {}
void Node::Parse(const std::string& regular) { void Node::Parse(const std::string& regular) {
type = Type::Addition; type = Type::Addition;
ParseCurrentType(std::string_view(regular.c_str(), regular.size())); ParseCurrentType(std::string_view(regular.c_str(), regular.size()));
for (int i = 0; i < 10; ++i) { Compression();
Compression();
Compression2();
}
} }
void Node::Print() const { void Node::Print() const {
@ -163,25 +160,6 @@ 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 { void Node::Print(int nesting_level) const {
auto PrintNesingLevel = [](int nesting_level) { auto PrintNesingLevel = [](int nesting_level) {
for (int i = 0; i < nesting_level; ++i) { for (int i = 0; i < nesting_level; ++i) {
@ -220,35 +198,3 @@ void Node::Print(int nesting_level) const {
i->Print(nesting_level + 1); 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;
}

View file

@ -1,40 +0,0 @@
#include <gtest/gtest.h>
#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)*"));
}

View file

@ -1,209 +0,0 @@
#include <gtest/gtest.h>
#include <random>
#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<char> 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<char> s(str.begin(), str.end());
if (s.size() == 0)
return true;
else {
if (s.size() == 1)
return *s.begin() != 'd';
else
return false;
}
};
ASSERT_EQ(DFA_graph.Accepted(""), 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<char> 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<char> 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));
}
}

View file

@ -1,69 +0,0 @@
#include <gtest/gtest.h>
#include <random>
#include "regular/RegularTree.hpp"
#include "converters/RegularToNFA.hpp"
#include "converters/NFAToDFA.hpp"
#include "converters/DFAToMinDFA.hpp"
#include "converters/DFAToFDFA.hpp"
#include "converters/InvertFDFA.hpp"
#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<char> alphabet, size_t len);
TEST(generic_tests, divided_5) {
DFAGraph DFA_graph;
size_t a[10];
for (int i = 0; i < 10; ++i) {
a[i] = DFA_graph.AddNewVertex();
}
auto add_edge = [&DFA_graph, &a](size_t in, size_t out, char x) {
DFA_graph.GetVertex(a[in]).AddEdge(x, a[out]);
};
add_edge(5, 6, '0');
add_edge(5, 1, '1');
add_edge(1, 2, '0');
add_edge(1, 3, '1');
add_edge(2, 4, '0');
add_edge(2, 0, '1');
add_edge(3, 1, '0');
add_edge(3, 2, '1');
add_edge(4, 3, '0');
add_edge(4, 4, '1');
add_edge(0, 0, '0');
add_edge(0, 1, '1');
DFA_graph.GetVertex(a[5]).SetStart(true);
DFA_graph.GetVertex(a[6]).SetFinal(true);
DFA_graph.GetVertex(a[0]).SetFinal(true);
DFA_graph = DFAGraphToMinDFAGraph(std::move(DFA_graph));
DFA_graph = NFAGraphToDFAGraph(RegularToNFAGraph(RegularTree(DFAGraphToRegular(std::move(DFA_graph)))));
auto check = [](const std::string& str) -> bool {
bool answer = true;
if (str.size() == 1) {
return str == "0";
}
if (str[0] == '0') {
return false;
}
int remainder = 0;
for (auto i: str) {
remainder = remainder * 2 + i - '0';
remainder %= 5;
}
return remainder == 0;
};
for (int i = 0; i < 2000; ++i) {
std::string test = GenerateRandomString({'0', '1'}, rnd() % 1000 + 1);
ASSERT_EQ(DFA_graph.Accepted(test), check(test));
}
}

View file

@ -26,13 +26,13 @@ TEST(check_equivalence_NFA_to_DFA, 1) {
for (int i = 0; i < N; ++i) for (int i = 0; i < N; ++i)
a[i] = tree.AddNewVertex(); a[i] = tree.AddNewVertex();
tree.GetVertex(a[0]).AddEdge('a', a[1]); tree.GetVertex(a[0])->AddEdge('a', a[1]);
tree.GetVertex(a[1]).AddEdge('a', a[2]); tree.GetVertex(a[1])->AddEdge('a', a[2]);
tree.GetVertex(a[0]).AddEdge('a', a[3]); tree.GetVertex(a[0])->AddEdge('a', a[3]);
tree.GetVertex(a[0]).SetStart(true); tree.GetVertex(a[0])->SetStart(true);
tree.GetVertex(a[2]).SetFinal(true); tree.GetVertex(a[2])->SetFinal(true);
tree.GetVertex(a[3]).SetFinal(true); tree.GetVertex(a[3])->SetFinal(true);
DFA::DFAGraph res = converters::NFAGraphToDFAGraph(std::move(tree)); 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) for (int i = 0; i < N; ++i)
a[i] = tree.AddNewVertex(); a[i] = tree.AddNewVertex();
tree.GetVertex(a[0]).AddEdge('a', a[1]); tree.GetVertex(a[0])->AddEdge('a', a[1]);
tree.GetVertex(a[0]).AddEdge('a', a[2]); tree.GetVertex(a[0])->AddEdge('a', a[2]);
tree.GetVertex(a[1]).AddEdge('b', a[1]); tree.GetVertex(a[1])->AddEdge('b', a[1]);
tree.GetVertex(a[2]).AddEdge('c', a[2]); tree.GetVertex(a[2])->AddEdge('c', a[2]);
tree.GetVertex(a[0]).SetStart(true); tree.GetVertex(a[0])->SetStart(true);
tree.GetVertex(a[1]).SetFinal(true); tree.GetVertex(a[1])->SetFinal(true);
tree.GetVertex(a[2]).SetFinal(true); tree.GetVertex(a[2])->SetFinal(true);
DFA::DFAGraph res = converters::NFAGraphToDFAGraph(std::move(tree)); DFA::DFAGraph res = converters::NFAGraphToDFAGraph(std::move(tree));