Unifikacja języków regularnych

Kapitoly: Zamykanie języków regularnych, Unifikacja, Dostęp, Różnica, Uzupełnienie, Konkatenacja, Wnioski

Mamy dwa języki regularne L1, L2. Udowodnimy, że ich związek L = L1 ∪ L2 jest również językiem regularnym.

Procedura wykorzystująca automat deterministyczny

Idea procedury

Mamy dwa języki regularne L1 i L2 i chcemy udowodnić, że ich związek L1 ∪ L2 jest również językiem regularnym. Ponieważ L1 i L2 są językami regularnymi, istnieją skończone automaty A1 i A2, które akceptują języki L1 i L2, więc L(A1) = L1 i L(A2) = L2 są poprawne. Następnie konstruujemy skończony automat A, który zaakceptuje język L1 ∪ L2, udowadniając, że język L1 ∪ L2 jest regularny.

Jak to zrobić? Mamy pod ręką skończone automaty A1 i A2, które akceptują każdy język. Możemy powiedzieć, że słowo w należy do języka L1 ∪ L2 wtedy i tylko wtedy, gdy jest akceptowane przez co najmniej jeden z automatów A1 lub A2.

Automat A może działać poprzez symulację obliczeń automatu A1 dla danych wejściowych w dla danych wejściowych w. Jeśli A1 zaakceptuje słowo w, to w również zaakceptuje A. Jeśli A1 odrzuci słowo w, to A nadal będzie próbował symulować obliczenia A2 dla wejścia w. Jeśli A2 zaakceptuje słowo w, wówczas A również zaakceptuje słowo w. W przeciwnym razie odrzuci je.

Pozostaje nam sformalizować, co to znaczy, że automat A "symuluje" obliczenia innego automatu.

Formalizacja

Mamy dwa regularne języki L1 i L2, które są akceptowane przez skończone automaty

\begin{eqnarray} A_1 &=& \left<Q_1, \Sigma_1, \delta_1, q_1, F_1\right> \A_2 &=& \left<Q_2, \Sigma_2, \delta_2, q_2, F_2\right>. \end{eqnarray}

Skonstruujemy skończony automat $A=\left<Q, \Sigma, \delta, q, F\right>$, który będzie akceptował język L = L1∪ L2. Wykorzystamy ideę symulacji dwóch automatów A1, A2. Wyobraźmy sobie więc, że mamy słowo w = w1w2… wn jako dane wejściowe, a teraz będzie on symulował postęp automatów A1 i A2 jednocześnie dla słowa w. Konfiguracja początkowa automatu A1 to <q1, w1w2… wn>, konfiguracja początkowa A2 to <q2, w1w2… wn>. Wykonamy teraz krok obliczeniowy w każdym automacie, aby uzyskać konfiguracje 1(q1, w1), w2… wn> i 2(q2, w1), w2… wn>.

Widzimy, że te konfiguracje różnią się tylko pierwszym komponentem, drugi - nieprzeczytana część słowa - jest zawsze taki sam. Tak więc nie musimy utrzymywać dwóch konfiguracji dwóch automatów podczas symulacji, ale potrzebujemy tylko jednej konfiguracji postaci <<qi, qj>, wl… wn>, gdzie qi ∈ Q1 i qj ∈ Q2. Innymi słowy, nasz skompilowany automat A będzie miał początkową konfigurację <<q1, q2>, w>. Pierwsza część pary <q1, q2> reprezentuje stan, w którym aktualnie znajduje się automat A1, a druga część reprezentuje aktualny stan automatu A2.

Możemy zatem napisać, że kompilowany automat A będzie miał zbiór stanów równy Q = Q1 × Q2. Będzie to iloczyn kartezjański stanów z poprzednich dwóch automatów. Następująca idea jest taka, że automat A będzie miał stan początkowy <q1, q2> i jeśli automat A1 przejdzie do stanu qi dla symbolu w1 i automat A2 przejdzie do stanu qj dla symbolu w1, to automat A przejdzie do stanu <qi, qj> dla symbolu w1.

Funkcję przejścia δ zapisujemy w następujący sposób (tutaj zakładamy, że aktualnie znajdujemy się w stanach qi i qj):

$$ \delta\left(\left<q_i, q_j\right>,w\right) = \left<\delta_1(q_i,w), \delta_2(q_j,w)\right> $$

Do uporządkowania pozostały już tylko drobne rzeczy. Dla alfabetu, $\Sigma = \Sigma_1 \cup \Sigma_2$. Stan początkowy jest równy q = <q1, q2>. A stany końcowe to wszystkie pary <qi, qj> takie, że albo qi ∈ F1 albo qj ∈ F2.

Ilustracja procedury

Weźmy dwa automaty. Pierwszym z nich jest automat A1, który akceptuje wszystkie słowa (w tym słowo puste), w których zera i jedynki występują naprzemiennie, tj. słowa postaci 01, 0101, 010101, ....

Drugi automat A2 akceptuje słowa zawierające co najmniej jedno zero:

Unifikacja tych języków to słowa, które albo zawierają zero, albo są postaci 01, 0101, ... Skonstruujemy teraz ostateczny automat $A=\left<Q, \Sigma, \delta, q, F\right>$, który zaakceptuje ten zunifikowany język. Najpierw pokażemy, jak będą wyglądać stany tego nowego automatu A. Będzie to iloczyn kartezjański stanów pierwszego i drugiego automatu:

$$ Q = Q_1 \times Q_2 = \left\{\left<q_0, p_0\right>, \left<q_0, p_1\right>, \left<q_1, p_0\right>, \left<q_1, p_1\right>, \left<q_2, p_0\right>, \left<q_2, p_1\right>\right\} $$

Tak na diagramie wyglądałoby sześć stanów automatu A, który akceptuje zunifikowany język L(A1) ∪ L(A2):

Nie przejmuj się, że istnieją stany, które składają się z par stanów - to tylko po to, aby dać ci lepsze wyobrażenie o tym, co faktycznie dzieje się w automacie. Stany można łatwo nazwać klasycznie q0, …, q5. Stany końcowe to te stany, które zawierają stan q0 lub p1, które są stanami końcowymi oryginalnego automatu. Stan początkowy to <p0, q0>.

Teraz musimy znaleźć wszystkie przejścia. Napiszmy taką tabelę:

$$ \begin{array}{c|c|c} &0&1\\\hline \left<q_0, p_0\right>\\ \left<q_0, p_1\right>\\ \left<q_1, p_0\right>\\ \left<q_1, p_1\right>\\ \left<q_2, p_0\right>\\ \left<q_2, p_1\right>\\ \end{array} $$

Tabelę będziemy uzupełniać na bieżąco. Pierwszą rzeczą, jaką zrobimy, jest znalezienie miejsca, do którego prowadzi przejście ze stanu <q0, p0> po wpisaniu 0. Dowiemy się, gdzie prowadzi przejście ze stanu q0 po wpisaniu 0 w automacie A1: prowadzi to do stanu q1. W automacie A2 przejście ze stanu p0 na zero prowadzi do stanu p1. W tabeli zapisujemy więc <q1, p1>:

$$ \begin{array}{c|c|c} &0&1\\\hline \left<q_0, p_0\right>&\left<q_1, p_1\right>\\ \left<q_0, p_1\right>\\ \left<q_1, p_0\right>\\ \left<q_1, p_1\right>\\ \left<q_2, p_0\right>\\ \left<q_2, p_1\right>\\ \end{array} $$

Na wejściu 1 otrzymujemy: dla automatu A1 mamy δ1(q0, 1) = q2, a dla automatu A2 mamy δ2(p0, 1) = p0. Otrzymujemy stan <q2, p0>.

$$ \begin{array}{c|c|c} &0&1\\\hline \left<q_0, p_0\right>&\left<q_1, p_1\right>&\left<q_2, p_0\right>\\ \left<q_0, p_1\right>\\ \left<q_1, p_0\right>\\ \left<q_1, p_1\right>\\ \left<q_2, p_0\right>\\ \left<q_2, p_1\right>\\ \end{array} $$

Uzupełnijmy resztę tabeli:

$$ \begin{array}{c|c|c} &0&1\\\hline \left<q_0, p_0\right>&\left<q_1, p_1\right>&\left<q_2, p_0\right>\\ \left<q_0, p_1\right>&\left<q_1, p_1\right>&\left<q_2, p_1\right>\\ \left<q_1, p_0\right>&\left<q_2, p_1\right>&\left<q_0, p_0\right>\\ \left<q_1, p_1\right>&\left<q_2, p_1\right>&\left<q_0, p_1\right>\\ \left<q_2, p_0\right>&\left<q_2,p_1\right>&\left<q_2, p_0\right>\\ \left<q_2, p_1\right>&\left<q_2,p_1\right>&\left<q_2,p_1\right>\\ \end{array} $$

I zgodnie z tą tabelą narysujemy resztę diagramu.

Możemy przetestować, czy automat działa tak, jak powinien. Spróbujmy zaakceptować słowo 0100. Automat przejdzie przez kolejne stany

$$ \left<q_0, p_0\right>, \left<q_1, p_1\right>, \left<q_0, p_1\right>, \left<q_1, p_1\right>, \left<q_2, p_1\right> $$

Ponieważ stan <q2, p1> jest stanem końcowym, automat A akceptuje słowo 0100. Jak by to działało, gdybyśmy spróbowali zaakceptować słowo 0100 za pomocą automatów A1 i A2? Automat A1 przechodziłby przez te stany sekwencyjnie:

$$ q_0, q_1, q_0, q_1, q_2 $$

Automat skończył w stanie q2, który nie jest stanem końcowym, więc automat A1 nie zaakceptowałby tego słowa. A co z automatem A2?

$$ p_0, p_1, p_1, p_1, p_1 $$

Stan p1 jest stanem końcowym, więc automat A2 zaakceptowałby słowo 0100. Zauważ, że automaty A1 i A2 znalazły się w stanach q2 i p1, co jest zgodne z automatem A znajdującym się w stanie <q2, p1>.

Procedura wykorzystująca automat niedeterministyczny

Przykład

Możemy udowodnić, że zbiór języków regularnych jest zamknięty w unii poprzez skonstruowanie niedeterministycznego automatu, co będzie znacznie prostsze.

Mamy więc dwa języki regularne L1, L2 i chcemy udowodnić, że ich unia L = L1 ∪ L2 jest również językiem regularnym. Ponieważ L1, L2 są językami regularnymi, muszą istnieć automaty A1, A2 akceptujące te języki. Są to L(A1) = L1 i L(A2) = L2. Używając tych automatów, skonstruujemy automat A akceptujący język L, czyli L(A) = L.

Załóżmy, że końcowe automaty A1 i A2 wyglądają następująco:

a

Skonstruowalibyśmy automat, który akceptuje połączenie tych dwóch języków, tworząc nowy stan początkowy i prowadząc dwa przejścia epsilon z tego stanu do oryginalnych stanów początkowych. To wszystko. Automat wyglądałby tak:

Formalizacja

Mamy dwa automaty $A_1=\left<Q_1, \Sigma, \delta_1, q_1, F_1\right>$ i $A_2=\left<Q_2, \Sigma, \delta_2, q_2, F_2\right>$. Konstruujemy automat $A=\left<Q, \Sigma, \delta, q_0, F\right>$, który będzie akceptował unię języków akceptowanych przez poprzednie automaty, tj. L(A) = L(A1)∪ L(A2). W ten sposób:

  • Q = Q1 ∪ Q2 ∪ {q0}
  • F = F1 ∪ F2

Definiujemy funkcję przejścia δ w następujący sposób:

$$ \delta(q,a)= \begin{cases} \delta_1(q,a)&\mbox{ Jeśli }&q\in Q_1\\ \delta_2(q,a)&\mbox{ Jeśli }&q\in Q_2\\ \left\{q_1, q_2\right\}&\mbox{ Jeśli }&q=q_0 \wedge a=\varepsilon\\ \emptyset&\mbox{ Jeśli }&q=q_0\wedge a\ne\varepsilon \end{cases} $$

Zasoby