Dear Gitlab users, as announced previously (and here), we will be downgrading this Gitlab instance delayed to the Community edition on Thursday, 25.08.22, at 5 pm. You may ignore the (upcoming) banner below displayed by Gitlab.

The module `Data.Array.Repa.FFTW` provides functions for Fast Fourier Transforms (FFT) for Repa arrays of up to three dimensions. Use the 1-d version to implement a simple low-pass filter that works as follows:

- First, an FFT is applied to the input signal.

- The coefficients corresponding to frequencies over some pre-determined cutoff are set to 0, the other ones are left untouched.

- Then an inverse FFT is performed.

The map from index `k` of the resulting array to the corresponding frequency for an FFT of length `n` is

```haskell

frq n k

| 2*k < n = k

| otherwise = k - n

```

Use the low-pass filter to denoise a signal created by adding uniformly distributed noise between $-0.03$ and $0.03$ to the function $x \mapsto exp(-x^2)$ for $x$ sampled on 200 points between $-2$ and $2$ and plot the results.

Note:

- The function, its noisy version and the filtered version should be real, but the FFT functions require and return `Complex Double` arrays.

- The FFT functions work with arrays in representation `F` (foreign). To convert from and to `D` or `U`, `copyS` can be used.

- A simple way to generate a list of `n` random numbers without using `IO` is

```haskell

take n . randomRs (-0.03, 0.03) $ mkStdGen 0

```

%% Cell type:code id: tags:

``` haskell

```

%% Cell type:markdown id: tags:

## problem 5

The *Jacobi* iterative algorithm for solving linear equations decomposes the matrix $A$ into the diagonal part $D$ and the remnant $R$:

$$A = D + R,$$

and then iterates the following way:

$$x^{( k + 1 )} = D^{ - 1} ( b - R x^{( k )} ),$$

where $x^{ ( k )}$ is the $k$-th approximation of $x$.

Implement a parallel Jacobi solver for linear systems using Repa arrays. Since Repa's `mmultP` (from `Data.Array.Repa.Algorithms.Matrix`) only works on `DIM2` arrays, the right hand side should be a matrix as well, i.e. you should effectively solve

$$A X = Y$$

for $X$, where $A$, $X$ and $Y$ are matrices. "Conventional" linear systems can then be solved by taking $X$ and $Y$ as matrices with only a single column.

Iterations should stop either after a pre-determined maximum number of iterations, or when the difference between preceeding iterates is smaller in norm than some pre-defined tolerance.

In order to actually use the parallelisation, this exercise should not be done in the notebook interface. You should also test your program on the 1d Poisson example from lecture 22 and examine its behaviour in ThreadScope.

implement a *Gauss-Seidel* algorithm for solving linear equations.

The Gauss–Seidel method is an iterative technique for solving a square system of n linear equations with unknown x:

$$A x = b$$

It is defined by the iteration

$$L_∗ x^{( k + 1 )} = b − U x^{( k )}$$

where $x^{( k )}$ is the $k$-th approximation or iteration of $x$ ,$x^{k + 1}$ is the next value of $x$ , and the matrix $A$ is decomposed into a lower triangular component $L_∗$ , and a strictly upper triangular component $U$: $A = L_∗ + U$

We rewrite this a little bit to for the algorithm:

$$x^{( k + 1 )} = T x^{( k )} + C$$

where

$$T = - L_∗^{-1} U$$ and $$C = L_∗^{-1} b$$

Write a recursive function which makes this iteration. The iteration should stop both from a tolerance value of the difference of adjacent $x$ and a maximum of iterations.

For a test case use the matrix and right hand side from the lecture.

Apply the method to the same test case as above, but this time reimplement it using the function

```haskell

conv :: Vec t -> Vec t -> Vec t

```

from `Numeric.LinearAlgebra.Repa`, which implements a convolution without actually creating the matrix. Note that `conv` returns a vector that is larger than the input; use the boundary values to handle this.

%% Cell type:code id: tags:

``` haskell

```

%% Cell type:markdown id: tags:

## problem 4

## problem 3

Let A be a $20.000 \times 20.000$ matrix, which entries are all zero besides the prime numbers $2, 3, 5, 7, \ldots, 224737$ on the diagonal and the number 1 in all entries $a_{ij}$ with

$$|i − j| = 1, 2, 4, 8, \ldots , 16384.$$

What is the $(1, 1)$ entry of $A^{−1}$? How can you check/visualize the structure of the matrix? Be sure to use a good method for saving the matrix.

The module `Data.Array.Repa.FFTW` provides functions for Fast Fourier Transforms (FFT) for Repa arrays of up to three dimensions. Use the 1-d version to implement a simple low-pass filter that works as follows:

- First, an FFT is applied to the input signal.

- The coefficients corresponding to frequencies over some pre-determined cutoff are set to 0, the other ones are left untouched.

- Then an inverse FFT is performed.

The map from index `k` of the resulting array to the corresponding frequency for an FFT of length `n` is

```haskell

frqnk

|2*k<n=k

|otherwise=k-n

```

Use the low-pass filter to denoise a signal created by adding uniformly distributed noise between $-0.03$ and $0.03$ to the function $x \mapsto exp(-x^2)$ for $x$ sampled on 200 points between $-2$ and $2$ and plot the results.

Note:

- The function, its noisy version and the filtered version should be real, but the FFT functions require and return `Complex Double` arrays.

- The FFT functions work with arrays in representation `F` (foreign). To convert from and to `D` or `U`, `copyS` can be used.

- A simple way to generate a list of `n` random numbers without using `IO` is

The *Jacobi* iterative algorithm for solving linear equations decomposes the matrix $A$ into the diagonal part $D$ and the remnant $R$:

$$A = D + R,$$

and then iterates the following way:

$$x^{( k + 1 )} = D^{ - 1} ( b - R x^{( k )} ),$$

where $x^{ ( k )}$ is the $k$-th approximation of $x$.

Implement a parallel Jacobi solver for linear systems using Repa arrays. Since Repa's `mmultP` (from `Data.Array.Repa.Algorithms.Matrix`) only works on `DIM2` arrays, the right hand side should be a matrix as well, i.e. you should effectively solve

$$A X = Y$$

for $X$, where $A$, $X$ and $Y$ are matrices. "Conventional" linear systems can then be solved by taking $X$ and $Y$ as matrices with only a single column.

Iterations should stop either after a pre-determined maximum number of iterations, or when the difference between preceeding iterates is smaller in norm than some pre-defined tolerance.

In order to actually use the parallelisation, this exercise should not be done in the notebook interface. You should also test your program on the 1d Poisson example from lecture 22 and examine its behaviour in ThreadScope.

implement a *Gauss-Seidel* algorithm for solving linear equations.

The Gauss–Seidel method is an iterative technique for solving a square system of n linear equations with unknown x:

$$A x = b$$

It is defined by the iteration

$$L_∗ x^{( k + 1 )} = b − U x^{( k )}$$

where $x^{( k )}$ is the $k$-th approximation or iteration of $x$ ,$x^{k + 1}$ is the next value of $x$ , and the matrix $A$ is decomposed into a lower triangular component $L_∗$ , and a strictly upper triangular component $U$: $A = L_∗ + U$

We rewrite this a little bit to for the algorithm:

$$x^{( k + 1 )} = T x^{( k )} + C$$

where

$$T = - L_∗^{-1} U$$ and $$C = L_∗^{-1} b$$

Write a recursive function which makes this iteration. The iteration should stop both from a tolerance value of the difference of adjacent $x$ and a maximum of iterations.

For a test case use the matrix and right hand side from the lecture.

%% Cell type:code id: tags:

``` haskell

{-# LANGUAGE FlexibleContexts #-}

importNumeric.LinearAlgebra.Repa

importNumeric.LinearAlgebra.Helpers

importqualifiedData.Array.RepaasRepa

importData.Array.Repahiding(map,(++))

-- lets first create a matrix a and right hand side as in the lecture