Як створити DFA з регулярного вираження без використання NFA?


12

Мета - створити DFA з регулярного виразу, а використання "Regular exp> NFA> DFA convert" - це не варіант. Як слід робити це?

Я задав це питання нашому професору, але він сказав мені, що ми можемо використовувати інтуїцію, і люб'язно відмовився давати будь-які пояснення. Тож я хотів вас запитати.

"Регулярний досвід> NFA> конверсія DFA" - це не варіант, оскільки таке перетворення потребує багато часу для перетворення досить складного регулярного виразу. Наприклад, для певного регексу "regex> NFA> DFA" людині потрібна 1 година. Мені потрібно конвертувати регулярний вираз в DFA менш ніж за 30 хвилин.


2
Вам потрібно надати більше контексту. Який (неформальний) алгоритм ви зараз використовуєте для перекладу регулярних виразів? Може бути корисним пояснити ваш процес на прикладі, наприклад, як a(a|ab|ac)*a+. Ви можете або безпосередньо перевести це на NDFA, який ви зменшите до DFA, або можете нормалізувати його до чогось, що негайно відображається в DFA.
амон

Чи потрібно це робити на конкретних прикладах будь-якими способами, або вам потрібно надати загальну процедуру. Щоб застосувати комп'ютер?
бабу

Відповіді:


18

Оскільки ви хочете "конвертувати регулярний вираз в DFA менше ніж за 30 хвилин", я вважаю, що ви працюєте вручну над відносно невеликими прикладами.

У цьому випадку ви можете використовувати алгоритм Бржозовського , який обчислює безпосередньо автомат Нерода мови (який, як відомо, дорівнює його мінімальному детермінованому автомату). Він заснований на прямому обчисленні похідних, а також працює для розширених регулярних виразів, що дозволяють перетинати та доповнювати. Недолік цього алгоритму полягає в тому, що він вимагає перевірити еквівалентність виразів, обчислених по шляху, дорогий процес. Але на практиці і для невеликих прикладів це дуже ефективно.[1]

Залишені частки . Нехай - мова і - слово. Тоді Мова називається лівий фактор (або ліва похідна ) з .A u u - 1 L = { v A u v L } u - 1 L LLAu

u1L={vAuvL}
u1LL

Неродовий автомат . Nerode автомат з є детермінований автомат , де , і функція переходу визначається для кожної за формулою Остерігайтеся цього досить абстрактного визначення. Кожен стан є лівим коефіцієнтом у слові, а значить, є мовою . Початковий стан - це мова , а набір кінцевих станів - це множина всіх лівих коефіцієнтівA ( L ) = ( Q , A , , L , F ) Q = { u - 1 L u A } F = { u - 1 L u L } a A ( u - 1 L ) a = a - 1 ( u - 1LA(L)=(Q,A,,L,F)Q={u1LuA}F={u1LuL}aA

(u1L)a=a1(u1L)=(ua)1L
ALALL по слову .L

Алгоритм Бжозовського . Нехай букви - букви. Ліві коефіцієнти можна обчислити за допомогою наступних формул: a,b

a11=0a1b={1if a=b0if aba1(L1L2)=a1L1u1L2,a1(L1L2)=a1L1u1L2,a1(L1L2)=a1L1u1L2,a1L=(a1L)L
a1(L1L2)={(a1L1)L2si 1L1,(a1L1)L2a1L2si 1L1

Приклад . Для отримуємо послідовно: що дає наступний мінімальний автомат. L=(a(ab))(ba)

1-1L=L=L1а-1L1=(аб)(а(аб))=L2б-1L1=а(ба)=L3а-1L2=б(аб)(а(аб))(аб)(а(аб))=бL2L2=L4б-1L2=а-1L3=(ба)=L5б-1L3=а-1L4=а-1(бL2L2)=а-1L2=L4б-1L4=б-1(бL2L2)=L2б-1L2=L2а-1L5=б-1L5=а(ба)=L3
Мінімальний автомат

[1] J. Brzozowski, Похідні від регулярних виразів, J.ACM 11 (4), 481–494, 1964.

Редагувати . (5 квітня 2015 р.) Я щойно виявив подібне запитання: Які алгоритми існують для побудови DFA, який розпізнає мову, описану заданим регулярним виразом? запитали на cstheory. Відповідь частково стосується питань складності.


Чи можете ви сказати більше про складність цього алгоритму?
бабу

@babou Перетворення RE в DFA - це важко PSPACE, тому це, безумовно, експоненціальне.
jmite

Це, мабуть, повинно входити у відповідь. ОП починається з "стандартні конструкції через NFA занадто повільні", і частина відповіді, здається, "невдача, насправді не швидке рішення". Залишилося обговорити, чи це тут краще, ніж стандартне будівництво. (cc @jmite)
Рафаель

@jmite Так, я очікував цього. Причина мого питання полягає в тому, чому такий спосіб побудови ДФА слід вважати простішим. (зверніть увагу: система потребувала цілий день, щоб повідомити мене про відповідь @ jmite).
бабу

2

Ж.-Є. Пін дає кращу відповідь з точки зору формальності та повноти, але я думаю, що є що сказати для «інтуїції», на яку натякає ваш професор.

У більшості з цих випадків найпростіше зробити звичайний вираз, зрозуміти, яку мову він приймає, а потім використовувати свою творчість / кмітливість, щоб побудувати DFA, що приймає цю мову.

Немає прямого способу зробити це, окрім алгоритмів, які інші дали, але ось кілька рекомендацій, які можуть виявитися корисними.

  1. Запитайте себе, чи можу я написати програму, яка приймає цю RE, використовуючи лише булі або дуже малі цілі змінні? Потім напишіть цю програму та перетворіть її в DFA, де є стан для кожної комбінації значень.

  2. Шукайте частини регулярного виразу, які ви знаєте, що можете прийняти детерміновано, де ви знаєте "Якщо я бачу це, то я повинен відповідати цій частині RE". Тут не завжди буде багато тонн, але виявлення цих частин може показати ті частини, які легко зробити DFA, тому ви можете витратити більше часу на деталі, які справді потребують недетермінізму.

  3. Побудова підмножини для NFA-> DFA насправді не така складна в алгоритмі. Тож якщо це завдання, а не іспит, можливо, буде швидше просто кодувати реалізацію та дозволити вашій програмі конвертувати NFA у DFA. Якщо ви використовували власний код, проблем із плагізмом не повинно бути.

Пам’ятайте, що незалежно від того, що ви робите, будь-яка техніка підірветься експоненціально в гіршому випадку (якщо тільки ви не знайдете для цього поліноміальний алгоритм, і в цьому випадку, вітаємо, ви довели і тепер ви мільйонер .)П=NП=ПSПАСЕ

Спробуйте "заглянути вперед", виріжте кути, коли ви можете використовувати свою інтуїцію в тих місцях, коли алгоритм потребує багатьох кроків, але його результат зрозумілий.


-2

Хоча це не правильний шлях, але він працює більшу частину часу.

Перший крок : Знайдіть найменший рядок, який можна прийняти регулярним виразом. Другий крок : намалюйте необхідні стани з транзакцією машини, що приймає мінімальний рядок. Третій крок : для всіх станів проведіть решту транзакцій з алфавітів.

Наприклад: Регулярне вираження (0 + 1) * 1 "Рядок, що закінчується на 1" Крок 1: Найменший рядок: 1 Крок 2: два стани Q0 і Q1. що мають транзакцію 1 від Q0 до Q1. і Q1 - стан, що приймає. Крок 3: для стану Q0 транзакція Q0 1 - це Q1. Тепер зробіть 0 транзакцій у самому Q0. Для штату Q1 транзакція 1 залишатиметься в Q1. І 0 транзакцій піде в Q0.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.