Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revision Previous revision
Next revision
Previous revision
lfa:exercise-sheet-2-solution [2021/01/18 16:42]
pdmatei
lfa:exercise-sheet-2-solution [2021/01/18 19:29] (current)
pdmatei
Line 6: Line 6:
  
 Pentru a intelege mai bine $math[fst(L)],​ il putem aplica pe un limbaj finit, dar si pe unul infinit: Pentru a intelege mai bine $math[fst(L)],​ il putem aplica pe un limbaj finit, dar si pe unul infinit:
-  * $math[fst(\{A,​BAAB,​AB\}= \{BA,A\}]+  * $math[fst(\{A,​BAAB,​AB\} = \{BA,A\}]
   * $math[fst(L(A^*B^+)) = \{B,​A,​AA,​BB,​AB,​ ... \}]   * $math[fst(L(A^*B^+)) = \{B,​A,​AA,​BB,​AB,​ ... \}]
  
-Conditia $math[\mid x\mid = \mid w\mid]+Conditia $math[\mid x\mid = \mid w\mid] ​ne obliga sa identificam **mijlocul** cuvintelor din $math[L]. In figura de mai jos, pe primul rand, sunt prezentate doua AFN-uri: unul pentru limbajul $math[L(A^*B^+)] si cel pentru $math[L(B^+A^*) = reverse(L(A^*B^+))]. 
 + 
 +Daca am putea executa, simultan, primul AFN pe cuvantul $math[AABB],​ si al doilea AFN pe cuvantul $math[BBAA],​ ambele automate ar ajunge in **aceeasi** stare dupa primele doua tranzitii (si consumarea prefixului $math[AA]), ceea ce indica faptul ca $math[AA \in fst(L(A^*B^+))]. 
 + 
 +Putem simula acest proces simultan construind un automat nou pentru limbajul $math[fst(L)] (ultimul rand din figura de mai jos pt exemplul nostru), plecand de la $math[L(A) = L] in care starile sunt de forma: 
 +  * $math[(q,​X)] unde $math[q] este o stare iar $math[X] este o multime de stari. 
 +  * **starea initiala** este $math[(q_0,​F)] - ceea ce indica faptul ca simulam automatul $math[A] incepand din starea lui initiala, si //​simultan//​ din toate starile lui finale; 
 +  * notam cu $math[pre(X) = \{r \in K\mid \exists c \in \Sigma . \delta(c,r) \in X\}] multimea tuturor **predecesorilor** unei stari din $math[X] (pe oricare simbol) 
 +  * pentru fiecare stare $math[Q = (q,X)] si fiecare tranzitie $math[\delta(q,​c) = q'] construim starea $math[Q'​=(q',​pre(X))] si tranzitia de la $math[Q] pe simbolul $math[c] catre $math[Q'​]. Aceasta semnifica faptul ca, pentru fiecare //​pas-inainte//​ al automatului $math[A], pe simbolul $math[c], urmarim si un //pas inapoi// catre toti predecesorii lui $math[X]. 
 +  * fiecare stare $math[(q,​X)] cu proprietatea ca $math[q \in X] este marcata ca stare finala (numarul de //​pasi-inainte//​ este egal cu cel de //​pasi-inapoi//​. 
 + 
 +{{ :​lfa:​sheet-solutions-3.jpg?​600 |}} 
 + 
 +Demonstratia ca automatul construit mai sus accepta exact $math[fst(L)] este lasata in continuare ca exercitiu.
  
-{{ :​lfa:​sheet-solutions-3.jpg?​500 |}} 
  
 2. Fie $ L_3 = \{ w \in \{0, 1\}^* \mid \#_{01}(w) = \#_{10}(w) \}$ (i.e. cuvintele conțin același număr de secvențe "​01"​ și "​10"​). Demonstrați că $ L_3$ //este regulat//. 2. Fie $ L_3 = \{ w \in \{0, 1\}^* \mid \#_{01}(w) = \#_{10}(w) \}$ (i.e. cuvintele conțin același număr de secvențe "​01"​ și "​10"​). Demonstrați că $ L_3$ //este regulat//.
 +
 +//​**Solutie:​**//​
 +
 +Scriem o expresie regulata pentru $math[L_3]. Pentru a gasi expresia corecta, putem incepe prin cateva observatii simple:
 +  * $math[L(0^*) \subseteq L_3]
 +  * $math[L(1^*) \subseteq L_3]
 +  * $math[L(0^+1^+0^+)^* \subseteq L_3]
 +  * $math[L(1^+0^+1^+)^* \subseteq L_3]
 +
 +Ultimele 2 subpuncte acopera atat sirurile care incep cu 1 (si trebuie obligatoriu sa se termine cu un 1), respectiv cele care incep cu 0 (si se termina cu 0). Putem combina expresiile de mai sus intr-una singura, facand aparitia 1-urilor (respectiv 0-urilor) intercalate sa fie optionala. Rezultatul final este: $math[(0^+1^*0^+)^* \cup (1^+0^*1^+)^* \cup 0 \cup 1]
  
 3. Demonstrați că $ L = \{ a^nb^mc^{n-m} \mid n \ge m \ge 0 \}$ //nu este// un limbaj regulat, fără a folosi izomorfisme. 3. Demonstrați că $ L = \{ a^nb^mc^{n-m} \mid n \ge m \ge 0 \}$ //nu este// un limbaj regulat, fără a folosi izomorfisme.
 +
 +//​**Solutie:​**//​
 +
 +Daca notam $math[k = n-m], atunci $math[ n = k + m] iar limbajul devine: $math[\{a^{k+m}b^mc^k \mid n,k \geq 0\}]. Pentru a folosi lema de pompare, alegem cuvantul $math[w_n = a^nb^n] (numarul de $math[c]-uri este 0, deci numarul de $math[a]-uri este egal cu numarul de $math[b]-uri). De asemenea, alegem $math[i=0]. Cum $math[\mid xy\mid \leq n], inseamna ca fragmentul $math[y] contine doar $math[a]-uri,​ asadar $math[xy^0z] va contine cel putin un $math[b] mai mult decat numarul de $math[a]-uri,​ deci cuvantul nu va apartine limbajului.
  
 4. Demonstrați că, pentru orice limbaj $ L$ //regulat// și //​infinit//,​ există două limbaje $ L_1$, $ L_2$ //​regulate//​ și //​infinite//,​ astfel încât $ L_1 \cap L_2 = \emptyset$ și $ L_1 \cup L_2 = L$. 4. Demonstrați că, pentru orice limbaj $ L$ //regulat// și //​infinit//,​ există două limbaje $ L_1$, $ L_2$ //​regulate//​ și //​infinite//,​ astfel încât $ L_1 \cap L_2 = \emptyset$ și $ L_1 \cup L_2 = L$.
 +
 +//​**Solutie:​**//​
 +
 +Daca $math[L] este un limbaj regulat infinit, atunci Lema de Pompare este adevarata pentru acesta, cu alte cuvinte $math[\exists n] astfel incat pentru orice cuvant $math[w] avand lungime mai mare sau egala cu $math[n], acesta poate fi impartit in $math[xyz] astfel incat $math[\mid xy\mid \leq n], $math[y\neq\epsilon] si \math[\forall k. xy^kz\in L]. Demonstratia Lemei de Pompare arata ca un astfel de $math[n] poate fi numarul de stari ale unui AFD care accepta $math[L]. Urmarind acelasi rationament,​ toate cuvintele //suficient de mari// sunt acceptate //prin traversarea unei stari// de cel putin doua ori:
 +
 +$math[(q_0,​xyz) \vdash^* (q,yz) \vdash^* (q,z) \vdash (q_f, \epsilon)]
 +
 +Plecand de la AFD-ul $math[A] care respecta conditia de mai sus, si de la //un ciclu// din acesta, de forma $math[q, q_1, q_2, \ldots q_k, q], construim doua AFD-uri:
 +  * $math[A_1] care contine aceleasi stari precum $math[A], plus starile $math[q',​ q'_1, q'_2, \ldots q'_k]. Tranzitia de la $math[q_k] la $math[q] este modificata catre $math[q'​],​ iar cea de la $math[q'​_k] - catre $math[q]. Restul tranzitiilor adaugate functioneaza exact ca cele din ciclul automatului $math[A]. $math[L(A_1)] va accepta toate cuvintele mai mici decat $math[n], precum si cele de forma $math[xy^{2k}z] (in urma loop-unrolling-ului).
 +  * $math[A_2] va fi construit dupa aceeasi strategie, astfel incat sa accepte **doar** cuvintele de forma $math[xy^{2k+1}z]:​
 +    * caile mai scurte de $math[k] de la starea initiala la o stare finala vor fi eliminate.
 +    * toate celelalte caile care nu trec prin $math[q] si care ajung la o stare finala vor fi eliminate. In felul acesta, avem garantia ca $math[L(A_1) \cap L(A_2) = \emptyset]
 +  * in acelasi timp $math[L(A_1) \cup L(A_2) = L(A)]