Регулярная аппроксимация КС-языков — различия между версиями

Материал из Викиконспекты
Перейти к: навигация, поиск
м (Идея алгоритма)
м (rollbackEdits.php mass rollback)
 
(не показаны 4 промежуточные версии 3 участников)
Строка 46: Строка 46:
 
     '''if''' !isLeftType(<tex>N_i</tex>) '''and''' !isRightType(<tex>N_i</tex>)  
 
     '''if''' !isLeftType(<tex>N_i</tex>) '''and''' !isRightType(<tex>N_i</tex>)  
 
         '''return''' cyclic
 
         '''return''' cyclic
:Когда функция <tex>\mathtt {getTheTypeOfMutualRecursiveSet}(N_i) = left, N_i </tex> состоит только из лево-рекурсивных нетерминалов.  
+
:Состояние <tex> left</tex> означает, что <tex> N_i </tex> состоит только из лево-рекурсивных нетерминалов.  
:Аналогично для <tex>\mathtt {getTheTypeOfMutualRecursiveSet}(N_i) = right </tex>.
+
:Состояние <tex> right</tex> означает, что <tex> N_i </tex> состоит только из право-рекурсивных нетерминалов.
:Когда функция <tex>\mathtt {getTheTypeOfMutualRecursiveSet}(N_i) = cyclic, N_i </tex> состоит только из правил, участвующих в рекурсии.
+
:Состояние <tex> cyclic</tex> означает, что <tex> N_i </tex> состоит только из правил, участвующих в рекурсии.
:Функция <tex>\mathtt {getTheTypeOfMutualRecursiveSet}(N_i) = self</tex>, для такого <tex>i </tex>, при котором грамматика самоприменима.   
+
:Состояние <tex> self</tex> означает, что  <tex>i </tex> такое, при котором грамматика самоприменима.   
 
Заметим, что <tex> \forall i </tex> <tex>\mathtt {getTheTypeOfMutualRecursiveSet}(N_i) \neq self </tex>, т.к в противном случае грамматика будет самоприменима.
 
Заметим, что <tex> \forall i </tex> <tex>\mathtt {getTheTypeOfMutualRecursiveSet}(N_i) \neq self </tex>, т.к в противном случае грамматика будет самоприменима.
 
В основе алгоритма будет рекурсивный обход грамматики. Спускаемся по грамматике до тех пор не приходим в нетерминал или символ алфавита:
 
В основе алгоритма будет рекурсивный обход грамматики. Спускаемся по грамматике до тех пор не приходим в нетерминал или символ алфавита:
Строка 65: Строка 65:
 
     <tex>\mathtt{Q} \leftarrow \varnothing</tex>
 
     <tex>\mathtt{Q} \leftarrow \varnothing</tex>
 
     <tex>\Delta \leftarrow \varnothing </tex>
 
     <tex>\Delta \leftarrow \varnothing </tex>
     s = createState()
+
     s = createState()               <font color=green>// createState создает некоторый объект, не принадлежащий <tex>Q</tex>, возвращает этот объект и добавляет его в <tex>Q</tex>  </font> 
 
     f = createState()
 
     f = createState()
 
     <tex>F \leftarrow \{f\} </tex>
 
     <tex>F \leftarrow \{f\} </tex>

Текущая версия на 19:21, 4 сентября 2022


Определения

Определение:
Контекстно-свободная грамматика G=N,Σ,P,S называется самоприменимой (англ. self-embeded), если AN:AαAβ, αεβε .


Определение:
Нетерминал AN в грамматике G=N,Σ,P,S называется рекурсивным (англ. recursive), если α,β(ΣN):AαAβ .


Определение:
Нетерминалы A,BN в грамматике G=N,Σ,P,S называются взаимно рекурсивными (англ. mutual recursive), если α1,β1,α2,β2(ΣN):Aα1Bβ1Bα2Aβ2 .


Алгоритм преобразования грамматики в конечный автомат

Лемма:
Не самоприменимая контекстно-свободная грамматика генерирует регулярный язык.
Доказательство:
В качестве конструктивного доказательства рассмотрим алгоритм построения конечного автомата по грамматике. Также приведем ссылку на формальное доказательство[1].

Идея алгоритма

Пусть, N множество рекурсивных нетерминалов из N. Пусть, P={N1,N2,,NK} разбиение N на k дизъюнктных множеств взаимно рекурсивных нетерминалов, N1N2Nk=Ni Ni.

Определим вспомогательную функцию isLeftType(Ni), которая возвращает true, если существует (AαBβ)P[ANiBNiαε].

Аналогично определим функцию isRightType(Ni), которая возвращает true, если существует (AαBβ)P[ANiBNiβε]

bool isLeftType(Ni: nonterminal): 
    return (AαBβ)P[ANiBNiαε]

bool isRightType(Ni: nonterminal): 
    return (AαBβ)P[ANiBNiβε]

Будем называть typeRecursive набор четырех величин {left,right,self,cycle}

Определим функцию getTheTypeOfMutualRecursiveSet(Ni):PtypeRecursive:

function getTheTypeOfMutualRecursiveSet(Ni: nonterminal): typeRecurcive
   if !isLeftType(Ni) and isRightType(Ni) 
       return left
   if isLeftType(Ni) and !isRightType(Ni) 
       return right
   if isLeftType(Ni) and isRightType(Ni) 
       return self
   if !isLeftType(Ni) and !isRightType(Ni) 
       return cyclic
Состояние left означает, что Ni состоит только из лево-рекурсивных нетерминалов.
Состояние right означает, что Ni состоит только из право-рекурсивных нетерминалов.
Состояние cyclic означает, что Ni состоит только из правил, участвующих в рекурсии.
Состояние self означает, что i такое, при котором грамматика самоприменима.

Заметим, что i getTheTypeOfMutualRecursiveSet(Ni)self, т.к в противном случае грамматика будет самоприменима. В основе алгоритма будет рекурсивный обход грамматики. Спускаемся по грамматике до тех пор не приходим в нетерминал или символ алфавита:

  1. Символ алфавит или ε — добавляем новое правило в автомат;
  2. Нерекурсивный нетерминал — запускаемся от всех правых частей правил, который терминал порождает;
  3. Рекурсивный нетерминал — в зависимости от типа рекурсивного нетерминала, продолжаем рекурсию (будет ясно из пседокода).

Псевдокод

Q — множество состояний ДКА.

Δ — множество переходов ДКА.

T — множество допускающих состояний.

function createFA(G: grammar): Automaton              // G=N,Σ,P,S 
    Q
    Δ
    s = createState()               // createState создает некоторый объект, не принадлежащий Q, возвращает этот объект и добавляет его в Q    
    f = createState()
    F{f}
    return makeFA(s,S,f)
     
function makeFA(q0: vertex, a: char, q1: vertex): Automaton
   if a == ε or a Σ             // пришли в лист дерева разбора
        Δ=Δ{(q0,a,q1)}
        return
   if a == Xβ where X(NΣ)β(NΣ)|β|>0  
        q = createState()
        makeFA(q0,X,q1)
        makeFA(q,β,q1)
        return
    if exist Ni where aNi  
         foreach b in Ni 
            qb = createState
         if getTheTypeOfMutualRecursiveSet(Ni) == left 
            foreach C in Ni where CX1XmX1,XmNi
               makeFA(q0,X1Xm,qC)             
            foreach C,D in Ni where CDX1XmX1,XmNi
               makeFA(qD,X1Xm,qC)
               Δ=Δ{(qa,ε,q1)}
          else                      // рекурсивный нетерминал right или cyclic   
            foreach C in Ni where CX1XmX1,XmNi
               makeFA(qC,X1Xm,q1)             
            foreach C,D in Ni where CDX1XmX1,XmNi
               makeFA(qD,X1Xm,qC)
               Δ=Δ{(q0,ε,qa)} 
             return
    foreach p in P where p == aβ
       makeFA(q0,β,q1)

Аппроксимации самоприменимой грамматики

В данном разделе покажем методы апроксимации: RTN (recursive transition network) аппроксимацию и MN (Mohri and Nederhof's) аппроксимацию — самоприменимой контекстно-свободной грамматики G=N,Σ,P,S к регулярной грамматике. Для удобства будем считать, что грамматика представлена в НФХ.

Автоматы TA,TB для грамматики AaBbAcABdAeBf

RTN аппроксимация

Построим, по данной грамматике аппроксимирующий ее конечный автомат.

Конечный автомат для грамматики AaBbAcABdAeBf
  1. Для каждого нетерминала A в грамматике, создадим новый конечный автомат TA, добавим в него два состояния qA и qA.
  2. Для каждого правила грамматике (AX1Xm)P, введм новые состояния в автомат этого нетерминала qA0qAm, а также добавим новые правила перехода в Δ: (qA,ε,q0),(qA0,X1,qA1),,(qAm1,Xm,qAm),(qAm,ε,qA).
  3. Таким образом мы построили множество конечных автоматов T = {TAAN} для каждого нетерминала A. Теперь объединим все в один автомат. Объединим все состоянии автоматов из T в множество Q. Скопируем все переходы каждого автомата из T в Δ. Далее для каждого перехода вида (q,A,p),AN, вместо него добавим два новых перехода: (q,ε,qA),(qA,ε,p).

MN аппроксимация

Построим по данной самоприменимой контекстно-свободной грамматике G регулярную грамматику G.

  1. Для каждого нетерминала AN из G, добавим нетерминалы A и A в G.
  2. Для каждого правила Aα0B1α1B2α2Bmαm, где B1,,BmNαiΣ. Добавим в G нетерминалы B1Bm,B1Bm и следуюшие правила: {Aα0B1B1α1B2BmαmA.
(Если m=0, тогда добавим правило Aα0A).

В итоге Gправоконтекстная грамматика, эквивалентная конечному автомату, который задает регулярный язык.

Пример

G={AαBαBβA|βG={AαBAB|εBβA|βBBαA|ε

Исходная грамматика G генерирует язык: {(ab)nann>0}. Результирущая грамматика G генирирует регулярный язык: (ab)+a.

Сравнение двух методов

Ясно, что оба языка, генерируемых конечным автомат для первого метода и апрокисимируещей граматикой для второго метода, содержат в себе язык генерируемый исходной грамматикой. Привлекателным свойством MN аппроксимации по сравнению с RTN, то, что она можеть быть применима к большим грамматикам: для каждого нетерминала грамматике G, добавляется не более одного нового нетерминала в G и размер результирующий грамматики максимум в 2 раза больше, чем размер исходной. Так как для RTN апроксимации грамматики G=N,Σ,P,S, количество состаяний апроксимируещего автомата в худшем случаи может составлять O(|N|2), что может быть критично для аппроксимации больших грамматик. Также,еще несколько эффекивных методов аппрокимации можно найти в статьях, приведенных в ссылках.

См. также

Примечания

Источники информации