diff options
author | Alberto Ruiz <aruiz@um.es> | 2009-06-04 09:01:56 +0000 |
---|---|---|
committer | Alberto Ruiz <aruiz@um.es> | 2009-06-04 09:01:56 +0000 |
commit | 6e0dd472ef8c570ec1924ac641e5872db30ac142 (patch) | |
tree | 64963c6af75cdbc02336de82b51136964f36dc73 /lib/Numeric/GSL/Root.hs | |
parent | f49ac4def26b38d3d084375007715156be347412 (diff) |
added some root finding algorithms
Diffstat (limited to 'lib/Numeric/GSL/Root.hs')
-rw-r--r-- | lib/Numeric/GSL/Root.hs | 117 |
1 files changed, 117 insertions, 0 deletions
diff --git a/lib/Numeric/GSL/Root.hs b/lib/Numeric/GSL/Root.hs new file mode 100644 index 0000000..ad1b72c --- /dev/null +++ b/lib/Numeric/GSL/Root.hs | |||
@@ -0,0 +1,117 @@ | |||
1 | {- | | ||
2 | Module : Numeric.GSL.Root | ||
3 | Copyright : (c) Alberto Ruiz 2009 | ||
4 | License : GPL | ||
5 | |||
6 | Maintainer : Alberto Ruiz (aruiz at um dot es) | ||
7 | Stability : provisional | ||
8 | Portability : uses ffi | ||
9 | |||
10 | Multidimensional root finding. | ||
11 | |||
12 | <http://www.gnu.org/software/gsl/manual/html_node/Multidimensional-Root_002dFinding.html> | ||
13 | |||
14 | The example in the GSL manual: | ||
15 | |||
16 | @import Numeric.GSL | ||
17 | import Numeric.LinearAlgebra(format) | ||
18 | import Text.Printf(printf) | ||
19 | |||
20 | rosenbrock a b [x,y] = [ a*(1-x), b*(y-x^2) ] | ||
21 | |||
22 | disp = putStrLn . format \" \" (printf \"%.3f\") | ||
23 | |||
24 | main = do | ||
25 | let (sol,path) = root Hybrids 1E-7 30 (rosenbrock 1 10) [-10,-5] | ||
26 | print sol | ||
27 | disp path | ||
28 | |||
29 | \> main | ||
30 | [1.0,1.0] | ||
31 | 0.000 -10.000 -5.000 11.000 -1050.000 | ||
32 | 1.000 -3.976 24.827 4.976 90.203 | ||
33 | 2.000 -3.976 24.827 4.976 90.203 | ||
34 | 3.000 -3.976 24.827 4.976 90.203 | ||
35 | 4.000 -1.274 -5.680 2.274 -73.018 | ||
36 | 5.000 -1.274 -5.680 2.274 -73.018 | ||
37 | 6.000 0.249 0.298 0.751 2.359 | ||
38 | 7.000 0.249 0.298 0.751 2.359 | ||
39 | 8.000 1.000 0.878 -0.000 -1.218 | ||
40 | 9.000 1.000 0.989 -0.000 -0.108 | ||
41 | 10.000 1.000 1.000 0.000 0.000 | ||
42 | @ | ||
43 | |||
44 | -} | ||
45 | ----------------------------------------------------------------------------- | ||
46 | |||
47 | module Numeric.GSL.Root ( | ||
48 | root, RootMethod(..) | ||
49 | ) where | ||
50 | |||
51 | import Data.Packed.Internal | ||
52 | import Data.Packed.Matrix | ||
53 | import Foreign | ||
54 | import Foreign.C.Types(CInt) | ||
55 | |||
56 | ------------------------------------------------------------------------- | ||
57 | |||
58 | data RootMethod = Hybrids | ||
59 | | Hybrid | ||
60 | | DNewton | ||
61 | | Broyden | ||
62 | deriving (Enum,Eq,Show) | ||
63 | |||
64 | -- | Nonlinear multidimensional root finding using algorithms that do not require | ||
65 | -- any derivative information to be supplied by the user. | ||
66 | -- Any derivatives needed are approximated by finite differences. | ||
67 | root :: RootMethod | ||
68 | -> Double -- ^ maximum residual | ||
69 | -> Int -- ^ maximum number of iterations allowed | ||
70 | -> ([Double] -> [Double]) -- ^ function to minimize | ||
71 | -> [Double] -- ^ starting point | ||
72 | -> ([Double], Matrix Double) -- ^ solution vector and optimization path | ||
73 | |||
74 | root method epsabs maxit fun xinit = rootGen (fi (fromEnum method)) fun xinit epsabs maxit | ||
75 | |||
76 | rootGen m f xi epsabs maxit = unsafePerformIO $ do | ||
77 | let xiv = fromList xi | ||
78 | n = dim xiv | ||
79 | fp <- mkVecVecfun (aux_vTov (fromList.f.toList)) | ||
80 | rawpath <- withVector xiv $ \xiv' -> | ||
81 | createMIO maxit (2*n+1) | ||
82 | (c_root m fp epsabs (fi maxit) // xiv') | ||
83 | "root" | ||
84 | let it = round (rawpath @@> (maxit-1,0)) | ||
85 | path = takeRows it rawpath | ||
86 | [sol] = toLists $ dropRows (it-1) path | ||
87 | freeHaskellFunPtr fp | ||
88 | return (take n $ drop 1 sol, path) | ||
89 | |||
90 | |||
91 | foreign import ccall "root" | ||
92 | c_root:: CInt -> FunPtr (CInt -> Ptr Double -> Ptr Double -> IO ()) -> Double -> CInt -> TVM | ||
93 | |||
94 | --------------------------------------------------------------------- | ||
95 | |||
96 | foreign import ccall "wrapper" | ||
97 | mkVecVecfun :: (CInt -> Ptr Double -> Ptr Double -> IO ()) | ||
98 | -> IO (FunPtr (CInt -> Ptr Double -> Ptr Double->IO())) | ||
99 | |||
100 | aux_vTov :: (Vector Double -> Vector Double) -> (CInt -> Ptr Double -> Ptr Double -> IO()) | ||
101 | aux_vTov f n p r = g where | ||
102 | V {fptr = pr} = f x | ||
103 | x = createV (fromIntegral n) copy "aux_vTov" | ||
104 | copy n' q = do | ||
105 | copyArray q p (fromIntegral n') | ||
106 | return 0 | ||
107 | g = withForeignPtr pr $ \p' -> copyArray r p' (fromIntegral n) | ||
108 | |||
109 | createV n fun msg = unsafePerformIO $ do | ||
110 | r <- createVector n | ||
111 | app1 fun vec r msg | ||
112 | return r | ||
113 | |||
114 | createMIO r c fun msg = do | ||
115 | res <- createMatrix RowMajor r c | ||
116 | app1 fun mat res msg | ||
117 | return res | ||