{-# LANGUAGE ScopedTypeVariables #-} -------------------------------------------------------------------------------- -- | -- Module : LevMar.Fitting -- Copyright : (c) 2009 Roel van Dijk & Bas van Dijk -- License : BSD-style (see the file LICENSE) -- -- Maintainer : vandijk.roel@gmail.com, v.dijk.bas@gmail.com -- Stability : Experimental -- -- This module provides the Levenberg-Marquardt algorithm specialised -- for curve-fitting. -- -- For additional documentation see the documentation of the levmar C -- library which this library is based on: -- -- -------------------------------------------------------------------------------- module LevMar.Fitting ( -- * Model & Jacobian. Model , SimpleModel , Jacobian , SimpleJacobian -- * Levenberg-Marquardt algorithm. , LMA_I.LevMarable , levmar , LinearConstraints , noLinearConstraints , Matrix -- * Minimization options. , LMA_I.Options(..) , LMA_I.defaultOpts -- * Output , LMA_I.Info(..) , LMA_I.StopReason(..) , CovarMatrix , LMA_I.LevMarError(..) -- *Type-level machinery , Z, S, Nat , SizedList(..) , NFunction ) where import qualified LevMar.Intermediate.Fitting as LMA_I import LevMar.Utils ( LinearConstraints , noLinearConstraints , convertLinearConstraints , Matrix , CovarMatrix , convertResult ) import TypeLevelNat ( Z, S, Nat ) import SizedList ( SizedList(..), toList, unsafeFromList ) import NFunction ( NFunction, ($*) ) -------------------------------------------------------------------------------- -- Model & Jacobian. -------------------------------------------------------------------------------- {- | A functional relation describing measurements represented as a function from @m@ parameters and an x-value to an expected measurement. For example, the quadratic function @f(x) = a*x^2 + b*x + c@ can be written as: @ type N3 = 'S' ('S' ('S' 'Z')) quad :: 'Num' r => 'Model' N3 r r quad a b c x = a*x^2 + b*x + c @ -} type Model m r a = NFunction m r (a -> r) -- | This type synonym expresses that usually the @a@ in @'Model' m r a@ -- equals the type of the parameters. type SimpleModel m r = Model m r r {- | The jacobian of the 'Model' function. Expressed as a function from @n@ parameters and an x-value to the @m@ partial derivatives of the parameters. See: For example, the jacobian of the quadratic function @f(x) = a*x^2 + b*x + c@ can be written as: @ type N3 = 'S' ('S' ('S' 'Z')) quadJacob :: 'Num' r => 'Jacobian' N3 r r quadJacob _ _ _ x = x^2 -- with respect to a ::: x -- with respect to b ::: 1 -- with respect to c ::: 'Nil' @ Notice you don't have to differentiate for @x@. -} type Jacobian m r a = NFunction m r (a -> SizedList m r) -- | This type synonym expresses that usually the @a@ in @'Jacobian' m r a@ -- equals the type of the parameters. type SimpleJacobian m r = Jacobian m r r -------------------------------------------------------------------------------- -- Levenberg-Marquardt algorithm. -------------------------------------------------------------------------------- -- | The Levenberg-Marquardt algorithm specialised for curve-fitting. levmar :: forall m k r a. (Nat m, Nat k, LMA_I.LevMarable r) => (Model m r a) -- ^ Model -> Maybe (Jacobian m r a) -- ^ Optional jacobian -> SizedList m r -- ^ Initial parameters -> [(a, r)] -- ^ Samples -> Integer -- ^ Maximum number of iterations -> LMA_I.Options r -- ^ Minimization options -> Maybe (SizedList m r) -- ^ Optional lower bounds -> Maybe (SizedList m r) -- ^ Optional upper bounds -> Maybe (LinearConstraints k m r) -- ^ Optional linear constraints -> Maybe (SizedList m r) -- ^ Optional weights -> Either LMA_I.LevMarError (SizedList m r, LMA_I.Info r, CovarMatrix m r) levmar model mJac params ys itMax opts mLowBs mUpBs mLinC mWghts = fmap convertResult $ LMA_I.levmar (convertModel model) (fmap convertJacob mJac) (toList params) ys itMax opts (fmap toList mLowBs) (fmap toList mUpBs) (fmap convertLinearConstraints mLinC) (fmap toList mWghts) where convertModel mdl = \ps -> mdl $* (unsafeFromList ps :: SizedList m r) convertJacob jac = \ps x -> toList ((jac $* (unsafeFromList ps :: SizedList m r)) x :: SizedList m r) -- The End ---------------------------------------------------------------------