Минимизация ДКА, алгоритм Хопкрофта (сложность O(n log n)) — различия между версиями

Материал из Викиконспекты
Перейти к: навигация, поиск
(Алгоритм)
Строка 4: Строка 4:
 
= Алгоритм =
 
= Алгоритм =
 
Основная идея минимизации ДКА состоит в объединении состояний автомата в блоки таким образом, что любые два состояния из разных блоков неэквивалентны и любые состояния из одного блока эквивалентны. Получившиеся блоки и будут состояниями минимального автомата.
 
Основная идея минимизации ДКА состоит в объединении состояний автомата в блоки таким образом, что любые два состояния из разных блоков неэквивалентны и любые состояния из одного блока эквивалентны. Получившиеся блоки и будут состояниями минимального автомата.
 +
 +
===Разбиения на блоки===
 +
Пусть <tex>Q</tex> - множество состояний ДКА. Разделим <tex>Q</tex> на 2 блока <tex>F</tex> и <tex>Q - F</tex>, где <tex>F</tex> - множество терминальных состояний и <tex>Q - F</tex>- множество нетерминальных состояний. Теперь будем делить блоки до тех пор, пока они не будут содержать только эквивалентные состояния. Для этого создадим множество сплитеров, где сплитер - это множество состояний. Для каждой буквы <tex>a</tex> из алфавита <tex>\Sigma</tex> создадим множество <tex>l_a</tex>, состоящее из состояний имеющих ребро в текущий сплитер по букве <tex>a</tex>. Если какой-нибудь блок имеет не нулевое пересечение с <tex>l_a</tex>, а также не является его подмножеством, то его можно разделить на два новых блока. Первый блок состоит из состояний, которые имеют ребра в текущий сплитер по букве <tex>a</tex>, а второй блок состоит из оставшихся состояний. Меньший из них добавим в множество сплитеров <tex>W</tex> и обновим множество блоков <tex>P</tex>. Продолжаем деление до тех пор пока множество сплитеров не пусто.
  
 
===Псевдокод===
 
===Псевдокод===
<tex>W</tex> {{---}} очередь из сплитеров.
+
<tex>W</tex> {{---}} множество сплитеров.
 
<tex>P</tex> {{---}} множество всех блоков ДКА.
 
<tex>P</tex> {{---}} множество всех блоков ДКА.
 
   <tex>W \leftarrow \{ F, Q - F \}</tex>
 
   <tex>W \leftarrow \{ F, Q - F \}</tex>
Строка 20: Строка 23:
 
           replace <tex>R</tex> in <tex>W</tex> with <tex>R_1</tex> and <tex>R_2</tex>
 
           replace <tex>R</tex> in <tex>W</tex> with <tex>R_1</tex> and <tex>R_2</tex>
 
         else
 
         else
           if <tex>\mid R_1 \mid \le \mid R_2 \mid</tex> then
+
           if <tex> |R_1| \le |R_2|</tex> then
 
             add <tex>R_1</tex> to <tex>W</tex>
 
             add <tex>R_1</tex> to <tex>W</tex>
 
           else
 
           else
Строка 26: Строка 29:
  
 
==Время работы алгоритма==
 
==Время работы алгоритма==
 +
Благодаря системе добавления множеств состояний в множество сплитеров, каждое ребро будет рассмотрено не более чем <tex>\log{n}</tex> раз. А так как ребер у нас порядка <tex> |\Sigma| * n </tex> то получаем <tex> O(n\log{n})</tex>

Версия 07:05, 6 ноября 2011

Постановка задачи

Пусть дан автомат распознающий определенный язык. Требуется найти автомат с наименьшим количеством состояний, который распознает этот же язык.

Алгоритм

Основная идея минимизации ДКА состоит в объединении состояний автомата в блоки таким образом, что любые два состояния из разных блоков неэквивалентны и любые состояния из одного блока эквивалентны. Получившиеся блоки и будут состояниями минимального автомата.

Разбиения на блоки

Пусть [math]Q[/math] - множество состояний ДКА. Разделим [math]Q[/math] на 2 блока [math]F[/math] и [math]Q - F[/math], где [math]F[/math] - множество терминальных состояний и [math]Q - F[/math]- множество нетерминальных состояний. Теперь будем делить блоки до тех пор, пока они не будут содержать только эквивалентные состояния. Для этого создадим множество сплитеров, где сплитер - это множество состояний. Для каждой буквы [math]a[/math] из алфавита [math]\Sigma[/math] создадим множество [math]l_a[/math], состоящее из состояний имеющих ребро в текущий сплитер по букве [math]a[/math]. Если какой-нибудь блок имеет не нулевое пересечение с [math]l_a[/math], а также не является его подмножеством, то его можно разделить на два новых блока. Первый блок состоит из состояний, которые имеют ребра в текущий сплитер по букве [math]a[/math], а второй блок состоит из оставшихся состояний. Меньший из них добавим в множество сплитеров [math]W[/math] и обновим множество блоков [math]P[/math]. Продолжаем деление до тех пор пока множество сплитеров не пусто.

Псевдокод

[math]W[/math] — множество сплитеров. [math]P[/math] — множество всех блоков ДКА.

 [math]W \leftarrow \{ F, Q - F \}[/math]
 [math]P \leftarrow \{ F, Q - F \}[/math]
 While [math]W[/math] is not empty do 
   select and remove [math]S[/math] from [math]W[/math]
   for all [math]a \in \Sigma[/math] do
     [math]l_a \leftarrow \delta^{-1} (S, a)[/math]
     for all [math]R[/math] in [math]P[/math] such that [math]R \cap l_a \ne \emptyset[/math] and [math]R \not \subseteq l_a [/math] do
       partition [math]R[/math] into [math]R_1[/math] and [math]R_2 : R_1 \leftarrow R \cap l_a [/math] and [math]R_2 \leftarrow R - R_1[/math]
       replace [math]R[/math] in [math]P[/math] with [math]R_1[/math] and [math]R_2[/math]
       if [math]R \in W[/math] then
         replace [math]R[/math] in [math]W[/math] with [math]R_1[/math] and [math]R_2[/math]
       else
         if [math] |R_1| \le |R_2|[/math] then
           add [math]R_1[/math] to [math]W[/math]
         else
           add [math]R_2[/math] to [math]W[/math]

Время работы алгоритма

Благодаря системе добавления множеств состояний в множество сплитеров, каждое ребро будет рассмотрено не более чем [math]\log{n}[/math] раз. А так как ребер у нас порядка [math] |\Sigma| * n [/math] то получаем [math] O(n\log{n})[/math]