CAPITOLUL 4 AUTOMATE PUSH-DOWN 4.. DEFINIREA UNUI AUTOMAT PUSH-DOWN Am văzut în capitolul 4 că există gramatici independente de context G pentru care nu există o maşini cu stări finite care recunosc n n limbajul LG ( ). Exemplul dat a fost limbajul L= {0 n=,, K }, el se compune din n 0-uri urmaţi de n -uri. Motivul pentru care nu există o MSF care să recunoască pe L este, că orice maşină care întâlneşte un şir din acest limbaj ar trebui să memoreze câţi de 0 apar în faţa şirului, iar atunci să verifice dacă numărul de -uri, care urmează, este acelaşi. Aşadar, orice maşină care recunoaşte L va avea nevoie de o memorie suplimentară capabilă să stocheze o cantitate arbitrară de informaţii. Deoarece, prin definiţie maşinile cu stări finite au doar un număr finit de stări, ele nu pot recunoaşte limbajul L. Demonstraţia completă este dată în paragraful 3.. Vom introduce acum un nou tip de dispozitiv, care poate memora imput-urile precedente şi comportamentul anterior. Aceste dispozitive se numesc automate push-down (APD); ele au avantajul de a fi uşor implementate pe calculator. Vom constata că orice limbaj independent de context poate fi recunoscut de o astfel de maşină. Un automat push-down se compune dintr-un număr finit de stări, un dispozitiv de intrare (împreună cu un cap de citire) şi o stivă cu un pointer de stivă. Figura 4.. ilustrează o reprezentare schematică a lui. Automatul push-down funcţionează în felul următor: În orice moment dat maşina se află într-o stare Q, pointer-ul de intrare (IP input pointer sau cap de citire) punctează spre un simbol a de pe banda de intrare iar pointer-ul de stivă (SP stack pointer) punctează spre un simbol Z de pe stivă. Locaţia simbolului Z se numeşte vârful stivei (TOS top of the
stack) Locaţiile sub vârful stivei sunt populate cu simboluri de stivă admise iar cele deasupra vârfului se consideră goale. Mărimea stivei nu este limitată, dar întotdeauna finită. Banda de intrare Vârful stivei Stiva Baza stivei Figura 4.. Automat push-down. Pe baza acestor informaţii (Q, a şi Z) maşina poate efectua una sau mai multe dintre următoarele acţiuni:. Schimbă starea.. Deplasează pointer-ul de intrare cu o unitate spre dreapta. 3. Înlocuieşte simbolul Z din vârful stivei printr-un număr finite de simboluri de stivă acceptate şi poziţionează pointer-ul de stivă pe vârful stivei. 4. Se opreşte. Reamintim, că decizia care va fi luată este în exclusivitate determinată de Q, a şi Z. În acţiunea de tip 3 este permisă înlocuirea lui Z
cu şirul vid λ. Caz în care acţiunea 3 înseamnă eliminarea simbolului Z din stivă şi deplasarea pointer-ului de stivă cu o poziţie în jos. Operaţia se numeşte POP. După ce una sau mai multe dintre acţiunile 3 au avut loc, maşina se va află într-o stare nouă ˆQ, cu pointer-ul de intrare punctând spre noul simbol de intrare â iar pointer-ul de stivă la noul simbol Ẑ din vârful stivei. Întregul proces se repetă până la oprirea maşinii. Simbolurile inferioare vârfului stivei sunt salvate de la o mişcare la alta; ele formează memoria maşinii. Odată ce s-au citite simbolurile benzii de intrare, ele se pierd pointer-ul de intrare se deplasa numai la dreapta. În schimb pointer-ul de stivă se poate deplasa în sus şi în jos. Simbolurile de intrare se salvează, în momentul citirii, prin trecerea lor pe stivă. Pentru o descriere completă a acestei maşini trebuie să specificăm: configuraţia ei, deci stare iniţială, conţinutul iniţial al benzii de intrare şi conţinutul stivei. Pentru simplificare, introducem următoarele convenţii referitoare la automatele push-down: C.. În configuraţia iniţială stiva conţine un singur simbol #. Acest simbol nu poate fi niciodată eliminat din stivă (stiva nu va fi vidă); el apare o singură dată pe stivă. Locaţie lui # se numeşte baza stivei. C.. Orice şir de intrare σ se termină în partea dreaptă cu simbolul $, astfel încât σ = σ $ ; acest simbol este unic în şirul de input. Motivul introducerii acestor simboluri speciale este ca maşina să poată detecta sfârşitul input-ului şi baza stivei. Ca şi maşinile cu stări finite, automatele push-down pot fi deterministe sau nedeterministe. În cazul determinist, fiind date Q, a şi Z, este permis doar un singur rând de acţiuni; în cazul nedeterminist există
cel puţin două alternative pentru anumite situaţii. Un automat push-down are unele dintre stările sale desemnate ca stări acceptate sau stări finale. Fie acum Σ un alfabet care nu conţine simbolul $, şi fie L un limbaj peste Σ. Spunem că un automat push-down determinist P acceptă L dacă sutn adevărate următoarele: Fiind dat un şir σ, setăm maşina P în starea ei iniţială Q 0 ; introducem şirul σ $ pe banda de intrare şi pointer-ul de intrare îl plasăm pe cel mai din stânga simbol din σ $. De asemenea, punem simbolul # pe baza stivei şi fixăm pointer-ul de stivă pe el. După un număr finit de paşi maşina P se opreşte. Dacă σ este în limbaj, P se va opri într-una din stările acceptate iar pointer-ul de intrare va puncta la simbolul $ (indicând că întregul input a fost citit). Dacă nu este în limbajul L, atunci P se va opri într-o altă configuraţie, adică, fie într-o stare neacceptată fie fără a scana întregul input σ (sau amândouă). Observăm, că pentru acceptarea şirului σ, nu facem specificaţii referitoare la conţinutul stivei. Definiţia modului de acceptare a unui limbaj de către un automat push-down nedeterminist este similară cu definiţia de acceptare a maşinii cu stări finite nedeterministe. Spunem că un şir σ este în limbajul generat de un automat push-down nedeterminist P, dacă şi numai dacă, începând din configuraţia iniţială, P poate ajunge, printr-o secvenţă de mişcări legale, într-o configuraţie acceptată. Înainte de a da definiţia formală a conceptelor discutate, să considerăm un exemplu.
Stare S t i v ă Simbol de intrare Q0 0 $ A # Oprit. Schimbă starea în Q.. Pune simbolul A în vârful stivei. 3. Deplasează pointer-ul de intrare cu o poziţie la dreapta. Opri t Opri t Oprit Schimbă starea în Q 3, pointerii rămân neschimbaţi. Stare Simbol de intrare Q 0 $. Rămâne în starea Q. S. Pune simbolul A în vârful Schimbă starea în Opri t A stivei. Q ; pointerii rămân t i 3. Deplasează pointer-ul de intrare neschimbaţi. v la dreapta. Ă Opri # Oprit Oprit t
Stare Simbol de intrare Q 0 $. Schimbă starea în Q. S. Scoate A în vârful stivei. A Oprit t 3. Deplasează pointer-ul de i intrare la dreapta. v ă # Oprit Oprit Oprit Schimbă starea în Q 3, pointerii rămân neschimbaţi. Stare Q 3 : Se opreşte în toate cazurile. n n Figura 4.. Un automat push-down pentru limbajul L= {0 n= 0,,, K }.
Configuraţia iniţială Pasul Pasul Pasul 3 Pasul 4 Pasul 5 Pasul 6 Pasul 7 Configuraţia finală Figura 4.3. Mişcările unui APD la input-ul 000. Exemplu 4.. Considerăm un automat push-down care acceptă n n limbajul L= {0 n= 0,,, K }. Acest APD va avea patru stări Q 0 (= starea iniţială), Q, Q şi Q 3 (starea acceptată). Alfabetul de intrare este Σ= {0,}. Fie, în afară de #, un simbol de stivă adiţional admis A. Maşina va opera în felul următor. De fiecare dată când simbolul de intrare este 0, se
adăugat un simbol A pe stivă. Aşadar, după ce toate 0-urile au fost citite maşina ştie câţi de 0 se află în input pentru fiecare 0 din input se salvează câte un A pe stivă. Pentru fiecare simbol de întâlnit, maşina şterge câte un A. În final, când ajunge la simbolul $ de pe banda te intrare, pointer-ul de stivă va puncta spre simbolul # din baza stivei numărul de -uri este egal cu numărul de A-uri salvate. Orice deviere de la această formă indică că şirul σ nu aparţine limbajului. Descrierea exactă a mişcărilor lui P este dată in tabelul din figura 4.. Maşina se va opri în starea Q 3 cu capul de citire pe $ dacă şi numai dacă şirul de intrare σ se compune din simboluri de 0 urmate de un număr egal de simboluri de. În orice altă situaţie el se va opri într-o altă stare cu (eventual) o parte a input-ului necitită. În figura 4.3. dăm secvenţa de mişcări a acestui APD cu input-ul 000. Evident, înainte de a trece la definiţii matematice formale, avem nevoie de unele notaţii pentru a descrie configuraţia unui automat push-down în orice moment dat. Desenarea de diagrame schematice de genul celor din figura 4.3. nu este convenabilă. Aşadar, descriem configuraţia unui APD printr-un triplet: σ$, Q, γ # = xkxk+ Kxp$, Q, ZtZt KZ#
Figura 4.4. Un APD în configuraţia xx k k Kxk$, QZZ, t t K Z#. + Partea necitită a input-ului este dată prin $ = xx k k K xp$ iar capul de σ + citire punctează pe simbolul x k. Starea curentă este Q. Conţinutul stivei este dat de γ # = ZZ t t K Z#, unde Z t este vârful stivei iar # este baza stivei. O maşină în configuraţia (4.) corespunde figurii 4.4. Cu această convenţie, mişcările maşinii din figura 4.3., por fi descrise astfel: 000$, Q,# 00$, Q, A# 0$, Q, AA# 0 $, Q, AAA# $, Q, AAA# $, Q, AA# $, Q, A# $, Q,# $, Q,# oprit 3 Vom nota pointer-ul de intrare cu IP (input pointer) iar pointer-ul de stivă cu SP (stack pointer). Definiţia 4.. Un automat push-down (APD) se compune din următoarele şase obiecte:. O mulţime nevidă Σ de simboluri de intrare admise. Această mulţime se numeşte alfabet de intrare şi nu conţine simbolul $.. O mulţime nevidă Γ de simboluri de stivă admise. Această mulţime este numită alfabetul stivei şi nu conţine simbolul #. 3. O mulţime finită de stări Q = { Q0, Q, K, Q n }. 4. O stare dedicată, notată Q 0 ( Q ), numită stare iniţială. 5. O mulţime nevidă F de stări, numite stări finale sau acceptate. 6. O funcţie de tranziţie δ ( Q, x, Z). Argumentele lui δ sunt: x un simbol din Σ sau $; Q o stare din Q, Z un simbol din Γ sau #.
Valorile lui δ ( Q, x, Z) sunt mulţimi finite (sau vide) de triplete de forma ( N, Qˆ, γ ) unde a) N este unul dintre simbolurile sau (stă sau se mişcă). b) ˆQ este o stare din Q. c) γ este un şir de caractere (eventual vid) din Γ, care poate fi urmat de simbolul #. În final avem: δ * : Q Σ ( {$}) Γ ( {#}) B({, } Q Γ { {# + λ}}) unde B ( E) desemnează mulţimea tuturor submulţimilor finite a unei * mulţimi E, şi D mulţimea tuturor şirurilor posibile de simboluri din D. Aşadar, folosind notaţia pentru expresii regulare, Γ * {# + λ} este mulţimea de şiruri de simboluri din Γ urmate fie de şirul vid λ fie de simbolul #. În plus, funcţia δ satisface următoarele condiţii: C. Pentru orice Q Q şi orice Z Γ, δ ( Q, $, Z) trebuie să conţină doar triplete de forma (, Qˆ, γ ). Aceasta corespunde cerinţei ca pointer-ul de intrare să nu poată trece de simbolul $. C. Pentru orice x Σ şi orice Q Q, δ ( Q, x, #) conţine doar triplete de forma ( N, Qˆ, γ #), unde γ este un şir de elemente din Γ. Aceasta corespunde cerenţei că simbolul # nu poate fi eliminat din baza stivei: dacă înlocuim # prin γ #, simbolul stivei # rămâne în baza stivei. C3. Pentru orice x Σ, Q Q şi Z Γ ( Z #), δ ( Q, x, Z) conţine doar triplete de forma (, ˆ * N Q, γ ), unde γ este un şir din Γ care nu
se termină cu #. Aceasta corespunde cerinţei ca # să apară numai la baza stivei. Un automat push-down cu Σ, Γ, Q, Q 0, F şi δ de genul celui de mai sus se va nota P= { Σ, Γ, Q, Q0, F, δ}. Funcţia δ din definiţia anterioară descrie mişcările posibile ale maşinii. Argumentele x, Q şi Z din δ reprezintă input-ul curent, starea curentă şi conţinutul vârfului stivei. Maşina definită prin definiţia 4.. este nedeterministă, deci valoarea lui δ este mulţimea mişcărilor posibile dintr-o configuraţie dată (pot fi mai multe). Fiecare astfel de mişcare posibilă este descrisă de un triplet ( N, Qˆ, γ ). Dacă N = atunci pointer-ul de intrare nu se schimbă la mişcarea următoarea va fi citit acelaşi simbol de intrare; dacă N = atunci pointer-ul de intrare se va muta cu o poziţie la dreapta. ˆQ desemnează următoarea mişcare a maşinii. γ este înţeles astfel: Dacă ( N, Qˆ, γ ) este un triplet din δ( Q, x, γ ), atunci simbolul Z din vârful stivei este înlocuit cu şirul γ. (Cel mai din stânga caracter din γ va fi noul vârf al stivei.) Condiţia C precizează că pointer-ul de intrare nu va trece de simbolul $. Condiţia C asigură că # nu va fi eliminat niciodată din baza stivei iar C3 garantează că # nu apare în altă locaţie de pe stivă decât în bază. Maşina se opreşte dacă δ ( Q, x, Z) = mulţimea vidă. Un automat push-down se numeşte determinist dacă, pentru fiecare x, Q şi Z, valoarea lui δ ( Q, x, Z) este mulţimea vidă sau conţine doar un singur triplet. Descriem în continuare, formal, mişcările unui automat push-down. Definiţia 4. Fie P un automat push-down. O configuraţie a lui P este tripletul σ$, Q, γ #, unde σ este un şir de caractere din Σ iar γ este
un şir de caractere din Γ. (Amândouă pot fi vide.) Fie xyk$, Q, ZW K# o configuraţie pentru P şi fie ( N, Qˆ, γ ) un triplet din δ ( Q, x, Z). Dacă N = atunci spunem că xyk$, Qˆ, γw K # este următoarea configuraţie legală, iar xyk$, Q, ZW K# xyk$, Qˆ, γw K# şi o numim mişcare legală. Dacă N = atunci spunem că configuraţie legală şi yk$, Qˆ, γwk # este următoarea xyk$, Q, ZW K# yk$, Qˆ, γw K# o numim de asemenea mişcare legală. Dacă δ ( Q, x, Z) =, vom spune că P se opreşte. Dacă C = σ$, Q, γ # şi C ˆ ˆ ˆ = σ$, Q, γ # sunt două configuraţii astfel încât este posibilă trecerea din C în C, printr-o secvenţă legală de mişcări, atunci notăm aceasta * σ$, Q, γ # ˆ σ$, Qˆ, ˆ γ #. O mişcare specială şi cu nume propriu pentru un APD este plasarea unui simbol A, în vârful stivei fără a elimina ceva din stivă. Funcţiile de tranziţie pentru astfel de mişcări sunt de forma δ ( Q, x, Z) = ( N, Qˆ, AZ) : Simbolul Z din vârful stivei a fost şters şi înlocuit cu şirul AZ; efectul
obţinut este plasarea lui A în vârful stivei. Această mişcare se numeşte push spunem că plasăm A în vârful stivei printr-o operaţie de push. Exemplu 4.. Considerăm APD-ul discutat anterior, care n n recunoaşte limbajul L= {0 n= 0,, K }. Descrierea formală este următoarea: Mulţimea Σ= {0,}, alfabetul stivei este Γ= { A}, mulţimea stărilor Q este { Q0, Q, Q, Q 3} şi mulţimea de stări acceptate este F = { Q3}. Starea iniţială este Q 0 iar funcţia δ este dată prin: Pentru starea Q 0 : δ( Q, 0, A) = δ( Q,, A) = δ( Q, $, A) = 0 0 0 δ ( Q, 0, #) = (, Q, A#) 0 δ ( Q,, #) = 0 δ ( Q, $, #) = (, Q, #) 0 3 Pentru starea Q : δ ( Q, 0, A) = (, Q, AA) δ ( Q,, A) = (, Q, A) δ( Q, 0, #) = δ( Q,, #) = δ( Q, $, #) = Pentru starea Q : δ( Q, 0, A) = δ( Q, $, A) = δ( Q,, A) = (, Q, λ) δ( Q, 0, #) = δ( Q,, #) = δ ( Q, $, #) = (, Q, #) 3
Pentru starea Q 3 : δ ( Q3, x, Z) = pentru toate valorile lui x Σ {$} şi Z Γ {#}. În exemplul de mai sus, pentru fiecare x, Q şi Z valoarea lui δ ( Q, x, Z) este un singur triplet sau mulţimea vidă. Aşadar, comportamentul maşinii este complet determinat la fiecare configuraţie. Aceste de maşini se numesc deterministe. Definiţia 4.3. Fie P= { Σ, Γ, Q, Q0, F, δ} un automat push-down. Dacă pentru fiecare x Σ {$}, Q Q şi Z Γ {#} valoarea lui δ ( Q, x, Z) este un singur triplet sau mulţimea vidă, spunem că P este determinist. Dacă P nu este determinist, spunem că P este nedeterminist. Fiind dat un automat push-down P, definiţia limbajului LP ( ) generat (recunoscut sau acceptat) de P este identică cu acea dată pentru maşinile cu stări finite (definiţia..). Un şir σ aparţine limbajului LP ( ) dacă şi numai dacă, P pornit în configuraţia iniţială σ $, Q0, #, trece printr-o secvenţă de mişcări legale şi se opreşte în configuraţia $, Q, γ, Q Q. Se cere ca întregul şir σ să fie citit iar ultima stare să fie una acceptată, dar nu se cere, cum o fac unii, ca stiva să fie vidă. Formal avem următoarele. Definiţia 4.4. Fie P= { Σ, Γ, Q, Q0, F, δ} un automat push-down. Limbajul LP ( ) generat (recunoscut sau acceptat) de P este definit prin * * ( ) = { σ σ Σ, σ$, 0, # $,, γ } LP Q Q Z
unde Q F şi δ ( Q, $, Z) =. * Exemplu 4.3. Fie Σ un alfabet; pentru fiecare şir σ Σ fie inversul lui σ. Adică, dacă Un palindrom peste Σ este un şir de forma σ R R R σ = abcd, σ = dcba, dacă σ = aab, σ = baa. R * σσ unde σ Σ. Exemple de palindroame sunt abcddcba ( σ = abcd ) şi aabbaa ( σ = aab ). Observăm că această definiţie este diferită de cea obişnuită un cuvânt care se citeşte la fel în ambele sensuri. De exemplu, conform definirii noastre, σ = abcba nu este un palindrom. Arătăm în continuare cum se construieşte un automat push-down P care recunoaşte limbajul de palindroame peste un alfabet dat Σ. În lini mari, maşina P va citi şirul de intrare şi va insera acest input, caracter cu caracter, pe stivă. La un moment dat, P ghiceşte că a ajuns la mijlocul şirului iar atunci compară conţinutul stivei, din vârf până în bază, cu restul input-ului. Dacă alegerea a fost bună şi input-ul este un palindrom, pointer-ul de intrare ajunge la simbolul $ în acelaşi timp când pointer-ul stivei ajunge la baza stivei marcată cu #. Definiţia exactă a lui P este următoarea:. Σ este o mulţime nevidă, finită dată.. Γ=Σ (alfabetul stivei şi alfabetul de intrare este aceleaşi). 3. Q0 Q Q Q3 Q = {,,, }. 4. Starea acceptată este Q 3 ( F = { Q3} ). 5. Funcţia de tranziţie este definită ca: i. 0 δ ( Q, x, #) = {(, Q, x#)} pentru toţi x Σ. ii. δ ( Q0, $, #) = {(, Q3, #)} iii. δ ( Q, x, Z) = {(, Q, xz), (, Q, Z)} pentru toţi x Σ şi Z Γ. iv. δ( Q, x, x) = {(, Q, λ)} pentru toţi x Σ.
v. Q Q3 δ (, $, #) = {(,, #)}. vi. δ ( Q, x, Z) = în toate cazurile nedefinite de i v. Mişcările se explică după cum urmează: i. P porneşte în starea iniţială Q 0 şi începe să insereze caracterele de intrare în vârful stivei. Majoritatea inserărilor sunt făcute în timpul stării Q. ii. Asigură că şirul vid λ este în LP ( ). iii. iv. P continuă să insereze simbolul de intrare pe stivă sau ghiceşte dacă mijlocul cuvântului a fost ajuns şi este timpul să compare conţinutul stivei cu restul input-ului. Aceasta este partea operaţiei în care maşina are un comportament nedeterminist. Simbolurile stivei sunt comparate, unul câte unul, cu restul input-ului. v. Cuvântul este găsit palindrom, deci P trece în starea acceptată. Observăm că din cauza lui iii, APD-ul este nedeterminist. Considerăm acum, ca exemplu, comportamentul lui P la input-ul σ = abccba : abccba$, Q, # bccba$, Q, a # ccba$, Q, ba # 0 cba, Q, cba # cba$, Q, cba # ba$, Q, ba # a$, Q, a# $, Q, # $, Q, # oprit 3 (4.) Subliniem faptul că maşina ar fi putut să ghicească greşite. De exemplu, ar fi putut să aştepte prea mult mijlocul şirului:
abccba$, Q, # bccba, Q, a # ccba$, Q, ba # 0 cba$, Q, cba # ba$, Q, ccba # ba$, Q, ccba # oprit Aici maşina se opreşte, într-o configuraţie neacceptată, deoarece δ ( Q, b, c) =. Aceasta însă nu însemnă că σ nu este în LP ( ); criteriul este să existe o posibilitate pentru P de a citi σ şi să se oprească într-o stare acceptată. Că există este demonstrat în (4.). Evident că dacă automatele push-down sunt folosite pentru recunoaşterea limbajelor de programare, acest tip de comportament nu poate fi admis (sau cel puţin să fie strict controlat) cu alte cuvinte, APD-ul să fie determinist. În cazul maşinilor cu stări finite maşinile deterministe şi nedeterministe se dovedesc a fi echivalente: Dat fiind o MSF nedeterministă M, există o MSF M astfel încât LM ( ) = LM ( ). Aceasta însă nu este adevărat pentru automatele push-down. De fapt, limbajul palindroamelor din exemplul 4.3. nu poate fi generată de orice APD determinist. * Teorema 4.. Fie L limbajul L = { σσ R σ {0,}} mulţimea tuturor polindroamelor compuse din simbolurile 0 şi. Nu există un automat push-down determinist P astfel încât L= L( P). Demonstraţie. Demonstraţia completă a acestei teoreme nu face parte din scopul acestei lucrări. Vom arăta doar că L nu poate fi recunoscut de un APD determinist care satisface următoarele trei condiţii:. Maşina se opreşte în orice stare dacă input-ul este gol, adică, δ ( Q, $, Z) = pentru toate stările Q şi simbolurile de stivă Z. Cu alte
cuvinte, după ce input-ul a fost citit în întregime, maşina nu poate face nici o mişcare.. Maşina acceptă şiruri doar cu stiva vidă. Acesta înseamnă că un şir este acceptat dacă şi numai dacă maşina se opreşte într-o stare finală iar stiva conţine numai simbolul #. 3. Maşina are doar o singură stare acceptată. Presupunând că o maşină deterministă P= { Σ, Γ, Q, Q0, F, δ} serveşte drept acceptor pentru limbajul L din ipoteză, şi mai presupunem că L satisface condiţiile 3 de mai sus. Din ipoteză, F are doar o stare acceptată, ˆQ * R R. Fie σ şi τ două şiruri din {0,} astfel încât σσ ττ să nu R fie în L, de exemplu σ = 0 şi τ =. Maşina P acceptă şirul σσ, R R σσ σσ, R R R R R ττ şi ττ ττ dar nu şi σσ ττ. După citirea lui R σσ maşina trebuie să se afle în starea acceptată ˆQ iar stiva trebuie să fie vidă (adică R R să conţină numai #). Aşadar, la input-ul σσ σσ maşina trece prin următoarea secvenţă de configuraţii: * * R R R ˆ 0 σσ σσ σσ $, Q, #, Q, # $, Qˆ, # (4.) Ca urmare, dacă P este pornit în starea ˆQ cu input-ul R σσ, se va opri în configuraţia acceptată. În acelaşi mod, la input-ul ττ R ττ R maşina va executa secvenţa de mişcări: * * R R R ˆ 0 ττ ττ ττ $, Q, #, Q, # $, Qˆ, # (4.3)
Starea ˆQ din mijlocul configuraţilor (4.) şi (4.3) este aceeaşi deoarece este stare acceptată, iar noi am presupus că există doar una singură. Dar R R acum să vedem ce se întâmplă când şirul σσ ττ este trimis lui P. După citirea primei părţi a şirului, R σσ, maşina se va afla în starea ˆQ şi stiva va conţine doar #. (Din teorema (4..).) În acest moment, P se află în configuraţia ττ R, Qˆ, # şi conform cu (4.3) el va trece în $, Q ˆ, #, R R adică, acceptă σσ ττ, despre care am presupus că nu este în limbaj. Deci L L( P). Pentru o demonstraţie completă, trebuie arătat că dat fiind un APD determinist P există alt APD determinist ˆP astfel încât să aibă 3 de mai sus. Pentru detalii vezi [3]. Q.E.D. LP ( ) = LP ( ˆ) şi ˆP 4.. LEGĂTURI CU GRAMATICILE INDEPENDENTE DE CONTEXT Abordăm în continuare o discuţie detaliată a rolului jucat de automatele push-down în recunoaşterea limbajelor independente de context. În capitolele şi 3 am studiat conceptul de maşină cu stări finite. Aceste maşini au fost uşor de implementat; cu toate acestea, ele puteau să recunoască doar limbaje simple limbaje regulare. Ne-a fost uşor să dăm un exemplu de limbaj nerecunoscut de nici una dintre aceste maşini. Automatele push-down sunt similare maşinilor cu stări finite exceptând un punct esenţial APD-urile au o memorie nelimitată sub forma de stivă. Este surprinzător faptul cum această mică facilitate face dintr-un APD un instrument atât de puternic, capabil să genereze limbaje independente de context arbitrare. De fapt, limbajele independente de context sunt chiar acele limbaje pentru care există un APD care le recunoaşte.
Teorema 4.. Fie L un limbaj, adică, o mulţime de şiruri peste un alfabet Σ. Atunci L este generat de un automat push-down dacă şi numai dacă L are o gramatică independentă de context. Demonstraţie. O demonstraţie completă a acestei teoreme nu este prea dificilă, dar oarecum lungă. Din acest motiv vom prezenta doar o schiţă într-o singură direcţie: Dată fiind o gramatică independentă de context G = { Σ, N, S, P}, să arătăm cum se construieşte un APD P astfel încât LP ( ) = L. Pentru demonstraţia completă şi detalii suplimentare, cititorul este invitat să consulte [3] sau [7]. Reamintim că o gramatică G este independentă de context dacă toate producţiile ei sunt de forma X γ, unde X este un neterminal iar γ * este un şir, eventuala vid, de terminale sau neterminale ( γ Σ { N} ). APD-ul de construit P va simula în esenţă derivarea cea mai din stânga pentru orice şir din LG ( ). Alfabetul de intrare pentru P va fi Σ, identic cu alfabetul lui G iar alfabetul stivei Γ pentru P va fi simbolurile speciale $ şi # nu aparţin lui Σ N Σ N. Presupunem că. Maşina va avea trei stări: Q 0 (starea iniţială), Q şi Q (starea acceptată). Majoritatea timpului maşina va rămâne în Q. P acţionează în felul următor: Fie σ un şir din LG ( ) şi fie S τ τ L σ derivarea cea mai din stânga a lui σ tranziţia între formele propoziţionale τi = τ i + fiind rezultatul înlocuirii neterminalului cel mai din stânga X a formei propoziţionale τ i, cu partea dreaptă a producţiei X tranziţie. Presupunem că primele mişcări sunt γ. Maşina va face o mişcare la fiecare astfel de S τ τ L x x Kx Aτ σ k *
unde x, x, K, x k sunt terminale iar următoarea producţia din derivare este A α. Ca urmare şirul σ este de forma σ = xx Kxkyy K yn, deoarece orice altă aplicare a unei reguli de producţie nu va afecta xx K x. În acest moment maşina P se va afla în configuraţia k yy K y $,, # n Q Aτ. (Pointer-ul de intrare punctează la y, primul simbol al părţii lui σ care urmează a fi derivat şi pointer-ul de stivă punctează pe A, următorul neterminal de înlocuit în derivarea ceea mai la stânga a lui σ ). Maşina va înlocui acum vârful stivei, adică, simbolul A, cu şirul α partea dreaptă a producţie A α. Dacă α începe cu un neterminal A ', avem aceeaşi situaţie, deci înlocuim A ' cu α ' partea dreaptă a producţiei A' α '. Repetăm procedura până când apare un terminal în vârful stivei. Aşadar, putem presupune că α începe cu un terminal. Acest terminal trebuie să fie y, altminteri A α nu poate fi producţia corect aleasă. Prin urmare, după ce A este înlocuit cu α, pointer-ul de intrare şi pointer-ul de stivă punctează amândouă spre acelaşi simbol y. În continuare eliminăm pe y din stivă şi deplasăm pointer-ul de intrare la dreapta, iar atunci repetăm procedeul. Evident că continuând în acest mod, maşina P va trece din configuraţia σ $, Q, # în $, Q, #, punct în care schimbăm starea în Q şi ne oprim. Definiţia completă a funcţiei de tranziţie este următoarea:. 0 δ ( Q, x, #) = {(, Q, S#)} pentru toate terminalele x. Aceasta are ca efect plasarea simbolului de start în vârful stivei şi trecerea în starea activă Q.. 0 δ ( Q, $, #) = {(, Q, S#)}. Această tranziţie particulară este necesară pentru cazul în care şirul vid λ este în limbajul LG ( ).
Simbolul de start S va fi plasat pe stivă; dacă λ LG ( ) eventual el va dispare. 3. δ Q x x Q (,, ) = {(,, λ)} pentru toate terminalele x. Pointer-ul de intrare şi pointer-ul de stivă punctează amândouă spre acelaşi simbol x. Se elimină x de pe stivă şi se citeşte următorul simbol. 4. Dacă x este terminal sau simbolul $, şi dacă A este un neterminal, atunci δ( Q, x, A) = {(, Q, α ), (, Q, α ), K, (, Q, α )} p unde A α α K αp sunt toate producţiile având A în partea stângă. Această regulă se aplică atunci când un neterminal se află în vârful stivei, şi maşina alege care dintre producţii va fi în continuare aplicată pentru a se potrivi cu simbolul curent de intrare x (precum şi restul input-ului). 5. Q Q δ (, $, #) = {(,, #)}. Întregul input a fost citit, stiva este vidă, deci maşina trece în starea acceptată. 6. δ ( Q, x, Z) = pentru restul de x, Q şi Z. Maşina P astfel construită este evident nedeterministă: Când regula 4 de mai sus este pe punctul de a fi aplicată, P alege producţia corectă care se va folosi. Este limpede, că dacă există o secvenţă de alegeri corecte (adică, dacă input-ul σ este în limbaj), P va accepta input-ul. De asemenea este adevărat că dacă P poate trece din configuraţia iniţială în ceea acceptată, atunci σ este derivabil în gramatica G. Demonstraţia completă a acestor consideraţii poate fi uşor construită, şi se bazează pe inducţia după lungimea şirului σ. Q.E.D.
Configuraţia lui M 0 Forma propoziţională corespunzătoare, vârful stivei este subliniat Comentarii a*( a+ a)$, Q, # Configuraţia iniţială a*( a+ a)$, Q, E# E E plasat în vârful stivei a*( a+ a)$, Q, T # T aplicat E T a*( a+ a)$, Q, T* F# T* F aplicat T T* F a*( a+ a)$, Q, F* F# F* F aplicat T F a*( a+ a)$, Q, a* F# a* F aplicat F a *( a+ a)$, Q, * F# a* F a eliminat din vârful stivei ( a+ a)$, Q, F# a* F * eliminat din vârful stivei ( a+ a)$, Q, ( E) # a*( E) aplicat F ( E) a+ a)$, Q, E)# a*( E ) ( eliminat din vârful stivei a+ a)$, Q, E+ T)# a*( E+ T) aplicat E E+ T a+ a)$, Q, T + T)# a*( T + T) aplicat E T a+ a)$, Q, F + T)# a*( F + T) aplicat T F a+ a)$, Q, a+ T)# a*( a+ T) aplicat F a + a)$, Q, + T)# a*( a+ T) a eliminat din vârful stivei a)$, Q, T )# a*( a+ T) + eliminat din vârful stivei
a)$, Q, F )# a*( a+ F) aplicat T F a)$, Q, a )# a*( a+ a) aplicat F a )$, Q, )# a*( a+ a) a eliminat din vârful stivei $, Q, # a*( a+ a) ) eliminat din vârful stivei $, Q, # oprit şi acceptat Configuraţia finală Figura 4.5. Mişcări ale uni APD. Exemplu 4.4. Fie gramatica expresiilor algebrice: E E+ T T T T* F F F ( E) a Regulile de tranziţie pentru automatul push-down corespunzător sunt următoarele: δ ( Q, x, #) = {(, Q, E#)} pentru toţi x Σ= { a, +,*,(,)} 0 δ ( Q, $, #) = {(, Q, E#)} 0 δ( Q, x, x) = {(, Q, λ)} pentru toţi x Σ δ ( Q, x, E) = {(, Q, E+ T), (, Q, T)} pentru toţi x Σ {$} δ ( Q, x, T) = {(, Q, T* F), (, Q, F)} pentru toţi x Σ {$} δ ( Q, x, F) = {(, Q, ( E)), (, Q, a)} pentru toţi x Σ {$} δ ( Q, $, #) = {(, Q, #)} Secvenţa de mişcări a APD-ului la input-ul a*( a+ a) este arătată în figura 4.5. Reamintim de natura nedeterministă a acestui APD. De exemplu, în
configuraţia a)$, Q, F )# (marcată cu în figura 4.5.), M alege valoarea corectă pentru δ ( Q, a, F), adică tripletul (, Q, a). Dacă ar alege cealaltă posibilitate (, Q, ( E)), APD-ul s-ar opri imediat într-o configuraţie neacceptată: a)$, Q, F)# a)$, Q, ( E))# oprit. Exemplu 4.5. În acest exemplu prezentăm construcţia şi funcţionarea unui APD plecând de la o gramatică G: S aba B bab C A bs b B as C aa λ Regulile de tranziţie rezultate sunt: δ ( Q, x, #) = {(, Q, S#)} pentru toţi x Σ= {,} a b 0 δ ( Q, $, #) = {(, Q, S#)} 0 δ( Q, x, x) = {(, Q, λ)} pentru toţi x Σ δ ( Q, x, S) = {(, Q, aba#), (, Q, B), (, Q, bab), (, Q, C)} pentru toţi x Σ {$} δ ( Q, x, A) = {(, Q, bs), (, Q, b)} pentru toţi x Σ {$} δ ( Q, x, B) = {(, Q, as)} pentru toţi x Σ {$} δ( Q, x, C) = {(, Q, aa), (, Q, λ)} pentru toţi x Σ {$} δ ( Q, $, #) = {(, Q, #)} Ca de obicei, Q 0 este starea iniţială iar Q este starea acceptată. În această gramatică şirul vid λ aparţine limbajului LG ( ), derivarea lui fiind
S C λ. APD-ul îl acceptă şi pe λ (cum ar trebui s-o şi facă); secvenţa de configuraţii este: $, Q, # $, Q, S# $, Q, C# 0 $, Q, # $, Q, # oprit Şirul baaa face parte din limbajul LG ( ); derivarea lui cea mai din stânga este S bab baas baaas baaac baaa. Mişcările corespunzătoare ale APD-ului sunt: baaa$, Q, # baaa$, Q, S # baaa$, Q, bab # 0 aaa$, Q, ab # aa$, Q, B # aa$, Q, as # a$, Q, S# a$, Q, as# $, Q, S# $, Q, C# $, Q, # $, Q, # oprit Cu acelaşi input baaa maşina ar fi putut să execute următoarea secvenţă de mişcări baaa$, Q, # baaa$, Q, S # baaa$, Q, aba# oprit 0 deoarece δ ( Q, b, a) =. Ca urmare, dacă σ este derivabil în LG ( ), atunci un APD poate efectua o secvenţă legală de mişcări rezultând în acceptarea lui σ. În capitolele 6 8 vom prezenta unele metodele pentru a face aceste maşini deterministe. Evident, aceasta nu este întotdeauna posibil (vezi teorema 4..). Aşadar, orice limbaj independent de context poate fi generat de un automat push-down. Reciproca este de asemenea adevărată: Dat fiind un
automat push-down P, există o gramatică independentă de context G astfel ca LP ( ) = LG ( ); nu vom da o demonstraţie a acestui rezultat. Ea nu este dificilă, însă incomodă şi lungă (vezi [3] sau [7]). 4.3. EVALUAREA EXPRESIILOR ARITMETICE Automatele push-down pot fi utilizate pentru evaluarea automată a expresiilor aritmetice. Problema se pune în felul următor: Vrem să programăm un calculator în aşa fel încât dacă introducem o expresie aritmetică, el o va evalua corect. De exemplu, dacă expresia este *(3+ *5) + 8* maşina execută mai întâi înmulţirea *5, adună rezultatul la 3, înmulţeşte acesta cu, etc. Ea ar trebui programată astfel încât să ştie ce are de făcut şi în ce ordine. Reamintim că maşina primeşte expresia secvenţial: Adică, citeşte mai întâi simbolul, atunci simbolul *, (, 3 etc. În momentul în care ajunge la sfârşitul input-ului ea să înţeleagă input-ului şi execută operaţiile necesare în ordinea corectă. Pentru simplificare, ne vom limita la expresii cu doar două operaţii binare, * şi +. Odată înţeleasă, metoda poate fi uşor de extinsă şi pentru alte operaţii (scădere, împărţire, ridicare la putere sau operaţii unare ca a ). Mai întâi prezentăm soluţia problemei în cazul în care expresia este introdusă în aşa numita notaţie postfixată (numită şi notaţia poloneză inversă). În această notare operaţia nu este scrisă între numere, ci după ele. Deci 3+ 7 se scrie ca 37 +, 8*4 ca 84*, etc. În general, dacă & denotă o operaţie binară (adunare, înmulţire sau altceva), atunci a& b se scrie ca ab &. Fiecare operaţie acţionează asupra primilor două operanzi precedenţi. De exemplu, notaţia postfixată ab + c* este înţeleasă ca ( ab + c)* = (( ab+ ) c)*, deci * acţionează asupra lui c şi lui ab +. Observăm că în notaţia postfixată nu sunt necesare parantezele: Expresia ab + c* este
unic descifrată dacă cerem ca fiecare operator să acţionează asupra celor doi operanzi precedenţi. Acum putem construi uşor un automat push-down care va evalua automat orice expresie aritmetică σ, presupunând că expresia este scrisă în forma postfixată. Maşina va avea numai o singură stare şi va acţiona conform următoarelor reguli:. Dacă simbolul de intrare este un număr, APD-ul plasează acest simbol în vârful stivei şi deplasează pointer-ul de intrare cu o unitate la dreapta.. Dacă input-ul este un operator, maşina scoate primele două numere din stivă, execută operaţia indicată, şi plasează rezultatul obţinut în vârful stivei. 3. Când marcajul de intrare $ este ajuns, stiva va conţine numai valoarea corectă a expresiei (presupunând că input-ul a fost gramatical corect). Considerăm de pildă expresia *(3+ *5) + 8*. Forma ei postfixată este 35* + *8* +. Mişcările APD-ului cu acest input sunt: 35* + *8* + $, # 35* + *8* + $, # 5* + *8* + $, 3# 5* + *8* + $, 3# * + *8* + $, 53# + *8* + $, 03# *8* + $, 3# 8* + $, 6# * + $, 86# * + $, 86 # + $, 66 # $, 4 # Am omis simbolul de start deoarece a fost întotdeauna acelaşi. Prin subliniere am vrut să diferenţiem între numărul 6 şi urmat de 6. Această metodă, deşi funcţionează destul de bine, nu rezolvă în întregime problema noastă, deoarece de regulă expresiile aritmetice nu sunt
exprimate în notaţia postfixată ci în foram normală cu operatorul scris între operanzi notaţia infixată. Deci avem nevoie de o modalitate automată (deterministă) pentru transcrierea expresiei aritmetice din notaţia uzuală în notaţia postfixată. Descrierea formală a notaţie postfixate este următoarea: Definiţia 4.5. Fie Σ mulţimea operanzilor (adică, numerele) şi fie mulţimea operatorilor (adică, +, *,, etc.). Atunci au loc:. Reprezentarea postfixată a fiecărui operand a este chiar a.. Dacă A este o expresie scrisă în forma infixată şi  este reprezentarea ei în notaţia postfixată, atunci reprezentarea postfixată a lui (A) este Â. 3. Dacă A şi B sunt expresii în notaţia infixată, şi Â, ˆB sunt transcrierile corespunzătoare în notaţia postfixată, atunci pentru orice operator &, transcrierea postfixată pentru A&B este AB ˆ ˆ &. Punctul se înţelege astfel: Fiind dată o notaţie postfixată  pentru A, notaţia postfixată pentru (A) este  (omitem parantezele). Similar, 3 spune că dacă ştim cum să reprezentăm A şi B în notaţie postfixată (ca  şi ca ˆB ), atunci ştim cum să reprezentăm A&B: anume ca AB ˆ ˆ &. Ceea ce dorim în continuare este să construim o schemă deterministă care va converti o notaţie infixată dată în transcrierea ei postfixată. Deci să convertească şirurile a+ b* c, a*( b+ c) în abc * +, abc + * etc. În general, dacă σ, σ, σ 3 şi σ sunt expresii aritmetice în notaţie infixată iar reprezentările lor postfixate sunt ˆ σ, ˆ σ, ˆ σ 3 şi ˆ σ atunci această schemă efectuează transcrieri indicate în (4.4). Primul lucru de remarcat despre această schemă este că operanzii în notaţia postfixată
apar în aceeaşi ordine ca în notaţia infixată, singurele schimbări sunt că parantezele au fost eliminate iar operatorii * şi + sunt interschimbaţi. σ ˆ σ σ + σ = ˆ σ ˆ σ + ( σ )*( σ ) = ˆ σ ˆ σ * σ *( σ + σ ) = ˆ σ ˆ σ ˆ σ + * 3 3 σ + ( σ )*( σ ) = ˆ σ ˆ σ ˆ σ * + 3 3 (4.4) Schema trebuie să ţină cont de priorităţile operatorilor. Astfel, în expresia a+ b* c, înmulţirea b* c se execută înaintea adunării, deci în notaţia postfixată simbolul * apare la dreapta lui +. Evident dacă o astfel de schemă are toate proprietăţile listate în (4.4), atunci ea va funcţiona corect în toate cazurile. Se observă că schema poate fi realizată determinist cu ajutorul unui automat push-down cu output. Mai întâi, explicăm cum funcţionează o astfel de maşină iar apoi vom da indicaţii pentru demonstrarea corectitudinii ei. Acest translator push-down va fi un automat push-down, descris în paragraful 4., împreună cu un dispozitiv de ieşire. Schematic el poate fi reprezentat ca în figura 4.6. Şir de intrare Stiva Output Figura 4.6. Un APD care traduce o notaţie infixată într-o notaţie postfixată.
Automatul push-down are doar o singură stare Q şi acţionează în felul următor. Iniţial, input-ul conţine o expresie aritmetică în notaţie infixată; stiva este vidă (adică, conţine doar marcajul #); banda de ieşire este goală; şi pointer-ul de ieşire punctează la cea mai din stânga poziţie a benzii. Presupunem că input-ul este delimitate în partea dreaptă de simbolul $ astfel ca T să poată detecta sfârşitul input-ului. La un moment dat maşina examinează simbolul curent din vârful stivei şi simbolul de intrare curent, putând efectua una din următoarele operaţii:. Emite unul sau mai multe simboluri pe banda de ieşire. Aceste simboluri pot fi luate fie din stivă fie de pe banda de intrare. Pointerii relevanţi sunt ajustaţi corespunzător (pointer-ul de intrare este deplasează la dreapta iar pointer-ul de stivă coboară). Pointer-ul de ieşire se deplasează la dreapta la următoarea poziţie liberă disponibilă.. Plasează simbolul de intrare curent în vârful stivei, ajustând ambii pointeri (Această operaţie se numeşte push). Simbolurile de intrarea admise sunt operanzii (adică, numerele) a, b, c,..., simbolurile de operatori sunt * şi +, parantezele ), ( şi simbolul de delimitare $. Simbolurile de stivă admise sunt +, * paranteza stângă ( şi simbolul din baza stivei #. Fiecărui simbol de stivă Z îi asociem două numere prioritatea de input IZ ( ) şi prioritatea de stivă SZ ( ) conform tabelului din figura 4.7.
Z IZ ( ) SZ ( ) * + ( 3 0 # 0 Figura 4.7. Funcţii de prioritate. Maşina se comportă în felul următor:. Dacă simbolul de intrare este unul dintre operanzii a, b, c,..., el este trimis spre output şi se citeşte următorul simbol. Pointer-ul de intrare şi cel de ieşire sunt ajustaţi corespunzător; stiva nu se schimbă.. Dacă simbolul de intrare x este (, +, sau *, adică, este şi simbol de stivă, atunci se compară valorile pentru I( x ) şi SZ ( ), unde Z este vârful curent al stivei. Vor avea loc următoarele: i. Dacă I( x) > S( Z) simbolul x este plasat în vârful stivei şi se citeşte următorul simbol. Pointerii de input şi de stivă sunt ajustate corespunzător, nu are loc un output. ii. Dacă I( x) S( Z) se emite ca output simbolul Z din vârful stivei, pointerii de stivă şi de ieşire sunt ajustaţi iar simbolul x este citit din nou (pointer-ul de intrare rămâne neschimbat). 3. Dacă simbolul de intrare este paranteza dreaptă ) stiva este trimisă la output, unul câte unul, până ce apare paranteza stângă (. Iar
atunci se elimină paranteza stângă ( din stivă nu este trimisă la ieşire; pointerii de stivă şi de output se ajustează corespunzător iar pointer-ul de intrare se deplasează la stânga. 4. Dacă simbolul de intrare x este $, atunci se trimite, începând din vârf, unul câte unul, conţinutul stivei spre ieşire până la marcajul de bază #. Descriem configuraţia maşinii T într-un moment dat printr-un triplet de şiruri astfel: xx Kx $, Z Z KZ #, yy Ky i i+ n j j k C C C INP TOS OUT (4.5) Unde C INP este simbolul de intrarea curent, C TOS vârful curent al stivei iar C OUT este pointer-ul de ieşire curent. APD-ul din figura 4.6. se află în configuraţia (4.5). Cu aceste notaţii, dăm în continuare unele exemple de mişcări ale lui T la diferite input-uri. Exemplu 4.6. Comportamentul maşinii T la diverse input-uri. Cu input-ul a+ b* c maşina se mişcă astfel: a+ b* c$, #, λ + b* c$, #, a b* c$, + #, a * c$, + #, ab c$, * + #, abc $, * + #, abc $, + #, abc* $, #, abc* + Cu input-ul ( a+ b)* c mişcările lui T sunt:
( a+ b)* c$, #, λ a+ b)* c$, (#, λ + b)* c$, (#, a b)* c$, + (#, a )* c$, + (#, ab * c$, + #, ab+ c$, *#, ab+ $, *#, ab + c $, #, ab + c* Dacă input-ul este ( a+ b* c)*( d + e), mişcările sunt: ( a+ b* c)*( d + e)$, #, λ a+ b* c)*( d + e)$, (#, λ + b* c)*( d + e)$, (#, a b* c)*( d + e)$, + (#, a * c)*( d + e)$, + (#, ab c)*( d + e)$, * + (#, ab )*( d + e)$, * + (#, abc *( d + e)$, #, abc* + ( d + e)$, *#, abc* + d + e)$, (*#, abc* + + e)$, (*#, abc* + d e)$, + (*#, abc* + d )$, + (*#, abc* + de $, *#, abc* + de+ $, #, abc* + de + * Evident maşina funcţionează corect în aceste exemple. De fapt, ea o va face în toate cazurile. Teorema 4.3. Fie T un automat push-down descris în figurile 4.5. şi 4.6. Dacă σ este o expresie aritmetică oarecare bine formată în notaţie infixată, atunci T va transforma σ în ˆ σ traducerea corectă a lui σ în notaţia postfixată. Demonstraţie. (O schiţă) Vom folosi inducţia după lungimea şirului de intrare. Singurele expresii aritmetice (în notaţia infixată) de lungime mai mică sau egală cu teri sunt: a, (a), a+ b şi a* b. Se observă uşor că T va traduce corect toate acestea. Presupunem acum că T funcţionează corect pentru toate expresiile de lungime cel mult n 3 şi fie
σ o expresie, de lungime n +, scrisă în notaţia infixată. Atunci σ este într-una din următoarele forme: i. σ = ( τ) ii. σ = τ+ τ iii. σ = τ* τ unde toţi τ sunt de lungime mai mică decât n. În fiecare caz T îl va traduce corect pe σ : i. Iniţial, T va trece din configuraţie ( τ)$, #, λ în τ)$, (#, λ. Iar atunci va opera asuprea lui τ, producând output-ul ˆ τ traducerea postfixată a lui τ fără a influenţa simbolul ( de pe stivă. Aşadar, la un moment dat va ajunge în configuraţia $, #, ˆ τ producând rezultatul corect. )$, (#, ˆ τ şi va trece în ii. T porneşte în configuraţia τ + τ $, #, λ. Din ipotezele inducţiei, el va traduce τ corect, deci după ce ultimul simbol din τ a fost citit, T se va afla în configuraţia + τ $, #, ˆ τ. De aici va trece în τ $, #, ˆ τ iar conform ipotezelor inducţiei el va continua să treacă în $, #, ˆˆ ττ +. Simbolul + din stivă va rămâne nedistribuit deoarece τ trebuie să înceapă cu un operand x sau paranteză stângă (; în ambele cazuri + rămâne pe stivă. Din această ultimă configuraţie, T va trece în $, #, ˆˆ ττ +, producând din nou traducerea corect. iii. Analog cu ii. Q.E.D. Trebuie să menţionăm aici că T nu detectează greşeli în input-ul original. Astfel, de exemplu, dacă input-ul σ este a+ * b output-ul lui T va
fi ab * +, amândouă fiind secvenţe fără înţeles. În capitolele 6 şi 8 vom construi analizatoare deterministe care nu vor evalua doar aceste expresii aritmetice, ci chiar vor putea decide dacă şirurile de intrare sunt corect formate. Maşina T, dată aici, nu este un analizator adevărat deoarece nu reconstruieşte arborele de derivare a input-ului. 4.4. LEMA DE POMPARE PENTRU APD-URI În paragrafele 4.. şi 4.. am văzut că automatele push-down sunt mult mai adaptabile decât maşinile cu stări finite. Mai exact, am găsit un limbaj acceptat de un APD dar nu de o maşină cu stări finite (exemplul 4..). Din acest motiv ne putem întreba dacă orice limbaj este recunoscut de un APD, sau (din teorema 4..) ce se întâmplă în cazul limbajelor cu gramatică independentă de context? Vom utiliza în mod special teorema 4.4., care este analoagă cu lema de pompare pentru maşini cu stări finite (teorema 3..). Teorema 4.4. (Lema de pompare pentru automate push-down). Fie G = { Σ, N, S, P} o gramatică independentă de context. Atunci există un număr k, care depinde numai de G, cu următoarea proprietate: Orice propoziţie σ din LG ( ) de lungime mai mare decât k poate fi scrisă ca σ = ατβτγ, unde α, β, γ, * τ şi τ sunt şiruri din Σ şi astfel încât pentru n n fiecare n = 0,,,3, K şirul σ = ατβτγ aparţine de asemenea lui LG ( ). Mai mult, unul din şirurile τ şi τ (sau amândouă) est diferit de şirul vid λ. Motivul pentru care teorema se referă la automate push-down este că limbajele cu gramatici independente de context sunt chiar acele limbaje care sunt recunoscute de automate push-down (teorema 4..).
Înainte de a trece la demonstraţie vom arăta cum se aplică această teoremă. n n n Exemplu 4.7. Fie L 0 limbajul L0 = { abc n= 0,,, K }. Aşadar, L se compune din şiruri având un număr egal de simboluri a, b şi c urmate succesiv. Vrem să arătăm că L 0 nu este acceptat de un APD, sau echivalent, nu are gramatică independentă de context. Presupunem deci, că L are o gramatică independentă de context G astfel ca L0 = L( G) şi fie k numărul corespunzător lui G din teorema 4.4. Dacă m > k, şirul m m m m m m σ = abc are lungimea 3m> k, deci σ poate fi scris ca abc = ατβτ γ, unde sau τ λ sau τ λ, şi pentru fiecare,, n n n = K şirul ατβτ γ este în limbajul L. Vom arăta că aceasta este imposibil. Presupunem că τ λ. Atunci τ trebuie să fie un şir format dintr-un singur tip de simboluri, adică, a, b, sau c. Într-adevăr, dacă de exemplu, τ conţine a-uri şi b-uri, atunci τ = ττ va avea a-uri (în al doilea τ ) care se află în dreapta b-urilor (în primul τ ). Dar aceasta implică că ατβτ γ nu este în L 0 contradicţie cu alegerea lui τ. Analog se procedează pentru τ conţinând a-uri şi c-uri sau b-uri şi c-uri. În acelaşi mod arătăm că dacă τ λ, atunci τ trebuie să fie un şir format fie numai din a-uri fie numai din b-uri sau c-uri. Dar atunci, considerăm din nou şirul ρ = ατ βτ γ care este garantat, prin teorema 4.4., a fi din L 0. Dacă τ se compune doar din a-uri iar τ numai din b-uri, atunci ρ are prea puţini de c. Dacă τ are numai b-uri şi τ numai c-uri, atunci ρ are prea puţini de a, etc. În toate cazurile posibile şirul ρ nu poate fi o propoziţie în limbajul L. Deci, într-adevăr, L nu poate avea o gramatică independentă de context.
Continuăm acum cu demonstraţia teoremei 4.4. Pentru simplificare, facem ipoteza că G nu are producţii vide, adică, producţii de forma A λ. Fiind dată o gramatică G, vom construi un număr k = k( G) astfel încât pentru orice şir σ din LG ( ) de lungime mai mare decât k, există o derivare a lui σ de forma * * * S α Xγ ατ Xτ γ ατ βτ γ = σ (4.6) unde X este un neterminal oarecare şi fie τ fie τ este un şir nevid. Într-adevăr, dacă (4.6) este adevărată, atunci * X τ Xτ şi * X β sunt derivări valide în G. Aşadar, toate dintre derivările următoare pot fi făcute în G: * * S αxγ αβγ * * * α γ ατ τ γ ατβτ γ * * * * S X X S α Xγ ατ Xτ γ ατ Xτ γ ατ βτ γ L şi se obţine teorema. Fie r lungimea celui mai lung şir din partea dreaptă a unei producţii n0 din G, şi fie n numărul de neterminale din G; n0 = n+. Punem k = r +. Fie acum σ un şir oarecare din LG ( ) a cărui lungime este mai mare decât k şi considerăm arborele lui de derivare ca în figura 4.8. Definim un drum într-un astfel de arbore ca fi secvenţa de noduri şi de segmente de drum care le leagă, începând din rădăcina S şi mergând prin neterminale până la
o frunză (adică, un terminal în σ ). Lungimea drumului este numărul acestor segmente de drum. Definim adâncimea arborelui ca fiind lungimea cea mai mare a acestor drumuri. Figura 4.8. Schemă de arbore de derivare pentru σ. Considerăm, de exemplu, gramatica G 0 a expresiilor aritmetice (exemplul.3.). Şirul σ = ( a+ a)* a are arborele de derivare din figura 4.9. Exemple de drumuri în acest arbore sunt: E-T-F-a, (de lungime 3), E-T-T-F-), (de lungime 4), E-T-T-F-E-E-T-F-a (de lungime 8), etc. Adâncimea arborelui este 8. Observăm că dacă şirul σ are un arbore de derivare de adâncime d, atunci σ nu poate avea mai mult de r d simboluri (pe orice nivel, fiecare nod poate avea cel mult r fii). Aşadar rădăcina S poate avea cel mult r fii, r fii de gradul, etc. Cu alte cuvinte, dacă numărul de frunze în arborele de derivare a unui şir σ este mai mare decât r d, atunci arborele de derivare trebuie să conţină un drum de lungime mai mare decât d.
Figura 4.9. Exemplu de arbore de derivare. Figura 4.0. Demonstraţia teoremei 4.4. σ = ατβτγ n0 Presupunem acum că şirul σ este mai lung decât k = r + şi considerăm un arbore de derivare pentru σ care are cel mai mic număr de noduri. (σ poate avea mai mult decât un singur arbore de derivare. Dacă există mai mulţi astfel de arbori de derivare minimali, se alege unul oarecare dintre
ei.) Din cele spuse adineauri, arborele de derivare pentru σ trebuie să conţină un drum de lungime mai mare decât n 0, adică, de lungime n0 + = n+ sau chiar mai mult (n este numărul de neterminale din G). Acest drum conţine exact un termina, toate celelalte noduri (cel puţin n + dintre ei) sunt neterminale. Aşadar, există un neterminal X care apare de două ori în acest drum, deci arborele de derivare a lui σ este de forma celui din figura 4.0. Unul dintre şirurile τ sau τ trebuie să fie diferit de λ, deoarece altfel am putea elimina întreaga porţiune a arborelui de derivare între primul X şi al doilea X, şi obţinem un arbore de derivare cu mai puţine simboluri. Dar aceasta ne arată că (4.6) este adevărat, deci am terminat demonstraţia. Q.E.D. 4.5. PROPRIETATEA DE ÎNCHIDERE A LIMBAJELOR INDEPENDENTE DE CONTEXT Am văzut în capitolul 3 (teorema 3.6) că dacă L, L şi L sunt limbaje regulare atunci L *, L, L+ L, LL şi L L sunt de asemenea regulare. Unele, dar nu toate, dintre aceste proprietăţi sunt adevărate şi pentru * limbajele independente de context. Reamintim că L este limbajul tuturor şirurilor de forma σσ K σn L ; L este mulţimea şirurilor care nu aparţin lui L; L+ L este reuniunea dintre L şi L ; LL este mulţimea şirurilor de forma σσ K σi Li şi L L este mulţimea şirurilor care se află atât în L cât şi în L. Teorema 4.5. Fie L, L şi L limbaje independente de context. Atunci limbajele L *, L+ L şi LL sunt de asemenea independente de context.
Demonstraţie. Presupunem că L are o gramatică independentă de * context G = { Σ, N, S, P}. Definim o nouă gramatică G astfel: Terminalele din Σ corespund celor din G. Neterminalele sunt aceleaşi ca pentru G, plus încă un simbol nou S *. Simbolul de start va fi atunci S * iar * * producţiile vor fi tot cele din G, plus S S S λ. Evident că * * * LG ( ) = ( LG ( )) şi G este o gramatică independentă de context. Pentru a arăta că reuniunea şi concatenarea a două gramatici independente de context este din nou independentă de context procedăm astfel. Fie G = { Σ, N, S, P} o gramatică independentă de context pentru limbajul i i i i i L i, i =,. Presupunem că neterminalele din L sunt disjuncte faţă de cele din L ; N N =. Pentru a construi o gramatică G = { Σ, N, S, P} pentru limbajul L + L luăm Σ=Σ Σ, N = N N plus încă un simbol nou S, care este şi noul simbol de start din G, iar producţiile sunt S S S plus toate producţiile din P şi P. Evident LG ( ) LG ( ) LG ( ) = +. Pentru a obţine o gramatică pentru limbajul LL, procedăm în exact aceeaşi manieră, însă introducem producţia S SSîn loc de S S S. Q.E.D. Exemplu 4.8. Intersecţie a două limbaje independente de context nu trebuie să fie independentă de context. Într-adevăr, limbajul n n M = { a b n= 0,,, K } este independent de context, fie gramatica lui k S asb λ. Limbajul M = { c k = 0,,, K } este de asemenea independent i de context. Analog, limbajele M3 = { a n= 0,, K } şi 4 { j j M = b c j = 0,,, K} sunt independente de context. Din teorema 4.5. avem că limbajele L L = M M şi L = M3M4 sunt independente de context. Limbajul, însă, L nu este independent de context. Observăm că L L este limbajul