Differences

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

Link to this comparison view

Next revision
Previous revision
pp:lazylab [2021/04/25 14:58]
pdmatei created
pp:lazylab [2021/04/25 17:20] (current)
calin_andrei.bucur
Line 1: Line 1:
 ====== 8. Lazy evaluation ====== ====== 8. Lazy evaluation ======
 +
 +When passing **parameters** to a function, programming language design offers **two options** which are not mutually exclusive (both strategies can be implemented in the language):
 +
 +  * **applicative** (also called **strict**) evaluation strategy:
 +    * parameters are always evaluated **first**
 +    * can be further refined into: **call-by-value** (e.g. as it happens in C) and **call-by-reference** (e.g. as it happens for objects in Java).
 +  * **normal** evaluation strategy (also called **non-strict**,​ and when implemented as part of the PL - **call-by-name**)
 +    * the function is always evaluated **first**
 +    * can be further refined into: **lazy**, which ensures that each expression is evaluated **at most once**
 +
 +For more details, see the lecture on lazy evaluation. In Haskell, the default evaluation strategy is **lazy**. However, there are ways in which we can force evaluation to be **strict**. In this lab, we will explore several programming constructs which benefit from lazy evaluation.
 +
 +
 +===== 8.1. Streams =====
 +
 +8.1.1. Define the stream of natural numbers ''​nat :: [Integer]''​\\
 +8.1.2. Define the stream of odd numbers. You can use other higher-order functions such as filter, map or zipWith.\\
 +8.1.3. Define the stream of Fibonacci numbers
 +
 +===== 8.2. Numerical approximations =====
 +
 +1. Define the ''​build''​ function which takes a generator ''​g''​ and an initial value ''​a0''​ and generates the infinite list: ''​[a0,​ g a0, g (g a0), g (g (g a0)), .%%.%%. ]''​
 +
 +2. Define the ''​select''​ function which takes a tolerance $math[e] and a list $math[l] and returns the element $math[l_n] which satisfies the following condition: $math[abs(l_n - l_{n+1}) < e]
 +
 +=== Numerical Constants ===
 +
 +== Phi ==
 +
 +We know that $math[\displaystyle \lim_{n \rightarrow \infty} \frac{F_{n+1}}{F_n} = \varphi] (where $math[F_n] is the n-th element of the Fibonacci sequence, and $math[\varphi] is [[https://​en.wikipedia.org/​wiki/​Golden_ratio|"​the Golden Ratio"​]]). More info [[https://​en.wikipedia.org/​wiki/​Golden_ratio#​Relationship_to_Fibonacci_sequence|here]].
 +
 +3. Write an approximation with ''​0.001''​ tolerance for the $math[\varphi] constant. Use the previously defined Fibonacci stream.
 +
 +== Pi ==
 +
 +Consider the sequence:
 +
 +$math[a_{n+1} = a_n + sin(a_n)]; where $math[a_0] is an //initial approximation//,​ randomly chosen (but not 0 because $math[a_{n+1} != a_n]).
 +
 +We know that $math[\displaystyle \lim_{n \rightarrow \infty} a_n = \pi]
 +
 +4. Write an approximation with ''​0.001''​ tolerance of the $math[\pi] constant.
 +
 +=== Square Root ===
 +
 +Given a number $math[k], we want to find a numerical approximation for $math[\sqrt{k}]. Consider the sequence:
 +
 +$math[a_{n+1} = \frac{1}{2}(a_n + \frac{k}{a_n})];​ where $math[a_0] is an //initial approximation//,​ randomly chosen.
 +
 +We know that $math[\displaystyle \lim_{n \rightarrow \infty} a_n = \sqrt{k}]; more info [[https://​en.wikipedia.org/​wiki/​Methods_of_computing_square_roots#​Babylonian_method | here]].
 +
 +5. Write a function that approximates $math[\sqrt{k}] with ''​0.001''​ tolerance.
 +
 +=== The Newton-Raphson Method ===
 +
 +The sequence used for the approximation of the square root can be derived from the [[https://​en.wikipedia.org/​wiki/​Newton%27s_method|Newton-Raphson method]], a generic method for finding the roots of a function (i.e. the points $math[x] for which $math[f(x) = 0]). Thus, for a function $math[f], we have the sequence:
 +
 +$math[x_{n+1} = x_n - \frac{f(x_n)}{f'​(x_n)}]
 +
 +We know that $math[\displaystyle \lim_{n \rightarrow \infty} x_n = r\ a.î.\ f(r) = 0].
 +
 +6. Write a function which takes a function and and its derivative and it approximates a root with ''​0.001''​ tolerance.
 +
 +=== Derivatives ===
 +
 +We can approximate the derivative of a function in a certain point using the definition of the derivative:
 +
 +$math[\displaystyle f'​(a)=\lim_{h \rightarrow 0} \frac{f(a+h)-f(a)}{h}]
 +
 +We can obtain better succesive approximations of the derivative in a point $math[a], using a smaller $math[h].
 +
 +7. Write a function which approximates the derivative of a function in a certain point. follow the steps:
 +
 +a) generate the sequence: $math[h_0, \frac{h_0}{2},​ \frac{h_0}{4},​ \frac{h_0}{8},​ ...] (where $math[h_0] is a randomly chosen //initial approximation//​)\\
 +b) generate the list of approximations for $math[f'​(a)],​ using the formula above\\
 +c) write the function that takes a function $math[f] and a point $math[a] and approximates $math[f'​(a)] with ''​0.001''​ tolerance, using the previous steps.
 +
 +=== Integrals (: ===
 +
 +Given a function $math[f], we can approximate the definite integral on $ [a, b]$, using the area of the trapezoid defined by $math[a, b, f(a), f(b)]:
 +
 +$math[\displaystyle \int_{a}^{b} f(x) dx \approx (b - a)\frac{f(a)+f(b)}{2}]
 +
 +We can obtain a better approximation by dividing the interval in two and adding the area of the two trapezoids defined by $math[a, m, f(a), f(m)] and $math[m, b, f(m), f(b)] (where $math[m] is the middle of the interval $ [a, b]$). We can obtain a better approximation by dividing these intervals in two and so on.
 +
 +8. Write a function which approximates the integral of a function on an interval. Follow the steps:
 +
 +a) Write a function which takes a function $math[f] and two points $math[a, b] and calculates the area of the trapezoid $math[a, b, f(a), f(b)]\\
 +b) Write a function which takes a (ascending) list of points and inserts between any two points their middle:
 +
 +''​[1,​ 4, 7, 10, 13] -%%>%% [1, 2.5, 4, 5.5, 7, 8.5, 10, 11.5, 13]''​
 +
 +c) Write a function which takes a function $math[f] and a list of points $math[p_0,\ p_1,\ p_2,\ p_3,\ ...] and returns the list containing the areas of trapezoids defined by two consecutive points:\\
 +
 +$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) Write a function which takes a function $math[f] and two points $math[a, b] and approximates $math[\displaystyle \int_{a}^{b} f(x) dx] with ''​0.001''​ tolerance, using the previous steps.
 +
 +===== Recommended Reading =====
 +
 +  * [[http://​worrydream.com/​refs/​Hughes-WhyFunctionalProgrammingMatters.pdf| Why Functional Programming Matters (especially section 4 "​Gluing Programs Together",​ where the lab exercises are inspired from)]]