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
pp:l06 [2018/04/02 12:48]
dmihai remove racket
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 38: Line 38:
  
  
-====Exerciții:​====+===== Exerciții: ​=====
  
 +{{:​pp:​lazy.zip|Laborator 8 - Schelet}}\\
  
-=== I. Șiruri ​===+==== I. Streams ====
  
-  - Construiți șirul numerelor naturale\\ +1. construiți șirul numerelor naturale\\ 
-  - Construiți șirul numerelor pare\\ +2. construiți șirul numerelor pare (puteți să va folosiți de șirul definit anterior)\\ 
-  - Construiți șirul ​numerelor lui Fibonacci ​+3. construiți șirul Fibonacci ​(în testele automate, șirul începe cu ''​1,​ 1, 2, 3, 5, 8, .%%.%%.''​)
  
-=== II. Aproximații ===+==== II. Aproximații ​numerice ====
  
-1. definiți funcție ''​build ​:: (a -> a) -> a -> [a]''​ care primeste o funcție 'generator' (pe care o numim ''​g'' ​în continuare), ​o valoare inițială ​(''​a0''​), și generază 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> +
-Comportamentul funcției ar trebui să fie identic cu cel al funcției ''​iterate'',​ deja existentă în Haskell.+
  
-<​code>​ +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]
-Prelude> :t iterate +
-iterate :: (-> a-> a -> [a] +
-</code> +
-</​note>​+
  
-2. definiți o funcție ''​select''​ care primește o toleranță ''​e'',​ o listă, și întoarce valoarea $math[a_n] din listă care satisface proprietatea:​ $math[abs(a_n - a_{n+1}) < e]+=== Constante numerice ===
  
-3. Aproximație pentru $math[\sqrt{k}]:​\\ +== phi ==
- 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. +
-       +
-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''​+
  
-5Aproximație pentru integrala unei funcții pe intervalul ​''​[a,b]''​:\\ +Ș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]]. 
- 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.+ 
 +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țș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. 
 + 
 +8. Scrieți o funcție care să aproximeze integrala unei funcții pe un interval. Urmăriți pașii: 
 + 
 +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: 
 + 
 +''​[14, 7, 10, 13] -%%>%% [1, 2.5, 4, 5.5, 7, 8.5, 10, 11.5, 13]''​ 
 + 
 +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[(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));​\ ​...] 
 + 
 +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. 
 + 
 +===== Recommended Reading ===== 
 + 
 +  * [[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)]]