W6. Детерминированные автоматы с магазином, конфигурации, лемма о накачке для КС-языков, автоматы с магазином и компиляторы
1. Краткое содержание
1.1 От конечных автоматов к автоматам с магазином
Мы уже знаем, что конечные автоматы (FSA) распознают регулярные языки. Но у FSA есть фундаментальное ограничение: у них есть лишь фиксированная конечная память — по сути только текущее состояние. Из-за этого некоторые языки распознать нельзя, например a.
Чтобы выйти за пределы регулярных языков, нужна модель с большей памятью. Естественное расширение — «прицепить» к FSA магазин (стек), получив автомат с магазином (PDA). Название «pushdown» отражает именно природу стека: новые элементы кладутся сверху, а снимается всегда верхний.
Неформально:
- FSA = блок конечного управления (только состояния)
- PDA = блок конечного управления + бесконечный стек
Иерархия моделей вычислений (от более слабой к более сильной) выглядит так:
- Комбинационная логика — без памяти
- Конечные автоматы (FSA) — фиксированная ограниченная память (фактически только текущее состояние)
- Автоматы с магазином (PDA) — неограниченная память в виде стека (может расти без предела)
- Машины Тьюринга — полноценная лента для чтения/записи (максимальная мощность)
PDA находятся ровно на ступень выше FSA и распознают контекстно-свободные языки (КС-языки, CFL), к которым относится большинство синтаксических конструкций языков программирования. Поэтому PDA — в центре компиляции: синтаксис языков программирования контекстно-свободен.
1.2 Стек: краткое напоминание
Стек — структура данных «последним пришёл — первым ушёл» (LIFO). Представьте стопку подносов в столовой: добавлять и снимать можно только сверху.
Операции:
- Push: положить новый символ на вершину стека.
- Pop: снять верхний символ со стека (и одновременно «прочитать» его).
У PDA стек изначально содержит особый символ дна стека
Пример — push
- Начальный стек: только
внизу - Push
: стек = (сверху вниз) - Push
: стек = - Push
: стек = - Pop: снимаем
; стек =
Последним положенный символ всегда снимается первым. Это свойство LIFO делает стек удобным для сопоставления вложенных структур вроде сбалансированных скобок.
Историческая справка: идею стека ввёл Алан Тьюринг в работе 1946 года об Automatic Computing Engine (ACE); операции он называл BURY и UNBURY и использовал их в теории подпрограмм.
1.3 Неформальное описание PDA
У PDA три компонента:
- Входная лента — только для чтения, слева направо (входная строка)
- Блок конечного управления — как у FSA, хранит текущее состояние
- Стек неограниченного размера — дополнительная память; контроллер читает вершину и заменяет её
На каждом шаге PDA одновременно смотрит на три вещи:
- Текущее состояние
- Следующий входной символ (или
для «тихого» шага) - Вершину стека
Исходя из этой тройки, он:
- Переходит в новое состояние
- Сдвигает головку по входу (или остаётся на месте при
-переходе) - Заменяет верхний символ стека на строку
С помощью стека PDA может:
- Кладуть (push) символы на стек (заменить верх
на , тогда сверху) - Снимать (pop) верхний символ (заменить верх
на ) - Не менять стек (заменить верх
на ) - Делать
-переходы — переходы без чтения входа, только со изменением стека
Критерий принятия: строка принимается, если после полного чтения PDA находится в принимающем (финальном) состоянии. Содержимое стека в конце для принятия финальным состоянием не важно.
1.4 Формальное определение PDA
Автомат с магазином (PDA) — это 7-кортеж:
где:
— конечное множество состояний — конечный входной алфавит (символы, читаемые с ленты) — конечный алфавит магазина (символы, которые могут лежать на стеке; и могут пересекаться) — функция переходов (частичное отображение в множество возможных исходов) — начальное состояние — начальный символ стека (маркер дна, кладётся на стек в начале) — множество принимающих (финальных) состояний
Как читать функцию переходов: переход
В состоянии
, читая входной символ (или ), при вершине стека : перейти в и заменить строкой .
На стрелках в диаграммах пишут:
- Чтобы положить
под : (заменить на ; теперь сверху ) - Чтобы снять
: - Чтобы оставить стек неизменным:
Ограничения на
- На стеке всегда есть хотя бы
никогда не удаляется со стека- Не кладутся дополнительные копии
на стек
1.5 Детерминированные автоматы с магазином (DPDA)
Общий PDA выше недетерминированен:
PDA
- Не больше одного перехода на шаг: для всех
, и множество содержит не более одного элемента. - Нет конфликта между чтением входа и
-переходами: для всех , и множества и не могут быть оба непустыми.
Второе условие: если есть
Зачем нужно правило про
Практическое соглашение: часто используют
1.6 Конфигурации и переходы
Чтобы формально описать работу PDA, вводят конфигурацию.
1.6.1 Конфигурация
Конфигурация — «мгновенный снимок» PDA в данный момент. В нём зафиксировано всё, что нужно для продолжения вычисления:
где:
— текущее состояние управляющего устройства — непрочитанный фрагмент входной строки — текущее содержимое стека (от верха к низу)
Соглашение: стек записывается сверху вниз. Если
Пример: конфигурация
Начальная конфигурация:
1.6.2 Переходы между конфигурациями
Символ
Случай 1 — чтение входного символа: если
Словами: съесть
Случай 2 —
Словами: не читать вход, снять
Ключевая разница: в случае 1 головка входа сдвигается на один символ; в случае 2 остаётся на месте.
1.6.3 Многошаговое вычисление:
Отношение
1.6.4 Принятие строки PDA
Строка
для некоторого
Проще говоря: из начальной конфигурации (состояние
- Весь вход прочитан (непрочитанное —
) - Текущее состояние принимающее (
) - Стек может быть любым (
произволен)
Язык, распознаваемый
1.7 Два режима принятия
PDA может принимать строку двумя способами:
- Принятие финальным состоянием: вход полностью прочитан и автомат в состоянии
. Содержимое стека не важно. - Принятие пустым стеком: вход полностью прочитан и на стеке только
(фактически «пусто»). Состояние не важно.
Для недетерминированных PDA эти режимы эквивалентны: любой язык, принимаемый одним способом, можно принять и другим (построив другой PDA). Для детерминированных PDA режимы не эквивалентны.
Тонкость про пустой стек: языки, принимаемые пустым стеком, должны быть беспрефиксными (prefix-free): ни одна строка языка не является собственным префиксом другой. Как только стек «опустел» на
1.8 Разобранный пример: PDA для
Классический пример: как PDA «считает» с помощью стека.
Стратегия: для каждого входного a положить на стек один символ b, снимать по одному b. Если ровно в момент, когда все b кончились, на стеке только
Спецификация PDA:
- Состояния:
(старт), (чтениеa), (чтениеb), (принятие) - Алфавит стека:
- Переходы:
| Переход | Запись | Смысл |
|---|---|---|
Первый a; положить |
||
Каждый следующий a; ещё один |
||
Первый b; снять один |
||
Каждый следующий b; снять |
||
| Вход исчерпан; сверху |
Трассировка для входа "aabb":
| Шаг | Состояние | Непрочитанный вход | Стек (сверху вниз) | Правило |
|---|---|---|---|---|
| 1 | ||||
| 2 | ||||
| 3 | ||||
| 4 | ||||
| 5 | ||||
| 6 | ПРИНЯТО |
Полное вычисление:
1.9 Ещё примеры PDA
1.9.1 PDA для
Стратегия: положить по одному a до единственного b. Символ b — «перекрёсток». После b снимать по одному a справа. Если в конце входа стек дошёл до a слева и справа одинаковой длины.
- Состояния:
(старт, фаза push), (фаза pop послеb), (принятие) - Переходы:
| Переход | Запись | Смысл |
|---|---|---|
Первый a до b: push |
||
Каждый следующий a до b$: push $A$ | | $q_0 \to q_1$ | $b,\, A / A$ | Видимb; стек не меняем, меняем состояние | | $q_1 \circlearrowleft$ | $a,\, A / \varepsilon$ | Каждыйaпослеb`: pop один |
||
| Все |
1.9.2 PDA для
Язык
Стратегия: вся
- Состояния:
(фаза push), (фаза pop после ), (принятие) - Ключевые переходы (фаза push, состояние
, петли): ; ; ; ; ;
- Опора (при чтении
): ; ; (все ведут ) - Фаза pop (
, петли): ; - Принятие:
( )
1.9.3 PDA для сбалансированных круглых скобок
Язык сбалансированных (корректно вложенных) скобок — типичный контекстно-свободный язык. Интуитивно каждой ( нужна парная ), пары должны быть правильно вложены.
- Состояния:
(старт), (работа), (принятие) - Переходы:
: — первая(: push : — каждая следующая(: push : — каждая): pop один (сопоставление с() : — вход кончился, «пустой» стек: принять
1.10 PDA и FSA: общая картина
- Каждый регулярный язык распознаётся PDA (достаточно симулировать FSA, не используя стек).
- PDA распознают языки, которые FSA не распознают (например,
). - Значит, класс контекстно-свободных языков строго шире класса регулярных.
- Регулярные языки
языки, распознаваемые PDA (контекстно-свободные) - Примеры КС, но не регулярных:
, , сбалансированные скобки - Примеры сильнее PDA:
(нужно считать три величины одновременно — одного стека недостаточно)
Память:
- FSA: фиксированная ограниченная память (только состояние — фиксированное число бит)
- PDA: конечное управление, но не фиксированный объём памяти — стек может расти неограниченно
- Ключевая мысль: регулярные языки про ограниченную память; контекстно-свободные требуют неограниченной памяти (но со специфической структурой LIFO)
1.11 PDA и компиляторы
PDA напрямую связаны с тем, как устроены современные компиляторы. Компилятор переводит исходный код (например, C, Python) в другой язык (например, машинный). Он состоит из нескольких фаз:
- Лексический анализ: разбивает исходный текст на лексемы (tokens) — минимальные осмысленные единицы (ключевые слова, идентификаторы, операторы и т.д.). Синтаксис лексем регулярный, поэтому эту фазу выполняет FSA (или движок регулярных выражений).
- Синтаксический анализ (разбор): проверяет, что последовательность токенов соответствует грамматике языка. В языках программирования есть вложенные структуры (сбалансированные скобки, вызовы функций, арифметические выражения) — это контекстно-свободно. Эту фазу выполняет PDA.
- Семантический анализ: типы, область видимости и т.п.
- Генерация и оптимизация кода: построение и улучшение целевого кода.
Почему разбор — это PDA? В языках есть конструкции, требующие согласованных/вложенных структур:
- блоки
{...}в C/Java begin...endв Pascal- арифметические выражения в скобках
- вложенные вызовы функций
Именно то, с чем PDA справляются, а FSA — нет.
Лексический анализ на FSA, потому что токены (идентификаторы, числа, ключевые слова) описываются регулярными шаблонами. Например, идентификатор в Pascal соответствует регулярной схеме <letter>(<letter>|<digit>)*, что легко распознать FSA.
Синтаксический анализ на PDA, потому что правила вроде «выражение — это терм, затем оператор, затем другое выражение, возможно со скобками» — контекстно-свободны.
«Контекстно-свободные грамматики с 1960-х играют центральную роль в технологии компиляторов… Существует автоматная нотация, называемая ‘автомат с магазином’, которая описывает ровно все и только контекстно-свободные языки.» — Джон Е. Хопкрофт, Раджив Мотвани и Джеффри Д. Ульман
1.12 Лемма о накачке для КС-языков (лемма Бар-Хиллеля)
Как лемма о накачке для регулярных языков помогает доказывать нерегулярность, так и для КС-языков есть аналог.
1.12.1 Лемма о накачке для регулярных языков (напоминание)
Лемма о накачке (FSA): если
(т.е. ) для любого
Контрапозиция — рабочий инструмент: если для некоторого слова из
1.12.2 Лемма Бар-Хиллеля (лемма о накачке для КС-языков)
Лемма Бар-Хиллеля: если
(хотя бы один из , непуст) («средняя» часть не слишком длинная) для любого (одновременная накачка и одинаковым числом повторов сохраняет строку в )
Главное отличие от регулярной леммы: в регулярном случае качают один отрезок
Наглядная связь с деревьями разбора (нормальная форма Хомского): в достаточно высоком дереве разбора какой-то нетерминал
1.12.3 Контрапозиция: как доказать «не КС»
Следствие (форма для доказательства): если для любого
Игра в двух лицах:
| Игрок 1 (противник) | Игрок 2 (вы) |
|---|---|
| Выбирает любое |
Выбираете |
| Выбирает разбиение |
Находите |
Вы выигрываете (и
1.12.4 Классический пример:
Утверждение:
Набросок доказательства: пусть
Расстояние от первого a до последнего c равно a, только b, только c, или a+b, или b+c).
Во всех случаях накачка при
- Если
содержит толькоa: при накачке добавляютсяa, но неbи неc, получаем . - Если только
b: аналогично . - Если только
c: . - Если
пересекаетaиb: добавляютсяaиb, но неc— строка не в . - Если
пересекаетbиc: добавляютсяbиc, но неa— та же проблема.
Итак, во всех случаях
1.13 За пределами PDA: пределы КС-языков
Не все языки — КС. Канонический пример —
Для таких языков нужна более сильная модель — машина Тьюринга с полноценной лентой чтения/записи. Стек — деструктивная память: после pop символ исчезает. Лента персистентна: чтение не разрушает символ.
Иерархия языков повторяет иерархию машин:
- Регулярные — FSA
- Контекстно-свободные — PDA (память стека)
- Контекстно-зависимые и далее — машины Тьюринга (память ленты)
2. Определения
- Автомат с магазином (PDA): модель с конечным управлением, входной лентой и неограниченным стеком. Формально — 7-кортеж
. PDA распознают ровно класс КС-языков. - Детерминированный PDA (DPDA): PDA, где (1)
для всех (на шаг не больше одного перехода), и (2) из следует для всех (нет конфликта между чтением входа и -переходами). - Недетерминированный PDA:
может содержать несколько исходов. Авомат принимает, если существует последовательность выборов, ведущая к принятию. - Стек: структура LIFO — основная память PDA. Операции: push (положить наверх) и pop (снять сверху).
- Алфавит магазина (
): конечное множество символов на стеке. Обычно включает маркер дна . - Символ дна стека (
): специальный символ внизу стека изначально. Никогда не удаляется и не дублируется. Когда он сверху, стек «пуст». - Входной алфавит (
): конечное множество символов входной ленты. Смысл отделён от , хотя множества могут пересекаться. - Функция переходов (
): . Переход : из , читая (или ) и вершину , перейти в и заменить на . -переход: переход без чтения входа — меняются состояние и/или стек «спонтанно».- Правило про
(условие DPDA): если из есть -переход при вершине , то не должно быть перехода с чтением входа из того же при той же вершине . - Конфигурация: тройка
— снимок PDA: состояние , непрочитанный вход , стек (сверху вниз). Также «мгновенное описание PDA». - Переход между конфигурациями (
): один шаг. если ; либо если . - Рефлексивно-транзитивное замыкание (
): — ноль или более шагов от к . - Принятие финальным состоянием:
принимается, если для некоторых , . Финальный стек не важен. - Принятие пустым стеком:
принимается, если для некоторого (не обязательно из ). Для DPDA два режима не эквивалентны. - Контекстно-свободный язык (КС, CFL): язык, распознаваемый PDA, или эквивалентно порождённый КС-грамматикой. Каждый регулярный — КС, обратное неверно.
- Лемма о накачке (регулярные языки): если
регулярен, существует такое, что каждое с раскладывается , , , и . - Лемма Бар-Хиллеля (КС): если
КС, существует такое, что каждое с раскладывается , , , и . - Компилятор: программа, переводящая исходный код одного языка (например, C) в другой (например, машинный), обычно через фазы: лексика, синтаксик, семантика, генерация кода.
- Лексический анализ: первая фаза; делит текст на токены. Использует FSA (регулярные шаблоны).
- Синтаксический анализ (парсинг): вторая фаза; проверяет соответствие грамматике и строит дерево разбора. Использует PDA для вложенных структур.
- Токен (лексема): минимальная осмысленная единица языка (например, идентификатор
sum, оператор+, ключевое словоif). Выделяется на лексике. - Дерево разбора (синтаксическое дерево): дерево грамматической структуры; листья — токены; внутренние узлы — правила.
- Абстрактное синтаксическое дерево (AST): упрощённое дерево для семантики, оптимизации и генерации.
- Беспрефиксный язык: в
ни одна строка не является собственным префиксом другой. Языки, принимаемые DPDA пустым стеком, должны быть беспрефиксными.
3. Формулы
- Формальное определение PDA:
где - Запись перехода:
— прочитать с входа (или ), снять , положить - Push
: заменить верх на — запись - Pop верхнего
: - Стек не менять:
- Условие DPDA 1:
для всех , , - Условие DPDA 2:
для всех , , - Конфигурация:
где , (остаток входа), (стек, сверху вниз) - Переход (чтение входа):
при - Переход (
): при - Принятие финальным состоянием:
для некоторых , - Распознаваемый язык:
- Лемма (регулярные):
регулярен : , , разбиение , , , - Лемма Бар-Хиллеля (КС):
КС : , , разбиение , , , - Контрапозиция (Бар-Хиллель):
не КС, если , , такое что разбиений с и : с
4. Примеры
4.1. Построить DPDA для (Лаба 6, Задание 1)
Постройте DPDA, распознающий язык a, затем ровно b.
Показать решение
Идея: на каждый прочитанный a нужно положить два символа стека (тогда для a накопится b. Когда все b прочитаны и на стеке только
Спецификация PDA:
- Состояния:
(старт), (чтениеa), (чтениеb), (принятие) - Алфавит стека:
- Состояния:
Переходы:
Переход Запись Смысл Первый a: положить дваКаждый следующий a: положить ещё два (чисто: заменить верхний на , добавляя два)Первый b: pop одинКаждый следующий b: popВсе сняты; принятьЗамечание про шаг push: при чтении
aпри вершине заменяем на — фактически сохраняем имеющийся и добавляем два сверху, то есть стек растёт на два на каждыйa. Эквивалентно: каждыйaдолжен добавить два символа — замена (плюс два) даёт соотношение .Трассировка для
"abb"( , ): : стек = : стек = : стек = : ПРИНЯТО
Трассировка для
"aabbbb"( , ): : стек = : стек = (чисто +2: добавляет два) : стек = : стек = : стек = : стек = — (ОШИБКА: недостаток стека — неверно, перепроверить)
Исправление: пересчитаем. Для
: после первогоaстек , затем заменяем верхний на для второгоa: стек (это 3 символа + ). Нужно маркера для .Другой подход: аккуратнее: на каждый
aкласть ровно два , используя отдельное состояние для второго push.Переход Запись Смысл Первый a: первыйСпонтанно: второй Следующий a(первый из пары push)… … … Самый простой корректный вариант: на каждый
a— два через вспомогательное состояние:- Состояния:
(старт), (только что прочитанa, нужен второй ), (готовы читатьaилиb), (чтениеb), (принятие)
Переход Запись Смысл Первый a: одинВторой (спонтанно)Ещё a: первый из двухНачало b: pop одинКаждый b: pop«Пустой» стек: принять
Ответ: DPDA с вспомогательным состоянием для второго a, затем pop по одному b, распознаёт
4.2. Построить DPDA для скобок арифметических выражений (Лаба 6, Домашнее задание 1)
Постройте DPDA, распознающий язык корректных скобок арифметических выражений (бинарные операции). Алфавит + — бинарный оператор.
Примеры в языке: (a + a), ((a) + (a + a)), ((a + a)) Язык — синтаксически корректные выражения со скобочными подвыражениями.
Показать решение
Идея: задача про простую грамматику выражений. Главное ограничение — баланс скобок: каждой ( нужна ), вложенность корректна. Символы + в этой упрощённой постановке — «наполнитель», не ломающий баланс.
Упрощение: для построения DPDA достаточно свойства баланса скобок. Символы + должны появляться в допустимых позициях грамматики; моделируем это, отслеживая открытые скобки на стеке.
Грамматика (неформально):
- Выражение: терм, или
(выражение), или выражение+выражение
В простом DPDA, отслеживающем только баланс скобок:
Состояния:
(работа), (принятие)- Алфавит стека:
, где маркирует открытую(
- Алфавит стека:
Переходы (петли на
):Запись Смысл Открыли (при «пустом» стеке: push(внутри другой: pushЗакрыли ): снять парныйПрочитали терм : стек не меняемТерм внутри скобок: стек не меняемОператор вне скобок: стек не меняем Оператор внутри скобок: стек не меняем Принятие:
: — баланс.Трассировка для
"(a+a)": : стек = : стек = : стек = : стек = : стек = : ПРИНЯТО
Ответ: DPDA отслеживает баланс скобок стеком и принимает, когда скобки согласованы и вход полностью прочитан.
4.3. Построить DPDA для (Лаба 6, Задание 2)
Постройте DPDA для
(Строка: непустая
Показать решение
Идея: положить на стек все символы a — b — d — e —
- Спецификация PDA:
- Состояния:
(push ), (push ), (pop ), (pop ), (принятие) - Алфавит стека:
- Состояния:
- Фаза 1 — push
(состояние , петли): ; ; ;
- Переход к фазе push
( ): при первомdилиeперейти в : ; ; ;
- Фаза 2 — push
( , петли): ; ;
- Опора на
( или , если пусто): ; (верх — символ : фаза pop- ) ; ( не было: сразу pop- : )
- Фаза 3 — pop
( , петли): ; (сопоставление , )- Переход к pop-
, когда на вершине или : на : ;
- Фаза 4 — pop
( , петли): ;
- Принятие:
:
Ответ: DPDA с фазами push
4.4. Построить DPDA для сбалансированных круглых и квадратных скобок (Лаба 6, Задание 3)
Постройте DPDA для языка вложенных сбалансированных скобок над алфавитом
Примеры в языке: (([])())(), (())[] Примеры не в языке: ([(]))()(), ([)]
Показать решение
Идея: стек хранит открытые разделители. Для ( кладём маркер [ — ) снимаем верх и проверяем, что это ] — что верх
Замечание: важно отвергнуть ([)] — закрывающие символы должны соответствовать последнему открытию. LIFO стека обеспечивает это естественно.
Спецификация:
- Состояния:
(старт, работа), (принятие) - Алфавит стека:
, где для(, для[
- Состояния:
Переходы (петли на
, кроме финального перехода принятия):Запись Смысл (при пустом стеке: push(при вершине : push(при вершине : push[при пустом стеке: push[при вершине : push[при вершине : push)при вершине : pop (совпало)]при вершине : pop (совпало)Принятие:
: — всё согласовано, только .Отклонение (неявно): если читается
), а сверху , перехода нет — автомат застревает и отвергает. Так корректно отвергается([)].Трассировка для
"([])": : стек = : стек = : стек = : стек = : ПРИНЯТО
Ответ: приведённый DPDA распознаёт язык вложенных сбалансированных скобок над
4.5. Построить DPDA для (Лаба 6, Задание 4)
Постройте DPDA для a и b (в любом порядке).
Показать решение
Идея: в отличие от a и b могут чередоваться как угодно. Стек используем как счётчик: кладём a (когда стек только b (когда только a при вершине b при вершине
Спецификация:
- Состояния:
(работа), (принятие) - Алфавит стека:
на стеке — «лишниеa»; — «лишниеb»
- Состояния:
Переходы (петли на
):Запись Смысл aпри балансе: push (+1 кa)aпри избыткеa: ещёaпри избыткеb: снять одинbпри балансе: pushbпри избыткеb: ещёbпри избыткеa: снять одинПринятие:
: — всё сократилось до : счётчики равны.Трассировка для
"abba": : стек = (избытокa= 1) : стек = (сокращение) : стек = (избытокb= 1) : стек = : ПРИНЯТО
Трассировка для
"aab"(должно отвергаться: ): : стек = : стек = : стек =- Вход кончился; стек
(не только ); -перехода принятия нет. ОТВЕРГНУТО
Ответ: приведённый DPDA использует стек как знаковый счётчик и распознаёт
4.6. Построить DPDA для (Лаба 6, Задание 5)
Постройте DPDA для
Показать решение
Идея: строка вида a, внутренний слой b, согласованный внутренний слой a, согласованный внешний слой b. Стек в двух фазах:
- Фаза 1 (внешние
a): положить копий для ведущихa. - Фаза 2 (внутренние
b): положить копий поверх . - Фаза 3 (внутренние
a): снять по одному на каждыйa(согласование внутреннихbиa). - Фаза 4 (внешние
b): снять по одному на каждыйb(согласование внешнихaиb).
Состояния:
(внешниеa), (внутренниеb), (внутренниеa), (внешниеb), (принятие)Переходы:
Переход Запись Смысл Первый внешний a: pushЕщё внешние a: pushПервый внутренний b: push надЕщё внутренние b: pushПервый внутренний a: popЕщё внутренние a: popПервый внешний b: pop (все сняты)Ещё внешние b: popВсё согласовано: принять Трассировка для
"abba"слишком коротка (минимум ):Трассировка для
"abab"( ): : стек = : стек = : стек = : стек = : ПРИНЯТО
Ответ: DPDA с фазами внешних a, внутренних b, внутренних a, внешних b распознаёт
4.7. Доказать, что не КС (Туториал 6, Пример 1)
Докажите леммой Бар-Хиллеля (леммой о накачке для КС-языков), что
Показать решение
Идея: в a, b и c должны совпадать. Лемма Бар-Хиллеля накачивает два отрезка синхронно, но любое «окно» длины
- От противного: пусть
КС. Пусть — длина накачки из леммы Бар-Хиллеля. - Слово:
, . - Любое разбиение
с и . - Где может лежать
: расстояние от первогоaдо последнегоcравно . Так как , окно не может одновременно покрыть все три типа. Возможны:- только
a, или толькоb, или толькоc, или a+b(безc), илиb+c(безa)
- только
- Накачка при
: рассмотрим . Во всех случаях:- Если
только изa: добавляютсяa, неbи неc— большеa, чемbиc. . - Если только из
b: аналогично . - Если только из
c: . - Если
пересекаетaиb: добавляютсяaиb, неc. . - Если пересекает
bиc: добавляютсяbиc, неa. .
- Если
- Вывод: во всех случаях
— противоречие с леммой. Значит не КС.
Ответ:
4.8. Построить DPDA для (Туториал 6, Пример 2)
Постройте DPDA для "aabb".
Показать решение
Идея: считать a стеком: по одному a, затем по одному pop на каждый b. Если после всех b на стеке только
Спецификация PDA:
- Состояния:
(старт), (чтениеa), (чтениеb), (принятие) - Алфавит стека:
- Входной алфавит:
- Состояния:
Переходы:
Переход Запись Смысл Первый a; push надДополнительные a; каждый раз pushПервый b; pop одинДополнительные b; каждый раз popВход кончился; сверху — все совпали; принятьПроверка детерминизма:
- У каждого
не больше одного исхода — условие 1. -переход использует вершину . Из нет читающего вход перехода при вершине — условие 2.
- У каждого
Трассировка для
"aabb":Шаг Состояние Непрочитанный вход Стек Правило 1 : push2 : push3 : pop4 : pop5 : к принятию6 ПРИНЯТО Полная цепочка конфигураций:
Ответ: DPDA с состояниями
4.9. Построить DPDA для (Туториал 6, Пример 3)
Постройте DPDA для
Показать решение
Идея: по одному a до единственного b. Символ b — опора: переключение из режима push в pop. После b — по одному pop на каждый a справа. Равенство чисел a слева и справа.
Спецификация:
- Состояния:
(старт, фаза push), (фаза pop послеb), (принятие) - Алфавит стека:
- Состояния:
Переходы:
Переход Запись Смысл Первый aдоb: pushКаждый следующий aдоb: pushПрочитали b: стек не меняем, переход в popКаждый aпослеb: popВсе совпали; принятьТрассировка для
"aba": : стек = : стек = (без изменений) : стек = : ПРИНЯТО
Трассировка для
"aabaa": : стек = : стек = : стек = : стек = : стек = : ПРИНЯТО
Ответ: DPDA с состояниями
4.10. Построить DPDA для (Туториал 6, Пример 4)
Постройте DPDA для
Показать решение
Идея: положить на стек каждый символ a — b —
Спецификация:
- Состояния:
(фаза push), (фаза pop), (принятие) - Алфавит стека:
, где кодируетa, —b
- Состояния:
Переходы:
Фаза push (
, петли):Запись Смысл Первый a: pushПервый b: pushСледующий aпри вершине : pushСледующий aпри вершине : pushСледующий bпри вершине : pushСледующий bпри вершине : pushОпора (чтение
, , стек не меняется):Запись Смысл пусто: перейти в pop при вершине : в pop при вершине : в popФаза pop (
, петли):Запись Смысл aи вершина : совпало, popbи вершина : совпало, popПринятие:
: — всё совпало.Трассировка для
"abcba"( , ): : стек = : стек = : стек = (без изменений) : стек = : стек = : ПРИНЯТО
Ответ: DPDA с состояниями