Commit 5a64e0b4 authored by Christoph Ruegge's avatar Christoph Ruegge
Browse files

Moved solution from exercises/ to solutions/

parent e326e3b1
%% Cell type:markdown id: tags:
# Exercises 26
# problem 1
Implement Newton's method for functions from $\mathbb{R}^n$ to $\mathbb{R}^n$ given as a function of the form
```haskell
newton :: (Vector Double -> Vector Double) -> (Vector Double -> Matrix Double) -> Vector Double -> Vector Double
newton f df initial = [...]
```
Here, `f` is the function whose root should be found, and `df` is its derivative (i.e. Jacobian). `initial` is an initial guess, and should return the first iterate for which the norm of the function value is smaller than some fixed bound.
%% Cell type:code id: tags:
``` haskell
import Numeric.Container
newton :: (Vector Double -> Vector Double) -> (Vector Double -> Matrix Double)
-> Vector Double -> Vector Double
newton f df initial = fst . head . filter stoprule $ iterate step (initial, f initial)
where step (x, y) = let x' = x - df x <\> y
in (x', f x')
stoprule :: (Vector Double, Vector Double) -> Bool
stoprule (_, y) = norm2 y < 1e-6
```
%% Cell type:code id: tags:
``` haskell
f :: Vector Double -> Vector Double
f x = fromList [ x0^2 + x1^2
, x0^2 - x1^2]
where x0 = x @> 0
x1 = x @> 1
df :: Vector Double -> Matrix Double
df x = fromLists [ [ 2*x0, 2*x1 ]
, [ 2*x0, -2*x1 ] ]
where x0 = x @> 0
x1 = x @> 1
newton f df (fromList [10, 20])
```
%%%% Output: display_data
%% Cell type:markdown id: tags:
# problem 2
(This is problem 4 of the SIAM 100-digit challenge.)
Consider the function
$$f(x, y) = e^{\sin(50x)} + \sin(60 e^y) + \sin(70\sin(x)) + \sin(\sin(80y)) - \sin(10(x+y)) + \frac{x^2 + y^2}{4}.$$
1. Plot the function using the `vis.py` script from the source repository.
2. Try to find the global minimum of the function by solving the equation
$$\nabla f(x, y) = 0$$
using Newton's method from problem 1.
Since the function oscillates very quickly and therefore has multiple local extrema, you should solve the equation for a sufficiently large number of initial values. Use a grid of $10 \times 10$ points in the square $(-0.5,\, 0.5)^2 \subset \mathbb{R}^2$ and run Newton's method on each of these points.
3. It may also be useful to try to refine the set of initial points until some heuristic criterion is fulfilled. Try to formulate such a criterion.
For reference, the global minimum is -3.306868647.
The function, its gradient and is Hessian are are implemented by the following Haskell functions:
```haskell
f :: Double -> Double -> Double
f x y = exp (sin (50*x))
+ sin (60 * exp y)
+ sin (70 * sin x)
+ sin (sin (80*y))
- sin (10 * (x+y))
+ (x^2 + y^2)/4
gradf :: Double -> Double -> [Double]
gradf x y = [dfx, dfy]
where dfx = 50 * cos (50*x) * exp (sin (50*x))
+ 70 * cos x * cos (70 * sin x)
- 10 * cos (10 * (x+y))
+ x/2
dfy = 60 * exp y * cos (60 * exp y)
+ 80 * cos (80*y) * cos (sin (80*y))
- 10 * cos (10 * (x+y))
+ y/2
hessf :: Double -> Double -> [[Double]]
hessf x y = [[hfxx, hfxy], [hfxy, hfyy]]
where hfxx = 2500 * cos (50*x) ^ 2 * exp (sin (50*x))
- 2500 * sin (50*x) * exp (sin (50*x))
- 70 * sin x * cos (70 * sin x)
- 4900 * cos x ^ 2 * sin (70 * sin x)
+ 100 * sin (10 * (x+y))
+ 1/2
hfyy = 60 * exp y * cos (60 * exp y)
- 3600 * exp y ^ 2 * sin (60 * exp y)
- 6400 * sin (80*y) * cos (sin (80*y))
- 6400 * cos (80*y) ^ 2 * sin (sin (80*y))
+ 100 * sin(10 * (x+y))
+ 1/2
hfxy = 100 * sin (10 * (x+y))
```
......
%% Cell type:markdown id: tags:
# Exercises 26
# problem 1
Implement Newton's method for functions from $\mathbb{R}^n$ to $\mathbb{R}^n$ given as a function of the form
```haskell
newton :: (Vector Double -> Vector Double) -> (Vector Double -> Matrix Double) -> Vector Double -> Vector Double
newton f df initial = [...]
```
Here, `f` is the function whose root should be found, and `df` is its derivative (i.e. Jacobian). `initial` is an initial guess, and should return the first iterate for which the norm of the function value is smaller than some fixed bound.
%% Cell type:code id: tags:
``` haskell
import Numeric.Container
newton :: (Vector Double -> Vector Double) -> (Vector Double -> Matrix Double)
-> Vector Double -> Vector Double
newton f df initial = fst . head . filter stoprule $ iterate step (initial, f initial)
where step (x, y) = let x' = x - df x <\> y
in (x', f x')
stoprule :: (Vector Double, Vector Double) -> Bool
stoprule (_, y) = norm2 y < 1e-6
```
%% Cell type:code id: tags:
``` haskell
f :: Vector Double -> Vector Double
f x = fromList [ x0^2 + x1^2
, x0^2 - x1^2]
where x0 = x @> 0
x1 = x @> 1
df :: Vector Double -> Matrix Double
df x = fromLists [ [ 2*x0, 2*x1 ]
, [ 2*x0, -2*x1 ] ]
where x0 = x @> 0
x1 = x @> 1
newton f df (fromList [10, 20])
```
%%%% Output: display_data
%% Cell type:markdown id: tags:
# problem 2
(This is problem 4 of the SIAM 100-digit challenge.)
Consider the function
$$f(x, y) = e^{\sin(50x)} + \sin(60 e^y) + \sin(70\sin(x)) + \sin(\sin(80y)) - \sin(10(x+y)) + \frac{x^2 + y^2}{4}.$$
1. Plot the function using the `vis.py` script from the source repository.
2. Try to find the global minimum of the function by solving the equation
$$\nabla f(x, y) = 0$$
using Newton's method from problem 1.
Since the function oscillates very quickly and therefore has multiple local extrema, you should solve the equation for a sufficiently large number of initial values. Use a grid of $10 \times 10$ points in the square $(-0.5,\, 0.5)^2 \subset \mathbb{R}^2$ and run Newton's method on each of these points.
3. It may also be useful to try to refine the set of initial points until some heuristic criterion is fulfilled. Try to formulate such a criterion.
For reference, the global minimum is -3.306868647.
The function, its gradient and is Hessian are are implemented by the following Haskell functions:
```haskell
f :: Double -> Double -> Double
f x y = exp (sin (50*x))
+ sin (60 * exp y)
+ sin (70 * sin x)
+ sin (sin (80*y))
- sin (10 * (x+y))
+ (x^2 + y^2)/4
gradf :: Double -> Double -> [Double]
gradf x y = [dfx, dfy]
where dfx = 50 * cos (50*x) * exp (sin (50*x))
+ 70 * cos x * cos (70 * sin x)
- 10 * cos (10 * (x+y))
+ x/2
dfy = 60 * exp y * cos (60 * exp y)
+ 80 * cos (80*y) * cos (sin (80*y))
- 10 * cos (10 * (x+y))
+ y/2
hessf :: Double -> Double -> [[Double]]
hessf x y = [[hfxx, hfxy], [hfxy, hfyy]]
where hfxx = 2500 * cos (50*x) ^ 2 * exp (sin (50*x))
- 2500 * sin (50*x) * exp (sin (50*x))
- 70 * sin x * cos (70 * sin x)
- 4900 * cos x ^ 2 * sin (70 * sin x)
+ 100 * sin (10 * (x+y))
+ 1/2
hfyy = 60 * exp y * cos (60 * exp y)
- 3600 * exp y ^ 2 * sin (60 * exp y)
- 6400 * sin (80*y) * cos (sin (80*y))
- 6400 * cos (80*y) ^ 2 * sin (sin (80*y))
+ 100 * sin(10 * (x+y))
+ 1/2
hfxy = 100 * sin (10 * (x+y))
```
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment