buffering calculations in haskell array initialization - haskell

Right now i am porting my mathematical solution from c# to Haskell, learning Haskell in process. I have following code for Thompson algorithm:
xi[N] = a[N] / c[N];
eta[N] = f[N] / c[N];
for (int i = N - 1; i > 0; i--)
{
var cbxip = (c[i] - b[i] * xi[i + 1]);
xi[i] = a[i] / cbxip;
eta[i] = (f[i] + b[i] * eta[i + 1]) / cbxip;
}
{
int i = 0;
var cbxip = (c[i] - b[i] * xi[i + 1]);
eta[i] = (f[i] + b[i] * eta[i + 1]) / cbxip;
}
How do I do it in Haskell?
I found info on array initialization, but I have several problems with it.
Say, I wrote the following code:
xi = [a[i] / (c[i] - b[i] * xi[i + 1]) | i <- 1..N-1] ++ [a[N] / c[N]]
etha = [(f[i] + b[i] * etha[i + 1] / (c[i] - b[i] * xi[i + 1]) | i <- 0..N-1] ++ [f[N] / c[N]]
The problems are following:
How do I specify I have to initialize array starting right? Do I even need to do so, or Haskell will grasp it by itself? If latter, how can it do that? isn't it is just a blackbox like[f(i)|i<-[a..b]] for a compiler?
(most problematic) For all i in [1..N-1] the part (c[i] - b[i] * xi[i + 1]) is going to be evaluated twice. How can I fix this? Prior mapping it to some other array will cost memory and is impossible as I don't have xi array yet.
I thought of something like simultaneous mapping, but I am confused with how to apply it to array initializing.

I would probably avoid using list comprehensions until you become really familiar with solving problems through recursion. Haskell is very different to C# in that you don't have "arrays" as such, which can be randomly accessed and inserted - you can't pre-allocate this space up front, because allocation is a side effect. Instead, consider everything to be linked lists, and to use recursion to iterate through them.
If we start with a top-down approach, we have a bunch of lists of numbers, and we need a function to iterate through them. If we passed these separately we would end up with a function signature like [n] -> [n] -> [n] -> [n] -> [n] -> ... This is probably not a good idea considering they all seem to be the same size, N. Instead, we can use a tuple (or pair of tuples) to contain them, eg.
thompson :: Num n => [(n, n, n, n, n, n)] -> [(n, n)]
thompson [] = [] -- pattern to terminate recursion for empty lists
-- these variables are equivalent to your a[i], etc in C#
thompson ((a, b, c, f, xi, eta):_) = ?
If we are duplicating your C# exactly, we probably want patterns for the case of 2 elements in the list, since it seems that each iteration needs to access the current and next elements. For 2 or more elements.
-- handle final 2 elements
thompson ((a, _, c, f, xi, eta):[]) = ((a / c), (f / c))
thompson ((a0, b0, c0, f0, xi0, eta0):(_,_,_,_,xi1,eta1):[]) = ?
-- handle the regular case.
thompson ((a0, b0, c0, f0, xi0, eta0):(a1,b1,c1,f1,xi1,eta1):tail) = ?
Once you have the overall iterative structure, it should become more obvious how to implement what's in the loop. The loop is basically a function which takes one of these tuples, plus a tuple for the next xi/eta and does some calculation, returning a new tuple for xi/eta (or in the final case, just eta). The a,b,c,f appear to not change.
doCalc1 :: Num n => (n, n, n, n, n, n) -> (n, n) -> (n, n)
doCalc1 (a, b, c, f, xi0, eta0) (xi1, eta1) = (a / cbxip, f + b * eta1 / cbxip)
where cbxip = c - b * xi1
doCalc2 :: Num n => Num n => (n, n, n, n, n, n) -> (n, n) -> n
doCalc2 (a, b, c, f, xi0, eta0) (xi1, eta1) = f + b * eta1 / cbxip
where cbxip = c - b * xi1
Now we just need to update thompson to call doCalc1/doCalc2, and recursively call itself with the tail.
thompson (head:next#(_,_,_,_,xi,eta):[])
= (xi, doCalc2 head (xi, eta)) : thompson [next]
thompson (head:next#(_,_,_,_,xi,eta):tail)
= doCalc1 head (xi, eta) : thompson (next:tail)

Related

Understanding implementation of Extended Euclidean algorithm

After some experimentation and search, I came up with the following definition:
emcd' :: Integer -> Integer -> (Integer,Integer,Integer)
emcd' a 0 = (a, 1, 0)
emcd' a b =
let (g, t, s) = emcd' b r
in (g, s, t - (q * s))
where
(q, r) = divMod a b
What's the meaning behind this expression t - (q * s) ?
I've tried to evaluate it by hand; even though I arrived at the correct result (1, -4, 15), I can't see why that expression returns the value of t.
There is a famous method for calculating s and t in as + bt = gcd(a, b). In the process of finding the gcd, I get several equations.
By reversing the steps in the Euclidean Algorithm, it is possible to find these integers a and b. Those resulting equations look like the expression t - (q * s); however, I can't figure out the exact process.
Since (q, r) = divMod a b, we have the equation
a = qb + r
and because of the recursive call, we have:
tb + sr = g
Substituting a-qb for r in the second equation, that means
tb + s(a-qb) = g
tb + sa - qsb = g
sa + (t-qs)b = g
This explains why s and t - q*s are good choices to return.

Binary Search in Fortran 95

I try to implement a binary search in Fortran 95 with a recursive function.
My error message is: /usr/bin/timeout: the monitored command dumped core
Does anyone have an idea how I could solve this problem?
The return value should be 2 for this little programm.
In addition: How can I expand my code to return the position number of the array "ar" to know where I can add my new element (i.e "2.9")? In case of 2.9 it should return 2. Another example, if I take 7.3 instead of 2.9 it should return 6 (between 7.0 and 8.0 of array "ar").
program h
real, dimension(7) :: ar
integer :: s
real :: outp
ar = (/2.0, 3.0, 4.0, 5.0, 7.0, 8.0, 9.0/)
s = sizeof(ar)
outp = findAr(ar, 1, s, 3.0)
print*, outp
end program h
recursive function findAr(ar, l, r, x) result(a)
real, dimension(size(ar)), intent(in) :: ar
integer, intent(in) :: l, r
real, intent(in) :: x
integer :: midd
real :: a
if (r >= 1) then
midd = l + (r - 1) / 2
if (ar(midd) == x) then
a = midd
else if (ar(midd) > x) then
a = findAr(ar, l, midd - 1, x)
else
a = findAr(ar, midd + 1, r, x)
end if
end if
end function findAr
The compiler error can be resolved as specified by the comments to your questions.
Concerning your 2nd question: How to extend your code for search values in between the array elements. One could ask in the same manner for values outside of your array (e.g. smaller than its minimum).
The following code is not using recursive functions nor is it an extension of your code.
You should keep in mind that unnecessary function calls create some overhead and could result in performance loss.
module bin_search_m
implicit none
contains
function bin_search(x, x1) result(i)
!! find index of nearest value in sorted array
real, intent(in) :: x(:)
!! sorted array
real, intent(in) :: x1
!! value to find
integer :: i
!! return array index
integer :: i0, i1
! starting interval is the whole array
i0 = 1
i1 = size(x)
! test if x1 is outside of interval [x(1), x(end)]
if (x1 <= x(i0)) then
i = i0
return
end if
if (x1 >= x(i1)) then
i = i1
return
end if
! binary search
do while (i1 > (i0 + 1))
i = (i1 + i0) / 2
if (x(i) < x1) then
i0 = i
else if (x(i) > x1) then
i1 = i
else
return
end if
end do
! pick index of value that is closer
i = merge(i0, i1, ((2 * x1) < (x(i0) + x(i1))))
end function
end module

Averaging ages across a list with foldl (Haskell)

I am doing some arbitrary operations in Haskell as I learn, and have been playing with a list of animals with certain properties, including age.
This is my script:
module Animals where
data Animal = CatThing String Int
| DogThing String Int
deriving Show
animalList :: [Animal]
animalList = [CatThing "Spot" 2, DogThing "Rex" 5]
-- write a function that returns the string component given an animal
getName :: Animal -> String
getName (CatThing name _) = name
getName (DogThing name _) = name
-- get the age of an animal (uses "map")
getAge :: Animal -> Int
getAge (CatThing _ age) = age
getAge (DogThing _ age) = age
-- sum age
sumAge :: Int -> [Int] -> Int
sumAge _ [b, c] = foldl (+) 0 [b, c]
-- average age
???
I am stuck on how to sum using foldl'. I know there is a sum function built in, but I am really trying to practice folds, so am trying to do it that way.
Does anyone have suggestions on how to proceed?
The code for your sum looks fine, I'd use foldl' instead of foldl so you don't risk a stack overflow, and also change that [b,c] pattern to a generic variable or even better point free so it looks better and it's also more general:
sumAge :: [Double] -> [Double]
sumAge = foldl' (+) 0
As for the average, you just sum and divide by the length:
averageAge :: [Double] -> Double
averageAge ls = sumAge ls / length ls
PS. In case your ages are integer, then the first function still works, but the average need to change:
averageInt :: [Int] -> Double
averageInt ls = (fromInteger . sum) ls / (fromInteger . length) ls
TL;DR version
Sum: sumAges animals = foldl (\age animal -> age + (getAge animal)) 0 animals
Average:
import Data.Sequence(foldlWithIndex, fromList)
average numbers = foldlWithIndex (\a i x -> let k = fromIntegral i in (k*a + x) / (k + 1)) 0 . fromList $ numbers
Long version
If you have an interest in math, it may help to understand the design of fold functions as equivalent to discovering sequence formulas by induction.
Sum
For sum, since you have s[i+1] = s[i] + x[i+1], you can simply use addition like you did, although you may have to convert before you add:
sumAges :: [Animal] -> Int
sumAges animals = foldl (\age animal -> age + (getAge animal)) 0 animals
sumAgesPointFree :: [Animal] -> Int
sumAgesPointFree = foldl (flip $ (+) . getAge) 0
Average
For example, one way to calculate the average of a list using a single fold function is to use a recursive mathematical version of calculating the rolling average of a sequence: m[i+1] = (i * m[i] + x[i+1]) / (i + 1). You can see this in how you calculate the average of lists of varying sizes:
{-
Not Haskell, just attempting mathematical notation without knowing MathML in Markdown.
m: mean or average
x: an element of a list or sequence
[]: subscript
-}
m[1] = x[1]
m[2] = (x[1] + x[2]) / 2 = (m[1] + x[2]) / 2 -- m[1] = x[1], so substitute
m[3] = (x[1] + x[2] + x[3]) / 3 -- (a+b)/n = a/n + b/n, so distribute
= (x[1] + x[2]) / 3 + x[3] / 3 -- a = n/n * a, n not in {0, Infinity}
= 2/2 * (x[1] + x[2]) / 3 + x[3] / 3 -- n/n * 1/a = n/a * 1/n
= 2/3 * (x[1] + x[2]) / 2 + x[3] / 3 -- m[2] = (x[1] + x[2])/2, so substitute
= 2/3 * m[2] + x[3] / 3
= 2*m[2] / 3 + x[3] / 3
= (2*m[2] + x[3]) / 3
...
m[i+1] = (i * m[i] + x[i+1]) / (i+1)
However, since this function would require the element index as a parameter, due to the List structure's lack of (convenient) indexing, the Sequence type from the Data.Sequence module may work out better than a List, especially considering the Data.Sequence module has this really nice foldlWithIndex function:
module Average(average) where
import Data.Sequence(foldlWithIndex, fromList)
average :: Fractional a => [a] -> a
average = foldlWithIndex averageByPrevious 0 . fromList
where averageByPrevious previous index current = (coefficient*previous + current) / (coefficient + 1)
where coefficient = fromIntegral index
Then you can simply run average list where list is some list you want to find the rolling average of. This is one way to calculate the average of a list using a single fold without adding a large performance overhead as you would by running multiple O(n) functions over the same list, even considering laziness as a benefit to the performance of multiple calls.
NOTE: I will admit, this is not easy to read, so average xs = (sum xs) / (length xs) as #Lorenzo said will work much better if legibility is more important than performance here.

Is it possible to generalise equations in Haskell?

Apologies for my poor wording of the question. I've tried searching for an answer but not knowing what to search is making it very difficult to find one.
Here is a simple function which calculates the area of a triangle.
triangleArea :: Float -> Float -> Float -> Float
triangleArea a b c
| (a + b) <= c = error "Not a triangle!"
| (a + c) <= b = error "Not a triangle!"
| (b + c) <= a = error "Not a triangle!"
| otherwise = sqrt (s * (s - a) * (s - b) * (s - c))
where s = (a + b + c) / 2
Three lines of the function have been taken up for the purposes of error checking. I was wondering if these three lines could be condensed into one generic line.
I was wondering if something similar to the following would be possible
(arg1 + arg2) == arg3
where Haskell knows to check each possible combination of the three arguments.
I think #behzad.nouri's comment is the best. Sometimes doing a little math is the best way to program. Here's a somewhat overdone expansion on #melpomene's solution, which I thought would be fun to share. Let's write a function similar to permutations but that computes combinations:
import Control.Arrow (first, second)
-- choose n xs returns a list of tuples, the first component of each having
-- n elements and the second component having the rest, in all combinations
-- (ignoring order within the lists). N.B. this would be faster if implemented
-- using a DList.
choose :: Int -> [a] -> [([a],[a])]
choose 0 xs = [([], xs)]
choose _ [] = []
choose n (x:xs) =
map (first (x:)) (choose (n-1) xs) ++
map (second (x:)) (choose n xs)
So..
ghci> choose 2 [1,2,3]
[([1,2],[3]),([1,3],[2]),([2,3],[1])]
Now you can write
triangleArea a b c
| or [ x + y <= z | ([x,y], [z]) <- choose 2 [a,b,c] ] = error ...
This doesn't address the question of how to shorten your error checking code, but you may be able to limit how often you repeat it by defining some new types with invariants. This function needs error checking because you can't trust the user to supply Float triples that make a reasonable triangle, and if you continue to define functions this way then every triangle-related function you write would need similar error checks.
However, if you define a Triangle type, you can check your invariants only once, when a triangle is created, and then all other functions will be guaranteed to receive valid triangles:
module Triangle (Triangle(), mkTriangle, area) where
data Triangle a = Triangle a a a deriving Show
mkTriangle :: (Num a, Ord a) => a -> a -> a -> Either String (Triangle a)
mkTriangle a b c
| a + b <= c = wrong
| a + c <= b = wrong
| b + c <= a = wrong
| otherwise = Right $ Triangle a b c
where wrong = Left "Not a triangle!"
area :: Floating a => Triangle a -> a
area (Triangle a b c) = sqrt (s * (s - a) * (s - b) * (s - c))
where s = (a + b + c) / 2
Here we export the Triangle type, but not its constructor, so that the client must use mkTriangle instead, which can do the required error checking. Then area, and any other triangle functions you write, can omit the checks that they are receiving a valid triangle. This general pattern is called "smart constructors".
Here are two ideas.
Using existing tools, you can generate all the permutations of the arguments and check that they all satisfy a condition. Thus:
import Data.List
triangleArea a b c
| any (\[x, y, z] -> x + y <= z) (permutations [a,b,c])
= error "Not a triangle!"
| otherwise = {- ... -}
This doesn't require writing very much additional code; however, it will search some permutations you don't care about.
Use the usual trick for choosing an element from a list and the left-overs. The zippers function is one I use frequently:
zippers :: [a] -> [([a], a, [a])]
zippers = go [] where
go b [] = []
go b (v:e) = (b, v, e) : go (v:b) e
We can use it to build a function which chooses only appropriate triples of elements:
triples :: [a] -> [(a, a, a)]
triples xs = do
(b1, v1, e1) <- zippers xs
(b2, v2, e2) <- zippers e1
v3 <- b1 ++ b2 ++ e2
return (v1, v2, v3)
Now we can write our guard like in part (1), but it will only consider unique pairings for the addition.
triangleArea a b c
| any (\(x, y, z) -> x + y <= z) (triples [a,b,c])
= error "Not a triangle!"
| otherwise = {- ... -}

Fibonacci's Closed-form expression in Haskell

How would the Fibonacci's closed form code look like in haskell?
Here's a straightforward translation of the formula to Haskell:
fib n = round $ (phi^n - (1 - phi)^n) / sqrt 5
where phi = (1 + sqrt 5) / 2
This gives correct values only up to n = 75, because it uses Double precision floating-point arithmetic.
However, we can avoid floating-point arithmetic by working with numbers of the form a + b * sqrt 5! Let's make a data type for them:
data Ext = Ext !Integer !Integer
deriving (Eq, Show)
instance Num Ext where
fromInteger a = Ext a 0
negate (Ext a b) = Ext (-a) (-b)
(Ext a b) + (Ext c d) = Ext (a+c) (b+d)
(Ext a b) * (Ext c d) = Ext (a*c + 5*b*d) (a*d + b*c) -- easy to work out on paper
-- remaining instance methods are not needed
We get exponentiation for free since it is implemented in terms of the Num methods. Now, we have to rearrange the formula slightly to use this.
fib n = divide $ twoPhi^n - (2-twoPhi)^n
where twoPhi = Ext 1 1
divide (Ext 0 b) = b `div` 2^n -- effectively divides by 2^n * sqrt 5
This gives an exact answer.
Daniel Fischer points out that we can use the formula phi^n = fib(n-1) + fib(n)*phi and work with numbers of the form a + b * phi (i.e. ℤ[φ]). This avoids the clumsy division step, and uses only one exponentiation. This gives a much nicer implementation:
data ZPhi = ZPhi !Integer !Integer
deriving (Eq, Show)
instance Num ZPhi where
fromInteger n = ZPhi n 0
negate (ZPhi a b) = ZPhi (-a) (-b)
(ZPhi a b) + (ZPhi c d) = ZPhi (a+c) (b+d)
(ZPhi a b) * (ZPhi c d) = ZPhi (a*c+b*d) (a*d+b*c+b*d)
fib n = let ZPhi _ x = phi^n in x
where phi = ZPhi 0 1
Trivially, Binet's formula, from the Haskell wiki page is given in Haskell as:
fib n = round $ phi ^ n / sq5
where
sq5 = sqrt 5
phi = (1 + sq5) / 2
Which includes sharing of the result of the square root. For example:
*Main> fib 1000
4346655768693891486263750038675
5014010958388901725051132915256
4761122929200525397202952340604
5745805780073202508613097599871
6977051839168242483814062805283
3118210513272735180508820756626
59534523370463746326528
For arbitrary integers, you'll need to be a bit more careful about the conversion to floating point values.
Note that Binet's value differs from the recursive formula by quite a bit at this point:
*Main> let fibs = 0 : 1 : zipWith (+) fibs (tail fibs)
*Main> fibs !! 1000
4346655768693745643568852767504
0625802564660517371780402481729
0895365554179490518904038798400
7925516929592259308032263477520
9689623239873322471161642996440
9065331879382989696499285160037
04476137795166849228875
You may need more precision :-)

Resources