Logică și structuri discrete Limbaje regulate și automate Marius Minea marius@cs.upt.ro http://www.cs.upt.ro/ marius/curs/lsd/ 24 noiembrie 2014
Un exemplu: automatul de cafea acțiuni (utilizator): introdu fisă, apasă buton răspuns (automat): toarnă cafea După o acțiune se întâmplă ceva? buton nu fisă (aparent) nu fisă buton da fisă a avut un efect intern: automatul a trecut în altă stare (se comportă altfel la acțiunea buton) fisă fisă buton buton dă două cafele? dacă da, câte fise poate ține minte? una sau mai multe, dar practic un număr finit stări finite Testăm cu diverse secvențe de intrări: corespunde specificației? Putem învăța structura automatului (din comportament) Testarea de conformanță și învățarea: importante în practică
Eliminarea comentariilor în C Comentariu C: încadrat între /* și */ sau toată linia după // Sursa nu are voie să se termine înăuntrul unui comentariu Cum recunoaștem un comentariu? Cum decidem dacă să acceptăm o sursă corectă? Trebuie să reținem unde ne aflăm în prelucrare (starea) în afara comentariului înăuntrul comentariului așteptând un posibil început de comentariu (după /) așteptând un posibil sfârșit de comentariu (după *) Acceptăm programul dacă în final, suntem în afara comentariului altfel respingem (nu acceptăm) programul Desigur, sintaxa C are multe alte reguli în afară de comentarii.
Ce e un limbaj (formal) Fie un alfabet Σ: o mulțime de simboluri (ex. caractere) Un cuvânt finit peste alfabetul Σ e un șir de simboluri din Σ a 1 a 2... a n a i Σ Notăm cu Σ mulțimea tuturor cuvintelor finite peste alfabetul Σ Σ = {a 1 a 2... a n a i Σ} steaua Kleene: zero sau mai multe apariții (în expresii regulate, vezi ulterior) Important: Σ are cuvinte de lungime nelimitată, dar nu infinite Un limbaj nu conține șiruri arbitrare, ele sunt construite după anumite reguli. Un limbaj formal L e o submulțime L Σ, definită după anumite reguli: gramatici, automate, expresii regulate, etc.
Automat finit determinist (DFA) Într-un automat trebuie să definim stările, trecerile dintr-o stare în alta (tranzițiile), starea inițială, și unde dorim să ajungem. Automat finit determinist: o mulțime de stări (unele acceptoare), o stare inițială, și tranziții în funcție de simbolurile de intrare. Un automat finit e un tuplu cu 5 elemente (cvintuplu) (Σ, S, s 0, δ, F ) Σ e un alfabet finit nevid de simboluri de intrare S e o mulțime finită nevidă de stări s 0 S e starea inițială δ : S Σ S e funcția de tranziție (pentru fiecare stare și intrare, dă starea următoare) F S e mulțimea stărilor acceptoare (unde dorim să ajungem)
Exemple de automate deterministe automat de paritate: acceptă șiruri de 0 și 1 cu număr par de 1 0 0 1 0 1 s 0 s 1 sau ca tabelă de tranziții s 0 s 0 s 1 s 1 1 s 1 s 0 s 0 e stare inițială și acceptoare în același timp automat care acceptă cuvinte cu oricâți de b (incl. 0) între doi a b b s a 0 s a 1 s a 0 s a 1 s 2 b s 2 ca δ să fie definită peste tot err a, b e necesară încă o stare err uneori în practică se omite a, b
Limbajul acceptat de un automat Notăm Σ cuvântul vid (fără niciun simbol). Definim inductiv o funcție de tranziție δ cu intrări cuvinte pentru orice s S: δ (s, ) = s n = 0 simboluri δ (s, a 1... a n ) = δ (δ(s, a 1 ), a 2... a n ) pentru n > 0 Altfel spus, δ (s 0, a 1... a n ) = δ (s 1, a 2... a n ) cu s 1 = δ(s 0, a 1 ) obținem starea după prima intrare, și aplicăm δ pe șirul rămas Automatul acceptă cuvântul w Σ dacă și numai dacă δ (s 0, w) F (cuvântul duce automatul într-o stare acceptoare)
Cum reprezentăm un automat? Matrice S Σ cu elemente din S (pentru fiecare stare și intrare, starea următoare) reprezintă explicit fiecare combinație 0 1 s 0 s 0 s 1 s 1 s 1 s 0 Sau: un dicționar care dă pentru fiecare stare funcția de tranziție reprezentată tot ca un dicționar (intrare, stare) Dacă într-o stare multe simboluri duc în aceeași stare următoare, asociem fiecărei stări: un dicționar (intrare, stare) o stare următoare implicită (pentru celelalte intrări)
Automate cu ieșiri numite și traductoare (engl. transducer) scopul nu mai e de a accepta, dispare mulțimea F în plus: un alfabet de ieșire Ω și o funcție de ieșire g automate de tip Moore ieșirea e funcție de stare: g : S Ω automate de tip Mealy ieșirea e funcție de stare și intrare g : S Σ Ω folosite pentru a modela circuite secvențiale
Intersecția, reuniunea și complementul limbajelor Un limbaj recunoscut de un automat se numește limbaj regulat vom vedea că se poate exprima prin expresii regulate Automatul pentru intersecția a două limbaje L 1 L 2 (numit uzual automatul produs) tranziționează simultan în ambele automate acceptă dacă ambele acceptă: Automatul pentru reuniunea a două limbaje L 1 L 2 tranziționează simultan în ambele automate (ca mai sus) acceptă dacă cel puțin unul acceptă Automatul pentru complement L acceptă dacă automatul original nu acceptă
Automate finite nedeterministe (NFA) Exemplu: toate șirurile de a, b, c care se termină în abc a, b, c s a 0 s b 1 s c 2 s 3 Din s 0, primind a, automatul poate rămâne în s 0 sau trece în s 1 automatul poate urma una din mai multe căi Un NFA acceptă dacă există o alegere ducând în stare acceptoare Funcția de tranziție e acum δ : S Σ P(S) dă o mulțime de stări în care poate trece automatul Avantaje: uneori se scrie mai ușor (permite să ghicim tranziția bună) când specificăm un sistem, permite o alegere la implementare
Conversie NFA-DFA Fie un NFA M = (Σ, S, s 0, δ, F ). Construim un DFA echivalent. Noua mulțime de stări va fi S = P(S) reținem mulțimea de stări în care s-ar putea afla M în cel mai rău caz, poate fi exponențial în dimensiunea inițială Obținem M = (Σ, S, s 0, δ, F ) cu S = P(S) δ (q, a) = s q δ(s, a) (pentru fiecare stare s q cu q P(S), reunim mulțimile stărilor în care se ajunge pe simbolul a) F = {s S s F } (mulțimea stărilor care au o stare acceptoare din F )
Conversie NFA-DFA (exemplu) a, b, c a b c 0 1 2 3 Când obținem o nouă mulțime adăugăm o linie la tabel. Scriem tabelul de tranziție cu mulțimea stărilor în care se trece pe fiecare simbol a b c {0} {0, 1} {0} {0} {0, 1} {0, 1} {0, 2} {0} {0, 2} {0, 1} {0} {0, 3} {0, 3} {0, 1} {0} {0} Fiecare mulțime obținută devine o stare în DFA-ul rezultat b, c a a c a Stările acceptoare a c 0 01 b 02 03 sunt cele care conțin o stare acceptoare b din automatul inițial. b, c
Putem exprima mai concis definiția unui limbaj? Un limbaj = o mulțime de cuvinte peste un alfabet Adesea suntem interesați în cuvinte cu structură simplă: un întreg: o secvență de cifre, eventual cu semn un real: parte întreagă + parte zecimală (una din ele opțională), exponent opțional un identificator: litere, cifre, _ începând cu literă sau _ fișiere cu numele 01-titlu.mp3, 02-alttitlu.mp3,... Unele limbaje pot fi recunoscute eficient de automate finite dar scrierea automatului ia efort se poate face mai simplu?
Operații pe limbaje Reuniunea, intersecția și complementul limbajelor regulate sunt limbaje regulate Mai putem defini: Concatenarea limbajelor L1 L2 = {w 1 w 2 w 1 L 1, w 2 L 2 } Închiderea Kleene (repetiția) L = {w n N.w = w 1 w 2... w n, w i L} nu repetiția aceluiași șir, ci concatenarea oricăror șiruri luând n = 0, rezultă L pentru orice L reprezintă șirul vid (niciun simbol, lungime 0)
Expresii regulate: definiție formală O expresie regulată descrie un limbaj (regulat). O expresie regulată peste un alfabet Σ e fie: 3 cazuri de bază: a limbajul vid denotă limbajul {} (cu șirul vid) denotă limbajul {a} cu a Σ 3 cazuri recursive: date e 1, e 2 expresii regulate, și următoarele sunt: (e 1 + e 2 ) reuniunea limbajelor în practică, notată adesea e 1 e 2 (alternativă, sau ) (e 1 e 2 ) concatenarea limbajelor e 1 închiderea Kleene a limbajului
Reguli de scriere și exemple Omitem paranteze cănd sunt clare din relațiile de precedență cel mai prioritar:, apoi concatenare și apoi reuniune + punctul pentru concatenare se omite În practică se mai folosesc abrevierile e? pentru e + (e, opțional) e + pentru e \ (e, cel puțin o dată) (0 + 1) mulțimea tuturor șirurilor din 0 sau 1 (0 + 1) 0 ca mai sus, încheiat cu 0 (numere pare în binar) 1(0 + 1) + 0 numere binare, fără zerouri inițiale inutile
Orice expresie regulată e recunoscută de un automat Construim prin inducție structurală Pentru cazurile de bază nu are stare acceptoare a a starea inițială e acceptoare acceptă simbolul a în celelalte trei cazuri, combinăm automatele limbajelor date rezultă un automat finit nedeterminist cu tranziții
Conversia expresie regulată automat Construcția pentru reuniune e 1 s i1 s f 1 e 2 s i2 s f 2 s i2 s f 2 e 1 + e 2 si1 s f 1 Construcția pentru închiderea Kleene e s i s f e s i s f
Conversia expresie regulată automat Construcția pentru concatenare e 1 s i1 s f 1 e 2 s i2 s f 2 e 1 e 2 s i1 s f 1 s i2 s f 2 În general, nu putem contopi s f 1 și s i2 : ajunși în s f 1 nu avem voie să revenim în e 1. Însă construcțiile de până acum asigură: o unică stare inițială, în care nu se revine o unică stare acceptoare, din care nu ies tranziții Atunci putem contopi la concatenare capetele lui e 1 și e 2.
Conversie din expresie regulată în automat Fie expresia (0+10)*(1+). Construim (comasând pașii triviali): 0 0 1 2 3 1 0 4 5 6 1 7 8 9 O tranziție se face spontan, fără a consuma un simbol de intrare ajuns într-o stare s, e ca și ajuns în orice stare s legată de s doar prin -tranziții (închiderea tranzitivă a relației definite de ) Deci, aflat în 0, e ca și cum s-ar afla în 1, 2, 4, 8 sau 9 Aflat în 7, e ca și cum s-ar afla în 1, 2, 4, 8, 9
Conversie din NFA cu tranziții în DFA 0 0 1 2 3 1 0 4 5 6 0 1 012489 1234789 59 1234789 1234789 59 59 1246789 1246789 1234789 59 s0 1 7 8 9 Liniile 1, 2 și 4 au destinații identice stările sunt echivalente. automat cu doar două stări (ignorând starea de eroare ) 0 0 1 s1 1
Conversia din automat în expresie regulată Dacă sunt mai multe noduri acceptoare, adaugăm un nod acceptor unic (cu tranziții spre el) Eliminăm pe rând fiecare nod în afară de cel inițial și acceptor: pentru orice nod intermediar i de eliminat pentru orice pereche (s, d) adaugă la muchia s d limbajul L si L ii L id
Conversie din automat în expresie regulată Șiruri de 0 și 1 care nu au doi 1 consecutivi 0 0 pe 1, trece în stare cu tranziție doar pe 0 0 1 1 Ambele stări sunt acceptoare adăugăm o unică stare acceptoare 0 0 0 10 0 1 1 f Eliminăm 1: 0 10 0 0 1 f Obținem astfel limbajul (0+10)*(1+) 0 f +1
Minimizarea automatelor Două stări s 1 și s 2 pot fi deosebite dacă există un cuvânt w care dintr-una din stări conduce la o stare acceptoare, și din cealaltă, nu δ (s 1, w) F δ (s 2, w) F Două stări care nu pot fi deosebite sunt echivalente pot fi înlocuite cu o singură stare Un DFA e minimal dacă nu există un automat cu mai puține stări care acceptă același limbaj. Diverși algoritmi de minimizare (ex. Hopcroft-Ullman, Moore) inițial, partiție cu 2 blocuri: F, S \ F (stări acceptoare sau nu) (o împărțire în potențiale clase de echivalență) desparte un bloc din partiție dacă pe un simbol, stările nu trec toate în același bloc din partiție (pot fi deosebite)
Conversie NFA-DFA și minimizare (exemplu) Cuvinte din a, b cu subșir aba: ghicim când începe subșirul dorit a, b a, b a b 0 01 0 a b a 01 01 02 0 1 2 3 02 013 0 013 013 023 023 013 03 03 013 03 Stările care conțin 3 (stare acceptoare) sunt acceptoare. Aici, ele trec tot timpul în stări acceptoare, deci sunt echivalente (caz simplu), și le putem comasa într-o singură stare (numită 3). b a a, b a b a 0 01 02 3 b
Recapitulare Un automat determinist definește un limbaj acceptat. Un astfel de limbaj se numește limbaj regulat. El poate fi exprimat și printr-o expresie regulată. Intersecția, reuniunea, și complementarea limbajelor regulate produc limbaje regulate (deci pot fi recunoscute de automate finite) Automatele finite nedeterministe se pot transforma în deterministe (deci recunosc tot limbaje regulate) dar numărul de stări poate crește exponențial Automatele finite pot fi minimizate, comasând stările echivalente. Automatele deterministe și nedeterministe și expresiile regulate au aceeași putere expresivă (descriu limbaje regulate).