Języki, automaty i obliczenia/Ćwiczenia 7: Twierdzenie Kleene'ego. Własności języków i gramatyk regularnych: Różnice pomiędzy wersjami

Z Studia Informatyczne
Przejdź do nawigacjiPrzejdź do wyszukiwania
Arek (dyskusja | edycje)
Nie podano opisu zmian
 
Rogoda (dyskusja | edycje)
(Brak różnic)

Wersja z 09:30, 23 sie 2006

Ćwiczenie

Zastosuj algorytm Automat2GReg do automatu o następującej funkcji przejść:

fs0s1s2s3as1s2s0s2bs3s2s2s2

gdzie s0 jest stanem początkowym oraz T={s0,s2}.

ROZWIĄZANIE. Pętla w liniach 7.--17. do zbioru P doda następujące produkcje: v0av1, v0bv3, v1av2, v1bv2, v2av0, v2bv2, v3av2, v3bv2. Ponieważ stanami końcowymi są s0 i s2, w pętli (w liniach 12.--14.) dodane zostaną jeszcze produkcje v01 oraz v21.

Ćwiczenie

Zbuduj automaty akceptujące języki generowane następującymi gramatykami (vi oznaczają symbole nieterminalne, a,b -- terminalne):

  1. v0av0, v0bv1, v0bv2, v1bv0, v1av2,

v2av0, v21.

  1. v0av1, v0b, v1bv0, v1av1, v11.

ROZWIĄZANIE punktu 1. Postępując zgodnie z algorytmem GReg2Automat, obliczamy funkcję przejść tworzonego automatu (w tym przypadku niedeterministycznego) o stanach s0,s1,s2 (stanem początkowym jest s0):

f(s0,a)={f0}, f(s0,b)={s1,s2}, f(s1,b)={s0,s2}, f(s2,a)=s0. Ponieważ w gramatyce istnieje produkcja v21, stan s2 oznaczamy jako końcowy.

ROZWIĄZANIE punktu 2. Ponieważ w gramatyce występuje produkcja v0b, która ma postać niezgodną z postacią produkcji będących wejściem algorytmu, przekształcamy gramatykę, usuwając tę produkcję i dodając dwie inne: v0bvk oraz vk1. Teraz możemy skonstruować automat. Jego zbiór stanów to s0,s1,sk, stanem początkowym jest s0, a funkcja przejść zdefiniowana jest następująco:

f(s0,a)=s1, f(s0,b)=sk, f(s1,a)=s1, s(s1,b)=s0.

Ponieważ w gramatyce wystąpiły produkcje v11 oraz vk1, stany v1 oraz vk są stanami końcowymi.

W wykładzie podany został algorytm Automat2WR1 budujący wyrażenie regularne na podstawie zadanego automatu. Opiszemy teraz inną metodę rozwiązania tego problemu, wykorzystującą równania na językach.

Dany niech będzie automat 𝒜=(S,A,f,s0,T). Chcemy zbudować wyrażenie regularne opisujące język akceptowany przez 𝒜. Do wyprowadzenia metody potrzebować będziemy lematu Ardena.

Lemat

(Arden) Niech RA+ i

SA* będą językami regularnymi. Wtedy równanie
X=XR+S

posiada jedyne rozwiązanie X=SR*, które jest językiem regularnym.

Zdefiniujmy najpierw Li jako język tych słów, które byłyby akceptowane przez 𝒜, gdyby stanem końcowym był stan

si

, tzn. gdyby

T={si}

:

Li={wA*: f(s0,w)=si}.

Zauważmy, że jeśli do stanu st wchodzą strzałki prowadzące ze stanów si1,si2,...,sin odpowiednio z etykietami a1,a2,...,an (i tylko takie), to

Lt=j=1nLijaj.

Obserwacja ta jest podstawą do konstrukcji metody otrzymywania wyrażenia regularnego na podstawie automatu. Będziemy budować układ równań, w którym każde równanie będzie postaci Li=jILjaj, I={i1,i2,...,in} , gdzie Li traktowane są jak niewiadome. Następnie układ taki rozwiążemy ze względu na każdą zmienną Li (tu pomocny będzie lemat Ardena). Szukanym przez nas wyrażeniem regularnym będzie wyrażenie postaci iILi, gdzie I jest zbiorem indeksów i stanów końcowych si automatu 𝒜.

Można postawić w tym momencie pytanie, czy budowany układ równań ma rozwiązanie, a jeśli tak, to czy jest ono jedyne. Okazuje się że w rozważanej przez nas sytuacji ma to miejsce, choć dowód tego faktu nie jest natychmiastowy. Fakt ten, podobnie jak lemat Ardena, podajemy tutaj bez dowodu.

Algorytm



{Automat2WR2 - buduje inną metodą wyrażenie regularne opisujące język akceptowany przez automat skończony.}

[1] Wejście: 𝒜=(S,A,f,s0,T) -- automat akceptujący język L.

Wyjście: r -- wyrażenie regularne opisujące język L.

for each sS

for each tS

for each Parser nie mógł rozpoznać (błąd składni): {\displaystyle \displaystyle a \in A\displaystyle L_s \leftarrow "";\displaystyle \triangleright} wyrażenie puste if f(t,a)=s

if Parser nie mógł rozpoznać (błąd składni): {\displaystyle \displaystyle L_s=""\displaystyle L_s \leftarrow L_ta} ; podstawiamy wyrażenie regularne else LsLs+Lta; podstawiamy wyrażenie regularne endif endif

endfor

endfor

if s=s0 and sTLsLs+1; podstawiamy wyrażenie regularne

endif

endfor

rozwiąż {Li=tSLt}i=0,...,|S|1;

rsiTLi;

return r;


Funkcja rozwiąż w algorytmie Automat2Wr2 rozwiązuje układ równań (mający na podstawie wcześniejszych uwag jednoznaczne rozwiązania), zwraca obliczone języki Li, i=0,...,|S|1.

Rozwiązanie można wykonać metodą rugowania, przechodząc od Ln do L1. Równanie Li=tSLt rozwiązujemy, korzystając ze wzoru w lemacie Ardena (rolę X w lemacie odgrywa Li) i podstawiamy do pozostałych równań (tzn. równań dla i=0,,i1). Mając już wyliczone L0, wyliczamy kolejne Li idąc od 1 do |S|1. Dla lepszego zrozumienia metody przedstawiamy następujący przykład.

Przykład

Dany niech będzie automat pokazany na rysunku Uzupelnic ja-lekcja8-c-rys1| (pominęliśmy tu dla uproszczenia jedną strzałkę wychodzącą ze stanu s2 w celu uniknięcia zwiększenia liczby stanów, gdyż chcąc formalnie narysować automat deterministyczny, musielibyśmy dodać stan s3 i zdefiniować f(s2,a)=s3, f(s3,a)=f(s3,b)=s3, ale widać, że wcale nie trzeba wtedy obliczać języka L3, gdyż z tego stanu nie da się już wyjść - jest to tzw. sink state).

RYSUNEK ja-lekjca8-c-rys1

Ułóżmy równania do naszego układu równań. Mamy:

{L0=L0b+L2b+1L1=L0a+L1aL2=L1b{L0=L0b+L1bb+1L1=L0a+L1aL0=L0b+L0aa*bb*+1.

Mamy więc L0=L0(b+a+bb)+1. Korzystając z lematu Ardena, otrzymujemy L0=1(b+a+bb)*=(b+a+bb)*. Podstawiając obliczone L0 do równania i obliczając pozostałe Li, otrzymujemy ostatecznie:

{L0=(b+a+bb)*L1=(b+a+bb)*a+L2=(b+a+bb)*a+b.

Ponieważ T={s0,s1,s2}, rozwiązaniem jest:

w=L0+L1+L2=(b+a+bb)*(1+a+(1+b)).

Ćwiczenie

Niech dany będzie automat 𝒜(S={s0,s1,s2,s3},A={a,b},f,s0,T={s0}) o następującej funkcji przejść:

fs0s1s2s3as1s2s0s3bs3s2s2s3

Wykorzystując algorytm Automat2WR2, wyznacz wyrażenie regularne odpowiadające językowi akceptowanemu przez 𝒜.

ROZWIĄZANIE. Po pierwsze zauważmy, że w obliczeniach nie musimy uwzględniać stanu s3 ani języka L3 stowarzyszonego z tym stanem. Układ równań będzie więc posiadał 3 równania o 3 niewiadomych L0, L1 oraz L2:

{L0=L2a+1L1=L0aL2=L1(a+b)+L2b

W równaniu drugim zamieniamy L0 na L2a+1 i otrzymujemy

{L1=(L2a+1)a=L2a2+aL2=L1(a+b)+L2b.

Teraz L1 w równaniu drugim zastępujemy prawą stroną równania

pierwszego:

L2=L1(a+b)+L2b=(L2a2+a)(a+b)+L2b=L2(a3+a2b+b)+a2+ab.

Korzystamy z lematu Ardena i otrzymujemy L2=(a2+ab)(a3+a2b+b)*. Podstawiamy to do równania L0=L2a+1 i otrzymujemy ostatecznie:

L0=(a2+ab)(a3+a2b+b)*a+1=(a2+ab)(a2(a+b)+b)*a+1.

Można pokazać, że wyrażenie to jest równoważne następującemu:

L0=(a(a+b)b*a)*.

Ćwiczenie

Dane niech będą automaty: nA-stanowy 𝒜 i nB-stanowy , oba nad alfabetem A i akceptujące odpowiednio języki L(𝒜) i L(). Pokaż, że problem stwierdzenia, czy dla dowolnego wA* zachodzi wL(𝒜)L(), jest rozstrzygalny:

  1. poprzez skonstruowanie niedeterministycznego automatu posiadającego O(nA+nB) stanów,
  2. poprzez skonstruowanie deterministycznego automatu nAnB-stanowego.

ROZWIĄZANIE punktu 1. Niech 𝒜=(SA,A,fA,sA0,TA) oraz =(SB,A,fB,sB0,TB) będą zadanymi automatami. Konstruujemy automat 𝒞=(S,A,f,s0,T) taki, że S=SASB{sB0}, s0=sA0, T=TB, gdy sB0∉TB, T=TBTA, gdy sB0TB, a funkcja przejść f jest zdefiniowana następująco:

Parser nie mógł rozpoznać (nieznana funkcja „\aligned”): {\displaystyle \displaystyle \aligned \forall s \in S_A, a \in A\ f(s,a) &=f_A(s,a) \\ \forall s \in S_B \backslash \{s_B^0\}, a \in A\ f(s,a) &= f_B(s,a) \\ \forall s \in T_A, a \in A\ f(s,a) &= f(s_B^0,a). \endaligned}

Zbiór stanów końcowych automatu 𝒜 staje się więc zbiorem stanów początkowych dla automatu , przy czym, jeśli sB0TB, to każdy ze stanów TA jest równocześnie stanem końcowym w automacie 𝒞. Zauważ, że:

wL(𝒜)L()wwL(𝒞)f(s0,w)TA=.

Oba warunki występujące po prawej stronie równoważności są algorytmicznie weryfikowalne i da się je sprawdzić w czasie O(|w|). Konstrukcja automatu 𝒞 w oczywisty sposób również jest algorytmizowalna i da się ją wykonać w czasie O(|A|(nA+nB)). Ponieważ |S|=nA+nB1, więc 𝒞 posiada O(nA+nB) stanów.

ROZWIĄZANIE punktu 2. Skorzystaj z konstrukcji z ćwiczenia Uzupelnic ja-lekcja7-c-cw1.1|

Ćwiczenie

Skonstruuj algorytm (oraz określ jego złożoność) dla następującego problemu (tym samym dowodząc jego rozstrzygalności):

Dany jest automat 𝒜=(S,A,f,s0,T). Czy L(𝒜)=?

ROZWIĄZANIE. Bez straty ogólności możemy założyć, że automat jest deterministyczny. W algorytmie wykorzystamy procedurę Zaznacz przedstawioną poniżej.

Algorytm



{PustośćJęzyka -- sprawdza, czy język akceptowany przez zadany automat jest pusty.}

[1] Wejście: 𝒜=(S,A,f,s0,T) -- deterministyczny automat akceptujący język L.

Wyjście: Odpowiedź true (tak) lub false (nie).

Zaznacz(s0);

for each sT

if zaznaczone[s]=1 return false endif

endfor

return true;


Algorytm



[1] procedure Zaznacz(sS)

zaznaczone[s]1;

for each aA

if zaznaczone[f(s,a)]1 Zaznacz(f(s,a)); endif

endfor

end procedure


Algorytm wykonuje przeszukanie automatu metodą DFS. Jego złożoność jest więc O(|A||S|) - liniowa ze względu na ilość stanów automatu. Złożoność pamięciowa także wynosi O(|A||S|).

ZADANIA DOMOWE

Ćwiczenie

Zastosuj algorytm Automat2GReg do automatu o następującej funkcji przejść:

fs0s1s2s3as1s3s3s3bs2s2s0s0

gdzie s0 jest stanem początkowym oraz T={s1}.

Ćwiczenie

Zbuduj automaty akceptujące języki generowane następującymi gramatykami (vi oznaczają symbole nieterminalne, a,b -- terminalne):

  1. v0av1, v0bv2, v0bv0, v1bv1, v1av0,

v2bv0, v2bv2, v21.

  1. v0bv2, v0b, v1bv0, v1av1, v11, v2av1.

Ćwiczenie

Zbuduj automaty (z pustymi przejściami) akceptujące poniższe języki:

  1. b((a+b)*+a),
  2. (a+b)*(a*b*),
  3. a(b*a*)*+1.

WSKAZÓWKA. Zastosuj algorytm WR2Automat.

Ćwiczenie

Niech dany będzie automat 𝒜(S={s0,s1,s2,s3},A={a,b},f,s0,T={s0}) o następującej funkcji przejść:

fs0s1s2s3as1s2s0s2bs3s2s2s2

Wykorzystując algorytm Automat2WR2, wyznacz wyrażenie regularne odpowiadające językowi akceptowanemu przez 𝒜.

Ćwiczenie

Skonstruuj algorytmy dla następujących problemów rozstrzygalnych:

  1. Równoważność dowolnych automatyów 𝒜 i .
  2. Nieskończoność języka L(𝒜) dla dowolnego automatu 𝒜.

WSKAZÓWKA do punktu 1. Metoda pierwsza: istnieje dokładnie jeden automat minimalny. Metoda druga: rozważ automat akceptujący przecięcie L(𝒜)L() tak jak w punkcie (2) zadania Uzupelnic cw_ai|. Jaki warunek muszą spełniać stany sSA,tSB, aby (s,t)T?

WSKAZÓWKI do punktu 2.

  1. Automat akceptuje nieskończenie wiele słów,

gdy w wyrażeniu regularnym odpowiadającym temu automatowi występuje gwiazdka Kleene'ego. Użyj metody z twierdzenia Kleene'ego (Twierdzenie 1.1, punkt 5.).

  1. Parser nie mógł rozpoznać (błąd składni): {\displaystyle \displaystyle \exists s \in S, w_1, w_2 \in A^*:\ f(s_0, w_1)=s \wedge f(s,w_2)=s...}

Ćwiczenie

fs0s1s2as1s1s2bs2s0s0

Dla automatów 𝒜=(SA,A,fA,sA0,TA) oraz =(SB,A,fB,sB0,TB) konstruujemy następujący automat 𝒞=(S,A,f,s0,T):

  • S=SA×SB,
  • s0=(sA0,sB0),
  • T={(s,t):sTA,tTB}
  • f((s,t),a)=(fA(s,a),fB(s,a)).

Zachodzi

wL(𝒜)L()wL(𝒞).