ICS-C2000 Tietojenkäsittelyteoria Kevät 2016 Kierros 7, 29. helmikuuta 4. maaliskuuta Demonstraatiotehtävien ratkaisut D1: Osoita, yhteydettömien kielten pumppauslemmaa käyttäen, että kieli {ww w {a,b} } ei ole yhteydetön. (Vihje: Tarkastele muotoa a n b n a n b n olevia merkkijonoja.) Ratkaisu: Yhteydettömien kielten pumppauslemma: Lemma 1 ( uvwxy-lemma ). Olkoon L yhteydetön kieli. Tällöin on olemassa sellainen n 1, että mikä tahansa z L, z n, voidaan jakaa osiin z = uvwxy siten, että vx 1, vwx n, uv i wx i y L kaikilla i = 0,1,2,... Kokeillaan ensin harjoituksen vuoksi (ja näyttääksemme, että pumpattavan merkkijonon valinta ei ole aina yhtä suoraviivaista kuin säännöllisten kielten pumppauslemman yhteydessä), mitä tapahtuisi jos valittaisiin pumpattavaksi merkkijono a n ba n b L. Tälle voidaan valita u = a n 1 v = a w = b x = a ja y = a n 1 b. Nyt uv i wx i y = a n 1+i ba i+n 1 b L kaikilla i = 0,1,2,... Eli merkkijonoa a n ba n b voidaan pumpata eikä se siis ollut oikea valinta kun pyritään näyttämään kieli ei-yhteydettömäksi. Valitaan seuraavaksi pumpattavaksi merkkijono z = a n b n a n b n L. Tarkastellaan kaikki tavat jakaa merkkijono pumppauslemman ehtojen, vx 1 ja vwx n, mukaisesti osiin z = uvwxy: (a) Alimerkkijono vwx sisältää pelkästään a-kirjaimia merkkijonon ensimmäisestä neljänneksestä: koska vx 1 pitää päteä, tällöin merkkijono uv 0 wx 0 y joko sisältää parittoman määrän merkkejä tai sen ensimmäinen puolisko loppuu a-merkkiin (joka on vuotanut alkuperäisen merkkijonon toisen puoliskon alusta) toisin kuin b-merkkiin loppuva toinen puolisko. Eli uv 0 wx 0 y / L. 1
(b) Tapaukset, joissa vwx sisältää merkkejä vain toisen, kolmannen tai neljännen neljänneksen sisältä voidaan käsitellä vastaavasti. (c) Alimerkkijono vwx sisältää merkkejä merkkijonon ensimmäisestä ja toisesta neljänneksestä: merkkijono uv 0 wx 0 y joko sisältää parittoman määrän merkkejä tai sen ensimmäinen puolisko loppuu a-merkkiin (joka on vuotanut alkuperäisen merkkijonon toisen puoliskon alusta) toisin kuin b-merkkiin loppuva toinen puolisko. Eli uv 0 wx 0 y / L. (d) Alimerkkijono vwx sisältää merkkejä merkkijonon kolmannesta ja neljännestä neljänneksestä: merkkijono uv 0 wx 0 y joko sisältää parittoman määrän merkkejä tai sen toinen puolisko alkaa b-merkillä (joka on vuotanut alkuperäisen merkkijonon ensimmäisen puoliskon lopusta) toisin kuin a-merkillä alkava ensimmäinen puolisko. Eli uv 0 wx 0 y / L. (e) Alimerkkijono vwx sisältää merkkejä merkkijonon toisesta ja kolmannesta neljänneksestä: merkkijono uv 0 wx 0 y on nyt muotoa a n b k a l b n, missä joko k < n tai l < n (tai molemmat). Tämän muotoiset merkkijonot eivät kuulu kieleen. (f) Koska pitää päteä vwx n, alimerkkijono vwx ei voi sisältää merkkejä merkkijonon a n b n a n b n kolmesta tai neljästä eri neljänneksestä. On siis käyty läpi kaikki mahdolliset tavat jakaa merkkijono osiin lemman vaatimusten mukaisesti ja näytetty, ettei mitään näistä osituksista voida pumpata lemman mukaisesti. Täten kieli ei ole yhteydetön. D2: Osoita, että yhteydettömien kielten luokka ei ole suljettu leikkausten eikä komplementtien suhteen. (Vihje: Esitä kieli {a k b k c k k 0} kahden yhteydettömän kielen leikkauksena.) Ratkaisu: Olkoon kieli L = {a k b k c k k 0}. Opetusmonisteessa (s.75) on todistettu, että tämä kieli ei ole yhteydetön. Osoitetaan, että yhteydettömät kielet eivät ole suljettuja leikkauksen suhteen esittämällä L:n kahden yhteydettömän kielen leikkauksena. Olkoon L 1 = {a i b k c k i,k 0} ja L 2 = {a k b k c i i,k 0}. Nyt sekä L 1 että L 2 ovat yhteydettömiä, mutta L = L 1 L 2, joten yhteydettömät kielet eivät ole suljettuja leikkauksen suhteen. Tuloksesta seuraa suoraan se, että yhteydettömät kielet eivät voi olla suljettuja komplementin suhteen, sillä ne ovat suljettuja unionin suhteen ja DeMorganin sääntöjen perusteella L 1 L 2 = L 1 L 2. Osoitetaan vielä lopuksi, että L 1 ja L 2 ovat todellakin yhteydettömiä muodostamalla niitä vastaavat kieliopit. Kielen L 1 generoi yhteydetön kielioppi G 1 = ({S,A,B,a,b,c},{a,b,c}, P 1,S), missä P 1 = {S AB,A aa ε,b bbc ε}. Kielen L 2 generoiva kielioppi G 2 = ({S,A,B,a,b,c},{a,b,c},P 2,S), P 2 = {S AB,A aab ε,b cb ε}. 2
D3: Muodosta kielioppia S (SS) S (S S) /0 a b vastaava pinoautomaatti. Tässä päätesymbolien joukko on Σ = {(,),,, /0, a, b}. Ratkaisu: Käyttämällä Orposen prujun luvun 3.7 (tai Sipserin kirjan Lemman 2.21 todistuksen) konstruktiota saadaan pinoautomaatti a,a / ε b,b / ε (,( / ε ),) / ε *,* / ε, / ε, / ε ε,s / ε,s / a ε,s / b ε,s / (SS) ε,s / S* ε,s / (S S) start ε,ε / S# loop ε, # / ε acc Tässä # on pinon pohjan merkitsemiseen käytetty uusi symboli ja käytetään lyhennysmerkintää s x,x / YZV t rakenteelle x,x / V s s' ε,ε / Z s'' ε,ε / Y t jotta voidaan laittaa useampia symboleja pinoon kerrallaan. Automaatin ideana on rakentaa annetulle merkkijonolle kieliopin mukaista vasenta johtoa pinoon käyttämällä muotoa ε,s/x 1...X n olevia siirtymiä kieliopin vastaaville produktioille S X 1...X n. Pinoon syntynyttä merkkijonoa verrataan automaatin syötteeseen muotoa x,x ε olevilla siirtymillä, missä x on päätesymboli. Tarkastellaan, kuinka automaatti voisi toimia syötteellä (a b ): 3
State Input Stack q start (a b ) ε q loop (a b ) S q loop (a b ) (S S) q loop a b ) S S) q loop a b ) a S) q loop b ) S) q loop b ) S ) q loop b ) b ) q loop ) ) q loop ) ) q loop ε q acc ε ε Tämä vastaa vasenta johtoa S lm (S S) lm (a S) lm (a S ) lm (a b ). Huom: kieliopin tuottama kieli L(G) määrittelee kaikki syntaktisesti oikeanmuotoiset aakkoston {a,b} yli muodostetut säännölliset lausekkeet. D4: Muodosta pinoautomaattia a,ε/a q 2 q 1 q 3 vastaava yhteydetön kielioppi. Ratkaisu: Yksi vaihtoehto on analysoida pinoautomaatin rakennetta ja päätellä suoraan sen hyväksymä kieli. Tässä yksinkertaisessa tapauksessa tämä onnistuu melko helposti ja nähdään, että automaatin hyväksymä kieli on ja siten eräs vastaava kielioppi on {a i b j i j} {a i c j i j} S B C B abb ab ε C acb ac ε 4
Näytetään seuraavassa kuitenkin systemaattinen tapa muodostaa yhteydetön kielioppi pinoautomaatista. Tämä pohjautuu Sipserin kirjan Lemman 2.27 todistukseen, joka sisältää formaalimman käsittelyn. Muutetaan ensin automaatti muotoon, jossa sillä on vain yksi hyväksyvä lopputila: a,ε/a q 1 q 2 ε,ε/ε q 3 ε,ε/ε ε,ε/ε q acc Seuraavaksi lisätään uusi, alussa pinoon laitettava ja viimeisellä askeleella poistettava pinon pohja -symboli $ sekä ennen viimeistä askelta pinon tyhjentävä lisätila, jolloin saadaan saman kielen hyväksyvä automaatti, jonka pino on aina tyhjä hyväksyvään tilaan päädyttäessä: a,ε/a ε,ε/$ ε,ε/ε ε,$/ε q 0 q 1 q 7 q acc q 2 q 3 ε,ε/ε ε,ε/ε ε,a/ε Lopuksi muokataan automaattia vielä niin, että sen jokaisella siirtymällä joko lisätään pinoon yksi pinosymboli tai poistetaan pinosta yksi pinosymboli (mutta ei molempia). Jotta päästään eroon siirtymistä, joko sekä poistavat että lisäävät pinoon tai eivät tee kumpaakaan, voidaan ottaa käyttöön tarvittava määrä välitiloja sekä mahdollisesti uusi pinosymboli (alla D): 5
q 0 a,ε/a ε,ε/$ q 1 ε,ε/d q 2 ε,ε/d q 3 ε,ε/d q 4 ε,d/ε ε,a/ε ε,d/ε ε,$/ε q 6 q7 q acc q 5 ε,d/ε Määritellään, että automaatti pääsee merkkijonolla x tilasta p tilaan q pino säilyttäen jos sillä on tilasta p merkkijonolla x ja tyhjällä pinolla käynnistettäessä suoritus, joka päätyy tilaan q siten, että koko merkkijono on käytetty ja pino on tyhjä. Esimerkiksi yllä oleva automaati pääsee merkkijonolla ε tilasta q 1 tilaan q 7 pino säilyttäen kahdella askeleella kulkemalla tilan q 6 kautta. Samoin se pääsee merkkijonolla aabb tilasta q 1 tilaan q 2 pino säilyttäen neljällä askeleella. Yllä esitettyjen muutosten jälkeen syntyneellä automaatilla on seuraavat hyödylliset ominaisuudet: Automaatti hyväksyy merkkijonon x jos ja vain jos se pääsee merkkijonolla x tilasta q 0 tilaan q acc pino säilyttäen. Automaatti pääsee merkkijonolla x tilasta p tilaan q pino säilyttäen tasan kolmella tavalla: (a) p = q ja x = ε. (b) x = yz, missä y,z Σ, ja automaatti pääsee merkkijonolla y tilasta p tilaan r pino säilyttäen ja merkkijonolla z tilasta r tilaan q pino säilyttäen. (c) x = σ 1 yσ 2, missä y Σ ja σ 1,σ 2 Σ {ε}, automaattissa on siirtymät (r,x) δ(p,σ 1,ε) ja (q,ε) δ(s,σ 2,X) jollekin pinosymbolille X ja automaatti pääsee merkkijonolla y tilasta r tilaan s pino säilyttäen. Muodostetaan pyydetty kielioppi ottamalla jokaiselle automaatin tilaparille p, q välikesymboli R p,q, josta johdettavat merkkijonot ovat täsmälleen ne, joilla automaatti pääsee tilasta p tilaan q pino säilyttäen. Kieliopin aloitussymboli on siis R q0,q acc. Muodostetaan produktiot yllä kuvatun kolmen tapauksen perusteella: (a) R p,p ε on produktio jokaiselle automaatin tilalle p. (b) R p,q R p,r R r,q on produktio kaikille automaatin tiloille p,r,q. (c) jos automaattissa on siirtymät (r,x) δ(p,σ 1,ε) ja (q,ε) δ(s,σ 2,X) jollekin pinosymbolille X ja σ 1,σ 2 Σ {ε}, niin R p,q σ 1 R r,s σ 2 on produktio. 6
Kielioppi yllä olevalle automaatille (vain osa produktioista kirjoitettu): R q0,q acc R q1,q 7 R q0,q 1 R q1,q acc... R q1,q 7 R q6,q 6 ar q1,q 7 R q1,q 2 R q2,q 7... R q1,q 2 ar q1,q 1 b ar q1,q 2 b... R q1,q 1 ε R q6,q 6 ε... D5: Laadi algoritmi, joka testaa onko annetun yhteydettömän kieliopin G = (V, Σ, P, S) tuottama kieli epätyhjä, so. voidaanko kieliopin lähtösymbolista S johtaa yhtään päätejonoa x Σ. Ratkaisu: Allaoleva proseduuri?generatesnonemptylanguage(g) ottaa syötteenä yhteydettömän kieliopin G, ja palauttaa arvon true, jos G:n generoima kieli ei ole tyhjä.?generatesnonemptylanguage(g = (V, Σ, P, S): context-free grammar) T Σ repeat V Σ times for each A X 1 X k P if A T X 1 X k T T T {A} if S T return true else return false Algoritmin idea on lähteä terminaalisymbolien joukosta Σ ja testata, onko näistä mahdollista perääntyä S:ään käyttäen joukon P produktioita käänteisesti. Perääntymistä simuloidaan iteroimalla V Σ kertaa saavutettavien symbolien joukkoa T. Perusteluksi sille, että V Σ askelta riittää, tarkastellaan sanaa z L(G), jolla on kielen sanoista kaikkein pienin jäsennyspuu. Jos z:lla on muotoa S uay uvaxy uvwxy oleva johto, missä u,v,w,x,y Σ, niin myös sana z = uwy voidaan johtaa kieliopin säännöillä 1. Tällöin kuitenkin z :n jäsennyspuu on pienempi kuin z:n jäsennyspuu, mikä on ristiriidassa sen oletuksen kanssa, että z:n puu on pienin. Tästä seuraa se, että missään z:n minimaalisen jäsennyspuun haaroissa ei voi esiintyä sama välike kahteen kertaan, joten algoritmissa riittää käydä sääntöjoukko läpi yhtä monta kertaa kuin kieliopissa on välikkeitä. 1 Vertaa yhteydettömien kielten pumppauslemmaan. 7
Tarkastellaan esimerkiksi kielioppia: S BAB ABA A aas bba B bbs c Algoritmin laskenta etenee joukon T osalta seuraavasti: T 0 = {a,b,c} T 1 = {a,b,c,b} (B c) T 2 = {a,b,c,a,b} T 3 = {a,b,c,a,b,c,s} (A bba) (S BAB,S ABA) Koska V Σ = 3, algoritmin suoritus päättyy ja T = T 3. Huomataan, että S T, joten kieli ei ole tyhjä. Pienin kieleen kuuluvan sanan jäsennyspuu on: S B A B c b B a c c Liite: Chomskyn normaalimuoto Muutetaan esimerkin vuoksi seuraava kielioppi Chomskyn normaalimuotoon: P = {S aas bbs ε A aaa b, B bbb a} Kielioppi on Chomskyn normaalimuodossa, mikäli seuraavat ehdot toteutuvat: 1. Ainoastaan alkuvälike S voi olla tyhjentyvä. 2. Alkuvälike S ei esiinny säännöissä oikealla puolella. 3. Mahdollisesti esiintyvää sääntöä S ε lukuunottamatta kaikki säännöt ovat muotoa A BC tai A a, missä A, B ja C ovat välikkeitä ja a terminaalisymboli. Kielioppi muutetaan normaalimuotoon vaiheittain: 8
1. Poistetaan lähtösymboli sääntöjen oikealta puolelta. Koska kieliopissa on säännöt S aas ja S bbs, lisätään uusi lähtösymboli S ja sääntö S S. Saadaan tulokseksi sääntöjoukko: 2. Poistetaan ε-produktiot. S S, S aas bbs ε A aaa b, B bbb a Koska Chomskyn normaalimuodossa ainoastaan lähtösymboli S saa olla tyhjentyvä, täytyy muut ε-säännöt poistaa kieliopista. Lasketaan aluksi tyhjentyvien välikkeiden joukko NULL: NULL 0 ={S} (S ε) NULL 1 ={S,S } (S S) NULL 2 ={S,S } = NULL Tämän jälkeen korvataan säännöt A X 1 X n joukolla sääntöjä { X i,x i / NULL A α 1 α 2, missä α i = X i tai ε,x i NULL Lopuksi poistetaan kaikki säännöt muotoa A ε (lukuunottamatta sääntöä S ε). Saadaan tulokseksi sääntöjoukko 2 : 3. Poistetaan yksikköproduktiot. S S ε S aas aa bbs bb A aaa b, B bbb a Seuraavaksi poistetaan kieliopista kaikki muotoa A B olevat säännöt, missä sekä A että B ovat välikkeitä. Lasketaan ensin joukot F(A) kaikilla A V Σ: F(A) = F(B) = F(S) = /0 F(S ) = {S} 2 Tarkkaan ottaen tässä vaiheessa pitäisi lisätä vielä uusi aloitusvälike S ja säännöt S ε S, mutta tässä tapauksessa ei synny ongelmia, vaikka käytetään S :a lähtösymbolina. 9
Välike B kuuluu joukkoon F(A) täsmälleen silloin, kun A:sta voidaan johtaa B käyttäen pelkkiä yksikköproduktioita. Sääntö A B korvataan sääntöjoukolla {A w C F(B) {B} : C w P}. Tulokseksi saadaan sääntöjoukko: 4. Poistetaan liian pitkät produktiot. S aas aa bbs bb ε S aas aa bbs bb A aaa b, B bbb a Viimeisessä vaiheessa lisätään kielioppiin uusi välike C σ sekä sääntö C σ σ kaikille σ Σ sekä jaetaan kaikki säännöt A w ( w > 2) ketjuksi sääntöjä, jotka kaikki johtavat tismalleen kaksi symbolia. Annetun kieliopin Chomskyn normaalimuodoksi saadaankin seuraava sääntöjoukko: Liite: CYK-algoritmi S C a S 1 C a A C b S 2 C b B ε S 1 AS S 2 BS S C a S 1 C a A C b S 2 C b B S 1 AS S 2 BS A C a A 1 b A 1 AA B C a B 1 a B 1 BB C a a C b b CYK-algoritmilla voidaan tutkia kuuluuko sana x = x 1 x n kieliopin G määrittelemään kieleen. Algoritmin kuluessa lasketaan välikejoukot N i,k. Joukko N i,k käsittää kaikki ne välikkeet, joista voidaan johtaa osajono x i x i+k 1, eli sanan x kohdasta i alkava k:n merkin mittainen osajono. Joukkojen laskemisessa voidaan käyttää apuna dynaamista ohjelmointia seuraavaan tapaan: N i,1 = {X X x i on produktio} N i,k = k 1 j=1 {X X Y Z on produktio, Y N i, j ja Z N i+ j,k j } kun k 2 10
Tarkastellaan kielioppia G: S C a D C a A C a E BC b a b A C a D C a A a B C a E BC b b D AC b E BC b C a a C b b Tarkistetaan, kuuluvatko sanat w 1 = aabbb ja w 2 = aabb kieleen (G). Koska w 2 on w 1 :n prefiksi, täytyy taulukko tehdä ainoastaan sanalle w 1. Lasketaan ensin joukot N i,1 jokaiselle 1 i 5: i 1 : a 2 : a 3 : b 4 : b 5 : b k 1 aabbb aabbb aabbb aabbb aabbb {S,A,C a } {S,A,C a } {S,B,C b } {S,B,C b } {S,B,C b } Kussakin taulukon solussa on alleviivattuna sitä vastaava sanan osajono. Lasketaan seuraavaksi N 1,2, eli niiden välikkeiden joukko, jolla voidaan johtaa sanan alussa oleva aa. Koska normaalimuotoisessa kieliopissa ei ole yhtään sääntöä, jolla voisi suoraan johtaa useamman kuin yhden terminaalisymbolin, voidaan aa saada ainoastaan siten, että johdetaan jostain välikkeestä kaksi a:n tuottavaa välikettä. Käytännössä tämä tapahtuu siten, että etsitään kaikki sellaiset välikkeet X, joille on olemassa sääntö X Y Z, missä Y N 1,1 ja Z N 2,1. N 1,1 = {S,A,C a } N 2,1 = {S,A,C a } N 1,2 = {S,A}. Tässä käytettiin sääntöjä S C a A ja A C a A. Solulle N 2,2 saadaan vastaavasti: N 2,1 = {S,A,C a } N 3,1 = {S,B,C b } N 2,2 = {D}. Ainoa ehdot täyttävä sääntö on D AC b. Kokonaisuudessaan taulukon toiseksi riviksi muodostuu: i 1 : a 2 : a 3 : b 4 : b 5 : b 1 aabbb aabbb aabbb aabbb aabbb {S,A,C a } {S,A,C a } {S,B,C b } {S,B,C b } {S,B,C b } k 2 aabbb aabbb aabbb aabbb {S,A} {D} {S,B,E} {S,B,E} 11
Solun N 1,3 kohdalla huomataan, että sanan kolme ensimmäistä merkkiä (aab) voidaan johtaa kahdella eri tavalla: 1. johdetaan a välikkeellä Y N 1,1 ja ab välikkeellä Z N 2,2 ; tai 2. johdetaan aa välikkeellä Y N 1,2 ja b välikkeellä Z N 3,1. Vastaavat joukot ovat: j = 1 N 1,1 = {S,A,C a } j = 2 N 1,2 = {S,A} N 2,2 = {D} N 3,1 = {S,B,C b } Tapausta j = 1 vastaava välikejoukko on {S,A} (S C a D, A C a D) ja tapausta j = 2 vastaava on {D} (D AC b ), joten N 1,3 = {S,A,D}. Samaan tapaan jatkamalla saadaan lopulta koko taulukoksi: i 1 : a 2 : a 3 : b 4 : b 5 : b 1 aabbb aabbb aabbb aabbb aabbb {S,A,C a } {S,A,C a } {S,B,C b } {S,B,C b } {S,B,C b } 2 aabbb aabbb aabbb aabbb {S,A} {D} {S,B,E} {S,B,E} k 3 aabbb aabbb aabbb {A,S,D} {S,B} {S,B,E} 4 aabbb aabbb /0 {S,B,E} 5 aabbb {S,B} Viimeisessä vaiheessa täytyi käydä läpi neljä eri kombinaatiota: (N 1,1, N 2,4 ), (N 1,2, N 3,3 ), (N 1,3, N 4,2 ) sekä (N 1,4, N 5,1 ). Koska S N 1,5, niin aabbb (G). Toisaalta, koska S / N 1,4, niin aabb / (G). Taulukosta voidaan konstruoida suoraan sanan w 1 jäsennyspuu käymällä se läpi takaperin: S saadaan soluun N 1,5 ruuduista N 1,1 ja N 2,4 käyttäen välikkeitä C a ja E, joten ensimmäisenä käytetään sääntöä S C a E. Ylläolevassa taulukossa on sanan w 1 johdossa käytetyt välikkeet alleviivattu. Kokonaisuudessaan jäsennyspuu on seuraavanlainen: 12
S C a E a B C b C a E b a B C b b b 13