l-bfgs-b-0.1: src/Numeric/LBFGSB/Convenience.hs
{-# LANGUAGE FlexibleContexts #-}
-- | Some functions that can be useful together with L-BFGS-B.
module Numeric.LBFGSB.Convenience(approximateGradient, listFunction, vectorFunction) where
import qualified Data.Vector.Storable as V
import qualified Data.Vector.Generic as GV
-- | @'approximateGradient' h f x@ is an approximation of the gradient
-- of @f@ at @x@, computed using central differences with step size
-- @h@.
approximateGradient :: (GV.Vector v Double) => Double -> (v Double -> Double) -> (v Double -> v Double)
approximateGradient h f x = GV.generate (GV.length x) (\i -> central h (\y -> f (replaceAt i y x)) (x GV.! i))
-- | Turn a function on lists into one on 'V.Storable' 'V.Vector's.
listFunction :: ([Double] -> Double) -> (V.Vector Double -> Double)
listFunction f = f . V.toList
-- | Turn a function on any generic 'GV.Vector's into one on 'V.Storable' 'V.Vector's.
vectorFunction :: (GV.Vector v Double) => (v Double -> Double) -> (V.Vector Double -> Double)
vectorFunction f = f . GV.convert
replaceAt :: (GV.Vector v a) => Int -> a -> v a -> v a
replaceAt n x xs
| n > GV.length xs - 1 || n < 0 = xs
| otherwise = xs GV.// [(n, x)]
central :: Double -> (Double -> Double) -> Double -> Double
central h f x = (f (x+h) - f (x-h))/(2*h)