diff options
Diffstat (limited to 'lib/Numeric/GSL')
-rw-r--r-- | lib/Numeric/GSL/Root.hs | 117 | ||||
-rw-r--r-- | lib/Numeric/GSL/gsl-aux.c | 101 | ||||
-rw-r--r-- | lib/Numeric/GSL/gsl-aux.h | 6 |
3 files changed, 213 insertions, 11 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 | ||
diff --git a/lib/Numeric/GSL/gsl-aux.c b/lib/Numeric/GSL/gsl-aux.c index 3802574..80c23fc 100644 --- a/lib/Numeric/GSL/gsl-aux.c +++ b/lib/Numeric/GSL/gsl-aux.c | |||
@@ -7,6 +7,7 @@ | |||
7 | #include <gsl/gsl_deriv.h> | 7 | #include <gsl/gsl_deriv.h> |
8 | #include <gsl/gsl_poly.h> | 8 | #include <gsl/gsl_poly.h> |
9 | #include <gsl/gsl_multimin.h> | 9 | #include <gsl/gsl_multimin.h> |
10 | #include <gsl/gsl_multiroots.h> | ||
10 | #include <gsl/gsl_complex.h> | 11 | #include <gsl/gsl_complex.h> |
11 | #include <gsl/gsl_complex_math.h> | 12 | #include <gsl/gsl_complex_math.h> |
12 | #include <string.h> | 13 | #include <string.h> |
@@ -288,6 +289,22 @@ int fft(int code, KCVEC(X), CVEC(R)) { | |||
288 | } | 289 | } |
289 | 290 | ||
290 | 291 | ||
292 | int deriv(int code, double f(double, void*), double x, double h, double * result, double * abserr) | ||
293 | { | ||
294 | gsl_function F; | ||
295 | F.function = f; | ||
296 | F.params = 0; | ||
297 | |||
298 | if(code==0) return gsl_deriv_central (&F, x, h, result, abserr); | ||
299 | |||
300 | if(code==1) return gsl_deriv_forward (&F, x, h, result, abserr); | ||
301 | |||
302 | if(code==2) return gsl_deriv_backward (&F, x, h, result, abserr); | ||
303 | |||
304 | return 0; | ||
305 | } | ||
306 | |||
307 | |||
291 | int integrate_qng(double f(double, void*), double a, double b, double prec, | 308 | int integrate_qng(double f(double, void*), double a, double b, double prec, |
292 | double *result, double*error) { | 309 | double *result, double*error) { |
293 | DEBUGMSG("integrate_qng"); | 310 | DEBUGMSG("integrate_qng"); |
@@ -440,7 +457,7 @@ void fdf_aux_min(const gsl_vector * x, void * pars, double * f, gsl_vector * g) | |||
440 | df_aux_min(x,pars,g); | 457 | df_aux_min(x,pars,g); |
441 | } | 458 | } |
442 | 459 | ||
443 | // conjugate gradient | 460 | |
444 | int minimizeWithDeriv(int method, double f(int, double*), void df(int, double*, double*), | 461 | int minimizeWithDeriv(int method, double f(int, double*), void df(int, double*, double*), |
445 | double initstep, double minimpar, double tolgrad, int maxit, | 462 | double initstep, double minimpar, double tolgrad, int maxit, |
446 | KRVEC(xi), RMAT(sol)) { | 463 | KRVEC(xi), RMAT(sol)) { |
@@ -492,18 +509,82 @@ int minimizeWithDeriv(int method, double f(int, double*), void df(int, double*, | |||
492 | OK | 509 | OK |
493 | } | 510 | } |
494 | 511 | ||
512 | //--------------------------------------------------------------- | ||
495 | 513 | ||
496 | int deriv(int code, double f(double, void*), double x, double h, double * result, double * abserr) | 514 | typedef void TrawfunV(int, double*, double*); |
497 | { | ||
498 | gsl_function F; | ||
499 | F.function = f; | ||
500 | F.params = 0; | ||
501 | 515 | ||
502 | if(code==0) return gsl_deriv_central (&F, x, h, result, abserr); | 516 | int only_f_aux_root(const gsl_vector*x, void *pars, gsl_vector*y) { |
517 | TrawfunV * f = (TrawfunV*) pars; | ||
518 | double* p = (double*)calloc(x->size,sizeof(double)); | ||
519 | double* q = (double*)calloc(x->size,sizeof(double)); | ||
520 | int k; | ||
521 | for(k=0;k<x->size;k++) { | ||
522 | p[k] = gsl_vector_get(x,k); | ||
523 | } | ||
524 | f(x->size,p,q); | ||
525 | for(k=0;k<y->size;k++) { | ||
526 | gsl_vector_set(y,k,q[k]); | ||
527 | } | ||
528 | free(p); | ||
529 | free(q); | ||
530 | return 0; //hmmm | ||
531 | } | ||
503 | 532 | ||
504 | if(code==1) return gsl_deriv_forward (&F, x, h, result, abserr); | 533 | int root(int method, void f(int, double*, int, double*), |
534 | double epsabs, int maxit, | ||
535 | KRVEC(xi), RMAT(sol)) { | ||
536 | REQUIRES(solr == maxit && solc == 1+2*xin,BAD_SIZE); | ||
537 | DEBUGMSG("root_only_f"); | ||
538 | gsl_multiroot_function my_func; | ||
539 | // extract function from pars | ||
540 | my_func.f = only_f_aux_root; | ||
541 | my_func.n = xin; | ||
542 | my_func.params = f; | ||
543 | size_t iter = 0; | ||
544 | int status; | ||
545 | const gsl_multiroot_fsolver_type *T; | ||
546 | gsl_multiroot_fsolver *s; | ||
547 | // Starting point | ||
548 | KDVVIEW(xi); | ||
549 | switch(method) { | ||
550 | case 0 : {T = gsl_multiroot_fsolver_hybrids;; break; } | ||
551 | case 1 : {T = gsl_multiroot_fsolver_hybrid; break; } | ||
552 | case 2 : {T = gsl_multiroot_fsolver_dnewton; break; } | ||
553 | case 3 : {T = gsl_multiroot_fsolver_broyden; break; } | ||
554 | default: ERROR(BAD_CODE); | ||
555 | } | ||
556 | s = gsl_multiroot_fsolver_alloc (T, my_func.n); | ||
557 | gsl_multiroot_fsolver_set (s, &my_func, V(xi)); | ||
505 | 558 | ||
506 | if(code==2) return gsl_deriv_backward (&F, x, h, result, abserr); | 559 | do { |
560 | status = gsl_multiroot_fsolver_iterate (s); | ||
507 | 561 | ||
508 | return 0; | 562 | solp[iter*solc+0] = iter; |
563 | |||
564 | int k; | ||
565 | for(k=0;k<xin;k++) { | ||
566 | solp[iter*solc+k+1] = gsl_vector_get(s->x,k); | ||
567 | } | ||
568 | for(k=xin;k<2*xin;k++) { | ||
569 | solp[iter*solc+k+1] = gsl_vector_get(s->f,k-xin); | ||
570 | } | ||
571 | |||
572 | iter++; | ||
573 | if (status) /* check if solver is stuck */ | ||
574 | break; | ||
575 | |||
576 | status = | ||
577 | gsl_multiroot_test_residual (s->f, epsabs); | ||
578 | } | ||
579 | while (status == GSL_CONTINUE && iter < maxit); | ||
580 | |||
581 | int i,j; | ||
582 | for (i=iter; i<solr; i++) { | ||
583 | solp[i*solc+0] = iter; | ||
584 | for(j=1;j<solc;j++) { | ||
585 | solp[i*solc+j]=0.; | ||
586 | } | ||
587 | } | ||
588 | gsl_multiroot_fsolver_free(s); | ||
589 | OK | ||
509 | } | 590 | } |
diff --git a/lib/Numeric/GSL/gsl-aux.h b/lib/Numeric/GSL/gsl-aux.h index e88322c..c9fd546 100644 --- a/lib/Numeric/GSL/gsl-aux.h +++ b/lib/Numeric/GSL/gsl-aux.h | |||
@@ -28,6 +28,8 @@ int zipC(int code, KCVEC(a), KCVEC(b), CVEC(r)); | |||
28 | 28 | ||
29 | int fft(int code, KCVEC(a), CVEC(b)); | 29 | int fft(int code, KCVEC(a), CVEC(b)); |
30 | 30 | ||
31 | int deriv(int code, double f(double, void*), double x, double h, double * result, double * abserr); | ||
32 | |||
31 | int integrate_qng(double f(double, void*), double a, double b, double prec, | 33 | int integrate_qng(double f(double, void*), double a, double b, double prec, |
32 | double *result, double*error); | 34 | double *result, double*error); |
33 | 35 | ||
@@ -43,4 +45,6 @@ int minimizeWithDeriv(int method, double f(int, double*), void df(int, double*, | |||
43 | double initstep, double minimpar, double tolgrad, int maxit, | 45 | double initstep, double minimpar, double tolgrad, int maxit, |
44 | KRVEC(xi), RMAT(sol)); | 46 | KRVEC(xi), RMAT(sol)); |
45 | 47 | ||
46 | int deriv(int code, double f(double, void*), double x, double h, double * result, double * abserr); | 48 | int root(int method, void f(int, double*, int, double*), |
49 | double epsabs, int maxit, | ||
50 | KRVEC(xi), RMAT(sol)); | ||