1
+ {-|
2
+ Module: Numeric.Roots
3
+ Description: Root finding algorithms
4
+ Copyright: (c) A.E. Drew, 2023
5
+ -}
1
6
module Numeric.Roots (
7
+ -- * Runner
8
+ solve ,
9
+ -- * Iterative steps
2
10
bisect ,
3
11
falsePosition ,
4
12
fixedPoint ,
5
13
newton ,
6
14
secant ,
7
- solve ,
8
15
) where
9
16
10
17
import Control.Monad.State
11
18
19
+ -- | Runs an iterative algorithm until it satisfies a stopping condition or
20
+ -- performs n iterations. The stopping condition takes the last two
21
+ -- approxiamtions.
12
22
solve :: (a -> a -> Bool ) -> Int -> State b a -> b -> Maybe a
13
23
solve stop n step s0 = case solutions of
14
24
[] -> Nothing
@@ -19,6 +29,13 @@ solve stop n step s0 = case solutions of
19
29
ps = evalState (replicateM n step) s0
20
30
ps' = tail ps
21
31
32
+ -- | \[
33
+ -- p_n = \frac{a_n + b_n}{2} \\
34
+ -- (a_n,b_n) = \begin{cases}
35
+ -- (p_{n-1},b_{n-1}) & \quad \text{if } f(a_{n-1})f(p) < 0 \\
36
+ -- (a_{n-1}, p_{n-1}) & \quad \text{else}
37
+ -- \end{cases}
38
+ -- \]
22
39
bisect :: (Eq a ,Fractional a ) => (a -> a ) -> State (a ,a ) a
23
40
bisect f = do (a,b) <- get
24
41
let s' | signAt p == signAt a = (p,b)
@@ -28,26 +45,44 @@ bisect f = do (a,b) <- get
28
45
put s'
29
46
return p
30
47
48
+ -- | \[
49
+ -- p_n = f(p_{n-1})
50
+ -- \]
31
51
fixedPoint :: (a -> a ) -> State a a
32
52
fixedPoint f = state $ \ p -> let p' = f p in (p', p')
33
53
54
+ -- | \[
55
+ -- p_n = \frac{p_{n-2}f(p_{n-1}) - p_{n-1}f(p_{n-2})}{f(p_{n-1}) - f(p_{n-2})}
56
+ -- \]
34
57
secant :: Fractional a => (a -> a ) -> State (a ,a ) a
35
58
secant f = do (p,p') <- get
36
- let fp = f p
37
- fp' = f p'
38
- p'' = (p* fp' - p'* fp)/ (fp' - fp)
59
+ let p'' = calcSecant f p p'
39
60
put (p',p'')
40
61
return p''
41
62
63
+ -- | \[
64
+ -- p_n = p_{n-1} - \frac{f(p_{n-1})}{f'(p_{n-1})}
65
+ -- \]
42
66
newton :: Fractional a => (a -> a ) -> (a -> a ) -> State a a
43
67
newton f f' = fixedPoint $ \ p -> p - (f p)/ (f' p)
44
68
69
+ -- | \[
70
+ -- p_n = \frac{p_{n-2}f(p_{n-1}) - p_{n-1}f(p_{n-2})}
71
+ -- {f(p_{n-1}) - f(p_{n-2})} \\
72
+ -- p_{n-1} = \begin{cases}
73
+ -- p_{n-1} & \quad \text{if } f(p_n)f(p_{n-1}) < 0 \\
74
+ -- p_{n-2} & \quad \text{else}
75
+ -- \end{cases}
76
+ -- \]
45
77
falsePosition :: (Eq a , Fractional a ) => (a -> a ) -> State (a ,a ) a
46
78
falsePosition f = do (p,p') <- get
47
- let fp = f p
48
- fp' = f p'
49
- p'' = (p* fp' - p'* fp)/ (fp' - fp)
79
+ let p'' = calcSecant f p p'
50
80
if signum (f p'') == signum (f p')
51
81
then put (p,p'')
52
82
else put (p',p'')
53
83
return p''
84
+
85
+ calcSecant :: Fractional a => (a -> a ) -> a -> a -> a
86
+ calcSecant f p p' = (p* fp' - p'* fp)/ (fp' - fp)
87
+ where fp = f p
88
+ fp' = f p'
0 commit comments