diff options
-rw-r--r-- | examples/minimize.hs | 18 | ||||
-rw-r--r-- | lib/Numeric/GSL/Minimization.hs | 34 | ||||
-rw-r--r-- | lib/Numeric/GSL/gsl-aux.c | 8 | ||||
-rw-r--r-- | lib/Numeric/GSL/gsl-aux.h | 2 | ||||
-rw-r--r-- | lib/Numeric/LinearAlgebra/Tests.hs | 15 |
5 files changed, 61 insertions, 16 deletions
diff --git a/examples/minimize.hs b/examples/minimize.hs index 5beba3b..8962006 100644 --- a/examples/minimize.hs +++ b/examples/minimize.hs | |||
@@ -13,6 +13,9 @@ df [x,y] = [20*(x-1), 40*(y-2)] | |||
13 | -- the conjugate gradient method | 13 | -- the conjugate gradient method |
14 | minimizeCG = minimizeConjugateGradient 1E-2 1E-4 1E-3 30 | 14 | minimizeCG = minimizeConjugateGradient 1E-2 1E-4 1E-3 30 |
15 | 15 | ||
16 | -- the BFGS2 method | ||
17 | minimizeBFGS2 = minimizeVectorBFGS2 1E-2 1E-2 1E-3 30 | ||
18 | |||
16 | -- a minimization algorithm which does not require the gradient | 19 | -- a minimization algorithm which does not require the gradient |
17 | minimizeS f xi = minimizeNMSimplex f xi (replicate (length xi) 1) 1E-2 100 | 20 | minimizeS f xi = minimizeNMSimplex f xi (replicate (length xi) 1) 1E-2 100 |
18 | 21 | ||
@@ -24,20 +27,27 @@ partialDerivative n f v = fst (derivCentral 0.01 g (v!!n)) where | |||
24 | (a,_:b) = splitAt n v | 27 | (a,_:b) = splitAt n v |
25 | 28 | ||
26 | main = do | 29 | main = do |
27 | -- conjugate gradient with true gradient | 30 | putStrLn "BFGS2 with true gradient" |
28 | let (s,p) = minimizeCG f df [5,7] | 31 | let (s,p) = minimizeBFGS2 f df [5,7] |
29 | print s -- solution | 32 | print s -- solution |
30 | disp p -- evolution of the algorithm | 33 | disp p -- evolution of the algorithm |
31 | let [x,y] = drop 2 (toColumns p) | 34 | let [x,y] = drop 2 (toColumns p) |
32 | mplot [x,y] -- path from the starting point to the solution | 35 | mplot [x,y] -- path from the starting point to the solution |
33 | 36 | ||
34 | -- conjugate gradient with estimated gradient | 37 | putStrLn "conjugate gradient with true gradient" |
38 | let (s,p) = minimizeCG f df [5,7] | ||
39 | print s | ||
40 | disp p | ||
41 | let [x,y] = drop 2 (toColumns p) | ||
42 | mplot [x,y] | ||
43 | |||
44 | putStrLn "conjugate gradient with estimated gradient" | ||
35 | let (s,p) = minimizeCG f (gradient f) [5,7] | 45 | let (s,p) = minimizeCG f (gradient f) [5,7] |
36 | print s | 46 | print s |
37 | disp p | 47 | disp p |
38 | mplot $ drop 2 (toColumns p) | 48 | mplot $ drop 2 (toColumns p) |
39 | 49 | ||
40 | -- without gradient, using the NM Simplex method | 50 | putStrLn "without gradient, using the NM Simplex method" |
41 | let (s,p) = minimizeS f [5,7] | 51 | let (s,p) = minimizeS f [5,7] |
42 | print s | 52 | print s |
43 | disp p | 53 | disp p |
diff --git a/lib/Numeric/GSL/Minimization.hs b/lib/Numeric/GSL/Minimization.hs index a1d009b..b95765f 100644 --- a/lib/Numeric/GSL/Minimization.hs +++ b/lib/Numeric/GSL/Minimization.hs | |||
@@ -2,14 +2,14 @@ | |||
2 | ----------------------------------------------------------------------------- | 2 | ----------------------------------------------------------------------------- |
3 | {- | | 3 | {- | |
4 | Module : Numeric.GSL.Minimization | 4 | Module : Numeric.GSL.Minimization |
5 | Copyright : (c) Alberto Ruiz 2006 | 5 | Copyright : (c) Alberto Ruiz 2006-9 |
6 | License : GPL-style | 6 | License : GPL-style |
7 | 7 | ||
8 | Maintainer : Alberto Ruiz (aruiz at um dot es) | 8 | Maintainer : Alberto Ruiz (aruiz at um dot es) |
9 | Stability : provisional | 9 | Stability : provisional |
10 | Portability : uses ffi | 10 | Portability : uses ffi |
11 | 11 | ||
12 | Minimization of a multidimensional function Minimization of a multidimensional function using some of the algorithms described in: | 12 | Minimization of a multidimensional function using some of the algorithms described in: |
13 | 13 | ||
14 | <http://www.gnu.org/software/gsl/manual/html_node/Multidimensional-Minimization.html> | 14 | <http://www.gnu.org/software/gsl/manual/html_node/Multidimensional-Minimization.html> |
15 | 15 | ||
@@ -17,6 +17,7 @@ Minimization of a multidimensional function Minimization of a multidimensional f | |||
17 | ----------------------------------------------------------------------------- | 17 | ----------------------------------------------------------------------------- |
18 | module Numeric.GSL.Minimization ( | 18 | module Numeric.GSL.Minimization ( |
19 | minimizeConjugateGradient, | 19 | minimizeConjugateGradient, |
20 | minimizeVectorBFGS2, | ||
20 | minimizeNMSimplex | 21 | minimizeNMSimplex |
21 | ) where | 22 | ) where |
22 | 23 | ||
@@ -132,7 +133,7 @@ The path to the solution can be graphically shown by means of: | |||
132 | 133 | ||
133 | @'Graphics.Plot.mplot' $ drop 2 ('toColumns' p)@ | 134 | @'Graphics.Plot.mplot' $ drop 2 ('toColumns' p)@ |
134 | 135 | ||
135 | -} | 136 | -} |
136 | minimizeConjugateGradient :: | 137 | minimizeConjugateGradient :: |
137 | Double -- ^ initial step size | 138 | Double -- ^ initial step size |
138 | -> Double -- ^ minimization parameter | 139 | -> Double -- ^ minimization parameter |
@@ -142,7 +143,27 @@ minimizeConjugateGradient :: | |||
142 | -> ([Double] -> [Double]) -- ^ gradient | 143 | -> ([Double] -> [Double]) -- ^ gradient |
143 | -> [Double] -- ^ starting point | 144 | -> [Double] -- ^ starting point |
144 | -> ([Double], Matrix Double) -- ^ solution vector, and the optimization trajectory followed by the algorithm | 145 | -> ([Double], Matrix Double) -- ^ solution vector, and the optimization trajectory followed by the algorithm |
145 | minimizeConjugateGradient istep minimpar tol maxit f df xi = unsafePerformIO $ do | 146 | minimizeConjugateGradient = minimizeWithDeriv 0 |
147 | |||
148 | {- | Taken from the GSL manual: | ||
149 | |||
150 | The vector Broyden-Fletcher-Goldfarb-Shanno (BFGS) algorithm. This is a quasi-Newton method which builds up an approximation to the second derivatives of the function f using the difference between successive gradient vectors. By combining the first and second derivatives the algorithm is able to take Newton-type steps towards the function minimum, assuming quadratic behavior in that region. | ||
151 | |||
152 | The bfgs2 version of this minimizer is the most efficient version available, and is a faithful implementation of the line minimization scheme described in Fletcher's Practical Methods of Optimization, Algorithms 2.6.2 and 2.6.4. It supercedes the original bfgs routine and requires substantially fewer function and gradient evaluations. The user-supplied tolerance tol corresponds to the parameter \sigma used by Fletcher. A value of 0.1 is recommended for typical use (larger values correspond to less accurate line searches). | ||
153 | -} | ||
154 | minimizeVectorBFGS2 :: | ||
155 | Double -- ^ initial step size | ||
156 | -> Double -- ^ minimization parameter tol | ||
157 | -> Double -- ^ desired precision of the solution (gradient test) | ||
158 | -> Int -- ^ maximum number of iterations allowed | ||
159 | -> ([Double] -> Double) -- ^ function to minimize | ||
160 | -> ([Double] -> [Double]) -- ^ gradient | ||
161 | -> [Double] -- ^ starting point | ||
162 | -> ([Double], Matrix Double) -- ^ solution vector, and the optimization trajectory followed by the algorithm | ||
163 | minimizeVectorBFGS2 = minimizeWithDeriv 1 | ||
164 | |||
165 | |||
166 | minimizeWithDeriv method istep minimpar tol maxit f df xi = unsafePerformIO $ do | ||
146 | let xiv = fromList xi | 167 | let xiv = fromList xi |
147 | n = dim xiv | 168 | n = dim xiv |
148 | f' = f . toList | 169 | f' = f . toList |
@@ -151,7 +172,7 @@ minimizeConjugateGradient istep minimpar tol maxit f df xi = unsafePerformIO $ d | |||
151 | dfp <- mkVecVecfun (aux_vTov df') | 172 | dfp <- mkVecVecfun (aux_vTov df') |
152 | rawpath <- withVector xiv $ \xiv' -> | 173 | rawpath <- withVector xiv $ \xiv' -> |
153 | createMIO maxit (n+2) | 174 | createMIO maxit (n+2) |
154 | (c_minimizeConjugateGradient fp dfp istep minimpar tol (fi maxit) // xiv') | 175 | (c_minimizeWithDeriv method fp dfp istep minimpar tol (fi maxit) // xiv') |
155 | "minimizeDerivV" | 176 | "minimizeDerivV" |
156 | let it = round (rawpath @@> (maxit-1,0)) | 177 | let it = round (rawpath @@> (maxit-1,0)) |
157 | path = takeRows it rawpath | 178 | path = takeRows it rawpath |
@@ -160,9 +181,8 @@ minimizeConjugateGradient istep minimpar tol maxit f df xi = unsafePerformIO $ d | |||
160 | freeHaskellFunPtr dfp | 181 | freeHaskellFunPtr dfp |
161 | return (sol,path) | 182 | return (sol,path) |
162 | 183 | ||
163 | |||
164 | foreign import ccall "gsl-aux.h minimizeWithDeriv" | 184 | foreign import ccall "gsl-aux.h minimizeWithDeriv" |
165 | c_minimizeConjugateGradient :: FunPtr (CInt -> Ptr Double -> Double) | 185 | c_minimizeWithDeriv :: CInt -> FunPtr (CInt -> Ptr Double -> Double) |
166 | -> FunPtr (CInt -> Ptr Double -> Ptr Double -> IO ()) | 186 | -> FunPtr (CInt -> Ptr Double -> Ptr Double -> IO ()) |
167 | -> Double -> Double -> Double -> CInt | 187 | -> Double -> Double -> Double -> CInt |
168 | -> TVM | 188 | -> TVM |
diff --git a/lib/Numeric/GSL/gsl-aux.c b/lib/Numeric/GSL/gsl-aux.c index 77e793e..3802574 100644 --- a/lib/Numeric/GSL/gsl-aux.c +++ b/lib/Numeric/GSL/gsl-aux.c | |||
@@ -441,7 +441,7 @@ void fdf_aux_min(const gsl_vector * x, void * pars, double * f, gsl_vector * g) | |||
441 | } | 441 | } |
442 | 442 | ||
443 | // conjugate gradient | 443 | // conjugate gradient |
444 | int minimizeWithDeriv(double f(int, double*), void df(int, double*, double*), | 444 | int minimizeWithDeriv(int method, double f(int, double*), void df(int, double*, double*), |
445 | double initstep, double minimpar, double tolgrad, int maxit, | 445 | double initstep, double minimpar, double tolgrad, int maxit, |
446 | KRVEC(xi), RMAT(sol)) { | 446 | KRVEC(xi), RMAT(sol)) { |
447 | REQUIRES(solr == maxit && solc == 2+xin,BAD_SIZE); | 447 | REQUIRES(solr == maxit && solc == 2+xin,BAD_SIZE); |
@@ -463,7 +463,11 @@ int minimizeWithDeriv(double f(int, double*), void df(int, double*, double*), | |||
463 | // Starting point | 463 | // Starting point |
464 | KDVVIEW(xi); | 464 | KDVVIEW(xi); |
465 | // conjugate gradient fr | 465 | // conjugate gradient fr |
466 | T = gsl_multimin_fdfminimizer_conjugate_fr; | 466 | switch(method) { |
467 | case 0 : {T = gsl_multimin_fdfminimizer_conjugate_fr; break; } | ||
468 | case 1 : {T = gsl_multimin_fdfminimizer_vector_bfgs2; break; } | ||
469 | default: ERROR(BAD_CODE); | ||
470 | } | ||
467 | s = gsl_multimin_fdfminimizer_alloc (T, my_func.n); | 471 | s = gsl_multimin_fdfminimizer_alloc (T, my_func.n); |
468 | gsl_multimin_fdfminimizer_set (s, &my_func, V(xi), initstep, minimpar); | 472 | gsl_multimin_fdfminimizer_set (s, &my_func, V(xi), initstep, minimpar); |
469 | do { | 473 | do { |
diff --git a/lib/Numeric/GSL/gsl-aux.h b/lib/Numeric/GSL/gsl-aux.h index cd17ef0..e88322c 100644 --- a/lib/Numeric/GSL/gsl-aux.h +++ b/lib/Numeric/GSL/gsl-aux.h | |||
@@ -39,7 +39,7 @@ int polySolve(KRVEC(a), CVEC(z)); | |||
39 | int minimize(double f(int, double*), double tolsize, int maxit, | 39 | int minimize(double f(int, double*), double tolsize, int maxit, |
40 | KRVEC(xi), KRVEC(sz), RMAT(sol)); | 40 | KRVEC(xi), KRVEC(sz), RMAT(sol)); |
41 | 41 | ||
42 | int minimizeWithDeriv(double f(int, double*), void df(int, double*, double*), | 42 | int minimizeWithDeriv(int method, double f(int, double*), void df(int, double*, double*), |
43 | double initstep, double minimpar, double tolgrad, int maxit, | 43 | double initstep, double minimpar, double tolgrad, int maxit, |
44 | KRVEC(xi), RMAT(sol)); | 44 | KRVEC(xi), RMAT(sol)); |
45 | 45 | ||
diff --git a/lib/Numeric/LinearAlgebra/Tests.hs b/lib/Numeric/LinearAlgebra/Tests.hs index 7758268..278df78 100644 --- a/lib/Numeric/LinearAlgebra/Tests.hs +++ b/lib/Numeric/LinearAlgebra/Tests.hs | |||
@@ -1,9 +1,9 @@ | |||
1 | {-# LANGUAGE CPP #-} | 1 | {-# LANGUAGE CPP #-} |
2 | {-# OPTIONS_GHC -fno-warn-unused-imports #-} | 2 | {-# OPTIONS_GHC -fno-warn-unused-imports -fno-warn-incomplete-patterns #-} |
3 | ----------------------------------------------------------------------------- | 3 | ----------------------------------------------------------------------------- |
4 | {- | | 4 | {- | |
5 | Module : Numeric.LinearAlgebra.Tests | 5 | Module : Numeric.LinearAlgebra.Tests |
6 | Copyright : (c) Alberto Ruiz 2007 | 6 | Copyright : (c) Alberto Ruiz 2007-9 |
7 | License : GPL-style | 7 | License : GPL-style |
8 | 8 | ||
9 | Maintainer : Alberto Ruiz (aruiz at um dot es) | 9 | Maintainer : Alberto Ruiz (aruiz at um dot es) |
@@ -105,6 +105,16 @@ expmTest2 = expm nd2 :~15~: (2><2) | |||
105 | , 2.718281828459045 | 105 | , 2.718281828459045 |
106 | , 2.718281828459045 ] | 106 | , 2.718281828459045 ] |
107 | 107 | ||
108 | --------------------------------------------------------------------- | ||
109 | |||
110 | minimizationTest = TestList [ utest "minimization conj grad" (minim1 f df [5,7] ~~ [1,2]) | ||
111 | , utest "minimization bg2" (minim2 f df [5,7] ~~ [1,2]) | ||
112 | ] | ||
113 | where f [x,y] = 10*(x-1)^2 + 20*(y-2)^2 + 30 | ||
114 | df [x,y] = [20*(x-1), 40*(y-2)] | ||
115 | a ~~ b = fromList a |~| fromList b | ||
116 | minim1 g dg ini = fst $ minimizeConjugateGradient 1E-2 1E-4 1E-3 30 g dg ini | ||
117 | minim2 g dg ini = fst $ minimizeVectorBFGS2 1E-2 1E-2 1E-3 30 g dg ini | ||
108 | 118 | ||
109 | --------------------------------------------------------------------- | 119 | --------------------------------------------------------------------- |
110 | 120 | ||
@@ -206,6 +216,7 @@ runTests n = do | |||
206 | , exponentialTest | 216 | , exponentialTest |
207 | , utest "integrate" (abs (volSphere 2.5 - 4/3*pi*2.5^3) < 1E-8) | 217 | , utest "integrate" (abs (volSphere 2.5 - 4/3*pi*2.5^3) < 1E-8) |
208 | , utest "polySolve" (polySolveProp [1,2,3,4]) | 218 | , utest "polySolve" (polySolveProp [1,2,3,4]) |
219 | , minimizationTest | ||
209 | ] | 220 | ] |
210 | return () | 221 | return () |
211 | 222 | ||