levmar-0.3: Numeric/LevMar/Fitting.hs
{-# 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 ---------------------------------------------------------------------