Differences
This shows you the differences between two versions of the page.
| Both sides previous revision Previous revision Next revision | Previous revision | ||
|
aa:lab:sol:2 [2023/10/23 11:12] vlad.juja |
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_1, 0, \rightarrow$ | $ q_1, 1, \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+6, g(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)+d, a>0 (aceeasi crestere ca n^2, fiind dominant in functie) | ||
| + | </note> | ||
| - | (ꞓ, q<sub>1</sub>, 100) ⊢ (1, q<sub>1</sub>, 00) ⊢ (10, q<sub>1</sub>, 0) ⊢ (100, q<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 descrescatoare, solutia este orice functie crescatoare. | ||
| + | Exemple soluții posibile: g(n)=c, c = constanta, g(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) ⊢ (1011, q<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_2, 1, \rightarrow$ | $ q_2, 0, \rightarrow$ | $ q_1, \square, \rightarrow$ | | + | f(n)=logn, g(n)=√n. Cum f si g sunt functiile f si g sunt monotone si cresctoare, verific 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 logn, g(n)=n. Cum f si g sunt functiile f si g sunt monotone si cresctoare, verific afirmatia utilizand limite. |
| - | | $ q_2$ | $ q_2, 0, \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 input. Ea va continua să scrie 1 la stânga și la dreapta pe bandă. | + | $ n+logn∈θ(n)$ |
| + | <note> | ||
| + | f(n)=n, g(n)=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→∞)(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 *a, size_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 și $ (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 (i == 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ânga, se 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> | ||