Skip to content

Commit

Permalink
Merge branch 'rewriting-automata' of https://github.com/OnionGrief/Ch…
Browse files Browse the repository at this point in the history
…ipollino into rewriting-automata
  • Loading branch information
Robby-the-paladin committed Jan 22, 2024
2 parents b1ce825 + 9a10f04 commit 4fa1cfc
Show file tree
Hide file tree
Showing 83 changed files with 1,544 additions and 1,903 deletions.
8 changes: 2 additions & 6 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,14 @@ build/
.idea/

cmake-build-debug/
cmake-build-debug-visual-studio/
cmake-build-debug-wsl/

.vs/
/CMakeSettings.json
/enc_temp_folder/
.idea/

cmake-build-debug/.cmake/api/v1/query/

cmake-build-debug/.cmake/api/v1/reply/

cmake-build-debug/

temp/
report.*
rendered_report.*
Expand Down
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,13 @@ set(CMAKE_CXX_STANDARD 17)
project(chipollino)

# Add sub directories
add_subdirectory(libs/InfInt)
add_subdirectory(libs/Fraction)
add_subdirectory(libs/AutomatonToImage)
add_subdirectory(libs/AutomataParser)
add_subdirectory(libs/Objects)
add_subdirectory(libs/Tester)
add_subdirectory(libs/Logger)
add_subdirectory(libs/FuncLib)
add_subdirectory(libs/Interpreter)
add_subdirectory(libs/InputGenerator)
add_subdirectory(apps/InterpreterApp)
Expand Down
65 changes: 36 additions & 29 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,18 +57,25 @@ TG.generate_task(3, 5, false, false);
* DFA — детерминированный конечный автомат
* PrefixGrammar - префиксная грамматика
* Int
* Boolean (где-то обозначен как t/f)
* String
* Boolean
* OptionalBool
* AmbiguityValue - мера неоднозначности
(Может принимать одно из 4-х значений: *Unambigious, Almost unambigious, Polynomially ambiguous, Exponentially
ambiguous*)
* Array - правила переписывания
* BRefRegex
* MFA

### Синтаксические конструкции

* **Regex**. Записываются в фигурных скобках. Пример: `{a*(b|c)*}`
* **RandomRegex**. Символ `*`. на место которого подставляются генерируемые регулярные выражения в верификаторе
* **Array**. Правила переписывания. Пример: `[[{a} {b}]]` (означает `a -> b`)
* **Function**. Название и список аргументов через пробел. Пример: `Glushkov {ab|a}`
* **Function sequence**. Последовательное применение функций справа-налево. Пример: `Annote.Glushkov.DeAnnote {a}`
* **Int**. Целое число. Пример: `8`
* **Varaible** - переменная. Примеры: `N1`, `N2`, `N3`
* **Varaible** - переменная. Примеры: `A`, `N1`, `N2`
* **Expression**. Function sequence, Int, Regex или Varaible

Для функций и последовательностей функций должны выполняться соответствия типов. Больше про типы фунцкий - ниже в
Expand Down Expand Up @@ -140,10 +147,9 @@ TG.generate_task(3, 5, false, false);
- `Antimirov: Regex -> NFA`
- `Glushkov: Regex -> NFA`
- `IlieYu: Regex -> NFA` — follow-автомат
- `PrefixGrammar: NFA -> PG` — возвращает префиксную грамматику для НКА
- `PGtoNFA: PG -> NFA` — преобразует префиксную грамматику в НКА
**TODO:**
- `Arden: NFA -> Regex` — строит регуялрное выражение по автомату
- `PrefixGrammar: NFA -> PrefixGrammar` — возвращает префиксную грамматику для НКА
- `PGtoNFA: PrefixGrammar -> NFA` — преобразует префиксную грамматику в НКА

**Преобразования внутри класса**

Expand All @@ -153,11 +159,13 @@ TG.generate_task(3, 5, false, false);
- `DeLinearize: Regex -> Regex` — снимает разметку Linearize
- `DeAnnote: Regex -> Regex` — снимает разметку Annote
**TODO:**
- `Disambiguate :: Regex -> Regex` — для 1-однозначных языков возвращает 1-однозначное регулярное выражение, для
- `Disambiguate: Regex -> Regex` — для 1-однозначных языков возвращает 1-однозначное регулярное выражение, для
остальных возвращает данное на вход

*Над конечными автоматами:*

- `Determinize: NFA -> DFA` — детерминизация без добавления состояния-ловушки
- `Minimize: NFA -> DFA` — минимизация без добавления состояния-ловушки
- `Determinize+: NFA -> DFA` — детерминизация с добавлением состояния-ловушки
- `Minimize+: NFA -> DFA` — минимизация с добавлением состояния-ловушки
- `RemoveTrap: DFA -> DFA` - удаление состояний-ловушек
Expand All @@ -170,58 +178,57 @@ TG.generate_task(3, 5, false, false);
- `DeLinearize: NFA -> NFA` — снимает разметку Linearize
- `Intersect: (NFA, NFA) -> NFA` — пересечение языков
- `Union: (NFA, NFA) -> NFA` — объединение языков
- `Difference: (NFA, NFA) -> NFA` — разность языков
**TODO:**
- `Determinize: NFA -> DFA` — детерминизация без добавления состояния-ловушки
- `Minimize: NFA -> DFA` — минимизация без добавления состояния-ловушки
- `Difference: (NFA, NFA) -> NFA` — разность языков

**Многосортные функции**

- `States: NFA -> Int` — возвращает количество состояний в автомате
- `ClassCard: DFA -> Int` — число классов эквивалентности в трасформационном моноиде
- `ClassLength: DFA -> Int` — самое длинное слово в классе эквивалентности трасформационного моноида
- `MyhillNerode: DFA -> Int` — возвращает число классов эквивалентности по Майхиллу–Нероуду
- `GlaisterShallit :: NFA -> Int` — определяет нижнюю границу количества состояний в НКА для языка
- `ClassCard: NFA -> Int` — число классов эквивалентности в трасформационном моноиде
- `ClassLength: NFA -> Int` — самое длинное слово в классе эквивалентности трасформационного моноида
- `MyhillNerode: NFA -> Int` — возвращает число классов эквивалентности по Майхиллу–Нероуду
- `GlaisterShallit: NFA -> Int` — определяет нижнюю границу количества состояний в НКА для языка
- `Ambiguity: NFA -> AmbiguityValue` — определяет меру неоднозначности автомата. Если число путей, по которым
распознается слово (длины от минимальной до $s^2$) растёт быстрее, чем полином степени |s|, где s — число состояний
НКА, то автомат экспоненциально неоднозначен. Если число путей растёт медленнее, чем линейная функция, то автомат
почти однозначен (либо однозначен, если путь всегда один). Иначе автомат полиномиально неоднозначен.
**TODO**:
- `PumpLength: Regex -> Int` — возвращает длину накачки языка
- `Normalize: (Regex, Array) -> Regex`
- `Normalize: (Regex, FileName) -> Regex`

**Предикаты**

*Для регулярных выражений:*

- `Subset: (Regex, Regex) -> t/f` — проверяет вложенность второго языка в первый
- `Equiv: (Regex, Regex) -> t/f` — проверяет, описывают ли регулярные выражения один язык
- `OneUnambiguity: Regex -> t/f` — проверяет, является ли регулярное выражение 1-однозначным. Регулярное выражение
- `Subset: (Regex, Regex) -> Boolean` — проверяет вложенность второго языка в первый
- `Equiv: (Regex, Regex) -> Boolean` — проверяет, описывают ли регулярные выражения один язык
- `OneUnambiguity: Regex -> Boolean` — проверяет, является ли регулярное выражение 1-однозначным. Регулярное выражение
является 1-однозначным, если возможно однозначно определить, какая позиция символа в регулярном выражении должна
соответствовать символу во входном слове, не заглядывая за пределы этого символа во входном слове.
- `Equal: (Regex, Regex) -> t/f` — проверяет буквальное равенство регулярных выражений (как строк, с учетом альтернатив)
- `Equal: (Regex, Regex) -> Boolean` — проверяет буквальное равенство регулярных выражений (как строк, с учетом альтернатив)

*Для конечных автоматов:*

- `Bisimilar: (NFA, NFA) -> t/f` — проверяет бисимилярность автоматов
- `Equiv: (NFA, NFA) -> t/f` — проверяет, описывают ли автоматы один язык
- `Equal: (NFA, NFA) -> t/f` — проверяет буквальное равенство автоматов
- `Subset: (NFA, NFA) -> t/f` — проверяет вложенность второго языка в первый
- `Minimal: DFA -> t/f` — проверяет, минимален ли детерминированный автомат
- `Minimal : NFA -> t/f/u` — проверяет, минимален ли недетерминированный автомат
- `Deterministic : NFA -> t/f` — проверяет автомат на детерминизированность
- `OneUnambiguity : NFA -> t/f` — проверяет, является ли язык 1-однозначным. 1-однозначный язык - это язык, описываемый
- `Bisimilar: (NFA, NFA) -> Boolean` — проверяет бисимилярность автоматов
- `Equiv: (NFA, NFA) -> Boolean` — проверяет, описывают ли автоматы один язык
- `Equal: (NFA, NFA) -> Boolean` — проверяет буквальное равенство автоматов
- `Subset: (NFA, NFA) -> Boolean` — проверяет вложенность второго языка в первый
- `Minimal: DFA -> Boolean` — проверяет, минимален ли детерминированный автомат
- `Minimal: NFA -> OptionalBool` — проверяет, минимален ли недетерминированный автомат
- `Deterministic: NFA -> Boolean` — проверяет автомат на детерминизированность
- `OneUnambiguity: NFA -> Boolean` — проверяет, является ли язык 1-однозначным. 1-однозначный язык - это язык, описываемый
1-однозначным регулярным выражением.
**TODO**:
- `SemDet: NFA -> t/f` — проверяет, является ли автомат семантически детерминированным. Язык состояния q — это \{w \|
- `SemDet: NFA -> Boolean` — проверяет, является ли автомат семантически детерминированным. Язык состояния q — это \{w \|
q→<sup>w</sup>q<sub>f</sub>} Семантическая детерминированность означает, что для всякой неоднозначности q<sub>i</sub>
→<sup>a</sup>q<sub>j<sub>1</sub></sub>, ..., q<sub>i</sub>→<sup>a</sup>q<sub>j<sub>k</sub></sub> существует такое
состояние q<sub>j<sub>s</sub></sub>, что языки всех q<sub>j<sub>t</sub></sub> (1 ⩽ t ⩽ k) вкладываются в его язык.

*Многосортные:*

- `Equal: (Int, Int) -> t/f`
- `Equal: (AmbiguityValue, AmbiguityValue) -> t/f`
- `Equal: (Int, Int) -> Boolean`
- `Equal: (Boolean, Boolean) -> Boolean`
- `Equal: (AmbiguityValue, AmbiguityValue) -> Boolean`

**Метод Test**

Expand Down
8 changes: 4 additions & 4 deletions apps/InputGeneratorApp/src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,7 @@ int main() {

/*
// Если кому-то вдруг нужна подборка трешовых регулярок
// RegexGenerator(int regex_length, int star_num, int star_nesting, int
// alphabet_size)
// RegexGenerator(int regex_length, int star_num, int star_nesting, int alphabet_size)
RegexGenerator RG(100, 20, 4, 4);
std::ofstream out;
Expand All @@ -29,9 +28,10 @@ int main() {
// Используем сгенерированный тест
TasksGenerator TG;
TG.generate_task(3, 5, false, false);
// TG.generate_test_for_all_functions();
TG.write_to_file("test.txt");

// Загружаем в интерпретатор файл с коммандами
interpreter.run_file("test.txt");
interpreter.generate_log("./resources/report.tex");
if (interpreter.run_file("test.txt"))
interpreter.generate_log("./resources/report.tex");
}
13 changes: 7 additions & 6 deletions apps/MetamorphicTestsApp/src/MetamorphicTests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ TEST(TestParsing, RandomRegexParsing) {
Regex r1(str);
string r1_str = r1.to_txt();
Regex r2(r1_str);
ASSERT_EQ(true, Regex::equivalent(r1, r2));
ASSERT_EQ(true, Regex::equivalent(r1, r2)) << str;
}
}

Expand All @@ -27,9 +27,9 @@ TEST(TestArden, RandomRegexEquivalence) {
string rgx_str = rg.generate_regex();
Regex r1(rgx_str), r2(rgx_str);
// ASSERT_TRUE(Regex::equivalent(r1, r2.to_thompson().to_regex()));
ASSERT_TRUE(Regex::equivalent(r1, r2.to_glushkov().to_regex()));
ASSERT_TRUE(Regex::equivalent(r1, r2.to_ilieyu().to_regex()));
ASSERT_TRUE(Regex::equivalent(r1, r2.to_antimirov().to_regex()));
ASSERT_TRUE(Regex::equivalent(r1, r2.to_glushkov().to_regex())) << rgx_str;
ASSERT_TRUE(Regex::equivalent(r1, r2.to_ilieyu().to_regex())) << rgx_str;
ASSERT_TRUE(Regex::equivalent(r1, r2.to_antimirov().to_regex())) << rgx_str;
}
}

Expand All @@ -38,7 +38,8 @@ TEST(TestEqual, ThompsonGlushkov) {
for (int i = 0; i < RegexNumber; i++) {
string rgx_str = rg.generate_regex();
Regex r(rgx_str);
ASSERT_TRUE(FiniteAutomaton::equal(r.to_thompson().remove_eps(), r.to_glushkov()));
ASSERT_TRUE(FiniteAutomaton::equal(r.to_thompson().remove_eps(), r.to_glushkov()))
<< rgx_str;
}
}

Expand All @@ -48,6 +49,6 @@ TEST(TestNFA, Test_equivalent_nfa_negative) {
for (int i = 0; i < 30; i++) {
string str = rg.generate_regex();
Regex r1(str), r2(str);
ASSERT_TRUE(FiniteAutomaton::equivalent(r1.to_thompson(), r2.to_antimirov()));
ASSERT_TRUE(FiniteAutomaton::equivalent(r1.to_thompson(), r2.to_antimirov())) << str;
}
}
5 changes: 2 additions & 3 deletions apps/UnitTestsApp/src/Example.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -172,8 +172,7 @@ void Example::parsing_nfa() {
c = r.to_ilieyu(); // to_thompson(-1);
cout << c.to_txt();
cout << "Parsing: aaaaaaaaaaaaaaaaaaabccccc\n";
cout << c.parsing_by_nfa("aaaaaaaaaaaaaaaaaaabccccc").second
<< endl; // true если распознал слово
cout << c.parse("aaaaaaaaaaaaaaaaaaabccccc").second << endl; // true если распознал слово
}

void Example::regex_generating() {
Expand Down Expand Up @@ -317,7 +316,7 @@ void Example::step() {
void Example::tester() {
Regex r("ab(ab|a)*ababa");
FiniteAutomaton dfa1 = r.to_thompson();
// cout << dfa1.parsing_by_nfa("abaaabaaababa");
// cout << dfa1.parse("abaaabaaababa");
// cout << dfa1.to_txt();
Regex r1("((ab)*a)*");
Regex r2("ab(ab|a)*ababa");
Expand Down
71 changes: 67 additions & 4 deletions apps/UnitTestsApp/src/UnitTests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -568,6 +568,56 @@ TEST(TestToMFA, ToMfa) {
MFAState(5, "5", true, {{Symbol::Ref(2), {MFATransition(1, {1}, unordered_set<int>())}}}));
}

TEST(TestToMFA, ToMfaAdditional) {
vector<MFAState> states = BackRefRegex("[a|b]:1*c").to_mfa_additional().get_states();
ASSERT_EQ(states.size(), 4);
ASSERT_EQ(states[0],
MFAState(0,
"S",
false,
{{"a", {MFATransition(1, {1}, unordered_set<int>())}},
{"b", {MFATransition(2, {1}, unordered_set<int>())}},
{"c", {MFATransition(3, unordered_set<int>(), unordered_set<int>())}}}));
ASSERT_EQ(states[1],
MFAState(1,
"a.0",
false,
{{"a", {MFATransition(1, {1}, unordered_set<int>())}},
{"b", {MFATransition(2, {1}, unordered_set<int>())}},
{"c", {MFATransition(3, unordered_set<int>(), {1})}}}));
ASSERT_EQ(states[2],
MFAState(2,
"b.1",
false,
{{"a", {MFATransition(1, {1}, unordered_set<int>())}},
{"b", {MFATransition(2, {1}, unordered_set<int>())}},
{"c", {MFATransition(3, unordered_set<int>(), {1})}}}));
ASSERT_EQ(states[3], MFAState(3, "c.2", true, {}));

states = BackRefRegex("([&2]:1[&1a]:2)*c").to_mfa_additional().get_states();
ASSERT_EQ(states.size(), 5);
ASSERT_EQ(states[0],
MFAState(0,
"S",
false,
{{Symbol::Ref(2), {MFATransition(1, {1}, unordered_set<int>())}},
{"c", {MFATransition(4, unordered_set<int>(), unordered_set<int>())}}}));
ASSERT_EQ(states[1],
MFAState(1, "&2.0", false, {{Symbol::Ref(1), {MFATransition(2, {2}, {1})}}}));
ASSERT_EQ(states[2],
MFAState(2,
"&1.1",
false,
{{"a", {MFATransition(3, unordered_set<int>(), unordered_set<int>())}}}));
ASSERT_EQ(states[3],
MFAState(3,
"a.2",
false,
{{Symbol::Ref(2), {MFATransition(1, {1}, {2})}},
{"c", {MFATransition(4, unordered_set<int>(), {2})}}}));
ASSERT_EQ(states[4], MFAState(4, "c.3", true, {}));
}

TEST(TestLanguage, Caching) {
Language::enable_retrieving_from_cache();

Expand Down Expand Up @@ -629,6 +679,12 @@ TEST(TestRemoveEps, MFA_RemoveEps) {
ASSERT_EQ(states[2], MFAState(2, "4", true, {}));
}

TEST(TestIsAcreg, BRegex_IsAcreg) {
ASSERT_TRUE(BackRefRegex("([&2b]:1&1[a*]:1[b*&1]:2)*").is_acreg());
ASSERT_FALSE(BackRefRegex("([a*]:1[&2b]:1&1[b*&1]:2)*").is_acreg());
ASSERT_FALSE(BackRefRegex("([&2]:1([&1]:2|[a]:2))*").is_acreg());
}

TEST(TestParsing, MFAParsing) {
using Test = std::tuple<string, string, bool>;
vector<Test> tests = {
Expand Down Expand Up @@ -656,13 +712,20 @@ TEST(TestParsing, MFAParsing) {

MemoryFiniteAutomaton mfa(BackRefRegex(rgx_str).to_mfa()),
mfa_add(BackRefRegex(rgx_str).to_mfa_additional());
ASSERT_EQ(mfa.parse_by_mfa(str).second, expected_res);
ASSERT_EQ(mfa.parse_by_mfa_additional(str).second, expected_res);
ASSERT_EQ(mfa_add.parse_by_mfa(str).second, expected_res);
ASSERT_EQ(mfa_add.parse_by_mfa_additional(str).second, expected_res);
ASSERT_EQ(mfa.parse(str).second, expected_res);
ASSERT_EQ(mfa.parse_additional(str).second, expected_res);
ASSERT_EQ(mfa_add.parse(str).second, expected_res);
ASSERT_EQ(mfa_add.parse_additional(str).second, expected_res);
});
}

TEST(TestReverse, BRegex_Reverse) {
ASSERT_TRUE(BackRefRegex::equal(BackRefRegex("([a*b]:1&1|b&1)").reverse(),
BackRefRegex("[ba*]:1&1|&1b")));
ASSERT_EQ(BackRefRegex("(cb)*(c[ca*b]:1&1b(c&1b)*)*").reverse().to_txt(),
"((b[ba*c]:1c)*b&1&1c)*(bc)*");
}

TEST(TestAmbiguity, AmbiguityValues) {
enum AutomatonType {
thompson,
Expand Down
Binary file removed documentation/images/antimirov1.png
Binary file not shown.
Binary file removed documentation/images/follow1.png
Binary file not shown.
Binary file removed documentation/images/follow2.png
Binary file not shown.
Binary file removed documentation/images/glushkov1.png
Binary file not shown.
Binary file removed documentation/images/tompson1.png
Binary file not shown.
Binary file removed documentation/images/tompson2.png
Binary file not shown.
Binary file removed documentation/images/tompson_rule1.png
Binary file not shown.
Binary file removed documentation/images/tompson_rule2.png
Binary file not shown.
Binary file removed documentation/images/tompson_rule3.png
Binary file not shown.
Binary file removed documentation/images/tompson_rule4.png
Binary file not shown.
Binary file removed documentation/images/tompson_rule5.png
Binary file not shown.
Binary file removed documentation/pdf/antimirov.pdf
Binary file not shown.
Binary file removed documentation/pdf/follow.pdf
Binary file not shown.
Binary file removed documentation/pdf/glushkov.pdf
Binary file not shown.
Binary file removed documentation/pdf/tomson.pdf
Binary file not shown.
Loading

0 comments on commit 4fa1cfc

Please sign in to comment.