Differences

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

Link to this comparison view

Next revision
Previous revision
aa:lab:sol:2 [2023/10/21 21:21]
tpruteanu created
aa:lab:sol:2 [2025/10/12 18:49] (current)
dmihai
Line 1: Line 1:
-====== ​Computing ​====== +===== Soluții notații asimptotice și analiză amortizată ​=====
-/* +
-<note important>​ +
-Solutii: ​ https://​drive.google.com/​file/​d/​1Y6JV-pDyuvejx3g8KL6SpWzbp52VMWnY/​view?​usp=sharing +
-</​note>​ +
-*/+
  
-===== Exerciții =====+==== Notații asimptotice ​====
  
-1.+1. Dați exemple de câte o funcție din următoarele clase de complexitate:​
  
-^  ^ 0 ^ 1 ^ $\square +O(n)
-| $ q_1$ | $ q_10\rightarrowq_11\rightarrow$ | $ q_2\square, \leftarrow$ ​ |  +<​note>​ 
-q_2| $ Y, 0, -$ | $ N, 1, -$ | $ N, \square, -$  | +Trebuie sa gasim functii care cresc maxim la fel de repede ca f(n)=n.  
 +Exemple soluții posibile: g(n)=n+6g(n)=8n+7 (aceeasi crestere), 
 +g(n)=log(n) (crestere mai mica) 
 +</​note>​ 
 +$Ω(log(n))$ 
 +<​note>​ 
 +Trebuie sa gasim functii care cresc mai repede sau la fel de repede ca f(n)=n^2.  
 +Exemple soluții posibile: g(n)=100*log(n)+5(aceeasi crestere)g(n)=n^3
 +g(n)=nlog(n) (mai repede) 
 +</​note>​ 
 +$θ(n^2)$ 
 +<​note>​ 
 +Trebuie sa gasim functii care cresc la fel de repede ca f(n)=log(n).  
 +Exemple soluții posibile: g(n)=a*n^2+b*n+c*log(n)+da>(aceeasi crestere ca n^2fiind dominant in functie) 
 +</​note>​
  
-(ꞓ, q<​sub>​1</sub>, 100⊢ (1, q<sub>1</sub>, 00) ⊢ (10, q<​sub>​1</sub>0) ⊢ (100q<​sub>​1</​sub>​⊢ (10, q<​sub>​2</sub>, 0) ⊢ (10, Y, 0)+(1/n)
 +<note> 
 +Trebuie sa gasim functii care cresc strict mai repede decat f(n)=1/n. 
 +Cum 1/n este o functie descrescatoaresolutia este orice functie crescatoare. 
 +Exemple soluții posibile: g(n)=cc = constantag(n)=n+23, g(n)=nlogn+n^4 etc. 
 +</note>
  
-(ꞓ, q<​sub>​1</​sub>,​ 1011⊢ (1, q<sub>1</​sub>,​ 011) ⊢ (10, q<​sub>​1</​sub>,​ 11⊢  +$ o(3^n)
-(101, q<​sub>​1</​sub>,​ 1⊢ (1011q<sub>1</sub>, □) ⊢ (101, q<​sub>​2</​sub>,​ 1) ⊢ (101, N, 1)+<note> 
 +Trebuie sa gasim functii care cresc strict mai incet decat f(n)=3^n. 
 +Exemple soluții posibile: g(n)=n^p,p>=0  etc. 
 +</note>
  
----- 
  
-2.+2. Verificați valoarea de adevăr a următoarelor propoziții:​
  
-^  ^ 0 ^ 1 ^ $\square +√n∈O(logn)
-| $ q_1$ | $ q_1, 1, \rightarrow$ | $ q_1, 0, \rightarrow$ | $ q_2, \square, \leftarrow$ ​ |  +<​note>​ 
-| $ q_2$ | $ q_21\rightarrow$ | $ q_2, 0, \rightarrow$ | $ q_1, \square, \rightarrow$ | +f(n)=logng(n)=√n. Cum f si g sunt functiile f si g sunt monotone si cresctoareverific afirmatia utilizand limite.
  
-(ꞓ, q<​sub>​1</​sub>,​ 1011⊢ (0, q<​sub>​1<​/sub>, 011⊢ (01, q<​sub>​1</​sub>,​ 11⊢ (010, q<​sub>​1<​/sub>, 1⊢ (0100, q<​sub>​1</​sub>,​ □⊢ +lim(n→∞)(g(n)/f(n))=lim(n→∞)(√n/log(n))=(l'​Hospital)lim(n→∞)(n/2*√n)=1/2*lim(n→∞)(√n)=+∞ =**Fals** 
-(010, q<​sub>​2</​sub>,​ 0⊢ (0101, q<​sub>​2</​sub>,​ □⊢ (0101□, q<​sub>​1</sub>, □) ⊢ +</note>
-(0101, q<​sub>​2</​sub>,​ □⊢ (0101□, q<​sub>​1</​sub>,​ □⊢ (0101, q<sub>2</sub>, □) ⊢ ...\\ \\+
  
-Se observă că mașina ciclează pentru acest input.+$ logn∈O(log(log n))$ 
 +<​note>​ 
 +f(n)=log(logn),​ g(n)=logn. Cum f si g sunt functiile f si g sunt monotone si cresctoare, verific afirmatia utilizand limite.
  
-----+lim(n→∞)⁡(g(n)/​f(n))=lim(n→∞)⁡(logn/​log(log n))=(l'​Hospital)lim(n→∞)⁡(1/​n / 1/logn * 1/​n)=1/​2*lim(n→∞)⁡(logn)=+∞ => **Fals** 
 +</​note>​
  
-3. Soluție: +n∈O(√n logn)
-^  ^ 0 ^ 1 ^ $\square +<​note>​ 
-| $ q_1$ | $ q_1, 0, \rightarrow$ | $ q_1, 1, \rightarrow$ | $ q_2, 1, \leftarrow$ ​ |  +f(n)=√n logng(n)=n. Cum f si g sunt functiile f si g sunt monotone si cresctoareverific afirmatia utilizand limite.
-| $ q_2$ | $ q_20\leftarrow$ | $ q_2, 1, \leftarrow$ | $ q_1, 1, \rightarrow$ | +
  
-(ꞓ, q<​sub>​1</​sub>,​ 01⊢ (0, q<​sub>​1<​/sub>, 1) ⊢ (01, q<​sub>​1</​sub>,​ □⊢ (0, q<​sub>​2</​sub>,​ 11⊢ (□, q<​sub>​2<​/sub>, 011⊢ (□, q<​sub>​2</​sub>,​ □011⊢ +lim(n→∞)(g(n)/f(n))=lim(n→∞)(n/√n logn)=lim(n→∞)(√n/logn)=(l'​Hospital)lim(n→∞)(1/2 * 1/n^2 / 1/n)=1/2*lim(n→∞)(1/n)=0 =**Fals** 
-(1, q<​sub>​1<​/sub>, 011⊢ (10, q<​sub>​1</​sub>,​ 11⊢ +</note>
-(101, q<​sub>​1</​sub>,​ 1⊢ (1011, q<​sub>​1</sub>, □) ⊢ (101, q<​sub>​2</sub>, 11) ⊢ +
-(10, q<​sub>​2</sub>, 111⊢ (1, q<​sub>​2</​sub>,​ 0111⊢ (□, q<​sub>​2<​/sub>, 10111⊢ (□, q<sub>2</sub>, □10111) ⊢ ...\\ \\+
  
-Se observă că mașina ciclează pentru acest inputEa va continua să scrie 1 la stânga și la dreapta pe bandă.+$ n+logn∈θ(n)$ 
 +<​note>​ 
 +f(n)=n, g(n)=n + lognCum f si g sunt functiile f si g sunt monotone si cresctoare, verific afirmatia utilizand limite.
  
-----+lim(n→∞)⁡(g(n)/​f(n))=lim(n→∞)⁡(n + logn/n)=1 + lim(n→∞)⁡(logn/​n)=(l'​Hospital)1 + lim(n→∞)⁡(1/​n)= 1 => **Adevarat** 
 +</​note>​
  
-4+$ log(nlogn)∈θ(logn)$ 
 +<​note>​ 
 +f(n)=logn, g(n)=log(nlogn). Cum f si g sunt functiile f si g sunt monotone si cresctoare, verific afirmatia utilizand limite.
  
-Acest exercițiu face referire la conceptul de Busy Beaver, mai precis cazurile cu 2 simboluri și 1,2 sau 3 stări. Aceasta este o problemă interesantă și deschisă din perspectiva teoriei calculabilității și a complexității algoritmice. Pentru a găsi numărul maxim de tranziții și funcția de tranziție $ \delta$, este nevoie de o abordare exploratorie și de un efort considerabil de analiză pentru fiecare configurație specifică a mașinii. \\ \\ +lim(n→∞)⁡(g(n)/​f(n))==(l'​Hospital)lim(n→∞)⁡(1/​nlogn*(logn+1) ​ /  1/​n)=lim(n→∞)⁡(1/​logn*(logn+1)) =lim(n→∞)⁡(1 + 1/logn)=1 => **Adevarat** 
 +</​note>​
  
 +$ √n∈ɷ(log n)$
 <​note>​ <​note>​
 +f(n)=logn, g(n)= √n. Cum f si g sunt functiile f si g sunt monotone si cresctoare, verific afirmatia utilizand limite.
  
-Mai multe informații ​găsiți aici: https://en.wikipedia.org/wiki/​Busy_beaver +lim(n→∞)⁡(g(n)/f(n))=lim(n→∞)⁡(√n/logn)= (l'​Hospital)lim(n→∞)⁡(1/2*√n)= ∞ => **Adevarat**
 </​note>​ </​note>​
  
-----+==== Analiză amortizată ====
  
-5.  +1
- +<​code ​c> 
-Fie $ M_f$ o Mașină Turing care "​computează"​ $ f \Rightarrow \forall w, M_f[w] \rightarrow f(w)$ \\ \\ +#include <stdio.h> 
-Similar, fie $ M_g$ o Mașină Turing care "​computează"​ $ g \Rightarrow \forall w, M_g[w] \rightarrow g(w)$ \\ \\ +#include <stdlib.h> 
- +#include <string.h>
-Pentru a nu apărea probleme, este important ca $ M_f$ și $ M_g$ să nu aibă stări cu aceeași denumire. Construim $ M_{fg}$ care începe prin a rula tranzițiile din $ M_f$ pe inputul $ w \Rightarrow$ obținem pe bandă $ f(w)$. Folosind stări auxiliare, mutăm cursorul până la începutul rezultatului aflat pe bandă, lăsând mașina $ M_{fg}$ în configurația:​ $ (□, Stare-Inițială-M_g,​ f(w))$, care rulează apoi tranzițiile din $ M_g$ pe noul input, $ f(w)$. În final se obține $ g(f(w))$, adică $ (g \circ f)(w)$. +
- +
----- +
- +
-6.  +
- +
-Trebuie să demonstrăm ​că putem echivala orice tranziție a mașinii $ M$ cu o tranziție sau un set de tranziții în cadrul mașinii $ M'$.\\ \\ +
- +
-Dacă mașina $ M$ are o tranziție care mută capul de citire la stânga sau la dreapta, atunci acea tranziție va arăta identic pentru mașina $ M'$, pentru că, în acest caz, nu există nici un fel de restricție+
- +
-Pentru $ \delta M(q,c) = (q',​c',​dir), ​ dir \in \{\leftarrow,​ \rightarrow\}$,​ construim $ \delta M'​(q,​c) = (q',​c',​dir)$.\\ \\ +
- +
-Dacă mașina $ M$ are o tranziție care nu modifică poziția capului de citire, putem simula acest comportament în cadrul mașinii $ M'$, mutând capul de citire la dreapta după care înapoi la stânga, trecând printr-o stare auxiliară. +
- +
-Pentru $ \delta M(q,c) = (q',​c',​-)$ construim $ \delta M'​(q,​c) = (q_{aux},​c',​\rightarrow)$ și $ \delta M'​(q_{aux},​x) = (q',​x,​\leftarrow)$,​ $ \forall x \in \Gamma$.  +
- +
----- +
- +
-7.  +
- +
-Soluția constă în a mapa fiecare tuplu $ t \in \Gamma ^k$ la un simbol din $ \Gamma'​$. Pentru a putea face acest lucru, $ \vert \Gamma ' \vert = \vert \Gamma \vert ^k$. \\ \\ +
- +
-Fie a și b simbolurile din $ \Gamma '$ la care se mapează tuplurile: $ (t_1,t_2 ... t_k)$, respectiv $ (t_1', t_2' ... t_k')$ din $ \Gamma ^k$. \\ \\ +
- +
-Construim $ \delta M'$ în felul următor: +
- +
-Pentru $ \delta M'(q, (t_1,t_2 ... t_k)) = (q', (t_1', t_2' ... t_k'), dir) \Rightarrow \delta M(q, a) = (q', b, dir), dir \in (\leftarrow,​ -, \rightarrow)$. +
- +
----- +
- +
-8.  +
- +
-Vom simula comportamentul mașinii $ M$ utilizând un caracter unic, care nu exista în $ \Gamma _M$, spre exemplu: $ ' \vert '$. Așadar, fie $ M'$ construită în următorul fel: +
- +
-$ \delta M'​(q,​c) = \delta M(q,c), \forall q \in Q_M, c \in \Gamma _M$ +
- +
-$ \Gamma _{M'} = \Gamma _M \cup \{ ' \vert ' \} , \{ ' \vert ' \} \notin \Gamma _M$ +
- +
-$ Q_{M'} = Q_M \cup \{ q_1', q_{1aux}'​ \}$ \\ \\ +
- +
-Pentru fiecare stare, vom insera tranziția care nu ne va permite depașirea acestui caracter spre stânga. +
- +
-$ \delta M'(q, ' \vert ') = (q, ' \vert ', \rightarrow ), \forall q \in Q$ \\ \\ +
- +
-În plus, în $ M'$ trebuie să schimbăm starea inițială pentru a scrie $ ' \vert '$ în stânga inputului. +
- +
-$ \delta M'​(q_1',​ c) = \delta M'​(q_{1aux}',​ c, \leftarrow ), \forall c \in \Gamma _M$ +
- +
-$ \delta M'​(q_{1aux}',​ □) = (q_1, ' \vert ', \rightarrow ), q_1 -$ starea inițială a mașinii $ M$ +
- +
-----+
  
-9.  
  
-Construim $ \delta M$ în felul următor: \\ \\+#define COUNTER_SIZE 100
  
-Pentru o tranziție care nu modifică poziția capului de citire, nu se schimbă nimic.+unsigned total_flips = 0;
  
-Pentru $ \delta M'(q,c) = (q',​c',​-)$ construim $ \delta M(q,​c) ​(q',​c',​-)$,​ $ q,q' \in Q_M \cup \{ Y, N, H \} , c,c' \in \Gamma _M$ \\ \\+int inc(unsigned *asize_t m) 
 +
 +    size_t i 0; 
 +    unsigned current_flips ​0;
  
-Pentru orice stare în care se ajunge cu tranziție la dreapta, adăugăm $ (n-1)$ extra stări ș$ (n-1)$ extra tranziții în $ M$.+    while (i < m && a[i] == 1) 
 +        a[i] = 0; 
 +        current_flips++;​ 
 +        i++; 
 +    }
  
-Pentru $ \delta M'(q,c) (q',​c',​ n \rightarrow)$, construim: \\ \\+    if (== m
 +        total_flips += current_flips;​ 
 +        return -1; 
 +    }
  
-$ \delta M(q,​c) ​(R_{n-1}q',c, \rightarrow)$+    a[i] = 1
 +    current_flips++;​
  
-$ \delta M(R_{n-1}q',​x) ​(R_{n-2}q',​x,​ \rightarrow),​ \forall x \in \Gamma _M$+    total_flips +current_flips;​
  
-$ \delta M(R_{n-2}q',x) = (R_{n-3}q',​x,​ \rightarrow),​ \forall x \in \Gamma _M$+    return 0; 
 +}
  
-$ ...$+int main(int argc, char *argv[]) 
 +
 +    unsigned counter[COUNTER_SIZE];​ 
 +    memset(counter,​ 0, sizeof(counter));​
  
-$ \delta M(R_1q',​x(q',x\rightarrow), \forall x \in \Gamma _M$ \\ \\+    if (argc < 2
 +        fprintf(stderr"​Usage:​ %s <​number_of_increments>​\n"​argv[0])
 +        return 1; 
 +    }
  
-Pentru orice stare în care se ajunge cu tranziție la stângase procedează similar.+    unsigned n = strtoull(argv[1]NULL, 10); 
 +    if (n == 0) { 
 +        fprintf(stderr,​ "​Invalid number of increments: %s\n", argv[1]); 
 +        return 1; 
 +    }
  
 +    for (int i = 0; i < n; i++) {
 +        inc(counter,​ COUNTER_SIZE);​
 +    }
  
 +    printf("​Total flips: %u\n", total_flips);​
 +}
 +</​code>​