Если останутся вопросы по функциональности, задайте их здесь
Принцип работы — на вход даётся файл с операциями над объектами, на выходе генерируется latex-файл с подробным описанием выполненных преобразований.
ВАЖНО! Для корректного составления latex-файла нужно поставить Graphviz, чтобы в
системе поддерживалась команда dot
. Без этого не будет работать генерация изображений автоматов.
Если в системе поддерживается команда pdflatex
, то тогда сразу будет генерироваться отчет в виде pdf-документа. Если
нет, необходимо установить Latex.
Сборка осуществляется через cmake. В wiki есть пример, как можно собрать.
Для запуска надо перейти в корневую папку проекта и там запустить собранное приложение. Пример на windows:
.\build\apps\InterpreterApp\Debug\InterpreterApp
В качестве опционального аргумента указывается путь к файлу с командами (по умолчанию test.txt).
Для удобства тестирования был создан генератор входных данных.
Его запуск на windows:
.\build\apps\InputGeneratorApp\Debug\InputGeneratorApp
В файле apps\InputGeneratorApp\src\main.cpp можно поменять параметры генерируемых тестов:
TG.generate_task(3, 5, false, false);
где 1 аргумент - количество операций, 2 аргумент - максимальное количество функций в последовательности.
Интерпретатор поддерживает следующие типы:
{a*(b|c)*}
*
. на место которого подставляются генерируемые регулярные выражения в верификаторе[[{a} {b}]]
(означает a -> b
)Glushkov {ab|a}
Annote.Glushkov.DeAnnote {a}
8
A
, N1
, N2
Для функций и последовательностей функций должны выполняться соответствия типов. Больше про типы функций - ниже в разделе Функции преобразователя.
В каждой строчке записана ровно одна команда. Поддерживаются команды пяти типов:
declaration
Присвоение переменной значения. Если в конце стоит !!
, выражение логируется в latex.
Синтаксис:
<varaible> = <expression> '!!'?
Пример:
A = Complement.Annote (Glushkov {a*}) !!
B = States.Reverse A
test
Аргументы:
1. НКА или регулярное выражение (язык 1)
2. регулярное выражение — тестовый сет (язык 2)
3. натуральное число — шаг итерации в сете
Подробнее про то, как работает — см.
в презентации.
Синтаксис:
Test <expression> <expression> <int>
Пример:
Test {(aa)*} {a*} 3
Test (Glushkov {(aa)*}) {a*} 1
predicate
Булева функция, записанная одной строчкой. Будет логироваться в любом случае.
Синтаксис:
<function> <expression>+
Пример:
Equiv (Antimirov {ab|a}) (Glushkov {ab|a})
verify
Аргументы:
1. Предикат (с конструкцией *
, на место которой подставляются сгенерированные регулярные выражения)
2. (опциональный) натуральное число — количество тестов
Синтаксис:
Verify <expression> <int>?
Пример:
Verify (Equal (Ambiguity.Glushkov.Arden.Glushkov *) (Ambiguity.Glushkov *))
set
Аргументы:
1. Имя флага:
- weak_type_comparison
— устанавливает эквивалентность типов DFA
и NFA
, т.е. допускает на вход NFA
для
функций, требующих DFА
TODO:
- log_theory
— добавляет теоретический блок к функциям в отчете
- auto_remove_trap_states
— отвечает за удаление ловушек
2. Значение флага: true
/ false
Синтаксис:
Set <flagName> <true/false>
* NFA
здесь можно понимать как FA
, для которого не обязан быть включённым флаг детерминизма.
Преобразования со сменой класса:
Thompson: Regex -> NFA
— строит автомат Томпсона по регулярному выражениюAntimirov: Regex -> NFA
Glushkov: Regex -> NFA
IlieYu: Regex -> NFA
— follow-автоматArden: NFA -> Regex
— строит регулярное выражение по автоматуPrefixGrammar: NFA -> PrefixGrammar
— возвращает префиксную грамматику для НКАPGtoNFA: PrefixGrammar -> NFA
— преобразует префиксную грамматику в НКАПреобразования внутри класса
Над регулярными выражениями:
Linearize: Regex -> Regex
— размечает буквы в регулярном выражении, как в алгоритме ГлушковаDeLinearize: Regex -> Regex
— снимает разметку LinearizeDeAnnote: Regex -> Regex
— снимает разметку AnnoteDisambiguate: Regex -> Regex
— для 1-однозначных языков возвращает 1-однозначное регулярное выражение, для
остальных возвращает данное на входНад конечными автоматами:
Determinize: NFA -> DFA
— детерминизация без добавления состояния-ловушкиMinimize: NFA -> DFA
— минимизация без добавления состояния-ловушкиDeterminize+: NFA -> DFA
— детерминизация с добавлением состояния-ловушкиMinimize+: NFA -> DFA
— минимизация с добавлением состояния-ловушкиRemoveTrap: DFA -> DFA
- удаление состояний-ловушекReverse: NFA -> NFA
— обращение ("переворачивает" автомат)Complement: DFA -> DFA
— дополнениеRemEps: NFA -> NFA
— удаление ε-правилMergeBisim: NFA -> NFA
— объединение эквивалентных по бисимуляции состоянийAnnote: NFA -> DFA
— навешивает разметку на все буквы в автомате, стоящие на недетерминированных переходахDeAnnote: NFA -> NFA
— снимает разметку AnnoteDeLinearize: NFA -> NFA
— снимает разметку LinearizeIntersect: (NFA, NFA) -> NFA
— пересечение языковUnion: (NFA, NFA) -> NFA
— объединение языковDifference: (NFA, NFA) -> NFA
— разность языковМногосортные функции
States: NFA -> Int
— возвращает количество состояний в автоматеClassCard: NFA -> Int
— число классов эквивалентности в трансформационном моноидеClassLength: NFA -> Int
— самое длинное слово в классе эквивалентности трансформационного моноидаMyhillNerode: NFA -> Int
— возвращает число классов эквивалентности по Майхиллу–НероудуGlaisterShallit: NFA -> Int
— определяет нижнюю границу количества состояний в НКА для языкаAmbiguity: NFA -> AmbiguityValue
— определяет меру неоднозначности автомата. Если число путей, по которым
распознается слово (длины от минимальной до $s^2$) растёт быстрее, чем полином степени |s|, где s — число состояний
НКА, то автомат экспоненциально неоднозначен. Если число путей растёт медленнее, чем линейная функция, то автомат
почти однозначен (либо однозначен, если путь всегда один). Иначе автомат полиномиально неоднозначен.PumpLength: Regex -> Int
— возвращает длину накачки языкаNormalize: (Regex, Array) -> Regex
Normalize: (Regex, FileName) -> Regex
Предикаты
Для регулярных выражений:
Subset: (Regex, Regex) -> Boolean
— проверяет вложенность второго языка в первыйEquiv: (Regex, Regex) -> Boolean
— проверяет, описывают ли регулярные выражения один языкOneUnambiguity: Regex -> Boolean
— проверяет, является ли регулярное выражение 1-однозначным. Регулярное выражение
является 1-однозначным, если возможно однозначно определить, какая позиция символа в регулярном выражении должна
соответствовать символу во входном слове, не заглядывая за пределы этого символа во входном слове.Equal: (Regex, Regex) -> Boolean
— проверяет буквальное равенство регулярных выражений
(как строк, с учетом альтернатив)Для конечных автоматов:
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-однозначным регулярным выражением.SemDet: NFA -> Boolean
— проверяет, является ли автомат семантически детерминированным. Язык состояния q — это
{w | q→wqf} Семантическая детерминированность означает, что для всякой неоднозначности q
i →aqj1, ..., qi→aqjk существует
такое состояние qjs, что языки всех qjt (1 ⩽ t ⩽ k) вкладываются в его
язык.Многосортные:
Equal: (Int, Int) -> Boolean
Equal: (Boolean, Boolean) -> Boolean
Equal: (AmbiguityValue, AmbiguityValue) -> Boolean
Методы регулярных выражений с обратными ссылками:
MFA: BRefRegex -> MFA
MFAexpt: BRefRegex -> MFA
Reverse: BRefRegex -> BRefRegex
IsAcreg: BRefRegex -> Boolean
Методы MFA:
RemEps: MFA -> MFA
AddTrap: MFA -> MFA
Complement: MFA -> MFA
Deterministic: MFA -> Boolean
Bisimilar: (MFA, MFA) -> OptionalBool
Action: MFA -> NFA
Symbolic: MFA -> NFA
ActionBisimilar: (MFA, MFA) -> Boolean
SymbolicBisimilar: (MFA, MFA) -> Boolean
Equal: (MFA, MFA) -> Boolean
MergeBisim: MFA -> MFA
Equal: (BRefRegex, BRefRegex) -> Boolean
Метод Test
Test: (Regex|NFA, Regex, Int) -> таблица
— порождает слова, принадлежащие второму языку (2 аргумент), раскрывая каждую
итерацию Клини начиная с 0 (пустого слова) и увеличивая с каждым разом на заданное значение (3 аргумент). Если в
регулярном выражении (для 2 языка) присутствуют альтернативы, то выбирается 1ая из них.
То есть
a*b
c шагом 2 раскрывается в ряд: b, aab, aaaab ...
(a*b)*c
c шагом 1 раскрывается в ряд: c, abc, aabaabc ...
Возвращает таблицу, в которой указаны результаты проверки на принадлежность каждого из порожденных слов первому языку (1
аргумент).
Завершает тестирование, когда сделано более 12 шагов, либо парсинг входной строки занимает больше 3 минут.
Верификатор гипотез
Verify: (Boolean, Int?) -> Int
- принимает на вход набор действий, содержащий единственный предикат. Строится сет
тестов, размер которого определяет 2й аргумент (значение по умолчанию - 20). В выражение на место конструкции *
подставляются случайные регулярные выражения.
В результатах тестирования выделяется доля тестов с положительным значением предиката, и примеры кейсов, когда гипотеза
не выполнилась.
Дополнительно о некоторых функциях и требованиях к входным данным можно почитать в файле.
Успехов!