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

Материал из Викиконспекты
Перейти к: навигация, поиск
(Постановка задачи)
Строка 1: Строка 1:
 
= Постановка задачи =
 
= Постановка задачи =
Пусть дан автомат распознающий определенный язык. Требуется найти [[ Эквивалентность_состояний_ДКА | эквивалентный автомат]] с наименьшим количеством состояний.
+
Пусть дан автомат, распознающий определенный язык. Требуется найти [[ Эквивалентность_состояний_ДКА | эквивалентный автомат]] с наименьшим количеством состояний.
  
 +
= Минимизация ДКА =
 +
Понятие [[ Эквивалентность_состояний_ДКА | эквивалентности состояний]] позволяет объединить состояния в блоки следующим образом.
 +
# Все состояния в блоке эквивалентны.
 +
# Любые два состояния, выбранные из разных блоков, неэквивалентны.
 +
Таким образом, основная идея минимизации ДКА состоит в разбиении множества состояний на блоки эквивалентности.
 +
===Пример минимизации ДКА===
 +
[[Изображение:Automaton1.png]][[Изображение:Automaton2.png]]
 +
 +
Первый блок состоит из состояния <tex>A</tex>, а второй из эквивалентных состояний <tex>B</tex> и <tex>C</tex>.
 
= Алгоритм =
 
= Алгоритм =
Основная идея минимизации состоит в разделении состояний ДКА на классы эквивалентности. Получившиеся классы и будут состояниями минимального автомата.
+
Алгоритм итеративно строит разбиение множества состояний следующим образом.
 
+
# Первоначальное разбиение множества состояний {{---}} класс допускающих состояний и класс недопускающих состояний.
===Разбиения на блоки===
+
# Алгоритм помещает оба эти класса в очередь.
Пусть <tex>Q</tex> {{---}} множество состояний ДКА. Разделим <tex>Q</tex> на 2 класса <tex>F</tex> и <tex>Q \setminus F</tex>, где <tex>F</tex> {{---}} множество терминальных состояний и <tex>Q \setminus 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>\Sigma</tex>, где <tex>c</tex> {{---}} текущий символ.
 +
# Все классы текущего разбиения разбиваются на 2 подкласса (один из которых может быть пустым). Первый состоит из состояний, которые по символу <tex>c</tex> переходят в сплиттер, а второй из всех оставшихся.  
 +
# Те классы, которые разбились на два непустых подкласса, заменяются этими подклассами в разбиении, а также меньший из двух подклассов добавляется в очередь.
 +
# Пока очередь не пуста, алгоритм выполняет п.3 – п.6.
  
 
===Псевдокод===
 
===Псевдокод===
<tex>W</tex> {{---}} множество сплиттеров.
+
<tex>Q</tex> {{---}} множество состояний ДКА.
<tex>P</tex> {{---}} множество всех блоков ДКА.
+
<tex>F</tex> {{---}} множество терминальных состояний.
 +
<tex>W</tex> {{---}} очередь.
 +
<tex>P</tex> {{---}} разбиение множества состояний ДКА.
 +
<tex>R</tex> {{---}} класс состояний ДКА.
 
   <tex>W \leftarrow \{ F, Q \setminus F \}</tex>
 
   <tex>W \leftarrow \{ F, Q \setminus F \}</tex>
 
   <tex>P \leftarrow \{ F, Q \setminus F \}</tex>
 
   <tex>P \leftarrow \{ F, Q \setminus F \}</tex>
   while <tex>W</tex> is not empty do
+
   while not isEmpty(<tex>W</tex>)
     select and remove <tex>S</tex> from <tex>W</tex>
+
     <tex>W</tex>.pop(<tex>S</tex>)
     for all <tex>a \in \Sigma</tex> do
+
     for all <tex>a \in \Sigma</tex>
      <tex>l_a \leftarrow \delta^{-1} (S, a)</tex>
+
       for all <tex>R</tex> in <tex>P</tex>  
       for all <tex>R</tex> in <tex>P : R \cap l_a \ne \emptyset</tex> and <tex>R \not \subseteq l_a </tex> do
+
         <tex>R_1 \leftarrow R \cap \delta^{-1} (S, a) </tex>
         partition <tex>R</tex> into <tex>R_1</tex> and <tex>R_2 : R_1 \leftarrow R \cap l_a </tex> and <tex>R_2 \leftarrow R - R_1</tex>
+
        <tex>R_2 \leftarrow R \setminus R_1</tex>
         replace <tex>R</tex> in <tex>P</tex> with <tex>R_1</tex> and <tex>R_2</tex>
+
         if <tex> |R_1| \ne 0</tex> & <tex>|R_2| \ne 0</tex>
        if <tex>R \in W</tex> then
+
           replace <tex>R</tex> in <tex>P</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>
+
            if <tex> |R_1| \le |R_2|</tex> then
        else
+
              <tex>W</tex>.push(<tex>R_1</tex>)
          if <tex> |R_1| \le |R_2|</tex> then
+
            else
            add <tex>R_1</tex> to <tex>W</tex>
+
              <tex>W</tex>.push(<tex>R_2</tex>)
          else
+
           
            add <tex>R_2</tex> to <tex>W</tex>
 
 
 
 
==Время работы алгоритма==
 
==Время работы алгоритма==
Благодаря системе добавления множеств состояний в множество сплиттеров, каждое ребро будет рассмотрено не более чем <tex>\log{n}</tex> раз. А так как ребер у нас порядка <tex> |\Sigma| * n </tex> то получаем <tex> O(n\log{n})</tex>
+
Благодаря системе добавления классов состояний в очередь, каждое ребро будет рассмотрено не более чем <tex>\log{n}</tex> раз. А так как ребер у нас порядка <tex> |\Sigma| * n </tex> то получаем <tex> O(n\log{n})</tex>
 
= Литература =
 
= Литература =
* ''Хопкрофт Д., Мотвани Р., Ульман Д.'' {{---}} '''Введение в теорию автоматов, языков и вычислений''', 2-е изд. : Пер. с англ. — Москва, Издательский дом «Вильямс», 2002. — 528 с. : ISBN 5-8459-0261-4 (рус.)
+
* ''Хопкрофт Д., Мотвани Р., Ульман Д.'' '''Введение в теорию автоматов, языков и вычислений''', 2-е изд. : Пер. с англ. — Москва, Издательский дом «Вильямс», 2002. — С. 177: ISBN 5-8459-0261-4 (рус.)
 
[[Категория: Теория формальных языков]]
 
[[Категория: Теория формальных языков]]
* ''J. E. Hopcroft.'' {{---}} '''An n log n algorithm for minimizing states in a finite automaton.''' Technical Report CS-71-190, Stanford University, January 1971.
+
* ''J. E. Hopcroft.'' '''An n log n algorithm for minimizing states in a finite automaton.''' Technical Report CS-71-190, Stanford University, January 1971.

Версия 04:29, 11 ноября 2011

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

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

Минимизация ДКА

Понятие эквивалентности состояний позволяет объединить состояния в блоки следующим образом.

  1. Все состояния в блоке эквивалентны.
  2. Любые два состояния, выбранные из разных блоков, неэквивалентны.

Таким образом, основная идея минимизации ДКА состоит в разбиении множества состояний на блоки эквивалентности.

Пример минимизации ДКА

Automaton1.pngAutomaton2.png

Первый блок состоит из состояния [math]A[/math], а второй из эквивалентных состояний [math]B[/math] и [math]C[/math].

Алгоритм

Алгоритм итеративно строит разбиение множества состояний следующим образом.

  1. Первоначальное разбиение множества состояний — класс допускающих состояний и класс недопускающих состояний.
  2. Алгоритм помещает оба эти класса в очередь.
  3. Из очереди извлекается класс, далее именуемый как сплиттер.
  4. Перебираются все символы из алфавита [math]\Sigma[/math], где [math]c[/math] — текущий символ.
  5. Все классы текущего разбиения разбиваются на 2 подкласса (один из которых может быть пустым). Первый состоит из состояний, которые по символу [math]c[/math] переходят в сплиттер, а второй из всех оставшихся.
  6. Те классы, которые разбились на два непустых подкласса, заменяются этими подклассами в разбиении, а также меньший из двух подклассов добавляется в очередь.
  7. Пока очередь не пуста, алгоритм выполняет п.3 – п.6.

Псевдокод

[math]Q[/math] — множество состояний ДКА. [math]F[/math] — множество терминальных состояний. [math]W[/math] — очередь. [math]P[/math] — разбиение множества состояний ДКА. [math]R[/math] — класс состояний ДКА.

 [math]W \leftarrow \{ F, Q \setminus F \}[/math]
 [math]P \leftarrow \{ F, Q \setminus F \}[/math]
 while not isEmpty([math]W[/math]) 
   [math]W[/math].pop([math]S[/math])
   for all [math]a \in \Sigma[/math]
     for all [math]R[/math] in [math]P[/math] 
       [math]R_1 \leftarrow R \cap \delta^{-1} (S, a) [/math]
       [math]R_2 \leftarrow R \setminus R_1[/math]
       if [math] |R_1| \ne 0[/math] & [math]|R_2| \ne 0[/math]
         replace [math]R[/math] in [math]P[/math] with [math]R_1[/math] and [math]R_2[/math]
           if [math] |R_1| \le |R_2|[/math] then
             [math]W[/math].push([math]R_1[/math])
           else
             [math]W[/math].push([math]R_2[/math])
           

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

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

Литература

  • Хопкрофт Д., Мотвани Р., Ульман Д. Введение в теорию автоматов, языков и вычислений, 2-е изд. : Пер. с англ. — Москва, Издательский дом «Вильямс», 2002. — С. 177: ISBN 5-8459-0261-4 (рус.)
  • J. E. Hopcroft. An n log n algorithm for minimizing states in a finite automaton. Technical Report CS-71-190, Stanford University, January 1971.