{-# LANGUAGE NoImplicitPrelude, UnicodeSyntax #-} -------------------------------------------------------------------------------- -- | -- Module: Numeric.LevMar.Fitting -- Copyright: (c) 2009 - 2010 Roel van Dijk & Bas van Dijk -- License: BSD-style (see the file LICENSE) -- Maintainer: Roel van Dijk <vandijk.roel@gmail.com> -- Bas van Dijk <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: -- <http://www.ics.forth.gr/~lourakis/levmar/> -- -------------------------------------------------------------------------------- module Numeric.LevMar.Fitting ( -- * Model & Jacobian. Model , SimpleModel , Jacobian , SimpleJacobian -- * Levenberg-Marquardt algorithm. , LevMar.LevMarable , levmar , LevMar.LinearConstraints -- * Minimization options. , LevMar.Options(..) , LevMar.defaultOpts -- * Output , LevMar.Info(..) , LevMar.StopReason(..) , LevMar.CovarMatrix , LevMar.LevMarError(..) ) where -------------------------------------------------------------------------------- -- Imports -------------------------------------------------------------------------------- -- from base: import Data.Functor ( fmap ) import Data.Either ( Either ) import Data.List ( map, unzip ) import Data.Maybe ( Maybe ) import Prelude ( Integer ) -- from levmar: import qualified Numeric.LevMar as LevMar -------------------------------------------------------------------------------- -- Model & Jacobian. -------------------------------------------------------------------------------- {-| A functional relation describing measurements represented as a function from a list of parameters and an x-value to an expected measurement. * Ensure that the length of the parameters list equals the lenght of the initial parameters list in 'levmar'. For example, the quadratic function @f(x) = a*x^2 + b*x + c@ can be written as: @ quad :: 'Num' r => 'Model' r r quad [a, b, c] x = a*x^2 + b*x + c @ -} type Model r a = [r] → (a → r) -- | This type synonym expresses that usually the @a@ in @'Model' r a@ -- equals the type of the parameters. type SimpleModel r = Model r r {-| The jacobian of the 'Model' function. Expressed as a function from a list of parameters and an x-value to the partial derivatives of the parameters. See: <http://en.wikipedia.org/wiki/Jacobian_matrix_and_determinant> * Ensure that the length of the parameters list equals the lenght of the initial parameters list in 'levmar'. * Ensure that the length of the output parameter derivatives list equals the length of the input parameters list. For example, the jacobian of the above @quad@ model can be written as: @ 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 ] @ (Notice you don't have to differentiate for @x@.) -} type Jacobian r a = [r] → (a → [r]) -- | This type synonym expresses that usually the @a@ in @'Jacobian' r a@ -- equals the type of the parameters. type SimpleJacobian r = Jacobian r r -------------------------------------------------------------------------------- -- Levenberg-Marquardt algorithm. -------------------------------------------------------------------------------- -- | The Levenberg-Marquardt algorithm specialised for curve-fitting. levmar ∷ LevMar.LevMarable r ⇒ Model r a -- ^ Model → Maybe (Jacobian r a) -- ^ Optional jacobian → [r] -- ^ Initial parameters → [(a, r)] -- ^ Samples → Integer -- ^ Maximum iterations → LevMar.Options r -- ^ Minimization options → LevMar.Constraints r -- ^ Constraints → Either LevMar.LevMarError ([r], LevMar.Info r, LevMar.CovarMatrix r) levmar model mJac params samples = LevMar.levmar (convertModel model) (fmap convertJacob mJac) params ys where (xs, ys) = unzip samples convertModel mdl = \ps → map (mdl ps) xs convertJacob jac = \ps → map (jac ps) xs -- The End ---------------------------------------------------------------------