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
lfa2021:proiect [2021/10/07 13:26]
pdmatei
lfa2021:proiect [2021/11/24 14:21] (current)
stefan.stancu [Structura punctajului]
Line 1: Line 1:
 ===== Proiect LFA - Lexer in Python sau Haskell ===== ===== Proiect LFA - Lexer in Python sau Haskell =====
  
-  * **[[lfa:​proiect:​etapa1 | Etapa 1 - Lexer cu AFD-uri]]** +==== Structura punctajului ====
-  * **[[lfa:​proiect:​etapa2 | Etapa 2 - Transformare Regex - AFD]]** +
-  * **[[lfa:​proiect:​etapa3 | Etapa 3 - Lexer cu Regexuri si parser]]**+
  
 +  * Proiectul valoreaza **3p**, care se impart egal intre etape.
 +  * O etapa se considera **trecuta**,​ daca, concomitent:​ (i) **a fost trimisa la deadline** si (ii) $math[pr=]70% din teste au trecut.
 +  * Daca o etapa **nu** a fost **trecuta**,​ ea poate fi trimisa sau retrimisa oricand, pentru $math[pmin=]60% din punctaj (adica 60% din valoarea testelor care trec).
 +  * Orice etapa **trecuta** poate fi retrimisa oricand, fara depunctare, pentru a obtine puncte in plus pentru teste aditionale care trec.
 +  * Exemple:
 +    * Studentul MP nu a **trecut** etapele 1 si 2 (nu a trimis etapa 1 la timp, si doar jumatate din teste au trecut la etapa 2), insa la etapa 3 a trimis tot proiectul 100% functional (toate testele trec). Punctajul lui este: 0.6p (Etapa 1) + 0.6p (Etapa 2) + 1p (Etapa 3) = 2.2p.
 +    * Studentul DM a **trecut** etapa 1 (cu 70% din teste), la fel si etapa 2 (tot cu 70% din teste). In loc sa trimita etapa 3, a lucrat la etapa 1 si a reusit sa faca toate testele sa treaca la aceasta. Punctajul lui este 1p (Etapa 1) + 0.7p (Etapa 2) = 1.7p.
 +    * Studentul XZ nu a **trecut** etapa 1 (a trimis la timp insa doar 50% din teste trec) si nu a trecut nici etapa 2 (din nou, a trimis la timp, insa doar 60% din teste trec). Etapa 3 nu a fost trimisa. Punctajul lui este 0.3p la etapa 1 (1p * 0.5teste * 0.6penalty) si 0.36p la etapa 2 (1p * 0.6teste * 0.6penalty))
 +  * **Ultima etapa va avea un deadline hard final** (punctajul obtinut pe aceasta este exclusiv cel de pe teste). Nu se mai pot trimite submisii (la nici o etapa), dupa expirarea deadline-ului acesta.
  
-====== Etapa 4 - Parsare Regex si limbaj ====== 
  
-Serializare lexer (ca sa ne legam direct cu etapa 1). 
- 
-Apoi parsare. Doua programe. 
- 
-==== Limbajul 1: Imperative ==== 
- 
-<​code>​ 
-<​prog>​ ::= <​variable>​ '​='​ <​expr>; ​      | 
-           begin <​instruction_list>​ end | 
-           while (<​expr>​) do <​prog>​ od    | 
-           if (<​expr>​) then <​prog>​ else <​prog>​ fi  
- 
-<​instruction_list>​ ::= [<​prog>​] ​ 
- 
-<​expr>​ ::= <​expr>​ + <​expr>​ | <​expr>​ > <​expr>​ | <​expr>​ == <​expr>​ | <​variable>​ | <​integer> ​ 
-                    
-</​code>​ 
- 
-==== Limbajul 2: Lisp ==== 
- 
-==== Limbajul 3: Html ??? ==== 
- 
- 
-===== Metodologia de testare: ===== 
-Combinam expresii din fisierul de referinta in specificatii. Mai sunt necesare detalii de clarificat. 
- 
-====== Etapa 3 - Conversie AFN AFD ====== 
- 
-===== Metodologia de testare: ===== 
- 
-Asemanator cu etapa 2. Folosim acelasi fisier de input, insa generam, in locul expresiilor PRENEX, nfa-uri, din lista de referinta. 
- 
-====== Etapa 2 - Conversie Regex AS la AFN ====== 
- 
-Obiectivul etapei 2 este conversia unei expresii regulate la un Automat Finit Nedeterminist. Aceasta transformare este un prim pas in conversia unei **specificatii** (expresia regulata) intr-o **implementare** (AFN). 
- 
-===== Descrierea inputului ===== 
-  * un prim pas in aceasta etapa este parsarea expresiilor regulate, si construirea unui arbore pentru acestea. Spre exemplu, expresia: ''​ab|c*''​ are asociat arborele: ''​UNION(CONCAT(a,​b),​STAR%%(%%c))''​. Datorita regulilor de precenta ale operatorilor,​ construirea acestui arbore este mai complicata, iar aceast task va fi amanat pentru etapa 4. Pentru a simplifica problema parsarii, expresiile vor fi prezentate **in forma prenex**. 
-  * In **forma prenex**, **//​operatorul preceda intotdeauna//​** operanzii. Prezentate astfel, expresiile pot fi parsate mult mai usor. Spre exemplu, expresia de mai sus in forma **prenex** este ''​UNION CONCAT a b STAR c''​. Observati similaritatea cu reprezentarea de arbore. ​ 
-  * Un test consta intr-un fisier ''​.in''​ ce contine: 
-    * **pe prima linie**, o expresie regulata in forma prenex 
-    * **in continuare**,​ cate un cuvant pe o linie 
-  * Exemplu: 
-<​code> ​ 
-UNION CONCAT a b STAR c 
-abc 
-abcccc 
-ccc 
-ab 
-</​code>​ 
- 
-===== Cerinta si descrierea outputului ===== 
- 
-Implementarea voastra va primi un fisier de test ''<​testxy.in>'',​ va construi **AFN-ul asociat** expresiei regulate, apoi va verifica daca acesta accepta cuvintele din fisierul de test. Implementarea va scrie la output un fisier ''<​testxy.out>''​ ce va contine, pe cate o linie ''​ACCEPT''​ sau ''​REJECT'',​ pentru fiecare din cuvintele de la input. Exemplu de fisier de output pentru input-ul anterior: 
- 
-<​code>​ 
-REJECT 
-REJECT 
-ACCEPT 
-ACCEPT 
-</​code>​ 
- 
-**Atentie**:​ Implementarea va fi punctata doar in masura in care respecta cerinta (se construieste un AFN folosind algoritmul prezentat la curs). 
- 
-===== Identitatea starilor ===== 
- 
-Implementarea algoritmului lui Thomson este complicata de faptul ca starile sunt reprezentate ca intregi. Spre exemplu, AFN-urile pentru expresiile ''​0''​ si ''​1''​ vor avea fiecare cate doua stari, cel mai probabil numerotate de la 0 la 1. Pentru a construi AFN-ul pentru ''​0|1'',​ trebuie sa **renumerotam** starile tinand cont de: 
-    * faptul ca trebuie sa creem o noua stare initiala, si una finala 
-    * starile AFN-ului pentru ''​0''​ trebuie sa fie **disjuncte** fata de cele ale lui ''​1''​ 
-    * logica AFN-urilor (ce cuvinte accepta) nu trebuie sa influentata de numerotare 
-    * renumerotarea trebuie sa fie **suficient de generala** (vom mai avea nevoie de ea la etapa 3), astfel incat sa se comporte ca un **map** (o aplicatie de //functie// peste stari). In aceasta etapa, //functia// va fi ''​+x''​. 
- 
-===== Parsarea formei Prenex ===== 
- 
-Pentru a parsa forma Prenex, avem nevoie de o stiva care sa retina parti ale expresiei / operatii parsate deja. Vom interactiona in doua feluri cu stiva: 
-  * **reducerea expresiilor** (sau cooling). ​ 
-      * Exemplul 1: daca pe stiva avem: ''​0 | Star(?) | ... '',​ atunci vom inlocui cele doua expresii cu : ''​ Star(0) | ...'' ​ 
-      * Exemplul 2: daca pe stiva avem: ''​Star(0) | Concat(?,?) | ... '',​ rezultatul reducerii va fi: ''​Concat(Star(0),?​) | ...''​ 
-  * ** adaugarea expresiilor**:​ vom citi operatorul sau operandul curent, si vom adauga elementele corespunzatoare pe stiva. ​ 
- 
-Implementarea voastra trebuie sa combine in mod eficient **adaugarea** cu **reducerea**. 
- 
-===== Developlement si testare ===== 
- 
-Pentru a testa AFN-urile generate de voi, aveti nevoie de o modalitate de afisare a acestora in text. Va sugeram sa ii adaugati si modalitate grafica. Atasam un script Python3 care poate fi folosit pentru a desena AFN-uri: 
-  * script-ul primeste in linia de comanda un fisier CSV ce contine un AFN, si deseneaza AFN-ul respectiv. 
-  * va fi necesar sa instalati anumite dependinte pentru a rula scriptul (e.g. networkx, numpy). 
-  * trebuie sa scrieti o procedura de afisare a unui AFN sub forma de CSV. Atasam un exemplu (AFN-ul generat pentru expresia ''​00*''​):​ 
-<​code>​ 
-from,​char,​to 
-0,0,1 
-1,ε,2 
-2,ε,3 
-2,ε,f5 
-3,0,4 
-4,ε,3 
-4,ε,f5 
-</​code>​ 
-      * prima linie este obligatorie si aceeasi pt orice AFN 
-      * tranzitiile sunt codificate pe linii, sub forma: ''​stare initiala, caracter, stare finala''​ 
-      * pentru legibilitate,​ starile finale au fost precedate de simbolul ''​f''​ 
-  * [TODO: link catre script pe github-ul LFA] 
- 
- 
- 
-===== Sugestii de implementare pentru Python ===== 
- 
-  * Folositi **clase** pentru reprezentarea interna a unei expresii regulate. Vom refolosi aceasta reprezentare in etapa 4. 
-  * Alegeti o implementare pentru AFN-uri care sa permita **refolosirea** (extinderea) ei pentru situatii in care **starile** au alta structura. (multimi de intregi in loc de intregi). 
-  * In procesul de parsare, instantiati cu ''​None''​ expresii a caror parsare este in curs de desfasurare. Ele vor fi modificate ulterior. 
- 
-===== Sugestii de implementare pentru Haskell ===== 
- 
-  * In tipul vostru de date care va retine expresii, adaugati constructori pentru expresii a caror parsare este in curs de desfasurare. Acestia vor fi folositi doar in timpul parsarii formei prenex. Spre exemplu, pe langa ''​Concat :: Expr -> Expr -> Expr'',​ definiti ''​LConcat :: Expr -> Expr''​. Acesta va codifica faptul ca am citit doar partea din **stanga** a unei concatenari. Asemanator, ''​LRConcat :: Expr''​ va codifica faptul ca am citit o concatenare si urmeaza sa citim operanzii acesteia. 
-  * Interactiunea cu stiva se face cel mai natural folosind **pattern matching** (si este mult mai simplu de implementat in Haskell). ​ 
-  * Pentru codificarea de NFA-uri: 
-    * Adaugati clasei ''​FA'',​ definita la etapa anterioara, metoda ''​relabel''​ (si implementati-o):​ 
- 
-<code Haskell> 
-class FA t where 
-    fromList :: State s => Set Char -> s -> [(s,​Char,​s)] -> [s] -> t s 
-    states :: (State s) => t s -> [s] 
-    relabel :: (State s, State s') => (s -> s') -> t s -> t s' 
-    size :: (State s) => t s -> Integer 
-</​code>​ 
-    * Bonus: de ce nu am folosit ''​fmap'',​ in locul functiei ''​relabel''? ​ 
-    ​ 
-    * Definiti tipul ''​Nfa a''​ si inrolati-l in clasa anterioara. O definitie (mai multe sunt posibile) este urmatoarea: 
-<code Haskell> 
-type NDelta a = Map (a,Char) (Set a) 
-data Nfa a = Nfa {nsigma :: Set Char, ninitial :: a, ndelta :: (NDelta a), nfin :: [a]} 
-</​code>​ 
- 
- 
- 
- 
- 
-===== Metodologia de testare: ===== 
-  * construim un fisier mare cu expresii regulate **de mana**, peste diverse alfabete, care sa acopere cat mai multe din toate situatiile posibile, impreuna cu cuvinte acceptate sau nu. Acest fisier va trebui discutat eventual cu fiecare dintre noi. Exemplu: 
-  <​code>​ 
-  0 
-  ACCEPT 0 
-  REJECT 01 
-  REJECT 10 
-  ​ 
-  00* 
-  ACCEPT 0000000000 
-  REJECT 1 
-  REJECT ε 
-  </​code>​ 
-  * parsam expresiile cu implementarea noastra, generam forma prenex, si creem **mai multe perechi de fisiere separate, input-output** - in fiecare fisier input se va gasi o expresie si cuvintele de test. Ficare fisier de output va marca rezultatul asteptat. Exemplu: 
-   * Test0.in 
- <​code>​ 
-  0 
-  0 
-  01 
-  10 
- </​code>​ 
-   * Test0.out 
- <​code>​ 
- ​ACCEPT ​ 
- ​REJECT 
- ​REJECT 
- </​code>​ 
-   * Test1.in 
-  <​code>​ 
-  CONCAT 0 STAR 0 
-  0000000000 
-  1 
-  ε 
-  </​code>​ 
-   * Test1.out 
-  ​ 
-  <​code>​ 
-  ACCEPT 
-  REJECT 
-  REJECT 
-  </​code>​ 
- 
-  * Vom verifica, fiecare, ca outputul este corect, folosind implementarile noastre. 
  
 +  * **[[lfa:​proiect:​etapa1 | Etapa 1 - Lexer cu AFD-uri]]**
 +  * **[[lfa:​proiect:​etapa2 | Etapa 2 - Transformare Regex - AFD]]**
 +  * **[[lfa:​proiect:​etapa3 | Etapa 3 - Lexer cu Regexuri si parser]]**
 +  * **[[lfa:​proiect:​checker | Checker]]**