diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 00000000..e9839f93 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,12 @@ +FROM ubuntu:18.04 as chipollino +ENV TZ=Europe/Moscow +RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone +RUN apt-get update +#COPY . /app/ + +COPY . ./app +WORKDIR /app/ +RUN ./scripts/install_packages.sh +#все делаем скриптом (скрипт не только в докере запускать можно) + +CMD ["./scripts/run_code_docker.sh"] diff --git a/apps/TestsApp/src/Example.cpp b/apps/TestsApp/src/Example.cpp index ac2a0265..2c4f7ed7 100644 --- a/apps/TestsApp/src/Example.cpp +++ b/apps/TestsApp/src/Example.cpp @@ -807,16 +807,17 @@ void Example::test_ambiguity() { using Test = tuple; vector tests = { - {0, "(a*)*", thompson, FiniteAutomaton::exponentially_ambiguous}, + //{0, "(a*)*", thompson, FiniteAutomaton::exponentially_ambiguous}, {1, "a*a*", glushkov, FiniteAutomaton::polynomially_ambigious}, {2, "abc", thompson, FiniteAutomaton::unambigious}, - {3, "b|a", thompson, FiniteAutomaton::almost_unambigious}, + //{3, "b|a", thompson, FiniteAutomaton::almost_unambigious}, {4, "(aa|aa)*", glushkov, FiniteAutomaton::exponentially_ambiguous}, {5, "(aab|aab)*", glushkov, FiniteAutomaton::exponentially_ambiguous}, {6, "a*a*((a)*)*", glushkov, FiniteAutomaton::polynomially_ambigious}, - {7, "a*a*((a)*)*", thompson, FiniteAutomaton::exponentially_ambiguous}, - {8, "a*(b*)*", thompson, FiniteAutomaton::exponentially_ambiguous}, - {9, "a*((ab)*)*", thompson, FiniteAutomaton::exponentially_ambiguous}, + //{7, "a*a*((a)*)*", thompson, + // FiniteAutomaton::exponentially_ambiguous}, + //{8, "a*(b*)*", thompson, FiniteAutomaton::exponentially_ambiguous}, + //{9, "a*((ab)*)*", thompson, FiniteAutomaton::exponentially_ambiguous}, {10, "(aa|aa)(aa|bb)*|a(ba)*", glushkov, FiniteAutomaton::almost_unambigious}, {11, "(aaa)*(a|)(a|)", ilieyu, FiniteAutomaton::almost_unambigious}, @@ -838,8 +839,8 @@ void Example::test_ambiguity() { glushkov, FiniteAutomaton::polynomially_ambigious}, {20, "(ab)*ab(ab)*|(ac)*(ac)*", glushkov, FiniteAutomaton::polynomially_ambigious}, - {21, "(a|b)*(f*)*q", thompson, - FiniteAutomaton::exponentially_ambiguous}, + // {21, "(a|b)*(f*)*q", thompson, + // FiniteAutomaton::exponentially_ambiguous}, {22, "((bb*c|c)c*b|bb*b|b)(b|(c|bb*c)c*b|bb*b)*", glushkov, FiniteAutomaton::exponentially_ambiguous}, }; diff --git a/libs/AutomatonToImage/src/AutomatonToImage.cpp b/libs/AutomatonToImage/src/AutomatonToImage.cpp index 96bc6328..e39b7c50 100644 --- a/libs/AutomatonToImage/src/AutomatonToImage.cpp +++ b/libs/AutomatonToImage/src/AutomatonToImage.cpp @@ -11,6 +11,16 @@ AutomatonToImage::~AutomatonToImage() {} /* void AutomatonToImage::to_image(string automat, int name) { char cmd[1024]; + + // для Linux: + + /*sprintf(cmd, + "dot -Tpng ./resources/input.dot > " + "./resources/output%d.png && rm ./resources/input.dot", + name); + + // для Windows: + sprintf(cmd, "dot -Tpng ./resources/input.dot > " "./resources/output%d.png && rm ./resources/input.dot", diff --git a/libs/Interpreter/src/Interpreter.cpp b/libs/Interpreter/src/Interpreter.cpp index 122729b9..b7b667a1 100644 --- a/libs/Interpreter/src/Interpreter.cpp +++ b/libs/Interpreter/src/Interpreter.cpp @@ -341,9 +341,11 @@ optional Interpreter::apply_function( } } if (function.name == "SemDet") { + log_template.load_tex_template("SemDet"); return ObjectBoolean(get_automaton(arguments[0]).semdet(&log_template)); } if (function.name == "PumpLength") { + log_template.load_tex_template("PumpLength"); return ObjectInt( get(arguments[0]).value.pump_length(&log_template)); } diff --git a/libs/Objects/include/Objects/FiniteAutomaton.h b/libs/Objects/include/Objects/FiniteAutomaton.h index 46df6a72..53cc50f9 100644 --- a/libs/Objects/include/Objects/FiniteAutomaton.h +++ b/libs/Objects/include/Objects/FiniteAutomaton.h @@ -74,7 +74,11 @@ class FiniteAutomaton : public BaseObject { map& was) const; // функция проверки на семантическую детерминированность - bool semdet_entry(bool annoted = false, iLogTemplate* log = nullptr) const; + bool semdet_entry(bool traps_removed = false, iLogTemplate* log = nullptr) const; + + // Поиск языков состояний + void get_state_languages(vector& state_languages, + bool annoted = false) const; public: FiniteAutomaton(); @@ -86,11 +90,15 @@ class FiniteAutomaton : public BaseObject { // визуализация автомата string to_txt() const override; // детерминизация ДКА - FiniteAutomaton determinize(iLogTemplate* log = nullptr, bool is_trim = true) const; - // построение eps-замыкания + FiniteAutomaton determinize(iLogTemplate* log = nullptr, + bool is_trim = true) const; + // удаление eps-переходов (построение eps-замыканий) FiniteAutomaton remove_eps(iLogTemplate* log = nullptr) const; + // удаление eps-переходов (доп. вариант) + FiniteAutomaton remove_eps_additional(iLogTemplate* log = nullptr) const; // минимизация ДКА (по Майхиллу-Нероуда) - FiniteAutomaton minimize(iLogTemplate* log = nullptr, bool is_trim = true) const; + FiniteAutomaton minimize(iLogTemplate* log = nullptr, + bool is_trim = true) const; // пересечение НКА (на выходе - автомат, распознающий слова пересечения // языков L1 и L2) static FiniteAutomaton intersection( @@ -147,7 +155,7 @@ class FiniteAutomaton : public BaseObject { bool subset(const FiniteAutomaton&, iLogTemplate* log = nullptr) const; // TODO // и тд - //начальное состояние + // начальное состояние int get_initial(); // определяет меру неоднозначности AmbiguityValue ambiguity(iLogTemplate* log = nullptr) const; diff --git a/libs/Objects/include/Objects/Regex.h b/libs/Objects/include/Objects/Regex.h index a4699a27..2e51db92 100644 --- a/libs/Objects/include/Objects/Regex.h +++ b/libs/Objects/include/Objects/Regex.h @@ -99,6 +99,11 @@ class Regex : BaseObject { void pre_order_travers() const; void clear(); + // Получение всех символов из строки + bool get_symbols_from_string(vector& res); + + void eps_removing(); + public: Regex(); Regex(const string&); diff --git a/libs/Objects/src/FiniteAutomaton.cpp b/libs/Objects/src/FiniteAutomaton.cpp index 8804367f..9b2641f7 100644 --- a/libs/Objects/src/FiniteAutomaton.cpp +++ b/libs/Objects/src/FiniteAutomaton.cpp @@ -338,6 +338,96 @@ FiniteAutomaton FiniteAutomaton::remove_eps(iLogTemplate* log) const { // Logger::init_step("RemEps"); FiniteAutomaton new_nfa(initial_state, states, language); + vector new_states; + map, int> visited_states; + + set q = closure({initial_state}, true); + string initial_state_identifier; + for (auto elem : q) { + initial_state_identifier += + (initial_state_identifier.empty() || states[elem].identifier.empty() + ? "" + : ", ") + + states[elem].identifier; + } + State new_initial_state = {0, q, initial_state_identifier, false, + map>()}; + visited_states[q] = 0; + new_states.push_back(new_initial_state); + + stack> s; + s.push(q); + set x; + int states_counter = 1; + while (!s.empty()) { + q = s.top(); + s.pop(); + for (const alphabet_symbol& symb : language->get_alphabet()) { + x.clear(); + for (int k : q) { + auto transitions_by_symbol = states[k].transitions.find(symb); + if (transitions_by_symbol != states[k].transitions.end()) { + for (int transition_by_symbol : + transitions_by_symbol->second) + x.insert(transition_by_symbol); + } + } + set q1; + set x1; + for (int k : x) { + x1.clear(); + q1 = closure({k}, true); + for (int m : q1) { + x1.insert(m); + } + if (!x1.empty()) { + if (visited_states.find(x1) == visited_states.end()) { + string new_state_identifier; + for (auto elem : x1) { + new_state_identifier += + (new_state_identifier.empty() || + states[elem].identifier.empty() + ? "" + : ", ") + + states[elem].identifier; + } + State new_state = {states_counter, x1, + new_state_identifier, false, + map>()}; + new_states.push_back(new_state); + visited_states[x1] = states_counter; + s.push(x1); + states_counter++; + } + new_states[visited_states[q]].transitions[symb].insert( + visited_states[x1]); + } + } + } + } + for (auto& state : new_states) { + for (auto elem : state.label) { + if (states[elem].is_terminal) state.is_terminal = true; + } + } + new_nfa.initial_state = 0; + new_nfa.states = new_states; + new_nfa = new_nfa.remove_unreachable_states(); + if (log) { + log->set_parameter("oldautomaton", *this); + log->set_parameter("result", new_nfa); + } + /*Logger::log("Автомат до удаления eps-переходов", + "Автомат после удаления eps-переходов", *this, new_nfa); + Logger::finish_step();*/ + return new_nfa; +} + +FiniteAutomaton FiniteAutomaton::remove_eps_additional( + iLogTemplate* log) const { + // Logger::init_step("RemEps"); + FiniteAutomaton new_nfa(initial_state, states, language); + for (auto& state : new_nfa.states) state.transitions = map>(); @@ -349,7 +439,7 @@ FiniteAutomaton FiniteAutomaton::remove_eps(iLogTemplate* log) const { } } vector> x; - for (alphabet_symbol symb : language->get_alphabet()) { + for (const alphabet_symbol& symb : language->get_alphabet()) { x.clear(); for (int k : q) { auto transitions_by_symbol = states[k].transitions.find(symb); @@ -2152,17 +2242,19 @@ std::optional FiniteAutomaton::get_prefix( auto res = get_prefix(*it2, state_end, was); if (res.has_value()) { ans = (string)it->first + (string)res.value(); + return ans; } - return ans; } } } return ans; } -bool FiniteAutomaton::semdet_entry(bool annoted, iLogTemplate* log) const { +void FiniteAutomaton::get_state_languages(vector& state_languages, + bool annoted) const { if (!annoted) { - return annote().semdet_entry(true); + annote().remove_trap_states().get_state_languages(state_languages, true); + return; } // Logger::log( //"Получение языка из производной регулярки автомата по префиксу"); @@ -2171,65 +2263,88 @@ bool FiniteAutomaton::semdet_entry(bool annoted, iLogTemplate* log) const { for (int i = 0; i < states.size(); i++) { if (states[i].is_terminal) final_states.push_back(i); } - std::vector state_languages; state_languages.resize(states.size()); for (int i = 0; i < states.size(); i++) { auto prefix = get_prefix(initial_state, i, was); was.clear(); - // cout << "Try " << i << "\n"; if (!prefix.has_value()) continue; Regex reg; // Получение языка из производной регулярки автомата по префиксу: - // this -> reg (arden?) reg = to_regex(); - // cout << "State: " << i << "\n"; - // cout << "Prefix: " << prefix.value() << "\n"; - // cout << "Regex: " << reg.to_txt() << "\n"; - // Logger::log("State", to_string(i)); - // Logger::log("Prefix", prefix.value()); - // Logger::log("Regex", reg.to_txt()); auto derivative = reg.prefix_derivative(prefix.value()); + //cout << prefix.value() << " " << reg.to_txt() << "\n"; if (!derivative.has_value()) continue; - state_languages[i] = derivative.value(); - // cout << "Derevative: " << state_languages[i].to_txt() << "\n"; - // Logger::log("Derevative", state_languages[i].to_txt()); - - // TODO: logs - if (log) { - log->set_parameter("state", i); - log->set_parameter("prefix", prefix.value()); - log->set_parameter("regex", reg); - log->set_parameter("derivative", state_languages[i]); - } - state_languages[i].make_language(); + state_languages[i].from_string(derivative.value().to_txt()); + state_languages[i] = state_languages[i].deannote(); + //cout << state_languages[i].to_txt() << "\n"; } - for (int i = 0; i < states.size(); i++) { - for (int j = 0; j < states.size(); j++) { - for (auto transition = states[j].transitions.begin(); - transition != states[j].transitions.end(); transition++) { - bool verified_ambiguity = false; +} + +bool FiniteAutomaton::semdet_entry(bool traps_removed, iLogTemplate* log) const { + if (!traps_removed) { + return remove_trap_states().semdet_entry(true, log); + } + vector state_languages; + get_state_languages(state_languages, false); + auto make_string_transition = [=](string from, alphabet_symbol through, + string to) { + string f = from; + string arrow = ">->>{" + string(through) + "}"; + string t = to; + return f + arrow + t; + }; + std::string ambiguous_transitions = ""; + for (int j = 0; j < states.size(); j++) { + for (auto transition = states[j].transitions.begin(); + transition != states[j].transitions.end(); transition++) { + bool verified_ambiguity = false; + if (transition->second.size() > 1) { + ambiguous_transitions += "Ambigous: "; for (auto it = transition->second.begin(); - it != transition->second.end(); it++) { - bool reliability = true; - for (auto it2 = transition->second.begin(); - it2 != transition->second.end(); it2++) { - if (!state_languages[*it].subset( - state_languages[*it2])) { - reliability = false; - break; - } + it != transition->second.end(); it++) { + ambiguous_transitions += + make_string_transition(states[j].identifier, transition->first, states[*it].identifier) + + ","; + } + } + for (auto it = transition->second.begin(); + it != transition->second.end(); it++) { + bool reliability = true; + for (auto it2 = transition->second.begin(); + it2 != transition->second.end(); it2++) { + if (!state_languages[*it].subset( + state_languages[*it2])) { + reliability = false; + break; } - verified_ambiguity |= reliability; } - if (!verified_ambiguity) { - // Logger::log("Результат SemDet", "false"); - // Logger::finish_step(); - return false; + verified_ambiguity |= reliability; + if (reliability && transition->second.size() > 1) { + ambiguous_transitions += + "Reliable:" + + make_string_transition(states[j].identifier, transition->first, states[*it].identifier) + + +"\\\\"; + } + } + if (!verified_ambiguity) { + // Logger::log("Результат SemDet", "false"); + // Logger::finish_step(); + ambiguous_transitions += "Reliable: none\\\\"; + if (log) { + log->set_parameter("ambiguous transitions", ambiguous_transitions); + log->set_parameter("semdet result", "false\\\\"); } + return false; } } } - // Logger::log("Результат SemDet", "true"); + if (log) { + if (ambiguous_transitions == "") { + ambiguous_transitions = "None"; + } + log->set_parameter("ambiguous transitions", ambiguous_transitions); + log->set_parameter("semdet result", "true\\\\"); + } return true; } @@ -2238,10 +2353,7 @@ bool FiniteAutomaton::semdet(iLogTemplate* log) const { if (log) { log->set_parameter("oldautomaton", *this); } - bool result = semdet_entry(log); - if (log) { - log->set_parameter("result", result); - } + bool result = semdet_entry(false, log); return result; // Logger::finish_step(); } diff --git a/libs/Objects/src/Regex.cpp b/libs/Objects/src/Regex.cpp index e840264b..e9d6c5b2 100644 --- a/libs/Objects/src/Regex.cpp +++ b/libs/Objects/src/Regex.cpp @@ -1222,7 +1222,7 @@ void Regex::get_prefix(int len, std::set* prefs) const { term_r->get_prefix(len - k, prefs2); for (auto i = prefs1->begin(); i != prefs1->end(); i++) { for (auto j = prefs2->begin(); j != prefs2->end(); j++) { - prefs->insert(*i + *j); + if (prefix_derivative(*i + *j)) prefs->insert(*i + *j); } } prefs1->clear(); @@ -1243,7 +1243,7 @@ void Regex::get_prefix(int len, std::set* prefs) const { get_prefix(len - k, prefs2); for (auto i = prefs1->begin(); i != prefs1->end(); i++) { for (auto j = prefs2->begin(); j != prefs2->end(); j++) { - prefs->insert(*i + *j); + if (prefix_derivative(*i + *j)) prefs->insert(*i + *j); } } prefs1->clear(); @@ -1364,6 +1364,26 @@ bool Regex::derivative_with_respect_to_sym(Regex* respected_sym, } } +void Regex::eps_removing() { + switch (type) { + case Type::alt: + case Type::conc: + term_l->eps_removing(); + term_r->eps_removing(); + if (term_l->type == Type::eps && term_r->type == Type::eps) { + clear(); + type = Type::eps; + } + break; + case Type::star: + term_l->eps_removing(); + if (term_l->type == Type::eps) { + clear(); + type = Type::eps; + } + } +} + bool Regex::partial_derivative_with_respect_to_sym( Regex* respected_sym, const Regex* reg_e, vector& result) const { Regex cur_result; @@ -1441,21 +1461,37 @@ bool Regex::partial_derivative_with_respect_to_sym( } } +bool Regex::get_symbols_from_string(vector& res){ + if (type == Type::symb) { + res.push_back(*this); + return true; + } + if (type == Regex::conc) { + vector resl, resr; + term_l->get_symbols_from_string(resl); + term_r->get_symbols_from_string(resr); + for (int i = 0; i < resl.size(); i++) { + res.push_back(resl[i]); + } + for (int i = 0; i < resr.size(); i++) { + res.push_back(resr[i]); + } + return true; + } + return false; +} + bool Regex::derivative_with_respect_to_str(std::string str, const Regex* reg_e, Regex& result) const { bool success = true; Regex cur = *reg_e; Regex next = *reg_e; - // cout << "start getting derevative for prefix " << str << " in " - // << reg_e->to_txt() << "\n"; - for (int i = 0; i < str.size(); i++) { - Regex sym; - sym.type = Type::symb; - sym.value.symbol = str[i]; - next.clear(); - success &= derivative_with_respect_to_sym(&sym, &cur, next); - // cout << "derevative for prefix " << sym->to_txt() << " in " - // << cur.to_txt() << " is " << next.to_txt() << "\n"; + Regex symbols; + symbols.from_string(str); + vector syms; + symbols.get_symbols_from_string(syms); + for (int i = 0; i < syms.size(); i++) { + success &= derivative_with_respect_to_sym(&syms[i], &cur, next); if (!success) { return false; } @@ -1498,13 +1534,12 @@ std::optional Regex::prefix_derivative(std::string respected_str) const { return ans; } // Длина накачки +// Длина накачки int Regex::pump_length(iLogTemplate* log) const { - // Logger::init_step("PumpLength"); + if (log) log->set_parameter("oldregex", *this); if (language->pump_length_cached()) { - // Logger::log("Длина накачки", to_string(language->get_pump_length())); - // Logger::finish_step(); if (log) { - log->set_parameter("pumplength", language->get_pump_length()); + log->set_parameter("pumplength1", language->get_pump_length()); log->set_parameter("cach", "(!) результат получен из кэша"); } return language->get_pump_length(); @@ -1515,14 +1550,12 @@ int Regex::pump_length(iLogTemplate* log) const { get_prefix(i, &prefs); if (prefs.empty()) { language->set_pump_length(i); - /*Logger::log( - "Длина накачки совпадает с длиной регулярного выражения"); - Logger::finish_step();*/ if (log) { - log->set_parameter("pumplength", i); + log->set_parameter("pumplength1", i); } return i; } + bool pumped = true; for (auto it = prefs.begin(); it != prefs.end(); it++) { bool was = false; for (int j = 0; j < it->size(); j++) { @@ -1532,40 +1565,48 @@ int Regex::pump_length(iLogTemplate* log) const { } } if (was) continue; - for (int j = 0; j < it->size(); j++) { - for (int k = j + 1; k <= it->size(); k++) { - Regex pumping; - std::string pumped_prefix; - pumped_prefix += it->substr(0, j); - pumped_prefix += "(" + it->substr(j, k - j) + ")*"; - pumped_prefix += it->substr(k, it->size() - k + j); - Regex a(pumped_prefix); - Regex b; - pumping.regex_union(&a, &b); - if (!derivative_with_respect_to_str(*it, this, - *pumping.term_r)) - continue; - pumping.generate_alphabet(pumping.alphabet); - pumping.language = make_shared(pumping.alphabet); - // cout << pumped_prefix << " " << pumping.term_r->to_txt(); - if (subset(pumping)) { - checked_prefixes[*it] = true; - language->set_pump_length(i); - /*cout << *it << "\n"; - cout << pumping.to_txt() << "\n"; - cout << to_txt() << "\n"; - cout << subset(pumping) << "\n"; - Regex pump2; - cout << subset(pump2);*/ - // Logger::log("Длина накачки", to_string(i)); - // Logger::finish_step(); - if (log) { - log->set_parameter("pumplength", i); - } - return i; - } + bool infix_pumped = false; + Regex pref(*it); + vector symbols; + pref.get_symbols_from_string(symbols); + for (int j = 0; j < symbols.size(); j++) { + std::string pumped_prefix; + for (int k = 0; k < j; k++) { + pumped_prefix += symbols[k].value.symbol; + } + pumped_prefix += "("; + for (int k = j; k < symbols.size(); k++) { + pumped_prefix += symbols[k].value.symbol; + } + pumped_prefix += ")*"; + Regex a; + if (!derivative_with_respect_to_str(*it, this, a)) { + continue; } + a.eps_removing(); + if (a.to_txt() != "") + pumped_prefix += "(" + a.to_txt() + ")"; + Regex pumping(pumped_prefix); + if (subset(pumping)) { + checked_prefixes[*it] = true; + infix_pumped = true; + break; + } + } + pumped &= infix_pumped; + } + std::string ch_prefixes; + for (auto it = checked_prefixes.begin(); it != checked_prefixes.end(); + it++) { + if (it->second) ch_prefixes += it->first + "\\\\"; + } + if (pumped) { + language->set_pump_length(i); + if (log) { + log->set_parameter("pumplength1", i); + log->set_parameter("pumplength2", ch_prefixes); } + return i; } } } @@ -1643,7 +1684,9 @@ bool Regex::subset(const Regex& r, iLogTemplate* log) const { // Logger::init_step("Subset"); // Logger::log("Первое регулярное выражение", to_txt()); // Logger::log("Второе регулярное выражение", r.to_txt()); - bool result = to_ilieyu().subset(r.to_ilieyu()); + auto il = to_ilieyu(); + auto ril = r.to_ilieyu(); + bool result = il.subset(ril); /*if (result) Logger::log("Результат Subset", "true"); else diff --git a/resources/template/ClassCard.tex b/resources/template/ClassCard.tex index d000add6..5b57f94e 100644 --- a/resources/template/ClassCard.tex +++ b/resources/template/ClassCard.tex @@ -1,3 +1,4 @@ +%include "TMtheory.tex" \section{ClassCard} \begin{frame}{Вычисление $\ClassCard\TypeIs\NFATYPE\to\IntTYPE$} Автомат: diff --git a/resources/template/ClassLength.tex b/resources/template/ClassLength.tex index 29aa909f..47a83823 100644 --- a/resources/template/ClassLength.tex +++ b/resources/template/ClassLength.tex @@ -1,3 +1,4 @@ +%include "TMtheory.tex" \section{ClassLength} \begin{frame}{Вычисление $\ClassLength\TypeIs\NFATYPE\to\IntTYPE$} Автомат: diff --git a/resources/template/Linearize.tex b/resources/template/Linearize.tex index 47334afe..2a128976 100644 --- a/resources/template/Linearize.tex +++ b/resources/template/Linearize.tex @@ -1,8 +1,10 @@ \section{Linearize} \begin{frame}{Преобразование $\Linearize\TypeIs\RegexTYPE\to\RegexTYPE$} + %begin detailed \begin{block}{\bf Определение} Если регулярное выражение $r\in\RegExp$ содержит $n$ вхождений букв алфавита $\Sigma$, тогда линеаризованное регулярное выражение $\Linearize(r)$ получается из $r$ приписыванием $i$-ой по счёту букве, входящей в $r$, индекса $i$. \end{block} % descriptive documentation + %end detailed Регулярное выражение до преобразования: %template_oldregex diff --git a/resources/template/MyhillNerode.tex b/resources/template/MyhillNerode.tex index 7b3b5685..893d11dd 100644 --- a/resources/template/MyhillNerode.tex +++ b/resources/template/MyhillNerode.tex @@ -1,3 +1,4 @@ +%include "TMtheory.tex" \section{MyhillNerode} \begin{frame}{$\MyhillNerode\TypeIs\NFATYPE\to\IntTYPE$} Автомат: diff --git a/resources/template/PumpLength.tex b/resources/template/PumpLength.tex index 36450caa..f4c07585 100644 --- a/resources/template/PumpLength.tex +++ b/resources/template/PumpLength.tex @@ -1,11 +1,29 @@ -\section{PumpLength} +%begin detailed +\section{Длина накачки} +\begin{frame}{Лемма о накачке} + \vspace{-5pt} + Если $G$ — это регулярная грамматика, то существует $n \in \mathbb{N}$, что $\forall w(w \in \Lang(G) \: \& \: |w| > n \Rightarrow \exists w_1, w_2, w_3(|w_2| > 0 \: \& \: |w_1| + |w_3| \leqslant n \: \& \: w = w_1w_2w_3 \: \& \: \forall k(k\geqslant0 \Rightarrow w_1w_2^kw_3 \in \Lang(G))$. Длина накачки $G$ - минимальное из таких $n$. + \begin{block}{\bf Алгоритм поиска длины накачки} + Пусть $R\in\RegExp$. По возрастанию значения $n$: + \begin{itemize} + \item Рассмотреть в $R$ все возможные префиксы $w$ длины $n$ и по каждому из них построить производную Брзозовски. + \item Перебрать инфиксы в пределах $n$-префиксов на предмет возможности накачки: а именно, если префикс $w$ в выражении $w\delta_w(R)$ допускает разбиение на $w_1w_2w_3$, то он накачивается $\Leftrightarrow \: \Lang((w_1(w_2) \star w_3\delta_w(R)) \subseteq \Lang(R)$. + \end{itemize} + Если все $n$-префиксы накачиваются, то $n$ и есть искомая длина накачки. + \end{block} +\end{frame} % descriptive documentation +%end detailed \begin{frame}{Вычисление $\PumpLength\TypeIs\RegexTYPE\to\IntTYPE$} - Регулярное выражение: + \vspace{-5pt} + Регулярное выражение: %template_oldregex - Результат: - %template_result + Длина накачки: + %template_pumplength1 % founded pump len + Накачиваемые префиксы: + %template_pumplength2 % prefixes + %template_cach \end{frame} diff --git a/resources/template/SemDet.tex b/resources/template/SemDet.tex index eb785b4f..d545bca5 100644 --- a/resources/template/SemDet.tex +++ b/resources/template/SemDet.tex @@ -1,10 +1,33 @@ -\section{SemDet} +\section{Семантический детерминизм} +%begin detailed +\begin{frame}{Семантический детерминизм} + \vspace{-5pt} + Язык состояния $q$ — это $\{w | q \xrightarrow{\text{$w$}} q\}$, где $q_f$ - финальное состояние. НКА $A$ семантически детеминирован, если для всякой неоднозначности $q_i \xrightarrow{\text{$a$}} {q_{j_1}} , ..., {q_i \xrightarrow{\text{$a$}} q_{j_k}}$ существует такое состояние $q_{j_s}$, что языки всех $q_{j_t}$ $(1 \leqslant t \leqslant k)$ вкладываются в его язык (это означает, что переход $q_i \xrightarrow{\text{$a$}} {q_{j_s}}$ надёжен: если слово распознаётся автоматом, оно обязательно будет распознано после такого перехода). + Языки состояний при этом строятся с помощью производных: в качестве аргумента производной достаточно взять произвольный префикс $v$, соответствующий переходу $q_0 \xrightarrow{\text{$v$}} q$. +\end{frame} +\begin{frame}{Алгоритм проверки семантического детерминизма} + \vspace{-5pt} + \begin{itemize} + \item Разметка автомата + \item Получение языков состояний, с помощью производных + \item Поиск неоднозначностей + \item Поиск состояния с надёжным переходом для каждой неоднозначности + \end{itemize} + +\end{frame} +%end detailed \begin{frame}{Предикат $\SemDet\TypeIs\NFATYPE\to\BooleanTYPE$} - Автомат: + \vspace{-5pt} + oldautomaton: %template_oldautomaton - Результат: - %template_result + Неоднозначные переходы и надёжные переходы: -\end{frame} + %template_ambiguous transitions + + + Семантический детерминизм: + + %template_semdet result +\end{frame} \ No newline at end of file diff --git a/resources/template/TMtheory.tex b/resources/template/TMtheory.tex new file mode 100644 index 00000000..654906d5 --- /dev/null +++ b/resources/template/TMtheory.tex @@ -0,0 +1,76 @@ +\section{Трансформационный моноид} % ClassCard %ClassLength +\begin{frame}{Основные свойства трансформационного моноида} + \vspace*{-6pt} + \begin{block}{\bf Определение} + Трансформационный моноид $\mathcal{M}_{\Aut}$ для ДКА $\Aut$ --- это моноид функций $F_{\xi}$ таких, что $F_{\xi}(q_i)= q_j\iff (q_i\transit{\xi} q_j$ в $\Aut)$. Иначе можно сказать, что трансформационный моноид $\mathcal{M}_{\Aut}$ определяется множеством классов эквивалентности + $\bigl\{w\mid w\in\Sigma^+\bigr\}$ таким, что $w_i = w_j\iff F_{w_i}=F_{w_j}$. + \end{block} % descriptive documentation + \begin{itemize} + \item $\mathcal{M}_{\Aut}$ определяется фактормножеством классов эквивалентности и правилами переписывания, задающими эквивалентность. $\empt$ обычно не включается в множество $w_i$. + \item Поскольку множество функций $F_{w_i}$ в случае ДКА конечно, то $\mathcal{M}_{\Aut}$ содержит конечное число классов эквивалентности (верно и обратное: каждый такой моноид определяет некоторый ДКА). + \item Трансмоноид строится для ДКА без ловушек; переход в ловушку обозначается в таблице переходов просто прочерком. + \item Для единообразия записи трансформаций и перестановок в алгебре, в таблице переходов пишут только номера состояний $\Aut$. + \end{itemize} % overall documentation +\end{frame} + +\begin{frame}{Построение трансформационного моноида} + \begin{center} + \begin{tikzpicture}[scale=0.15] % the initial automaton placeholder + \tikzstyle{every node}+=[inner sep=0pt] + \draw [black] (24.9,-17.8) circle (3); + \draw (24.9,-17.8) node {$q_0$}; + \draw [black] (36.2,-17.8) circle (3); + \draw (36.2,-17.8) node {$q_1$}; + \draw [black] (47.8,-17.8) circle (3); + \draw (47.8,-17.8) node {$q_2$}; + \draw [black] (47.8,-17.8) circle (2.4); + \draw [black] (27.9,-17.8) -- (33.2,-17.8); + \fill [black] (33.2,-17.8) -- (32.4,-17.3) -- (32.4,-18.3); + \draw (30.55,-17.3) node [above] {$a$}; + \draw [black] (23.294,-15.28) arc (240.24286:-47.75714:2.25); + \draw (23.94,-10.5) node [above] {$b$}; + \fill [black] (25.92,-14.99) -- (26.75,-14.55) -- (25.89,-14.05); + \draw [black] (34.58,-15.289) arc (240.57068:-47.42932:2.25); + \draw (35.03,-10.45) node [above] {$a,c$}; + \fill [black] (37.21,-14.99) -- (38.04,-14.54) -- (37.16,-14.04); + \draw [black] (45.951,-20.128) arc (-51.88249:-128.11751:6.401); + \fill [black] (45.95,-20.13) -- (45.01,-20.23) -- (45.63,-21.02); + \draw (42,-21.99) node [below] {$b$}; + \draw [black] (46.477,-15.12) arc (234:-54:2.25); + \draw (47.8,-10.55) node [above] {$b,c$}; + \fill [black] (49.12,-15.12) -- (50,-14.77) -- (49.19,-14.18); + \draw [black] (38.655,-16.105) arc (114.1229:65.8771:8.185); + \fill [black] (38.65,-16.1) -- (39.59,-16.23) -- (39.18,-15.32); + \draw (42,-14.89) node [above] {$a$}; + \end{tikzpicture} + \end{center} + \only<1>{Oпределим соответствие между буквами и множествами переходов по ним и будем расширять этот список новыми словами в лексикографическом порядке. Если очередное слово задаёт такую же трансформацию, как и уже рассмотренное, порождаем соответствующее правило переписывания.}%overall documentation + + \begin{center} + \begin{tabular}{c||c}\hline + \cellcolor{blue!10}\textbf{Классы эквивалентности} & \cellcolor{blue!10}\textbf{Правила переписывания} \\\hline\hline + \smallskip + $\begin{array}{r|ccc} % the equivalence class table placeholder + & 0 & 1 & 2 \\\hline + a & 1 & 1 & 1 \\ + b & 0 & 2 & 2 \\ + c & - & 1 & 2\only<2>{ \\ + ab & 2 & 2 & 2 \\ + bc & - & 2 & 2 \\ + ca & - & 1 & 1 + } + \end{array}$ + & + \only<2>{$\begin{array}{cc} % the rewrite rule table placeholder + aa\to a & ac\to a \\ + ba \to a & bb\to b \\ + cb\to bc & cc\to c \\ + abc\to ab & bca\to ca \\ + cab\to bc + \end{array}$} + \end{tabular} + \end{center} + Всего классов эквивалентности: $6$ % the ClassCard placeholder + + Максимальная длина факторслова в классах эквивалентности: $2$ % the ClassLength placeholder +\end{frame} \ No newline at end of file diff --git a/resources/template/head.tex b/resources/template/head.tex index 0f2a7972..ffd10e88 100644 --- a/resources/template/head.tex +++ b/resources/template/head.tex @@ -127,7 +127,7 @@ \def\Arden{\mathtt{Arden}} \def\RemoveTrap{\mathtt{RemoveTrap}} \def\Test{\mathtt{Test}} -\def\Test{\mathtt{Verify}} +\def\Verify{\mathtt{Verify}} \def\VoidTYPE{\mathtt{VOID}} \def\RegexTYPE{\mathtt{Regex}} diff --git a/resources/template/tomson-short.tex b/resources/template/tomson-short.tex deleted file mode 100644 index 2e5feacf..00000000 --- a/resources/template/tomson-short.tex +++ /dev/null @@ -1,8 +0,0 @@ -\begin{frame}{Пример автомата Томпсона} - Исходное регулярное выражение: - %template_initial_regex % the initial regexp placeholder displaystyle - - Автомат Томпсона: - - %template_thompson % the Thompson diagram placeholder -\end{frame} \ No newline at end of file diff --git a/scripts/build_docker.sh b/scripts/build_docker.sh new file mode 100755 index 00000000..69441f1a --- /dev/null +++ b/scripts/build_docker.sh @@ -0,0 +1,3 @@ +#!/bin/bash +cd .. +sudo docker build -t chipollino . \ No newline at end of file diff --git a/scripts/chipollino.txt b/scripts/chipollino.txt new file mode 100644 index 00000000..53852c96 --- /dev/null +++ b/scripts/chipollino.txt @@ -0,0 +1,65 @@ +^^^^^^^^^^^^^^^^^^^^^^^^?P5?^:^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + .5YY5J: + ^5YYYY5! + :5YYYYY5Y?^ + :5YYYYYY5P57 + 7PP5YYYYYY555? + 5YYPYYYYYYYPY57.^!?JJ7. + J5Y5PYYYYYYYYY55PPPGJ~. + ~5YY5YYYYYYYYPPGP5GJ. + :~~!5YYYYYYYYYYPP5555P: + YGGPPP5YYPPP55PP5555YY?!~^:.. + ^5YY5555PPG5555P55YJ7~^^^~~!!!!~~~^:.. + . ^P55555JJYY?!~~^^^!?77~^^^^^^^~~!!!~:. + .?5?YY?~^7!^^^^^^^^!~^^^^^^^^^^^^^^^~!7!: + ^J7^!?^^!!^^^^^^^^^^^^^7J!^^^^^^^^^^^^^^~?! + .77^^^^^^J7!^^^^^^^^^^^^^BG~7^^^^~!!!!~~^^^^7? + ~J~^^^^^^~!:^!7~^^^^^^^^^^J###7^^!7777777!^^^:Y~ + .??^^^^^^^^^^^!#P~~^^^^^^^^^^?GG7:^!?777777?!^^:?! + :J!^^^^^^^^^^^^^GB5B7^^^~7??7~:^^^!~^~7777777~^^^Y. + .J~^^^^^^^^^^~^^^~P#&J^^^Y55557:^~!!^^^^^~~~~^^^^J~ + ?!^^^^^^^~!77777!^^!!^^^^~!!!~~!!!^^^^^^^^^^^^^~?^ + :Y^^^^^^^!7777777?!^^!~~~~~7JY5Y~^^^^^^^^^^^^^~?7. + ~J:^^^^^~77777777?~^^~~~^^^~7?7^^^^^^^^^^^^^~77: + :Y^^^^^^^77777777!^^^^^^^^^^~!~^^^^^^^^^^~77~: + !J^^^^^^^~!!!!~^^^^^^^^^^^^^^^^^^^^^~!77!: + ^?7~^^^^^^^^^^^^^^^^^^^^^^^^^^~!!7?!^. + ^!777!!~~~^^^^^^^^^~~~!777??7J~..^. + .::^~~!!!!!!!!77~~~~!!!!!~?. !^^::... + 7~ ^!!:^~JY? ..::^^^^^^:. + .~!:!~. .!^... :5GJ ..:^~!: + .^~~~: :!~:Y~ .5GY. .. :Y + .:~!~^. ~GG5. :PG5^::^^: .J + :~!^. .^: YGG? ~GGY.~Y^. :7 + .!~: ::.: .~^^^ ~GGG^ 7GGY^7 ~~ + :7: .^~7~~. .! :GGGY .:^!7?JGGG5! ?. + ~? .7? :! :GGGG?J5PGGGGGGGGGY !^ + ~?: ^7: !: ?GGGGGGGGGGGGGGGGGG? ~~ + .!!^. .~!Y!YGGGGGGGGGGGGGGGGGGGG! !^ + .^!~^. !YGGGGGGGGGGGGGGGGGGGGGGP~!? + .:~~^:..:77^5GGGGGGGGGGGGGGGGGGGGGGP~7. + :!??7!~:~GGGGGGGGGGGGGGGGGGGGGGGGJ7!~ + ~??~~!::~5GGGGGGGGGGGGGGGGGGGGGGGGG~!^ + ~!??!!!JPGGGGGGGGGGGGGGGGGGGGGGGGGB?. + ..YGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGJ + !GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGY + ^GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGY + .PGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGB7 + .5GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG: + YGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGBJ + .YGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG. + :5GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGB~ + ~PGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGB? + 7GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGBJ + JBGGGPPPGGGGGGGGGGGGGGGGGGGGGGGGGGGBJ + ?BGGG5YYYYY5GGGGGGBBBGBBBGGGGGGGGGGG? + ^GGP5YYYYY55GGGGGBGY7:YGGGGGGGGGGGGG! + ~PGPPP555Y5GGGGGG57: :GGGGGGGGGGGG5^ + .!YGGGGGGGGGGGGGBGJ^ ~5GGGGGGGGGGGG~ + !BPPPPPPGGGGGGGP7. .YGGGGGGGPPPPGGG! + !55555555Y5PBGG5: ~GGGGP55555YY?7YJ + :GPPPY77?5Y5Y!:: .:^?JYYYYYJYJ?YJ + .~7JJYJJJ?!: + + Thank you for using Chipollino! + diff --git a/scripts/install_packages.sh b/scripts/install_packages.sh new file mode 100755 index 00000000..9243de5e --- /dev/null +++ b/scripts/install_packages.sh @@ -0,0 +1,40 @@ +#!/bin/bash +BASEDIR=$(pwd) +apt-get update +apt-get install -y make cmake dos2unix wget dot2tex build-essential dos2unix +read -p 'Установить TEX? Необходим для вывода в PDF (Y/N) ' need_tex +if [ "$need_tex" == "Y" ]; then + apt-get install -y texlive-latex-extra +fi +# install refal5 +if grep "refal" ~/.bashrc; then +echo "У вас уже есть РЕФАЛ, вы прекрасны!" +else +echo "Ставлю РЕФАЛ" +cd /usr/src +mkdir refal && cd refal +wget http://www.botik.ru/pub/local/scp/refal5/ref5_081222.zip +unzip ref5_081222.zip +rm makefile +cp makefile.lin makefile +make +echo "export PATH=$PATH:/usr/src/refal" >> ~/.bashrc +fi +cd $BASEDIR +rm -fR ./build +mkdir build +cd ./build/ +cmake ../. && cmake --build . +cd ../refal +dos2unix MathMode.ref +dos2unix Postprocess.ref +dos2unix Preprocess.ref +dos2unix TestGenerator.ref +export PATH=$PATH:/usr/src/refal +refc MathMode.ref +refc Postprocess.ref +refc Preprocess.ref +refc TestGenerator.ref +cat ./../scripts/chipollino.txt +#Надо написать сборку рефал-программ когда они будут в одной ветке, возможно еще что-то надо (для текущего комиита все собирается) - вроде есть на будущее +#make diff --git a/scripts/readme.md b/scripts/readme.md new file mode 100644 index 00000000..bf2a46a0 --- /dev/null +++ b/scripts/readme.md @@ -0,0 +1,27 @@ +# Скрипты для работы с Chipollino +## Оглавление +[Docker](#Docker) +[Linux♥](#Linux) +[Окна](#Windows) +[Прочее](#Other) +## Docker +Вам вообще круто, в текущем каталоге запускайте ```build_docker.sh``` - он соберет и скачает все необходимое! +Для запуска Chipollino запускайте ```run_docker.sh```, предварительно положив ```Test.txt``` в корень проекта ```../.``` + +После запуска из докера подтянутся : +* ```../resources/report.tex``` - сгенерированный Tex файл +* ```../report.pdf``` - сгенерированный Pdf файл (Если вы согласились с установкой Tex) +* ```../test.txt``` - Тест (мы могли его генерировать) + +## Linux +Вы крутые, в текущем каталоге запускайте ```install_packages.sh``` - он соберет и скачает все необходимое! +Для запуска Chipollino запускайте ```runcode.sh```, предварительно положив ```Test.txt``` в корень проекта ```../.``` + +После запуска вы можете использовать : +* ```../resources/report.tex``` - сгенерированный Tex файл +* ```../report.pdf``` - сгенерированный Pdf файл (Если вы согласились с установкой Tex) +* ```../test.txt``` - Тест (мы могли его генерировать) +## Windows (ReactOS) +Ну вам я сочуствую, виндой пользоваться ... +## Прочие +Ну если вы используете другую систему то вы крутой и сами разберетесь😎 Ну или докер. diff --git a/scripts/run_code_docker.sh b/scripts/run_code_docker.sh new file mode 100755 index 00000000..3862adfe --- /dev/null +++ b/scripts/run_code_docker.sh @@ -0,0 +1,15 @@ +#!/bin/bash +#копируем тест +rm test.txt +cp /original/test.txt ./test.txt +#выполняем программу +./scripts/runcode.sh +#вытаскиваем тест +cp -i ./test.txt /original/test.txt +chmod 777 /original/test.txt +#вытаскиваем дот +cp -i ./resources/report.tex /original/resources/report.tex +chmod 777 /original/resources/report.tex +#вытаскиваем pdf +cp -i ./report.pdf /original/report.pdf +chmod 777 /original/report.pdf diff --git a/scripts/run_docker.sh b/scripts/run_docker.sh new file mode 100755 index 00000000..c6b2b17c --- /dev/null +++ b/scripts/run_docker.sh @@ -0,0 +1,5 @@ +#!/bin/bash +cd .. +sudo docker run -it --rm --name runchipollino -v $(pwd):/original/ chipollino + +#sudo docker build -t chipollino . \ No newline at end of file diff --git a/scripts/runcode.sh b/scripts/runcode.sh new file mode 100755 index 00000000..b25608f8 --- /dev/null +++ b/scripts/runcode.sh @@ -0,0 +1,24 @@ +#!/bin/bash +if which pdflatex; then +echo "У вас есть Tex и мы попытаемся собрать pdf" +else +read -p 'Установить TEX? Необходим для вывода в PDF (Y/N) ' need_tex +if [ "$need_tex" == "Y" ]; then + apt-get install -y texlive-latex-extra +fi +fi +echo 'Добро пожаловать, что вы хотите запустить?' +read -p 'Интерпретатор I Генератор G Тесты T ' command +if [ "$command" == "I" ]; then + echo 'run Interpreter' + ./build/apps/InterpreterApp/InterpreterApp +fi +if [ "$command" == "G" ]; then + echo 'run Generator' + ./build/apps/InputGeneratorApp/InputGeneratorApp +fi +if [ "$command" == "T" ]; then + echo 'run TestApp' + ./build/apps/TestsApp/TestsApp +fi +#make