Table of Contents

Evaluare leneșă

Moduri de evaluare a unei expresii:

Evaluare aplicativă vs. evaluare normală

Fie urmatoarea expresie, scrisă într-o variantă relaxată a Calculului Lambda (în care valori numerice și operații pe acestea sunt permise, iar funcțiile sunt în formă uncurried):

(λx.λy.(x + y) 1 2)

Evident, în urma aplicării funcției de mai sus, expresia se va evalua la 3. Să observăm, însă, cazul în care parametrii funcției reprezintă aplicații de funcții:

(λx.λy.(x + y) 1 (λz.(z + 2) 3))

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ă

Evaluarea aplicativă (eager evaluation) este cea în care fiecare expresie este evaluată imediat. În exemplul de mai sus, evaluarea aplicativă va decurge astfel:

(λx.λy.(x + y) 1 (λz.(z + 2) 3))
(λx.λy.(x + y) 1 5)
6

Evaluare normală

Spre deosebire de evaluarea aplicativă, evaluarea normală va întarzia evaluarea unei expresii, până când aceasta este folosită efectiv. Exemplu:

(λx.λy.(x + y) 1 (λz.(z + 2) 3))
(1 + (λz.(z + 2) 3))
(1 + 5)
6

Exerciții:

Laborator 8 - Schelet

I. Streams

1. construiți șirul numerelor naturale
2. construiți șirul numerelor pare (puteți să va folosiți de șirul definit anterior)
3. construiți șirul Fibonacci (în testele automate, șirul începe cu 1, 1, 2, 3, 5, 8, ...)

II. Aproximații numerice

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)), ... ]

2. Definiți funcția select care primește o toleranță $ e$ și o listă $ l$ și întoarce elementul $ l_n$ care satisface proprietatea: $ abs(l_n - l_{n+1}) < e$

Constante numerice

phi

Știm că $ \displaystyle \lim_{n \rightarrow \infty} \frac{F_{n+1}}{F_n} = \varphi$ (unde $ F_n$ este al n-lea element din șirul lui Fibonacci, iar $ \varphi$ este "proporția de aur"). Mai multe informații aici.

3. Scrieți o aproximare cu toleranță 0.001 a constantei $ \varphi$ . Folosiți-vă de stream-ul Fibonacci definit anterior.

pi

Fie șirul:

$ a_{n+1} = a_n + sin(a_n)$ ; unde $ a_0$ este o aproximare inițială, aleasă arbitrar (dar diferită de 0 pentru ca $ a_{n+1} != a_n$ ).

Știm că $ \displaystyle \lim_{n \rightarrow \infty} a_n = \pi$

4. Scrieți o aproximare cu toleranță 0.001 a constantei $ \pi$ .

Rădăcină pătrată

Fiind dat un număr $ k$ , vrem să găsim o aproximare numerică pentru $ \sqrt{k}$ . Fie șirul:

$ a_{n+1} = \frac{1}{2}(a_n + \frac{k}{a_n})$ ; unde $ a_0$ este o aproximare inițială, aleasă arbitrar.

Știm că $ \displaystyle \lim_{n \rightarrow \infty} a_n = \sqrt{k}$ ; mai multe informații găsiți aici.

5. Scrieți o funcție care aproximează $ \sqrt{k}$ cu toleranța 0.001.

Metoda Newton-Raphson

Șirul folosit pentru aproximarea rădăcinii pătrate se poate deriva din metoda Newton-Raphson, o metodă generică pentru a găsi rădăcinile unei funcții (i.e. punctele $ x$ pentru care $ f(x) = 0$ ). Astfel pentru o funcție $ f$ , avem șirul:

$ x_{n+1} = x_n - \frac{f(x_n)}{f'(x_n)}$

Știm că $ \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 $ f$ . Dacă nu avem o astfel de implementare, putem aproxima derivata unei funcții într-un anumit punct. Folosindu-ne de definiția derivatei:

$ \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 $ a$ , folosind un $ 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: $ h_0, \frac{h_0}{2}, \frac{h_0}{4}, \frac{h_0}{8}, \ldots$ (unde $ h_0$ este o aproximare inițială, aleasă arbitrar)
b) generați lista aproximarilor lui $ f'(a)$ , folosind formula de mai sus
c) scrieți funcția care primește o funcție $ f$ și un punct $ a$ și aproximează $ f'(a)$ cu toleranța 0.001, folosindu-vă de subpunctele anterioare.

Integrale

Dându-se o funcție $ f$ , putem aproxima integrala definită pe intervalul $ [a, b]$, folosind aria trapezului definit de $ a, b, f(a), f(b)$ :

$ \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 $ a, m, f(a), f(m)$ și de $ m, b, f(m), f(b)$ (unde $ 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 $ f$ și două puncte $ a, b$ și calculează aria trapezului $ 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:

[1, 4, 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 $ f$ și o listă de puncte $ p_0,\ p_1,\ p_2,\ p_3,\ \ldots$ și întoarce lista ariilor trapezelor descrise de două puncte consecutive:

$ (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));\ \ldots$

d) Scrieți o funcție care primește o funcție $ f$ și două puncte $ a, b$ și aproximează $ \displaystyle \int_{a}^{b} f(x) dx$ cu toleranța 0.001, folosindu-vă de subpunctele anterioare.