diff options
-rw-r--r-- | CHANGES | 7 | ||||
-rw-r--r-- | examples/fitting.hs | 24 | ||||
-rw-r--r-- | hmatrix.cabal | 3 | ||||
-rw-r--r-- | lib/Numeric/GSL.hs | 2 | ||||
-rw-r--r-- | lib/Numeric/GSL/Fitting.hs | 147 | ||||
-rw-r--r-- | lib/Numeric/GSL/gsl-aux.c | 97 | ||||
-rw-r--r-- | lib/Numeric/LinearAlgebra/Tests.hs | 17 |
7 files changed, 282 insertions, 15 deletions
@@ -1,3 +1,8 @@ | |||
1 | 0.9.2.0 | ||
2 | ======= | ||
3 | |||
4 | Added GSL Nonlinear Least-Squares fitting using Levenberg-Marquardt. | ||
5 | |||
1 | 0.9.1.0 | 6 | 0.9.1.0 |
2 | ======= | 7 | ======= |
3 | 8 | ||
@@ -6,7 +11,7 @@ | |||
6 | - Added offset of Vector, allowing fast, noncopy subVector (slice). | 11 | - Added offset of Vector, allowing fast, noncopy subVector (slice). |
7 | Vector is now identical to Roman Leshchinskiy's Data.Vector.Storable.Vector, | 12 | Vector is now identical to Roman Leshchinskiy's Data.Vector.Storable.Vector, |
8 | so we can convert from/to them in O(1). | 13 | so we can convert from/to them in O(1). |
9 | 14 | ||
10 | - Removed Data.Packed.Convert, see examples/vector.hs | 15 | - Removed Data.Packed.Convert, see examples/vector.hs |
11 | 16 | ||
12 | 0.8.3.0 | 17 | 0.8.3.0 |
diff --git a/examples/fitting.hs b/examples/fitting.hs new file mode 100644 index 0000000..8298c52 --- /dev/null +++ b/examples/fitting.hs | |||
@@ -0,0 +1,24 @@ | |||
1 | -- nonlinear least-squares fitting | ||
2 | |||
3 | import Numeric.GSL.Fitting | ||
4 | import Numeric.LinearAlgebra | ||
5 | |||
6 | xs = map return [0 .. 39] | ||
7 | sigma = 0.1 | ||
8 | ys = map return $ toList $ fromList (map (head . expModel [5,0.1,1]) xs) | ||
9 | + scalar sigma * (randomVector 0 Gaussian 40) | ||
10 | |||
11 | dat :: [([Double],[Double],Double)] | ||
12 | |||
13 | dat = zipWith3 (,,) xs ys (repeat sigma) | ||
14 | |||
15 | expModel [a,lambda,b] [t] = [a * exp (-lambda * t) + b] | ||
16 | |||
17 | expModelDer [a,lambda,b] [t] = [[exp (-lambda * t), -t * a * exp(-lambda*t) , 1]] | ||
18 | |||
19 | (sol,path) = fitModel 1E-4 1E-4 20 (resM expModel, resD expModelDer) dat [1,0,0] | ||
20 | |||
21 | main = do | ||
22 | print dat | ||
23 | print path | ||
24 | print sol | ||
diff --git a/hmatrix.cabal b/hmatrix.cabal index ac38460..5416c09 100644 --- a/hmatrix.cabal +++ b/hmatrix.cabal | |||
@@ -1,5 +1,5 @@ | |||
1 | Name: hmatrix | 1 | Name: hmatrix |
2 | Version: 0.9.1.0 | 2 | Version: 0.9.2.0 |
3 | License: GPL | 3 | License: GPL |
4 | License-file: LICENSE | 4 | License-file: LICENSE |
5 | Author: Alberto Ruiz | 5 | Author: Alberto Ruiz |
@@ -79,6 +79,7 @@ library | |||
79 | Numeric.GSL.Polynomials, | 79 | Numeric.GSL.Polynomials, |
80 | Numeric.GSL.Minimization, | 80 | Numeric.GSL.Minimization, |
81 | Numeric.GSL.Root, | 81 | Numeric.GSL.Root, |
82 | Numeric.GSL.Fitting, | ||
82 | Numeric.GSL.ODE, | 83 | Numeric.GSL.ODE, |
83 | Numeric.GSL.Vector, | 84 | Numeric.GSL.Vector, |
84 | Numeric.GSL, | 85 | Numeric.GSL, |
diff --git a/lib/Numeric/GSL.hs b/lib/Numeric/GSL.hs index 5442586..ae4c81e 100644 --- a/lib/Numeric/GSL.hs +++ b/lib/Numeric/GSL.hs | |||
@@ -20,6 +20,7 @@ module Numeric.GSL ( | |||
20 | , module Numeric.GSL.Minimization | 20 | , module Numeric.GSL.Minimization |
21 | , module Numeric.GSL.Root | 21 | , module Numeric.GSL.Root |
22 | , module Numeric.GSL.ODE | 22 | , module Numeric.GSL.ODE |
23 | , module Numeric.GSL.Fitting | ||
23 | , module Data.Complex | 24 | , module Data.Complex |
24 | , setErrorHandlerOff | 25 | , setErrorHandlerOff |
25 | ) where | 26 | ) where |
@@ -31,6 +32,7 @@ import Numeric.GSL.Polynomials | |||
31 | import Numeric.GSL.Minimization | 32 | import Numeric.GSL.Minimization |
32 | import Numeric.GSL.Root | 33 | import Numeric.GSL.Root |
33 | import Numeric.GSL.ODE | 34 | import Numeric.GSL.ODE |
35 | import Numeric.GSL.Fitting | ||
34 | import Data.Complex | 36 | import Data.Complex |
35 | 37 | ||
36 | 38 | ||
diff --git a/lib/Numeric/GSL/Fitting.hs b/lib/Numeric/GSL/Fitting.hs new file mode 100644 index 0000000..6e91b2d --- /dev/null +++ b/lib/Numeric/GSL/Fitting.hs | |||
@@ -0,0 +1,147 @@ | |||
1 | {- | | ||
2 | Module : Numeric.GSL.Fitting | ||
3 | Copyright : (c) Alberto Ruiz 2010 | ||
4 | License : GPL | ||
5 | |||
6 | Maintainer : Alberto Ruiz (aruiz at um dot es) | ||
7 | Stability : provisional | ||
8 | Portability : uses ffi | ||
9 | |||
10 | Nonlinear Least-Squares Fitting | ||
11 | |||
12 | <http://www.gnu.org/software/gsl/manual/html_node/Nonlinear-Least_002dSquares-Fitting.html> | ||
13 | |||
14 | The example program in the GSL manual (see examples/fitting.hs): | ||
15 | |||
16 | @dat = [ | ||
17 | ([0.0],[6.0133918608118675],0.1), | ||
18 | ([1.0],[5.5153769909966535],0.1), | ||
19 | ([2.0],[5.261094606015287],0.1), | ||
20 | ... | ||
21 | ([39.0],[1.0619821710802808],0.1)] | ||
22 | |||
23 | expModel [a,lambda,b] [t] = [a * exp (-lambda * t) + b] | ||
24 | |||
25 | expModelDer [a,lambda,b] [t] = [[exp (-lambda * t), -t * a * exp(-lambda*t) , 1]] | ||
26 | |||
27 | (sol,path) = fitModel 1E-4 1E-4 20 (resM expModel, resD expModelDer) dat [1,0,0] | ||
28 | |||
29 | \> path | ||
30 | (6><5) | ||
31 | [ 1.0, 76.45780563978782, 1.6465931240727802, 1.8147715267618197e-2, 0.6465931240727797 | ||
32 | , 2.0, 37.683816318260355, 2.858760367632973, 8.092094813253975e-2, 1.4479636296208662 | ||
33 | , 3.0, 9.5807893736187, 4.948995119561291, 0.11942927999921617, 1.0945766509238248 | ||
34 | , 4.0, 5.630494933603935, 5.021755718065913, 0.10287787128056883, 1.0338835440862608 | ||
35 | , 5.0, 5.443976278682909, 5.045204331329302, 0.10405523433131504, 1.019416067207375 | ||
36 | , 6.0, 5.4439736648994685, 5.045357818922331, 0.10404905846029407, 1.0192487112786812 ] | ||
37 | \> sol | ||
38 | [(5.045357818922331,6.027976702418132e-2), | ||
39 | (0.10404905846029407,3.157045047172834e-3), | ||
40 | (1.0192487112786812,3.782067731353722e-2)]@ | ||
41 | |||
42 | -} | ||
43 | ----------------------------------------------------------------------------- | ||
44 | |||
45 | module Numeric.GSL.Fitting ( | ||
46 | -- * Levenberg-Marquardt | ||
47 | nlFitting, FittingMethod(..), | ||
48 | -- * Utilities | ||
49 | fitModel, resM, resD | ||
50 | ) where | ||
51 | |||
52 | import Data.Packed.Internal | ||
53 | import Numeric.LinearAlgebra | ||
54 | import Foreign | ||
55 | import Foreign.C.Types(CInt) | ||
56 | import Numeric.GSL.Internal | ||
57 | |||
58 | ------------------------------------------------------------------------- | ||
59 | |||
60 | data FittingMethod = LevenbergMarquardt -- ^ Interface to gsl_multifit_fdfsolver_lmsder. This is a robust and efficient version of the Levenberg-Marquardt algorithm as implemented in the scaled lmder routine in minpack. Minpack was written by Jorge J. More, Burton S. Garbow and Kenneth E. Hillstrom. | ||
61 | deriving (Enum,Eq,Show,Bounded) | ||
62 | |||
63 | |||
64 | -- | Nonlinear multidimensional least-squares fitting. | ||
65 | nlFitting :: FittingMethod | ||
66 | -> Double -- ^ absolute tolerance | ||
67 | -> Double -- ^ relative tolerance | ||
68 | -> Int -- ^ maximum number of iterations allowed | ||
69 | -> (Vector Double -> Vector Double) -- ^ function to be minimized | ||
70 | -> (Vector Double -> Matrix Double) -- ^ Jacobian | ||
71 | -> Vector Double -- ^ starting point | ||
72 | -> (Vector Double, Matrix Double) -- ^ solution vector and optimization path | ||
73 | |||
74 | nlFitting method epsabs epsrel maxit fun jac xinit = nlFitGen (fi (fromEnum method)) fun jac xinit epsabs epsrel maxit | ||
75 | |||
76 | nlFitGen m f jac xiv epsabs epsrel maxit = unsafePerformIO $ do | ||
77 | let p = dim xiv | ||
78 | n = dim (f xiv) | ||
79 | fp <- mkVecVecfun (aux_vTov (checkdim1 n p . f)) | ||
80 | jp <- mkVecMatfun (aux_vTom (checkdim2 n p . jac)) | ||
81 | rawpath <- createMatrix RowMajor maxit (2+p) | ||
82 | app2 (c_nlfit m fp jp epsabs epsrel (fi maxit) (fi n)) vec xiv mat rawpath "c_nlfit" | ||
83 | let it = round (rawpath @@> (maxit-1,0)) | ||
84 | path = takeRows it rawpath | ||
85 | [sol] = toRows $ dropRows (it-1) path | ||
86 | freeHaskellFunPtr fp | ||
87 | freeHaskellFunPtr jp | ||
88 | return (subVector 2 p sol, path) | ||
89 | |||
90 | foreign import ccall "nlfit" | ||
91 | c_nlfit:: CInt -> FunPtr TVV -> FunPtr TVM -> Double -> Double -> CInt -> CInt -> TVM | ||
92 | |||
93 | ------------------------------------------------------- | ||
94 | |||
95 | checkdim1 n _p v | ||
96 | | dim v == n = v | ||
97 | | otherwise = error $ "Error: "++ show n | ||
98 | ++ " components expected in the result of the function supplied to nlFitting" | ||
99 | |||
100 | checkdim2 n p m | ||
101 | | rows m == n && cols m == p = m | ||
102 | | otherwise = error $ "Error: "++ show n ++ "x" ++ show p | ||
103 | ++ " Jacobian expected in nlFitting" | ||
104 | |||
105 | ------------------------------------------------------------ | ||
106 | |||
107 | err model dat vsol = zip sol errs where | ||
108 | sol = toList vsol | ||
109 | c = max 1 (chi/sqrt (fromIntegral dof)) | ||
110 | dof = length dat - (rows cov) | ||
111 | chi = pnorm PNorm2 (fromList $ cost (fst model) dat sol) | ||
112 | js = fromLists $ jacobian (snd model) dat sol | ||
113 | cov = inv $ trans js <> js | ||
114 | errs = toList $ scalar c * sqrt (takeDiag cov) | ||
115 | |||
116 | |||
117 | |||
118 | -- | Higher level interface to 'nlFitting' 'LevenbergMarquardt'. The optimization function and | ||
119 | -- Jacobian are automatically built from a model f vs x = 0 and its derivatives, and a list of | ||
120 | -- instances x to be fitted. | ||
121 | |||
122 | fitModel :: Double -- ^ absolute tolerance | ||
123 | -> Double -- ^ relative tolerance | ||
124 | -> Int -- ^ maximum number of iterations allowed | ||
125 | -> ([Double] -> x -> [Double], [Double] -> x -> [[Double]]) -- ^ (model, derivatives) | ||
126 | -> [x] -- ^ instances | ||
127 | -> [Double] -- ^ starting point | ||
128 | -> ([(Double, Double)], Matrix Double) -- ^ (solution, error) and optimization path | ||
129 | fitModel epsabs epsrel maxit model dt xin = (err model dt sol, path) where | ||
130 | (sol,path) = nlFitting LevenbergMarquardt epsabs epsrel maxit | ||
131 | (fromList . cost (fst model) dt . toList) | ||
132 | (fromLists . jacobian (snd model) dt . toList) | ||
133 | (fromList xin) | ||
134 | |||
135 | cost model ds vs = concatMap (model vs) ds | ||
136 | |||
137 | jacobian modelDer ds vs = concatMap (modelDer vs) ds | ||
138 | |||
139 | -- | Model-to-residual for association pairs with sigma, to be used with 'fitModel'. | ||
140 | resM :: ([Double] -> x -> [Double]) -> [Double] -> (x, [Double], Double) -> [Double] | ||
141 | resM m v = \(x,ys,s) -> zipWith (g s) (m v x) ys where g s a b = (a-b)/s | ||
142 | |||
143 | -- | Associated derivative for 'resM'. | ||
144 | resD :: ([Double] -> x -> [[Double]]) -> [Double] -> (x, [Double], Double) -> [[Double]] | ||
145 | resD m v = \(x,_,s) -> map (map (/s)) (m v x) | ||
146 | |||
147 | |||
diff --git a/lib/Numeric/GSL/gsl-aux.c b/lib/Numeric/GSL/gsl-aux.c index 0fcde1c..f258fb1 100644 --- a/lib/Numeric/GSL/gsl-aux.c +++ b/lib/Numeric/GSL/gsl-aux.c | |||
@@ -23,6 +23,7 @@ | |||
23 | #include <gsl/gsl_rng.h> | 23 | #include <gsl/gsl_rng.h> |
24 | #include <gsl/gsl_randist.h> | 24 | #include <gsl/gsl_randist.h> |
25 | #include <gsl/gsl_odeiv.h> | 25 | #include <gsl/gsl_odeiv.h> |
26 | #include <gsl/gsl_multifit_nlin.h> | ||
26 | #include <string.h> | 27 | #include <string.h> |
27 | #include <stdio.h> | 28 | #include <stdio.h> |
28 | 29 | ||
@@ -668,9 +669,10 @@ int root(int method, void f(int, double*, int, double*), | |||
668 | 669 | ||
669 | // working with the jacobian | 670 | // working with the jacobian |
670 | 671 | ||
671 | typedef struct {int (*f)(int, double*, int, double *); int (*jf)(int, double*, int, int, double*);} Tfjf; | 672 | typedef struct {int (*f)(int, double*, int, double *); |
673 | int (*jf)(int, double*, int, int, double*);} Tfjf; | ||
672 | 674 | ||
673 | int f_aux_root(const gsl_vector*x, void *pars, gsl_vector*y) { | 675 | int f_aux(const gsl_vector*x, void *pars, gsl_vector*y) { |
674 | Tfjf * fjf = ((Tfjf*) pars); | 676 | Tfjf * fjf = ((Tfjf*) pars); |
675 | double* p = (double*)calloc(x->size,sizeof(double)); | 677 | double* p = (double*)calloc(x->size,sizeof(double)); |
676 | double* q = (double*)calloc(y->size,sizeof(double)); | 678 | double* q = (double*)calloc(y->size,sizeof(double)); |
@@ -687,20 +689,20 @@ int f_aux_root(const gsl_vector*x, void *pars, gsl_vector*y) { | |||
687 | return 0; | 689 | return 0; |
688 | } | 690 | } |
689 | 691 | ||
690 | int jf_aux_root(const gsl_vector * x, void * pars, gsl_matrix * jac) { | 692 | int jf_aux(const gsl_vector * x, void * pars, gsl_matrix * jac) { |
691 | Tfjf * fjf = ((Tfjf*) pars); | 693 | Tfjf * fjf = ((Tfjf*) pars); |
692 | double* p = (double*)calloc(x->size,sizeof(double)); | 694 | double* p = (double*)calloc(x->size,sizeof(double)); |
693 | double* q = (double*)calloc((x->size)*(x->size),sizeof(double)); | 695 | double* q = (double*)calloc((jac->size1)*(jac->size2),sizeof(double)); |
694 | int i,j,k; | 696 | int i,j,k; |
695 | for(k=0;k<x->size;k++) { | 697 | for(k=0;k<x->size;k++) { |
696 | p[k] = gsl_vector_get(x,k); | 698 | p[k] = gsl_vector_get(x,k); |
697 | } | 699 | } |
698 | 700 | ||
699 | (fjf->jf)(x->size,p,x->size,x->size,q); | 701 | (fjf->jf)(x->size,p,jac->size1,jac->size2,q); |
700 | 702 | ||
701 | k=0; | 703 | k=0; |
702 | for(i=0;i<x->size;i++) { | 704 | for(i=0;i<jac->size1;i++) { |
703 | for(j=0;j<x->size;j++){ | 705 | for(j=0;j<jac->size2;j++){ |
704 | gsl_matrix_set(jac,i,j,q[k++]); | 706 | gsl_matrix_set(jac,i,j,q[k++]); |
705 | } | 707 | } |
706 | } | 708 | } |
@@ -709,9 +711,9 @@ int jf_aux_root(const gsl_vector * x, void * pars, gsl_matrix * jac) { | |||
709 | return 0; | 711 | return 0; |
710 | } | 712 | } |
711 | 713 | ||
712 | int fjf_aux_root(const gsl_vector * x, void * pars, gsl_vector * f, gsl_matrix * g) { | 714 | int fjf_aux(const gsl_vector * x, void * pars, gsl_vector * f, gsl_matrix * g) { |
713 | f_aux_root(x,pars,f); | 715 | f_aux(x,pars,f); |
714 | jf_aux_root(x,pars,g); | 716 | jf_aux(x,pars,g); |
715 | return 0; | 717 | return 0; |
716 | } | 718 | } |
717 | 719 | ||
@@ -723,9 +725,9 @@ int rootj(int method, int f(int, double*, int, double*), | |||
723 | DEBUGMSG("root_fjf"); | 725 | DEBUGMSG("root_fjf"); |
724 | gsl_multiroot_function_fdf my_func; | 726 | gsl_multiroot_function_fdf my_func; |
725 | // extract function from pars | 727 | // extract function from pars |
726 | my_func.f = f_aux_root; | 728 | my_func.f = f_aux; |
727 | my_func.df = jf_aux_root; | 729 | my_func.df = jf_aux; |
728 | my_func.fdf = fjf_aux_root; | 730 | my_func.fdf = fjf_aux; |
729 | my_func.n = xin; | 731 | my_func.n = xin; |
730 | Tfjf stfjf; | 732 | Tfjf stfjf; |
731 | stfjf.f = f; | 733 | stfjf.f = f; |
@@ -781,8 +783,77 @@ int rootj(int method, int f(int, double*, int, double*), | |||
781 | OK | 783 | OK |
782 | } | 784 | } |
783 | 785 | ||
786 | //-------------- non linear least squares fitting ------------------- | ||
787 | |||
788 | int nlfit(int method, int f(int, double*, int, double*), | ||
789 | int jac(int, double*, int, int, double*), | ||
790 | double epsabs, double epsrel, int maxit, int p, | ||
791 | KRVEC(xi), RMAT(sol)) { | ||
792 | REQUIRES(solr == maxit && solc == 2+xin,BAD_SIZE); | ||
793 | DEBUGMSG("nlfit"); | ||
794 | const gsl_multifit_fdfsolver_type *T; | ||
795 | gsl_multifit_fdfsolver *s; | ||
796 | gsl_multifit_function_fdf my_f; | ||
797 | // extract function from pars | ||
798 | my_f.f = f_aux; | ||
799 | my_f.df = jf_aux; | ||
800 | my_f.fdf = fjf_aux; | ||
801 | my_f.n = p; | ||
802 | my_f.p = xin; // !!!! | ||
803 | Tfjf stfjf; | ||
804 | stfjf.f = f; | ||
805 | stfjf.jf = jac; | ||
806 | my_f.params = &stfjf; | ||
807 | size_t iter = 0; | ||
808 | int status; | ||
809 | |||
810 | KDVVIEW(xi); | ||
811 | //DMVIEW(cov); | ||
812 | |||
813 | switch(method) { | ||
814 | case 0 : { T = gsl_multifit_fdfsolver_lmsder; break; } | ||
815 | default: ERROR(BAD_CODE); | ||
816 | } | ||
817 | |||
818 | s = gsl_multifit_fdfsolver_alloc (T, my_f.n, my_f.p); | ||
819 | gsl_multifit_fdfsolver_set (s, &my_f, V(xi)); | ||
820 | |||
821 | do { status = gsl_multifit_fdfsolver_iterate (s); | ||
822 | |||
823 | solp[iter*solc+0] = iter+1; | ||
824 | solp[iter*solc+1] = gsl_blas_dnrm2 (s->f); | ||
825 | |||
826 | int k; | ||
827 | for(k=0;k<xin;k++) { | ||
828 | solp[iter*solc+k+2] = gsl_vector_get(s->x,k); | ||
829 | } | ||
830 | |||
831 | iter++; | ||
832 | if (status) /* check if solver is stuck */ | ||
833 | break; | ||
834 | |||
835 | status = gsl_multifit_test_delta (s->dx, s->x, epsabs, epsrel); | ||
836 | } | ||
837 | while (status == GSL_CONTINUE && iter <= maxit); | ||
838 | |||
839 | int i,j; | ||
840 | for (i=iter; i<solr; i++) { | ||
841 | solp[i*solc+0] = iter; | ||
842 | for(j=1;j<solc;j++) { | ||
843 | solp[i*solc+j]=0.; | ||
844 | } | ||
845 | } | ||
846 | |||
847 | //gsl_multifit_covar (s->J, 0.0, M(cov)); | ||
848 | |||
849 | gsl_multifit_fdfsolver_free (s); | ||
850 | OK | ||
851 | } | ||
852 | |||
853 | |||
784 | ////////////////////////////////////////////////////// | 854 | ////////////////////////////////////////////////////// |
785 | 855 | ||
856 | |||
786 | #define RAN(C,F) case C: { for(k=0;k<rn;k++) { rp[k]= F(gen); }; OK } | 857 | #define RAN(C,F) case C: { for(k=0;k<rn;k++) { rp[k]= F(gen); }; OK } |
787 | 858 | ||
788 | int random_vector(int seed, int code, RVEC(r)) { | 859 | int random_vector(int seed, int code, RVEC(r)) { |
diff --git a/lib/Numeric/LinearAlgebra/Tests.hs b/lib/Numeric/LinearAlgebra/Tests.hs index 3f7c847..f8f8bd5 100644 --- a/lib/Numeric/LinearAlgebra/Tests.hs +++ b/lib/Numeric/LinearAlgebra/Tests.hs | |||
@@ -143,6 +143,22 @@ odeTest = utest "ode" (last (toLists sol) ~~ [-1.7588880332411019, 8.36434890871 | |||
143 | 143 | ||
144 | --------------------------------------------------------------------- | 144 | --------------------------------------------------------------------- |
145 | 145 | ||
146 | fittingTest = utest "levmar" ok | ||
147 | where | ||
148 | xs = map return [0 .. 39] | ||
149 | sigma = 0.1 | ||
150 | ys = map return $ toList $ fromList (map (head . expModel [5,0.1,1]) xs) | ||
151 | + scalar sigma * (randomVector 0 Gaussian 40) | ||
152 | dat = zipWith3 (,,) xs ys (repeat sigma) | ||
153 | |||
154 | expModel [a,lambda,b] [t] = [a * exp (-lambda * t) + b] | ||
155 | expModelDer [a,lambda,_b] [t] = [[exp (-lambda * t), -t * a * exp(-lambda*t) , 1]] | ||
156 | |||
157 | sol = fst $ fitModel 1E-4 1E-4 20 (resM expModel, resD expModelDer) dat [1,0,0] | ||
158 | ok = and (zipWith f sol [5,0.1,1]) where f (x,d) r = abs (x-r)<2*d | ||
159 | |||
160 | --------------------------------------------------------------------- | ||
161 | |||
146 | randomTestGaussian = c :~1~: snd (meanCov dat) where | 162 | randomTestGaussian = c :~1~: snd (meanCov dat) where |
147 | a = (3><3) [1,2,3, | 163 | a = (3><3) [1,2,3, |
148 | 2,4,0, | 164 | 2,4,0, |
@@ -292,6 +308,7 @@ runTests n = do | |||
292 | && rank ((2><3)[1,0,0,1,7*eps,0]) == 2 | 308 | && rank ((2><3)[1,0,0,1,7*eps,0]) == 2 |
293 | , utest "block" $ fromBlocks [[ident 3,0],[0,ident 4]] == (ident 7 :: CM) | 309 | , utest "block" $ fromBlocks [[ident 3,0],[0,ident 4]] == (ident 7 :: CM) |
294 | , odeTest | 310 | , odeTest |
311 | , fittingTest | ||
295 | ] | 312 | ] |
296 | return () | 313 | return () |
297 | 314 | ||