ad 0.12 → 0.13
raw patch · 11 files changed
+174/−117 lines, 11 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
+ Numeric.AD.Internal: instance Iso (f a) (AD f a)
+ Numeric.AD.Internal: instance Iso a (Id a)
+ Numeric.AD.Internal: instance Iso a a
+ Numeric.AD.Internal: probed :: f a -> f (AD Id a)
+ Numeric.AD.Internal: unprobed :: f (AD Id a) -> f a
Files
- Numeric/AD.hs +8/−8
- Numeric/AD/Classes.hs +37/−37
- Numeric/AD/Directed.hs +9/−9
- Numeric/AD/Forward.hs +11/−11
- Numeric/AD/Internal.hs +32/−10
- Numeric/AD/Internal/Forward.hs +9/−9
- Numeric/AD/Internal/Tower.hs +9/−9
- Numeric/AD/Newton.hs +37/−5
- Numeric/AD/Reverse.hs +8/−8
- Numeric/AD/Tower.hs +8/−8
- ad.cabal +6/−3
Numeric/AD.hs view
@@ -6,15 +6,15 @@ -- License : BSD3 -- Maintainer : ekmett@gmail.com -- Stability : experimental--- Portability : GHC only +-- Portability : GHC only -- -- Mixed-Mode Automatic Differentiation.--- +-- -- Each combinator exported from this module chooses an appropriate AD mode. ----------------------------------------------------------------------------- -module Numeric.AD - ( +module Numeric.AD+ ( -- * Gradients grad, grad2 @@ -58,9 +58,9 @@ import Data.Foldable (Foldable, foldr') import Control.Applicative import Numeric.AD.Classes (Mode(..))-import Numeric.AD.Internal (AD(..), probe, unprobe)+import Numeric.AD.Internal (AD(..), probed, unprobe) import Numeric.AD.Forward (diff, diffUU, diff2, diff2UU, diffUF, diff2UF)-import Numeric.AD.Tower (diffsUU, diffs0UU , diffsUF, diffs0UF , diffs, diffs0, taylor, taylor0) +import Numeric.AD.Tower (diffsUU, diffs0UU , diffsUF, diffs0UF , diffs, diffs0, taylor, taylor0) import Numeric.AD.Reverse (diffFU, diff2FU, grad, grad2) import qualified Numeric.AD.Forward as Forward@@ -77,9 +77,9 @@ | n > m = Reverse.jacobian2 f bs | otherwise = Forward.jacobian2 f bs where- as = f (probe <$> bs)+ as = f (probed bs) n = size bs m = size as size :: Foldable f => f a -> Int- size = foldr' (\_ b -> 1 + b) 0 + size = foldr' (\_ b -> 1 + b) 0 {-# INLINE jacobian2 #-}
Numeric/AD/Classes.hs view
@@ -6,14 +6,14 @@ -- License : BSD3 -- Maintainer : ekmett@gmail.com -- Stability : experimental--- Portability : GHC only +-- Portability : GHC only -- ----------------------------------------------------------------------------- module Numeric.AD.Classes- ( + ( -- * AD modes- Mode(..) + Mode(..) , one -- * Automatically Deriving AD , Jacobian(..)@@ -30,7 +30,7 @@ infixl 8 **! infixl 7 *!, /!, ^*, *^, ^/-infixl 6 +!, -!, <+> +infixl 6 +!, -!, <+> infix 4 ==! -- | Higher-order versions of the stock numerical methods.@@ -56,20 +56,20 @@ -- class (Show1 t, Eq t) => Num1 t where fromInteger1 :: Num a => Integer -> t a (+!),(-!),(*!) :: Num a => t a -> t a -> t a- negate1, abs1, signum1 :: Num a => t a -> t a + negate1, abs1, signum1 :: Num a => t a -> t a -- class Num1 t => Fractional1 t where (/!) :: Fractional a => t a -> t a -> t a recip1 :: Fractional a => t a -> t a- fromRational1 :: Fractional a => Rational -> t a + fromRational1 :: Fractional a => Rational -> t a --- class (Num1 t, Ord1 t) => Real1 t +-- class (Num1 t, Ord1 t) => Real1 t toRational1 :: Real a => t a -> Rational -- unsafe --- class Fractional1 t => Floating1 t - pi1 :: Floating a => t a +-- class Fractional1 t => Floating1 t+ pi1 :: Floating a => t a exp1, log1, sqrt1 :: Floating a => t a -> t a- (**!), logBase1 :: Floating a => t a -> t a -> t a + (**!), logBase1 :: Floating a => t a -> t a -> t a sin1, cos1, tan1, asin1, acos1, atan1 :: Floating a => t a -> t a sinh1, cosh1, tanh1, asinh1, acosh1, atanh1 :: Floating a => t a -> t a @@ -86,7 +86,7 @@ encodeFloat1 :: RealFloat a => Integer -> Int -> t a exponent1 :: RealFloat a => t a -> Int significand1 :: RealFloat a => t a -> t a- scaleFloat1 :: RealFloat a => Int -> t a -> t a + scaleFloat1 :: RealFloat a => Int -> t a -> t a isNaN1, isInfinite1, isDenormalized1, isNegativeZero1, isIEEE1 :: RealFloat a => t a -> Bool atan21 :: RealFloat a => t a -> t a -> t a @@ -100,13 +100,13 @@ enumFromThenTo1 :: (Num a, Enum a) => t a -> t a -> t a -> [t a] -- class Bounded1 t where- minBound1 :: (Num a, Bounded a) => t a + minBound1 :: (Num a, Bounded a) => t a maxBound1 :: (Num a, Bounded a) => t a class Lifted t => Mode t where -- | Embed a constant- lift :: Num a => a -> t a + lift :: Num a => a -> t a -- | Vector sum (<+>) :: Num a => t a -> t a -> t a@@ -118,7 +118,7 @@ (^*) :: Num a => t a -> a -> t a -- | Scalar division- (^/) :: Fractional a => t a -> a -> t a + (^/) :: Fractional a => t a -> a -> t a -- | > 'zero' = 'lift' 0 zero :: Num a => t a@@ -139,9 +139,9 @@ negOne = lift (-1) {-# INLINE negOne #-} --- | 'Primal' is used by 'deriveMode' but is not exposed +-- | 'Primal' is used by 'deriveMode' but is not exposed -- via the 'Mode' class to prevent its abuse by end users--- via the AD data type. +-- via the AD data type. -- -- It provides direct access to the result, stripped of its derivative information, -- but this is unsafe in general as (lift . primal) would discard derivative@@ -153,7 +153,7 @@ -- | 'Jacobian' is used by 'deriveMode' but is not exposed -- via 'Mode' to prevent its abuse by end users--- via the 'AD' data type. +-- via the 'AD' data type. class (Mode t, Mode (D t)) => Jacobian t where type D t :: * -> * @@ -168,7 +168,7 @@ withPrimal :: (Jacobian t, Num a) => t a -> a -> t a withPrimal t a = unary (const a) one t -fromBy :: (Jacobian t, Num a) => t a -> t a -> Int -> a -> t a +fromBy :: (Jacobian t, Num a) => t a -> t a -> Int -> a -> t a fromBy a delta n x = binary (\_ _ -> x) one (fromIntegral1 n) a delta fromIntegral1 :: (Integral n, Lifted t, Num a) => n -> t a@@ -176,7 +176,7 @@ {-# INLINE fromIntegral1 #-} square1 :: (Lifted t, Num a) => t a -> t a-square1 x = x *! x +square1 x = x *! x {-# INLINE square1 #-} on :: (a -> a -> c) -> (b -> a) -> b -> b -> c@@ -193,16 +193,16 @@ -- | @'deriveLifted' t@ provides ----- > instance Lifted $t +-- > instance Lifted $t -- -- given supplied instances for ----- > instance Lifted $t => Primal $t where ... +-- > instance Lifted $t => Primal $t where ... -- > instance Lifted $t => Jacobian $t where ...--- +-- -- The seemingly redundant @'Lifted' $t@ constraints are caused by Template Haskell staging restrictions. deriveLifted :: Q Type -> Q [Dec]-deriveLifted _t = [d| +deriveLifted _t = [d| instance Lifted $_t where (==!) = (==) `on` primal compare1 = compare `on` primal@@ -219,16 +219,16 @@ fromRational1 = lift . fromRational (/!) = lift2 (/) $ \x y -> (recip1 y, x) recip1 = lift1 recip (negate1 . square1)- + pi1 = lift pi exp1 = lift1_ exp const log1 = lift1 log recip1 logBase1 x y = log1 y /! log1 x sqrt1 = lift1_ sqrt (\z _ -> recip1 (lift 2 *! z))- (**!) = lift2_ (**) (\z x y -> (y *! z /! x, z *! log1 x)) -- error at 0 ** n + (**!) = lift2_ (**) (\z x y -> (y *! z /! x, z *! log1 x)) -- error at 0 ** n sin1 = lift1 sin cos1 cos1 = lift1 cos $ \x -> negate1 (sin1 x)- tan1 x = sin1 x /! cos1 x + tan1 x = sin1 x /! cos1 x asin1 = lift1 asin $ \x -> recip1 (sqrt1 (one -! square1 x)) acos1 = lift1 acos $ \x -> negate1 (recip1 (sqrt1 (one -! square1 x))) atan1 = lift1 atan $ \x -> recip1 (one +! square1 x)@@ -238,16 +238,16 @@ asinh1 = lift1 asinh $ \x -> recip1 (sqrt1 (one +! square1 x)) acosh1 = lift1 acosh $ \x -> recip1 (sqrt1 (square1 x -! one)) atanh1 = lift1 atanh $ \x -> recip1 (one -! square1 x)- + succ1 = lift1 succ (const one) pred1 = lift1 pred (const one) toEnum1 = lift . toEnum- fromEnum1 = discrete1 fromEnum + fromEnum1 = discrete1 fromEnum enumFrom1 a = withPrimal a <$> discrete1 enumFrom a enumFromTo1 a b = withPrimal a <$> discrete2 enumFromTo a b enumFromThen1 a b = zipWith (fromBy a delta) [0..] $ discrete2 enumFromThen a b where delta = b -! a enumFromThenTo1 a b c = zipWith (fromBy a delta) [0..] $ discrete3 enumFromThenTo a b c where delta = b -! a- + toRational1 = discrete1 toRational floatRadix1 = discrete1 floatRadix floatDigits1 = discrete1 floatDigits@@ -260,20 +260,20 @@ isNegativeZero1 = discrete1 isNegativeZero isIEEE1 = discrete1 isIEEE exponent1 = exponent . primal- scaleFloat1 n = unary (scaleFloat n) (scaleFloat1 n one) + scaleFloat1 n = unary (scaleFloat n) (scaleFloat1 n one) significand1 x = unary significand (scaleFloat1 (- floatDigits1 x) one) x atan21 = lift2 atan2 $ \vx vy -> let r = recip1 (square1 vx +! square1 vy) in (vy *! r, negate1 vx *! r)- properFraction1 a = (w, a `withPrimal` pb) where - pa = primal a + properFraction1 a = (w, a `withPrimal` pb) where+ pa = primal a (w, pb) = properFraction pa truncate1 = discrete1 truncate round1 = discrete1 round ceiling1 = discrete1 ceiling- floor1 = discrete1 floor + floor1 = discrete1 floor |]- + varA :: Q Type-varA = varT (mkName "a") +varA = varT (mkName "a") -- | Find all the members defined in the 'Lifted' data type liftedMembers :: Q [String]@@ -308,13 +308,13 @@ instanceD (cxt (f [classP ''Lifted [t], classP n [varA]])) (conT n `appT` (t' `appT` varA)) (concatMap lower1 ds)- where + where lower1 :: Dec -> [Q Dec] lower1 (SigD n' _) | p n'' = [valD (varP n') (normalB (varE n'')) []] where n'' = primed n' lower1 _ = [] primed n' = mkName $ base ++ [prime]- where + where base = nameBase n' h = head base prime | isSymbol h || h `elem` "/*-<>" = '!'
Numeric/AD/Directed.hs view
@@ -6,14 +6,14 @@ -- License : BSD3 -- Maintainer : ekmett@gmail.com -- Stability : experimental--- Portability : GHC only +-- Portability : GHC only -- -- Allows the choice of AD 'Mode' to be specified at the term level for -- benchmarking or more complicated usage patterns. ----------------------------------------------------------------------------- module Numeric.AD.Directed- ( + ( -- * Derivatives diffUU , diff2UU@@ -44,11 +44,11 @@ -- TODO: use a data types a la carte approach, so we can expose more methods here -- rather than just the intersection of all of the functionality-data Direction - = Forward - | Reverse - | Tower - | Mixed +data Direction+ = Forward+ | Reverse+ | Tower+ | Mixed deriving (Show, Eq, Ord, Read, Bounded, Enum, Ix) diffUU :: Num a => Direction -> (forall s. Mode s => AD s a -> AD s a) -> a -> a@@ -58,7 +58,7 @@ diffUU Mixed = F.diffUU {-# INLINE diffUU #-} -diff2UU :: Num a => Direction -> (forall s. Mode s => AD s a -> AD s a) -> a -> (a, a) +diff2UU :: Num a => Direction -> (forall s. Mode s => AD s a -> AD s a) -> a -> (a, a) diff2UU Forward = F.diff2UU diff2UU Reverse = R.diff2UU diff2UU Tower = T.diff2UU@@ -69,7 +69,7 @@ diff = diffUU {-# INLINE diff #-} -diff2 :: Num a => Direction -> (forall s. Mode s => AD s a -> AD s a) -> a -> (a, a) +diff2 :: Num a => Direction -> (forall s. Mode s => AD s a -> AD s a) -> a -> (a, a) diff2 = diff2UU {-# INLINE diff2 #-}
Numeric/AD/Forward.hs view
@@ -6,14 +6,14 @@ -- License : BSD3 -- Maintainer : ekmett@gmail.com -- Stability : experimental--- Portability : GHC only +-- Portability : GHC only -- -- Forward mode automatic differentiation -- ----------------------------------------------------------------------------- module Numeric.AD.Forward- ( + ( -- * Gradient grad , grad2@@ -46,7 +46,7 @@ {-# INLINE diff #-} -- | The 'diff2' function calculates the result and first derivative of scalar-to-scalar function by 'Forward' 'AD'-diff2 :: Num a => (forall s. Mode s => AD s a -> AD s a) -> a -> (a, a) +diff2 :: Num a => (forall s. Mode s => AD s a -> AD s a) -> a -> (a, a) diff2 = diff2UU {-# INLINE diff2 #-} @@ -56,7 +56,7 @@ {-# INLINE diffUU #-} -- | The 'diff2UU' function calculates the result and first derivative of scalar-to-scalar function by 'Forward' 'AD'-diff2UU :: Num a => (forall s. Mode s => AD s a -> AD s a) -> a -> (a, a) +diff2UU :: Num a => (forall s. Mode s => AD s a -> AD s a) -> a -> (a, a) diff2UU f a = unbundle $ apply f a {-# INLINE diff2UU #-} @@ -66,7 +66,7 @@ {-# INLINE diffUF #-} -- | The 'diff2UF' function calculates the result and first derivative of a scalar-to-non-scalar function by 'Forward' 'AD'-diff2UF :: (Functor f, Num a) => (forall s. Mode s => AD s a -> f (AD s a)) -> a -> f (a, a) +diff2UF :: (Functor f, Num a) => (forall s. Mode s => AD s a -> f (AD s a)) -> a -> f (a, a) diff2UF f a = unbundle <$> apply f a {-# INLINE diff2UF #-} @@ -78,15 +78,15 @@ jacobian :: (Traversable f, Traversable g, Num a) => (forall s. Mode s => f (AD s a) -> g (AD s a)) -> f a -> g (f a) jacobian f as = transposeWith (const id) t p- where - (p, t) = bind2 (fmap tangent . f) as + where+ (p, t) = bind2 (fmap tangent . f) as {-# INLINE jacobian #-} jacobian2 :: (Traversable f, Traversable g, Num a) => (forall s. Mode s => f (AD s a) -> g (AD s a)) -> f a -> g (a, f a) jacobian2 f as = transposeWith row t p- where - (p, t) = bind2 f as - row x as' = (primal x, tangent <$> as') + where+ (p, t) = bind2 f as+ row x as' = (primal x, tangent <$> as') {-# INLINE jacobian2 #-} grad :: (Traversable f, Num a) => (forall s. Mode s => f (AD s a) -> AD s a) -> f a -> f a@@ -95,6 +95,6 @@ grad2 :: (Traversable f, Num a) => (forall s. Mode s => f (AD s a) -> AD s a) -> f a -> (a, f a) grad2 f as = (primal b, tangent <$> bs)- where + where (b, bs) = bind2 f as {-# INLINE grad2 #-}
Numeric/AD/Internal.hs view
@@ -1,4 +1,4 @@-{-# LANGUAGE GeneralizedNewtypeDeriving, TemplateHaskell, FlexibleContexts, FlexibleInstances #-}+{-# LANGUAGE GeneralizedNewtypeDeriving, TemplateHaskell, FlexibleContexts, FlexibleInstances, MultiParamTypeClasses #-} ----------------------------------------------------------------------------- -- | -- Module : Numeric.AD.Internal@@ -6,7 +6,7 @@ -- License : BSD3 -- Maintainer : ekmett@gmail.com -- Stability : experimental--- Portability : GHC only +-- Portability : GHC only -- ----------------------------------------------------------------------------- module Numeric.AD.Internal@@ -15,6 +15,8 @@ , Id(..) , probe , unprobe+ , probed+ , unprobed ) where import Control.Applicative@@ -24,19 +26,27 @@ import Data.Traversable (Traversable, mapAccumL) import Data.Foldable (Foldable, toList) -zipWithT :: (Foldable f, Traversable g) => (a -> b -> c) -> f a -> g b -> g c +zipWithT :: (Foldable f, Traversable g) => (a -> b -> c) -> f a -> g b -> g c zipWithT f as = snd . mapAccumL (\(a:as') b -> (as', f a b)) (toList as) --- | 'AD' serves as a common wrapper for different 'Mode' instances, exposing a traditional --- numerical tower. Universal quantification is used to limit the actions in user code to +class Iso a b where+ iso :: f a -> f b+ osi :: f b -> f a++instance Iso a a where+ iso = id+ osi = id++-- | 'AD' serves as a common wrapper for different 'Mode' instances, exposing a traditional+-- numerical tower. Universal quantification is used to limit the actions in user code to -- machinery that will return the same answers under all AD modes, allowing us to use modes -- interchangeably as both the type level \"brand\" and dictionary, providing a common API.-newtype AD f a = AD { runAD :: f a } deriving (Lifted, Mode, Primal)+newtype AD f a = AD { runAD :: f a } deriving (Iso (f a), Lifted, Mode, Primal) let f = varT (mkName "f") in deriveNumeric (conT ''AD `appT` f) f newtype Id a = Id a deriving- (Eq, Ord, Show, Enum, Bounded, Num, Real, Fractional, Floating, RealFrac, RealFloat, Monoid)+ (Iso a, Eq, Ord, Show, Enum, Bounded, Num, Real, Fractional, Floating, RealFrac, RealFloat, Monoid) probe :: a -> AD Id a probe a = AD (Id a)@@ -44,6 +54,18 @@ unprobe :: AD Id a -> a unprobe (AD (Id a)) = a +pid :: f a -> f (Id a)+pid = iso++unpid :: f (Id a) -> f a+unpid = osi++probed :: f a -> f (AD Id a)+probed = iso . pid++unprobed :: f (AD Id a) -> f a+unprobed = unpid . osi+ instance Functor Id where fmap f (Id a) = Id (f a) @@ -53,7 +75,7 @@ instance Monad Id where return = Id- Id a >>= f = f a + Id a >>= f = f a instance Lifted Id where (==!) = (==)@@ -62,14 +84,14 @@ fromInteger1 = fromInteger (+!) = (+) (-!) = (-)- (*!) = (*) + (*!) = (*) negate1 = negate abs1 = abs signum1 = signum (/!) = (/) recip1 = recip fromRational1 = fromRational- toRational1 = toRational + toRational1 = toRational pi1 = pi exp1 = exp log1 = log
Numeric/AD/Internal/Forward.hs view
@@ -6,7 +6,7 @@ -- License : BSD3 -- Maintainer : ekmett@gmail.com -- Stability : experimental--- Portability : GHC only +-- Portability : GHC only -- -- Unsafe and often partial combinators intended for internal usage. --@@ -65,23 +65,23 @@ type D Forward = Id unary f (Id dadb) (Forward b db) = Forward (f b) (dadb * db) lift1 f df (Forward b db) = Forward (f b) (dadb * db)- where + where Id dadb = df (Id b) lift1_ f df (Forward b db) = Forward a da- where + where a = f b Id da = df (Id a) (Id b) ^* db binary f (Id dadb) (Id dadc) (Forward b db) (Forward c dc) = Forward (f b c) da- where + where da = dadb * db + dc * dadc lift2 f df (Forward b db) (Forward c dc) = Forward a da- where + where a = f b c- (Id dadb, Id dadc) = df (Id b) (Id c) + (Id dadb, Id dadc) = df (Id b) (Id c) da = dadb * db + dc * dadc lift2_ f df (Forward b db) (Forward c dc) = Forward a da- where + where a = f b c (Id dadb, Id dadc) = df (Id a) (Id b) (Id c) da = dadb * db + dc * dadc@@ -95,7 +95,7 @@ inner !i !j a = (j + 1, bundle a $ if i == j then 1 else 0) bind2 :: (Traversable f, Num a) => (f (AD Forward a) -> b) -> f a -> (b, f b)-bind2 f as = dropIx $ mapAccumL outer (0 :: Int, b0) as +bind2 f as = dropIx $ mapAccumL outer (0 :: Int, b0) as where outer (!i, _) _ = let b = f $ snd $ mapAccumL (inner i) (0 :: Int) as in ((i + 1, b), b) inner !i !j a = (j + 1, bundle a $ if i == j then 1 else 0)@@ -106,7 +106,7 @@ -- traversable could be empty. So instead we use one as a 'skeleton' transposeWith :: (Functor f, Foldable f, Traversable g) => (b -> f a -> c) -> f (g a) -> g b -> g c transposeWith f as = snd . mapAccumL go xss0- where + where go xss b = (tail <$> xss, f b (head <$> xss)) xss0 = toList <$> as
Numeric/AD/Internal/Tower.hs view
@@ -6,7 +6,7 @@ -- License : BSD3 -- Maintainer : ekmett@gmail.com -- Stability : experimental--- Portability : GHC only +-- Portability : GHC only -- ----------------------------------------------------------------------------- @@ -31,7 +31,7 @@ -- Local combinators zeroPad :: Num a => [a] -> [a]-zeroPad xs = xs ++ repeat 0 +zeroPad xs = xs ++ repeat 0 {-# INLINE zeroPad #-} d :: Num a => [a] -> a@@ -39,7 +39,7 @@ d _ = 0 {-# INLINE d #-} -d2 :: Num a => [a] -> (a, a) +d2 :: Num a => [a] -> (a, a) d2 (a:da:_) = (a, da) d2 (a:_) = (a, 0) d2 _ = (0, 0)@@ -73,7 +73,7 @@ Tower [] <+> bs = bs as <+> Tower [] = as Tower (a:as) <+> Tower (b:bs) = Tower (c:cs)- where + where c = a + b Tower cs = Tower as <+> Tower bs @@ -86,16 +86,16 @@ type D Tower = Tower unary f dadb b = bundle (f (primal b)) (tangents b *! dadb) lift1 f df b = bundle (f (primal b)) (tangents b *! df b)- lift1_ f df b = a where + lift1_ f df b = a where a = bundle (f (primal b)) (tangents b *! df a b) - binary f dadb dadc b c = bundle (f (primal b) (primal c)) (tangents b *! dadb +! tangents c *! dadc) + binary f dadb dadc b c = bundle (f (primal b) (primal c)) (tangents b *! dadb +! tangents c *! dadc) lift2 f df b c = bundle (f (primal b) (primal c)) (tangents b *! dadb +! tangents c *! dadc) where- (dadb, dadc) = df b c - lift2_ f df b c = a where + (dadb, dadc) = df b c+ lift2_ f df b c = a where a0 = f (primal b) (primal c) da = tangents b *! dadb +! tangents c *! dadc- a = bundle a0 da + a = bundle a0 da (dadb, dadc) = df a b c deriveLifted (conT ''Tower)
Numeric/AD/Newton.hs view
@@ -6,12 +6,12 @@ -- License : BSD3 -- Maintainer : ekmett@gmail.com -- Stability : experimental--- Portability : GHC only +-- Portability : GHC only -- ----------------------------------------------------------------------------- module Numeric.AD.Newton- ( + ( -- * Newton's Method (Forward AD) findZero , inverse@@ -29,30 +29,62 @@ import Numeric.AD.Internal import Data.Foldable (all) import Data.Traversable (Traversable)-import Numeric.AD.Forward (diff, diff2) -import Numeric.AD.Reverse (grad2) +import Numeric.AD.Forward (diff, diff2)+import Numeric.AD.Reverse (grad2) +-- | The 'findZero' function finds a zero of a scalar function using+-- Newton's method; its output is a stream of increasingly accurate+-- results. (Modulo the usual caveats.)+--+-- Examples:+--+-- > take 10 $ findZero (\\x->x^2-4) 1 -- converge to 2.0+--+-- > module Data.Complex+-- > take 10 $ findZero ((+1).(^2)) (1 :+ 1) -- converge to (0 :+ 1)@+-- findZero :: Fractional a => (forall s. Mode s => AD s a -> AD s a) -> a -> [a] findZero f x0 = iterate (\x -> let (y,y') = diff2 f x in x - y/y') x0 {-# INLINE findZero #-} +-- | The 'inverseNewton' function inverts a scalar function using+-- Newton's method; its output is a stream of increasingly accurate+-- results. (Modulo the usual caveats.)+--+-- Example:+--+-- > take 10 $ inverseNewton sqrt 1 (sqrt 10) -- converge to 10+-- inverse :: Fractional a => (forall s. Mode s => AD s a -> AD s a) -> a -> a -> [a] inverse f x0 y = findZero (\x -> f x - lift y) x0 {-# INLINE inverse #-} +-- | The 'fixedPoint' function find a fixedpoint of a scalar+-- function using Newton's method; its output is a stream of+-- increasingly accurate results. (Modulo the usual caveats.) fixedPoint :: Fractional a => (forall s. Mode s => AD s a -> AD s a) -> a -> [a] fixedPoint f = findZero (\x -> f x - x) {-# INLINE fixedPoint #-} +-- | The 'extremum' function finds an extremum of a scalar+-- function using Newton's method; produces a stream of increasingly+-- accurate results. (Modulo the usual caveats.) extremum :: Fractional a => (forall t s. (Mode t, Mode s) => AD t (AD s a) -> AD t (AD s a)) -> a -> [a] extremum f x0 = findZero (diff f) x0 {-# INLINE extremum #-} +-- | The 'gradientDescent' function performs a multivariate+-- optimization, based on the naive-gradient-descent in the file+-- @stalingrad\/examples\/flow-tests\/pre-saddle-1a.vlad@ from the+-- VLAD compiler Stalingrad sources. Its output is a stream of+-- increasingly accurate results. (Modulo the usual caveats.)+--+-- It uses reverse mode automatic differentiation to compute the gradient. gradientDescent :: (Traversable f, Fractional a, Ord a) => (forall s. Mode s => f (AD s a) -> AD s a) -> f a -> [f a] gradientDescent f x0 = go x0 fx0 gx0 0.1 (0 :: Int) where (fx0, gx0) = grad2 f x0- go x fx gx !eta !i + go x fx gx !eta !i | eta == 0 = [] -- step size is 0 | fx1 > fx = go x fx gx (eta/2) 0 -- we stepped too far | all (==0) gx = [] -- gradient is 0
Numeric/AD/Reverse.hs view
@@ -6,11 +6,11 @@ -- License : BSD3 -- Maintainer : ekmett@gmail.com -- Stability : experimental--- Portability : GHC only +-- Portability : GHC only -- -- Mixed-Mode Automatic Differentiation.--- --- For reverse mode AD we use 'System.Mem.StableName.StableName' to recover sharing information from +--+-- For reverse mode AD we use 'System.Mem.StableName.StableName' to recover sharing information from -- the tape to avoid combinatorial explosion, and thus run asymptotically faster -- than it could without such sharing information, but the use of side-effects -- contained herein is benign.@@ -18,7 +18,7 @@ ----------------------------------------------------------------------------- module Numeric.AD.Reverse- ( + ( -- * Gradient grad , grad2@@ -57,19 +57,19 @@ grad2 :: (Traversable f, Num a) => (forall s. Mode s => f (AD s a) -> AD s a) -> f a -> (a, f a) grad2 f as = (primal r, unbind vs $ partialArray bds r) where (vs, bds) = bind as- r = f vs + r = f vs {-# INLINE grad2 #-} -- | The 'jacobian' function calculates the jacobian of a non-scalar-to-non-scalar function with reverse AD lazily in @m@ passes for @m@ outputs. jacobian :: (Traversable f, Functor g, Num a) => (forall s. Mode s => f (AD s a) -> g (AD s a)) -> f a -> g (f a)-jacobian f as = unbind vs . partialArray bds <$> f vs where +jacobian f as = unbind vs . partialArray bds <$> f vs where (vs, bds) = bind as {-# INLINE jacobian #-} -- | The 'jacobian2' function calculates both the result and the Jacobian of a nonscalar-to-nonscalar function, using @m@ invocations of reverse AD, -- where @m@ is the output dimensionality. Applying @fmap snd@ to the result will recover the result of 'jacobian' jacobian2 :: (Traversable f, Functor g, Num a) => (forall s. Mode s => f (AD s a) -> g (AD s a)) -> f a -> g (a, f a)-jacobian2 f as = row <$> f vs where +jacobian2 f as = row <$> f vs where (vs, bds) = bind as row a = (primal a, unbind vs (partialArray bds a)) {-# INLINE jacobian2 #-}@@ -105,7 +105,7 @@ -- | The 'diff' function is a synonym for 'diffUU'. diff :: Num a => (forall s. Mode s => AD s a -> AD s a) -> a -> a-diff = diffUU +diff = diffUU {-# INLINE diff #-} -- | The 'diff2' function is a synonym for 'diff2UU'.
Numeric/AD/Tower.hs view
@@ -6,14 +6,14 @@ -- License : BSD3 -- Maintainer : ekmett@gmail.com -- Stability : experimental--- Portability : GHC only +-- Portability : GHC only -- -- Higher order derivatives via a \"dual number tower\". -- ----------------------------------------------------------------------------- module Numeric.AD.Tower- ( + ( -- * Taylor Series taylor, taylor0 , maclaurin, maclaurin0@@ -23,7 +23,7 @@ , diffsUU , diffs0UU , diffsUF- , diffs0UF + , diffs0UF -- * Synonyms , diffs, diffs0 , diff, diff2@@ -40,7 +40,7 @@ import Numeric.AD.Internal.Tower diffsUU :: Num a => (forall s. Mode s => AD s a -> AD s a) -> a -> [a]-diffsUU f a = getADTower $ apply f a +diffsUU f a = getADTower $ apply f a {-# INLINE diffsUU #-} diffs0UU :: Num a => (forall s. Mode s => AD s a -> AD s a) -> a -> [a]@@ -74,19 +74,19 @@ {-# INLINE taylor0 #-} maclaurin :: Fractional a => (forall s. Mode s => AD s a -> AD s a) -> a -> [a]-maclaurin f = taylor f 0 +maclaurin f = taylor f 0 {-# INLINE maclaurin #-} maclaurin0 :: Fractional a => (forall s. Mode s => AD s a -> AD s a) -> a -> [a]-maclaurin0 f = taylor0 f 0 +maclaurin0 f = taylor0 f 0 {-# INLINE maclaurin0 #-} diffUU :: Num a => (forall s. Mode s => AD s a -> AD s a) -> a -> a-diffUU f a = d $ diffs f a +diffUU f a = d $ diffs f a {-# INLINE diffUU #-} diff2UU :: Num a => (forall s. Mode s => AD s a -> AD s a) -> a -> (a, a)-diff2UU f a = d2 $ diffs f a +diff2UU f a = d2 $ diffs f a {-# INLINE diff2UU #-} diff :: Num a => (forall s. Mode s => AD s a -> AD s a) -> a -> a
ad.cabal view
@@ -1,5 +1,5 @@ Name: ad-Version: 0.12+Version: 0.13 License: BSD3 License-File: LICENSE Copyright: Edward Kmett 2010@@ -8,8 +8,11 @@ Stability: Experimental Category: Math Homepage: http://comonad.com/reader/-Synopsis: Mixed-Mode Automatic Differentiation.-Description: Forward, reverse, and higher-order automatic differentiation with a common API+Synopsis: Automatic Differentiation+Description: + Forward, reverse, and higher-order automatic differentiation combinators with a common API.+ . + Type-level \"branding\" is used to prevent the end user from confusing infinitesimals. Build-Type: Simple Build-Depends: