Differences
This shows you the differences between two versions of the page.
Both sides previous revision Previous revision Next revision | Previous revision | ||
pp:l06 [2019/04/14 00:27] dmihai |
pp:l06 [2020/02/05 15:50] (current) dmihai [Exerciții:] |
||
---|---|---|---|
Line 1: | Line 1: | ||
- | ====== Întârzierea evaluării ====== | + | ====== Evaluare leneșă ====== |
Line 17: | Line 17: | ||
<code>(λx.λy.(x + y) 1 (λz.(z + 2) 3))</code> | <code>(λx.λy.(x + y) 1 (λz.(z + 2) 3))</code> | ||
- | Desigur, evaluarea expresiei ''(λz.(z + 2) 3)'' va genera valoarea ''5'', de unde deducem că rezultatul final al expresiei va fi ''6'' ( adunarea lui 1 cu rezultatul anterior ). În cadrul acestui raționament, am presupus că parametrii sunt evaluați înaintea aplicării funcției asupra acestora. Vom vedea, în cele ce urmează, că evaluarea se poate realiza și in alt mod. | + | Desigur, evaluarea expresiei ''(λz.(z + 2) 3)'' va genera valoarea ''5'', de unde deducem că rezultatul final al expresiei va fi ''6'' (adunarea lui 1 cu rezultatul anterior). În cadrul acestui raționament, am presupus că parametrii sunt evaluați înaintea aplicării funcției asupra acestora. Vom vedea, în cele ce urmează, că evaluarea se poate realiza și in alt mod. |
====Evaluare aplicativă==== | ====Evaluare aplicativă==== | ||
Line 39: | Line 39: | ||
===== Exerciții: ===== | ===== Exerciții: ===== | ||
+ | |||
+ | {{:pp:lazy.zip|Laborator 8 - Schelet}}\\ | ||
==== I. Streams ==== | ==== I. Streams ==== | ||
Line 48: | Line 50: | ||
==== II. Aproximații numerice ==== | ==== II. Aproximații numerice ==== | ||
- | 1. definiți funcția ''build :: (a -%%>%% a) -%%>%% a -%%>%% [a]'' care primește un generator ''g'' și o valoare inițială ''a0'' și generează lista: ''[a0, g a0, g (g a0), g (g (g a0)), .%%.%%. ]'' | + | 1. Definiți funcția ''build'' care primește un generator ''g'' și o valoare inițială ''a0'' și generează lista infinită: ''[a0, g a0, g (g a0), g (g (g a0)), .%%.%%. ]'' |
- | + | ||
- | <note tip> | + | 2. Definiți funcția ''select'' care primește o toleranță $math[e] și o listă $math[l] și întoarce elementul $math[l_n] care satisface proprietatea: $math[abs(l_n - l_{n+1}) < e] |
- | Comportamentul funcției ar trebui să fie identic cu cel al funcției ''iterate'', deja existentă în Haskell. | + | |
+ | === Constante numerice === | ||
+ | |||
+ | == phi == | ||
+ | |||
+ | Știm că $math[\displaystyle \lim_{n \rightarrow \infty} \frac{F_{n+1}}{F_n} = \varphi] (unde $math[F_n] este al n-lea element din șirul lui Fibonacci, iar $math[\varphi] este [[https://en.wikipedia.org/wiki/Golden_ratio|"proporția de aur"]]). Mai multe informații [[https://en.wikipedia.org/wiki/Golden_ratio#Relationship_to_Fibonacci_sequence|aici]]. | ||
+ | |||
+ | 3. Scrieți o aproximare cu toleranță ''0.001'' a constantei $math[\varphi]. Folosiți-vă de stream-ul Fibonacci definit anterior. | ||
+ | |||
+ | == pi == | ||
+ | |||
+ | Fie șirul: | ||
+ | |||
+ | $math[a_{n+1} = a_n + sin(a_n)]; unde $math[a_0] este o //aproximare inițială//, aleasă arbitrar (dar diferită de 0 pentru ca $math[a_{n+1} != a_n]). | ||
+ | |||
+ | Știm că $math[\displaystyle \lim_{n \rightarrow \infty} a_n = \pi] | ||
+ | |||
+ | 4. Scrieți o aproximare cu toleranță ''0.001'' a constantei $math[\pi]. | ||
+ | |||
+ | === Rădăcină pătrată === | ||
+ | |||
+ | Fiind dat un număr $math[k], vrem să găsim o aproximare numerică pentru $math[\sqrt{k}]. Fie șirul: | ||
+ | |||
+ | $math[a_{n+1} = \frac{1}{2}(a_n + \frac{k}{a_n})]; unde $math[a_0] este o //aproximare inițială//, aleasă arbitrar. | ||
+ | |||
+ | Știm că $math[\displaystyle \lim_{n \rightarrow \infty} a_n = \sqrt{k}]; mai multe informații găsiți [[https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method | aici]]. | ||
+ | |||
+ | 5. Scrieți o funcție care aproximează $math[\sqrt{k}] cu toleranța ''0.001''. | ||
+ | |||
+ | === Metoda Newton-Raphson === | ||
+ | |||
+ | Șirul folosit pentru aproximarea rădăcinii pătrate se poate deriva din [[https://en.wikipedia.org/wiki/Newton%27s_method|metoda Newton-Raphson]], o metodă generică pentru a găsi rădăcinile unei funcții (i.e. punctele $math[x] pentru care $math[f(x) = 0]). Astfel pentru o funcție $math[f], avem șirul: | ||
+ | |||
+ | $math[x_{n+1} = x_n - \frac{f(x_n)}{f'(x_n)}] | ||
+ | |||
+ | Știm că $math[\displaystyle \lim_{n \rightarrow \infty} x_n = r\ a.î.\ f(r) = 0]. | ||
+ | |||
+ | 6. Scrieți o funcție care primește o funcție și derivata acesteia și aproximează o rădăcină cu toleranța ''0.001''. | ||
+ | |||
+ | === Derivate === | ||
+ | |||
+ | La exercițiul anterior, ne-am folosit de o altă funcție (implementată manual) care să ne calculeze exact derivata funcției $math[f]. Dacă nu avem o astfel de implementare, putem aproxima derivata unei funcții într-un anumit punct. Folosindu-ne de definiția derivatei: | ||
+ | |||
+ | $math[\displaystyle f'(a)=\lim_{h \rightarrow 0} \frac{f(a+h)-f(a)}{h}] | ||
+ | |||
+ | Putem obține aproximări succesive din ce în ce mai bune ale derivatei unei funcții într-un punct $math[a], folosind un $math[h] din ce în ce mai mic. | ||
+ | |||
+ | 7. Scrieți o funcție care să aproximeze derivata unei funcții într-un punct. Urmăriți pașii: | ||
+ | |||
+ | a) generați șirul: $math[h_0, \frac{h_0}{2}, \frac{h_0}{4}, \frac{h_0}{8}, ...] (unde $math[h_0] este o //aproximare inițială//, aleasă arbitrar)\\ | ||
+ | b) generați lista aproximarilor lui $math[f'(a)], folosind formula de mai sus\\ | ||
+ | c) scrieți funcția care primește o funcție $math[f] și un punct $math[a] și aproximează $math[f'(a)] cu toleranța ''0.001'', folosindu-vă de subpunctele anterioare. | ||
+ | |||
+ | === Integrale === | ||
+ | |||
+ | Dându-se o funcție $math[f], putem aproxima integrala definită pe intervalul $ [a, b]$, folosind aria trapezului definit de $math[a, b, f(a), f(b)]: | ||
+ | |||
+ | $math[\displaystyle \int_{a}^{b} f(x) dx \approx (b - a)\frac{f(a)+f(b)}{2}] | ||
+ | |||
+ | Putem obține o aproximare mai bună împărțind intervalul în două și însumând aria celor două trapeze definite de $math[a, m, f(a), f(m)] și de $math[m, b, f(m), f(b)] (unde $math[m] este mijlocul intervalului $ [a, b]$). Putem obține o aproximare și mai bună împărțind aceste două intervale în două și tot așa. | ||
- | <code> | + | 8. Scrieți o funcție care să aproximeze integrala unei funcții pe un interval. Urmăriți pașii: |
- | Prelude> :t iterate | + | |
- | iterate :: (a -> a) -> a -> [a] | + | |
- | </code> | + | |
- | </note> | + | |
- | 2. definiți funcția ''select'' care primește o toleranță $math[e] și o listă $math[l] și întoarce elementul $math[l_n] care satisface proprietatea: $math[abs(l_n - l_{n+1}) < e] | + | a) Scrieți o funcție care primește o funcție $math[f] și două puncte $math[a, b] și calculează aria trapezului $math[a, b, f(a), f(b)]\\ |
+ | b) Scrieți o funcție care primește o listă (crescătoare) de puncte și inserează între oricare două elemente mijlocul acestor: | ||
- | === 3. Rădăcină pătrată === | + | ''[1, 4, 7, 10, 13] -%%>%% [1, 2.5, 4, 5.5, 7, 8.5, 10, 11.5, 13]'' |
- | Fiind dat un număr $math[k], am vrea să găsim o aproximare numerică a $math[\sqrt{k}]. Fie șirul: | + | c) Scrieți o funcție care primește o funcție $math[f] și o listă de puncte $math[p_0,\ p_1,\ p_2,\ p_3,\ ...] și întoarce lista ariilor trapezelor descrise de două puncte consecutive:\\ |
- | $math[a_{n+1} = \frac{1}{2}(a_n + \frac{k}{a_n})] | + | $math[(p_0, p_1, f(p_0), f(p_1));\ (p_1, p_2, f(p_1), f(p_2));\ (p_2, p_3, f(p_2), f(p_3));\ ...] |
- | Știm că $math[\displaystyle \lim_{n \rightarrow \infty} a_n = \sqrt{k}] | + | d) Scrieți o funcție care primește o funcție $math[f] și două puncte $math[a, b] și aproximează $math[\displaystyle \int_{a}^{b} f(x) dx] cu toleranța ''0.001'', folosindu-vă de subpunctele anterioare. |
- | a) Scrieți o funcție care calculează $math[\sqrt{k}] cu toleranța ''0.01'', exploatând faptul că șirul: $math[a_n = 1/2(a_{n-1} + k/a_{n-1})] converge către $math[\sqrt{k}] când ''n'' tinde la infinit. | + | ===== Recommended Reading ===== |
- | + | ||
- | 4. Aproximație pentru derivata unei funcții ''f'' într-un punct ''a'':\\ | + | |
- | a) Scrieți o funcție care generează lista: ''[h_0, h_0/2, h_0/4, h_0/8, ...]''\\ | + | |
- | b) Scrieți o funcție care calculează lista aproximarilor lui ''f'(a)'', calculate astfel: $math[\displaystyle f'(a)=\lim_{h \rightarrow 0} \frac{f(a+h)-f(a)}{h}]\\ | + | |
- | c) Scrieți o funcție care calculează derivata in ''a'' a unei funcții ''f'', cu toleranța ''0.01'' | + | |
- | 5. Aproximație pentru integrala unei funcții pe intervalul ''[a,b]'':\\ | + | * [[http://worrydream.com/refs/Hughes-WhyFunctionalProgrammingMatters.pdf| Why Functional Programming Matters (în special secțiunea 4 "Gluing Programs Together", de unde sunt inspirate exercițiile din laborator)]] |
- | a) Scrieți o funcție care aproximează valoarea integralei unei funcții ''f'' între ''a'' și ''b'', cu toleranța ''0.01''. Strategia de îmbunătățire a unei aproximări constă în spargerea intervalului ''[a,b]'' în două sub-intervale de dimensiune egală ''[a,m]'' si ''[m,b]'', calculul integralei pe fiecare, și adunarea rezultatului. | + |