Here is my problem: I need a Haskell function that computes an approximation of the sine of some number, using the associated Taylor serie ...
In C++ I wrote this:
double msin(double number, int counter = 0, double sum = 0)
{
// sin(x) = x - (x'3 / 3!) + (x'5 / 5!) - (x'7 / 7!) + (x'9 / 9!)
if (counter <= 20)
{
if (counter % 2 == 0)
sum += mpow(number, counter * 2 + 1) / mfak(counter * 2 + 1) ;
else
sum -= mpow(number, counter * 2 + 1) / mfak(counter * 2 + 1) ;
counter++;
sum = msin(number, counter, sum);
return sum;
}
return (sum* 180.0 / _PI);
}
Now I am trying to do it in Haskell and I have no idea how... For now I was trying something like this (it doesn't really work, but it is work in progress ;) ):
This works:
mfak number = if number < 2
then 1
else number *( mfak (number -1 ))
mpow number potenca = if potenca == 0
then 0
else if potenca == 1
then 1
else (number * (mpow number (potenca-1)))
This doesn't work:
msin :: Double -> Int -> Double -> Double
msin number counter sum = if counter <= 20
then if counter `mod` 2==0
then let sum = sum + (msin 1 (let counter = counter+1 in counter) sum) in sum
else let sum = sum + (msin 1 (let counter = counter+1 in counter) sum) in sum
else sum* 180.0 / 3.14
Updated....doesn't compile :/ "Couldn't match expected type Double' with actual type Int'"
msin :: Double -> Int -> Double -> Double
msin number counter sum = if counter <= 20
then if counter `mod` 2==0
then let sum' = sum + ((mpow number (counter*2+1))/(mfak counter*2+1)) in msin number (counter+1) sum'
else let sum' = sum - ((mpow number (counter*2+1))/(mfak counter*2+1)) in msin number (counter+1) sum'
else sum* 180.0 / 3.14
As you can see, the biggest problem is how to add something to "sum", increase "counter" and go in recursion again with these new values...
P.S. I am new to Haskell so try to explain your solution as much as you can please. I was reading some tutorials and that, but I can't find how to save the result of some expression into a value and then continue with other code after it... It just returns my value each time I try to do that, and I don't want that....
So thanks in advance for any help!
I would rework the algorithm a bit. First we can define the list of factorial inverses:
factorialInv :: [Double]
factorialInv = scanl (/) 1 [1..] -- 1/0! , 1/1! , 1/2! , 1/3! , ...
Then, we follow with the sine coefficients:
sineCoefficients :: [Double]
sineCoefficients = 0 : 1 : 0 : -1 : sineCoefficients
Then, given x, we multiply both the above lists with the powers of x, pointwise:
powerSeries :: [Double] -- ^ Coefficients
-> Double -- ^ Point x on which to compute the series
-> [Double] -- ^ Series terms
powerSeries cs x = zipWith3 (\a b c -> a * b * c) cs powers factorialInv
where powers = iterate (*x) 1 -- 1 , x , x^2 , x^3 , ...
Finally, we take the first 20 terms and sum them up.
sine :: Double -> Double
sine = sum . take 20 . powerSeries sineCoefficients
-- i.e., sine x = sum (take 20 (powerSeries sineCoefficients x))
The problem is expressions like let stevec = stevec+1 in stevec. Haskell is not an imperative language. This does not add one to stevec. Instead it defines stevec to be a number that is one more than itself. No such number exists, thus you will get an infinite loop or, if you are lucky, a crash.
Instead of
stevec++;
vsota = msin(stevilo, stevec, vsota);
You should use something like
let stevec' = stevec + 1
in msin stevilo stevec' vsota
or just
msin stevilo (stevec + 1) vsota
(There's also something here that I don't understand. You are going to need mpow and mfak. Where are they?)
As you can see the biggest problem is how to add something to "vsota",
In a functional language you would use recursion here - the variable vstota is implemented as a function parameter which is passed from call to call as a list is processed.
For example, to sum a list of numbers, we would write something like:
sum xs = go 0 xs
where go total [] = total
go total (x:xs) = go (total+x) xs
In an imperative language total would be a variable which gets updated. Here is is a function parameter which gets passed to the next recursive call to go.
In your case, I would first write a function which generates the terms of the power series:
sinusTerms n x = ... -- the first n terms of x - (x'3 / 3!) + (x'5 / 5!) - (x'7 / 7!) ...
and then use the sum function above:
sinus n x = sum (sinusTerms n x)
You may also use recursive lists definitions to get [x, x^3, x^5 ...] and [1, 1/3!, 1/5! ...] infinite sequences. When they are done, the rest is to multiply their items each by other and take the sum.
sinus count x = sum (take count $ zipWith (*) ifactorials xpowers)
where xpowers = x : map ((x*x)*) xpowers
ifactorials = 1 : zipWith (/) ifactorials [i*(i+1) | i <- [2, 4 .. ]]
Also, it would be better to define xpowers = iterate ((x*x)*) x, as it seems to be much more readable.
I’ve tried to follow your conventions as much as I could. For mfak and mpow, you should avoid using if as it is clearer to write them using pattern matching :
mfak :: Int -> Int
mfak 0 = 1
mfak 1 = 1
mfak n = n * mfak (n - 1)
mpow :: Double -> Int -> Double
mpow _ 0 = 1
mpow x 1 = x
mpow x p = x * mpow x (p - 1)
Before calculating the sinus, we create a list of coefficients [(sign, power, factorial)] :
x - (x^3 / 3!) + (x^5 / 5!) - (x^7 / 7!) + (x^9 / 9!)
→ [(1,1,1), (-1,3,6), (1,5,120), (-1,7,5040), (1,9,362880)]
The list is created infinite by a list comprehension. First we zip the lists [1,-1,1,-1,1,-1...] and [1,3,5,7,9,11...]. This gives us the list [(1,1), (-1,3), (1,5), (-1,7)...]. From this list, we create the final list [(1,1,1), (-1,3,6), (1,5,120), (-1,7,5040)...]:
sinCoeff :: [(Double, Int, Double)]
sinCoeff = [ (fromIntegral s, i, fromIntegral $ mfak i)
| (s, i) <- zip (cycle [1, -1]) [1,3..]]
(cycle repeats a list indefinitely, [1,3..] creates an infinite list which starts at 1 with a step of 2)
Finally, the msin function is near the definition. It also uses a list comprehension to achieve its goeal (note that I kept the * 180 / pi though I’m not sure it should be there. Haskell knows pi).
msin :: Int -> Double -> Double
msin n x = 180 * sum [ s * mpow x p / f | (s, p, f) <- take n sinCoeff] / pi
(take n sinCoeff returns the first n elements of a list)
You may try the previous code with the following :
main = do
print $ take 10 sinCoeff
print $ msin 5 0.5
print $ msin 10 0.5
The expression is of the form x*P(x2).
For maximal efficiency, the polynomial in x2 must be evaluated using the Horner rule rather than computing the powers of x2 separately.
The coefficient serie with the factorial values can be expressed recursively in Haskell, just like is commonly done for the Fibonacci series. Using the ghci interpreter as our testbed, we have:
$ ghci
GHCi, version 8.8.4: https://www.haskell.org/ghc/ :? for help
λ>
λ>
λ> nextCoeffs d c = c : (nextCoeffs (d+1) ((-c)/(fromIntegral $ (2*d+2)*(2*d+3))))
λ>
λ> allCoeffs = nextCoeffs 0 1.0
λ>
where d is the depth inside the serie and c the current coefficient.
Sanity check: the coefficient at depth 3 must be the inverse of 7!
λ>
λ> 1.0 /(allCoeffs !! 3)
-5040.0
λ>
The Horner rule can be rendered in Haskell thru the foldr1 :: (a -> a -> a) -> [a] -> a library function.
As is customary in Haskell, I take the liberty to put the term count as the leftmost argument because it is the one most likely to be held constant. This is for currying (partial evaluation) purposes.
So we have:
λ> :{
|λ> msin count x = let { s = x*x ; cs = take count allCoeffs ;
|λ> stepFn c acc = acc*s + c ; }
|λ> in x * (foldr1 stepFn cs)
|λ> :}
Sanity checks, taking 20 terms:
λ>
λ> pi
3.141592653589793
λ>
λ> msin 20 (pi/6)
0.49999999999999994
λ>
λ> msin 20 (pi/2)
1.0
λ>
Side note 1: final multiplication by 180 / π is only of interest for inverse trigonometric functions.
Side note 2: in practice, to get a reasonably fast convergence, one should reduce the input variable x into the [-π,+π] interval using the periodicity of the sine function.
Related
Hello every body im training some SMLs and im creating a code to get deviation of a int list . in the process of it , i need to get a Real list out of some numbers in a int list , which it doesnt let me get them. heres my code :
fun mean [] = 0.0
| mean (first::rest) =
let
fun sum [] = 0
| sum (x::xs) = x + sum xs
fun counter [] = 0
| counter (y::ys) = 1 + counter ys
in
Real.fromInt (sum (first::rest)) / Real.fromInt (counter (first::rest))
end;
fun deviation [] = 0.0
| deviation (first::rest) =
let
fun diff (x::xs) = (x - mean (x::xs)) :: diff xs;
in
diff (first , first::rest) + deviation rest
end;
the problem is here :
fun diff (x::xs) = (x - mean (x::xs) ) :: diff xs;
diff is a recursive function, but the base case is never defined. When you try to run diff on an empty list, you will get a pattern match error.
You also define diff to accept a list, but you call it with a tuple.
You define diff as returning a list, given that you are using ::, but then you use addition on the result of that function, which will not work.
Improving mean
You can simplify your sum and counter functions with folds.
fun mean [] = 0.0
| mean lst =
let
val sum = foldl op+ 0 lst
val counter = foldl (fn (_, c) => c + 1) 0 lst
in
Real.fromInt sum / Real.fromInt counter
end;
But this requires iterating the entire list twice, when both pieces of information can be ascertained at the same time.
fun sumLen(lst) =
foldl (fn (x, (sum, len)) => (sum+x, len+1)) (0, 0) lst
mean can now be implemented as:
fun mean(lst) =
let
val (sum, len) = sumLen(lst)
in
Real.fromInt sum / Real.fromInt len
end
Deviation
To get the differences from the mean for a list, you need only use map.
fun diffs(lst) =
let
val m = mean(lst)
in
map (fn x => Real.fromInt x - m) lst
end
Consider evaluating the following.
diffs [1, 2, 3, 4, 5, 6, 7, 8]
The result is:
[~3.5, ~2.5, ~1.5, ~0.5, 0.5, 1.5, 2.5, 3.5]
From there you can use map and Math.pow to square those differences, foldl to sum them, divide by the length of the list, and then Math.sqrt to get the standard deviation.
Lets say we have a record which defines students:
type student = {
name : string;
age : int;
grades : (float) list;
}
And safe them in a list like this:
let studentlist = [ {name="alex"; age=7; grades=[1.;2.;3.]} ;
{name="bianca"; age=6; grades=[1.;1.;2.]} ];;
My aim is to compute the grade average of a special student which I choose per age, I select the student with the function search:
let search a lst = List.find( fun {age;_} -> a = age)lst
And compute the average with the help-functions , named sum, length and finally avr :
let rec sum lst =
match lst with
| [] -> 0.0
| h :: t -> h +. sum t
let length lst = float_of_int (List.length lst);;
let avr lst = sum lst /. length lst;;
I don't know how to combine those functions to compute the average properly!
Most of what you've done seems to work. For instance, search works.
utop # search 7 studentlist;;
- : student = {name = "alex"; age = 7; grades = [1.; 2.; 3.]}
If you want to access the grades field of that record, use . for record access.
utop # (search 7 studentlist).grades;;
- : float list = [1.; 2.; 3.]
Now that you have a list of float values, finding the sum or average of them should be easy by passing that value as an argument to the relevant function you've already defined.
Bear in mind that when you use List.find in search, if you search for an age that is not present, you will get a Not_found exception that you will want to handle.
As an aside, note that your avr function iterates over the list twice. Once to compute the sum, and ocne to compute the length.
It is possible to computer the sum, the length, and the average in a single pass. We can use a fold to do this. First off, we can define a basic left fold:
let rec foldl f init lst =
match lst with
| [] -> init
| x::xs -> foldl f (f init x) xs
Consider using this to compute the length of a list:
foldl (fun i _ -> i + 1) 0 [1.; 2.; 3.]
When evaluated:
foldl (fun i _ -> i + 1) 0 [1.; 2.; 3.]
foldl (fun i _ -> i + 1) (0 + 1) [2.; 3.]
foldl (fun i _ -> i + 1) (1 + 1) [3.]
foldl (fun i _ -> i + 1) (2 + 1) []
3
But we can pass a tuple of values to foldl, building up the length, sum, and average as we go.
utop # let (len, sum, avg) = foldl
(fun (len, sum, avg) x ->
let sum = sum +. x in
let len = len + 1 in
let flen = float_of_int len in
(len, sum, sum /. flen))
(0, 0., 0.)
[1.; 2.; 3.];;
val len : int = 3
val sum : float = 6.
val avg : float = 2.
I'm trying to solve a decomposition problem with backtracking and list Monad in Haskell. Here is the problem statement: given a positive integer n, find all lists of consecutive integers (in range i..j) whose sum is equal to n.
I came out with the following solution which seems to work fine. Could someone suggest a better/more efficient implementation using list Monad and backtracking?
Any suggestions are welcome. Thanks in advance.
import Control.Monad
decompose :: Int -> [[Int]]
decompose n = concatMap (run n) [1 .. n - 1]
where
run target n = do
x <- [n]
guard $ x <= target
if x == target
then return [x]
else do
next <- run (target - n) (n + 1)
return $ x : next
test1 = decompose 10 == [[1,2,3,4]]
test2 = decompose 9 == [[2,3,4],[4,5]]
The sum of a range of numbers k .. l with k≤l is equal to (l×(l+1)-k×(k-1))/2. For example: 1 .. 4 is equal to (4×5-1×0)/2=(20-0)/2=10; and the sum of 4 .. 5 is (5×6-4×3)/2=(30-12)/2=9.
If we have a sum S and an offset k, we can thus find out if there is an l for which the sum holds with:
2×S = l×(l+1)-k×(k-1)
0=l2+l-2×S-k×(k-1)
we can thus solve this equation with:
l=(-1 + √(1+8×S+4×k×(k-1)))/2
If this is an integral number, then the sequence exists. For example for S=9 and k=4, we get:
l = (-1 + √(1+72+48))/2 = (-1 + 11)/2 = 10/2 = 5.
We can make use of some function, like the Babylonian method [wiki] to calculate integer square roots fast:
squareRoot :: Integral t => t -> t
squareRoot n
| n > 0 = babylon n
| n == 0 = 0
| n < 0 = error "Negative input"
where
babylon a | a > b = babylon b
| otherwise = a
where b = quot (a + quot n a) 2
We can check if the found root is indeed the exact square root with by squaring the root and see if we obtain back the original input.
So now that we have that, we can iterate over the lowerbound of the sequence, and look for the upperbound. If that exists, we return the sequence, otherwise, we try the next one:
decompose :: Int -> [[Int]]
decompose s = [ [k .. div (sq-1) 2 ]
| k <- [1 .. s]
, let r = 1+8*s+4*k*(k-1)
, let sq = squareRoot r
, r == sq*sq
]
We can thus for example obtain the items with:
Prelude> decompose 1
[[1]]
Prelude> decompose 2
[[2]]
Prelude> decompose 3
[[1,2],[3]]
Prelude> decompose 3
[[1,2],[3]]
Prelude> decompose 1
[[1]]
Prelude> decompose 2
[[2]]
Prelude> decompose 3
[[1,2],[3]]
Prelude> decompose 4
[[4]]
Prelude> decompose 5
[[2,3],[5]]
Prelude> decompose 6
[[1,2,3],[6]]
Prelude> decompose 7
[[3,4],[7]]
Prelude> decompose 8
[[8]]
Prelude> decompose 9
[[2,3,4],[4,5],[9]]
Prelude> decompose 10
[[1,2,3,4],[10]]
Prelude> decompose 11
[[5,6],[11]]
We can further constrain the ranges, for example specify that k<l, with:
decompose :: Int -> [[Int]]
decompose s = [ [k .. l ]
| k <- [1 .. div s 2 ]
, let r = 1+8*s+4*k*(k-1)
, let sq = squareRoot r
, r == sq*sq
, let l = div (sq-1) 2
, k < l
]
This then gives us:
Prelude> decompose 1
[]
Prelude> decompose 2
[]
Prelude> decompose 3
[[1,2]]
Prelude> decompose 4
[]
Prelude> decompose 5
[[2,3]]
Prelude> decompose 6
[[1,2,3]]
Prelude> decompose 7
[[3,4]]
Prelude> decompose 8
[]
Prelude> decompose 9
[[2,3,4],[4,5]]
Prelude> decompose 10
[[1,2,3,4]]
Prelude> decompose 11
[[5,6]]
NB This answer is slightly tangential since the question specifically calls for a direct backtracking solution in Haskell. Posting it in case there is some interest in other approaches to this problem, in particular using off-the-shelf SMT solvers.
These sorts of problems can be easily handled by off-the-shelf constraint solvers, and there are several libraries in Haskell to access them. Without going into too much detail, here's how one can code this using the SBV library (https://hackage.haskell.org/package/sbv):
import Data.SBV
decompose :: Integer -> IO AllSatResult
decompose n = allSat $ do
i <- sInteger "i"
j <- sInteger "j"
constrain $ 1 .<= i
constrain $ i .<= j
constrain $ j .< literal n
constrain $ literal n .== ((j * (j+1)) - ((i-1) * i)) `sDiv` 2
We simply express the constraints on i and j for the given n, using the summation formula. The rest is simply handled by the SMT solver, giving us all possible solutions. Here're a few tests:
*Main> decompose 9
Solution #1:
i = 4 :: Integer
j = 5 :: Integer
Solution #2:
i = 2 :: Integer
j = 4 :: Integer
Found 2 different solutions.
and
*Main> decompose 10
Solution #1:
i = 1 :: Integer
j = 4 :: Integer
This is the only solution.
While this may not provide much insight into how to solve the problem, it sure leverages existing technologies. Again, while this answer doesn't use the list-monad as asked, but hopefully it is of some interest when considering applications of SMT solvers in regular programming.
for a given list by user s=[x1,x2,...,xk] I need to calculate the sum of
x1 * (x2+x3+...x4)
+ (x1+x2) * (x3+x4+...xk)
+ ...
+ (x1+x2+...+x(k-2)) * (x(k-1) + xk)
+ (x1+x2+...+x(k-1)) * xk
from a function [Int]->Int
Please see the math formula in the following photo for better understanding :
https://imgur.com/gallery/Oqgpkcu
just tried very little things like calculating the sum of the list minus the last element. By the way i must implement all of this by using lists and very basic functions (head, tail ,init )
xsum :: [Int] -> Int
xsum s = sumIntList (init s)
sumIntList :: [Int] -> Int
sumIntList (h:t) = h + sumIntList t
sumIntList [] = 0
some of the result that SHOULD be produced by the calling of the function are :
xsum [4,5,8]
124
xsum [1..100]
341665830
Thanks for reading !
The image you provided says * rather than ^. It would be good to see some of your attempts. One simple approach would be to map the function splitAt across each possible index, then use the function sum on each pair to get the (initial segment sum, final segment sum) pair, then for each pair multiply its elements together, then sum all the resulting products. How far can you get with coding that up?
EDIT: to save potential future readers from scrolling through all the comments, a potential implementation is given below that uses only sum. It is suboptimal because it sums the same sublists many times over, a better implementation might start by using scanl in both directions to generate the partial sums and proceed from there.
xsum (x:xs#(y:ys)) = x * sum xs + xsum ((x+y):ys)
xsum _ = 0
EDIT2: We have a (sort of) forwards-travelling and backwards-travelling thing going on, I like it!
xsum = fst . xsum'
where xsum' (x:xs#(y:ys)) = (\(acc,s) -> (acc + x * (s-x),s) ) $ xsum' ((x+y):ys)
xsum' [] = (0,0)
xsum' [x] = (0,x)
I'm trying to iterate a list and square all the number and add them together
sumsq (x:xs) =
let total = 0
loop length(x:xs) (x:xs) total
loop 0 (x:xs) = return ()
loop n (x:xs) total =
do
let
sq = ((x:xs)!!n)^2
total = total + sq
loop ((n-1) (x:xs) total)
But I'm getting parse error in loop. Where am I going wrong?
Also is there a better way to do this?
First of all - you miss spaces! It is significant.
Second, you forget in from let ... in. We could not use in in do-notation:
sumsq (x:xs) =
let total = 0 in
loop length(x:xs) (x:xs) total
Third, you do not use x and xs form (x:xs) :
sumsq xs =
let total = 0 in
loop (length xs) xs total
And we unite our length xsin one block. It is fourth.
Fifth, we have 3, not 2 arguments for loop:
loop 0 xs total = return total
Sixth, (!!) work from 0, but you use it from 1, so (xs !! (n -1)) is right
Seventh, you don't need to use monad, just recursion. So, get rid from return and do
Eighth. you have infinite recursive total = total + smth
Ninth, we can't use arguments as tuple, so, you final working result is :
sumsq xs =
let total = 0 in
loop (length xs) xs total
loop 0 xs total = total
loop n xs total = loop (n-1) xs total1
where
sq = (xs !! (n -1)) ^2
total1 = total + sq
UPDATED
If we are talking about complexity, it is not good - O(n^2) as it is mentioned in comments : for each element we seek this element.
We could simplify our loop function and get rid of n argument:
loop [] total = total
loop (x:xs) total = loop xs total1
where
sq = x ^ 2
total1 = total + sq
and our sumsq function we write:
sumsq xs = loop xs 0
P.S.
This is an implementation much easier function sumsq = sum. map (^ 2)
If I understood you correctly, you could simply do this with map and sum:
Prelude> let myFun = sum . map (^2)
Prelude> myFun [1, 2, 3]
14
Or with foldl1 and lambda:
Prelude> let myFun' = foldl1 (\s x -> s + x^2)
Prelude> myFun' [1, 2, 3, 4]
30
Surely something like this would be the usual approach?
sumSquared :: [Integer] -> Integer
sumSquared [] = 0
sumSquared (x:xs) = (x * x) + sumSquared xs
Or you could do this even more succinctly with foldr, or sum and map (like #soon's answer)
The do must be more indented than the word loop.
Apart from that, you don't need do (or return) at all here, unless you can answer the question which monad this is for?
There are more problems with your code. One of the most severe is this:
You don't seem to know what "pattern matching" is, nor what it is good for. You really want to learn about it, otherwise you can't write any good programs.