packages feed

ad 0.21 → 0.22

raw patch · 6 files changed

+150/−94 lines, 6 filesPVP ok

version bump matches the API change (PVP)

API changes (from Hackage documentation)

- Numeric.AD.Internal.Composition: O :: f (AD g a) -> :. f g a
- Numeric.AD.Internal.Composition: compose :: AD f (AD g a) -> AD (f :. g) a
- Numeric.AD.Internal.Composition: decompose :: AD (f :. g) a -> AD f (AD g a)
- Numeric.AD.Internal.Composition: instance (Mode f, Mode g) => Lifted (f :. g)
- Numeric.AD.Internal.Composition: instance (Mode f, Mode g) => Mode (f :. g)
- Numeric.AD.Internal.Composition: instance (Primal f, Mode g, Primal g) => Primal (f :. g)
- Numeric.AD.Internal.Composition: newtype (:.) f g a
- Numeric.AD.Internal.Composition: runO :: :. f g a -> f (AD g a)
- Numeric.AD.Internal.Composition: type On f g = g :. f
+ Numeric.AD: hessian :: (Traversable f, Num a) => (forall s. (Mode s) => f (AD s a) -> AD s a) -> f a -> f (f a)
+ Numeric.AD: hessianTensor :: (Traversable f, Traversable g, Num a) => (forall s. (Mode s) => f (AD s a) -> g (AD s a)) -> f a -> g (f (f a))
+ Numeric.AD.Internal.Composition: ComposeFunctor :: f (g a) -> ComposeFunctor f g a
+ Numeric.AD.Internal.Composition: ComposeMode :: f (AD g a) -> ComposeMode f g a
+ Numeric.AD.Internal.Composition: composeMode :: AD f (AD g a) -> AD (ComposeMode f g) a
+ Numeric.AD.Internal.Composition: decomposeFunctor :: ComposeFunctor f g a -> f (g a)
+ Numeric.AD.Internal.Composition: decomposeMode :: AD (ComposeMode f g) a -> AD f (AD g a)
+ Numeric.AD.Internal.Composition: instance (Foldable f, Foldable g) => Foldable (ComposeFunctor f g)
+ Numeric.AD.Internal.Composition: instance (Functor f, Functor g) => Functor (ComposeFunctor f g)
+ Numeric.AD.Internal.Composition: instance (Mode f, Mode g) => Lifted (ComposeMode f g)
+ Numeric.AD.Internal.Composition: instance (Mode f, Mode g) => Mode (ComposeMode f g)
+ Numeric.AD.Internal.Composition: instance (Primal f, Mode g, Primal g) => Primal (ComposeMode f g)
+ Numeric.AD.Internal.Composition: instance (Traversable f, Traversable g) => Traversable (ComposeFunctor f g)
+ Numeric.AD.Internal.Composition: newtype ComposeFunctor f g a
+ Numeric.AD.Internal.Composition: newtype ComposeMode f g a
+ Numeric.AD.Internal.Composition: runComposeMode :: ComposeMode f g a -> f (AD g a)
+ Numeric.AD.Reverse: hessian :: (Traversable f, Num a) => (forall s. (Mode s) => f (AD s a) -> AD s a) -> f a -> f (f a)
+ Numeric.AD.Reverse: hessianM :: (Traversable f, Monad m, Num a) => (forall s. (Mode s) => f (AD s a) -> m (AD s a)) -> f a -> m (f (f a))
+ Numeric.AD.Reverse: hessianTensor :: (Traversable f, Functor g, Num a) => (forall s. (Mode s) => f (AD s a) -> g (AD s a)) -> f a -> g (f (f a))

Files

Numeric/AD.hs view
@@ -16,12 +16,16 @@ module Numeric.AD     (     -- * Gradients (Reverse Mode)-      grad, grad'-    , gradWith, gradWith'+      grad+    , grad'+    , gradWith+    , gradWith'      -- * Jacobians (Mixed Mode)-    , jacobian, jacobian'-    , jacobianWith, jacobianWith'+    , jacobian+    , jacobian'+    , jacobianWith+    , jacobianWith'      -- * Jacobians (Reverse Mode)     , gradF@@ -30,9 +34,16 @@     , gradWithF'      -- * Jacobians (Forward Mode)-    , jacobianT, jacobianWithT+    , jacobianT+    , jacobianWithT -    -- * Hessians (Forward-On-Reverse Mode)+    -- * Hessian (Forward-On-Reverse)+    , hessian++    -- * Hessian Tensors (Forward-On-Mixed)+    , hessianTensor++    -- * Hessian Vector Products (Forward-On-Reverse)     , hessianProduct     , hessianProduct' @@ -87,7 +98,7 @@ import Numeric.AD.Forward  (diff, diff', diffF, diffF', du, du', duF, duF', diffM, diffM', jacobianT, jacobianWithT)  import Numeric.AD.Tower    (diffsF, diffs0F , diffs, diffs0, taylor, taylor0, maclaurin, maclaurin0) import Numeric.AD.Reverse  (grad, grad', gradWith, gradWith', gradM, gradM', gradWithM, gradWithM', gradF, gradF', gradWithF, gradWithF')-import Numeric.AD.Internal.Composition (compose, decompose)+import Numeric.AD.Internal.Composition  import qualified Numeric.AD.Forward as Forward import qualified Numeric.AD.Reverse as Reverse@@ -147,7 +158,7 @@ --  -- Or in other words, we take the directional derivative of the gradient. hessianProduct :: (Traversable f, Num a) => (forall s. Mode s => f (AD s a) -> AD s a) -> f (a, a) -> f a-hessianProduct f = duF (grad (decompose . f . fmap compose))+hessianProduct f = duF (grad (decomposeMode . f . fmap composeMode))  -- | @'hessianProduct'' f wv@ computes both the gradient of a non-scalar-to-scalar @f@ at @w = 'fst' <$> wv@ and the product of the hessian @H@ at @w@ with a vector @v = snd <$> wv@ using \"Pearlmutter\'s method\". The outputs are returned wrapped in the same functor. --@@ -156,5 +167,14 @@ -- Or in other words, we take the directional derivative of the gradient. --  hessianProduct' :: (Traversable f, Num a) => (forall s. Mode s => f (AD s a) -> AD s a) -> f (a, a) -> f (a, a)-hessianProduct' f = duF' (grad (decompose . f . fmap compose))+hessianProduct' f = duF' (grad (decomposeMode . f . fmap composeMode)) +-- hessianProductWith' :: (Traversable f, Num a) => (a -> a -> a -> a -> b) -> (forall s. Mode s. f (AD s a) -> AD s a) -> f (a, a) -> f b++-- | Compute the hessian via the jacobian of the gradient. gradient is computed in reverse mode and then the jacobian is computed in forward mode.+hessian :: (Traversable f, Num a) => (forall s. Mode s => f (AD s a) -> AD s a) -> f a -> f (f a)+hessian f = Forward.jacobian (grad (decomposeMode . f . fmap composeMode))++-- | Compute the order 3 Hessian tensor on a non-scalar-to-non-scalar function via the forward-mode Jacobian of the mixed-mode Jacobian of the function.+hessianTensor :: (Traversable f, Traversable g, Num a) => (forall s. Mode s => f (AD s a) -> g (AD s a)) -> f a -> g (f (f a))+hessianTensor f = decomposeFunctor . Forward.jacobian (ComposeFunctor . jacobian (fmap decomposeMode . f . fmap composeMode))
Numeric/AD/Forward.hs view
@@ -166,8 +166,8 @@  -- | Compute the product of a vector with the Hessian using forward-on-forward-mode AD.  hessianProduct :: (Traversable f, Num a) => (forall s. Mode s => f (AD s a) -> AD s a) -> f (a, a) -> f a-hessianProduct f = duF (grad (decompose . f . fmap compose))+hessianProduct f = duF (grad (decomposeMode . f . fmap composeMode))  -- | Compute the gradient and hessian product using forward-on-forward-mode AD.  hessianProduct' :: (Traversable f, Num a) => (forall s. Mode s => f (AD s a) -> AD s a) -> f (a, a) -> f (a, a)-hessianProduct' f = duF' (grad (decompose . f . fmap compose))+hessianProduct' f = duF' (grad (decomposeMode . f . fmap composeMode))
Numeric/AD/Internal/Composition.hs view
@@ -12,98 +12,111 @@ -----------------------------------------------------------------------------  module Numeric.AD.Internal.Composition-    ( (:.)(..)-    , On-    , compose-    , decompose+    ( ComposeFunctor(..)+    , ComposeMode(..)+    , composeMode+    , decomposeMode     ) where +import Data.Traversable+import Control.Applicative+import Data.Foldable import Numeric.AD.Classes import Numeric.AD.Internal -newtype (f :. g) a = O { runO :: f (AD g a) }+-- * Functor composition +newtype ComposeFunctor f g a = ComposeFunctor { decomposeFunctor :: f (g a) } -type On f g = g :. f+instance (Functor f, Functor g) => Functor (ComposeFunctor f g) where+    fmap f (ComposeFunctor a) = ComposeFunctor (fmap (fmap f) a)+    +instance (Foldable f, Foldable g) => Foldable (ComposeFunctor f g) where+    foldMap f (ComposeFunctor a) = foldMap (foldMap f) a+    +instance (Traversable f, Traversable g) => Traversable (ComposeFunctor f g) where+    traverse f (ComposeFunctor a) = ComposeFunctor <$> traverse (traverse f) a -compose :: AD f (AD g a) -> AD (f :. g) a-compose (AD a) = AD (O a)+newtype ComposeMode f g a = ComposeMode { runComposeMode :: f (AD g a) } -decompose :: AD (f :. g) a -> AD f (AD g a)-decompose (AD (O a)) = AD a+composeMode :: AD f (AD g a) -> AD (ComposeMode f g) a+composeMode (AD a) = AD (ComposeMode a) -instance (Primal f, Mode g, Primal g) => Primal (f :. g) where-    primal = primal . primal . runO+decomposeMode :: AD (ComposeMode f g) a -> AD f (AD g a)+decomposeMode (AD (ComposeMode a)) = AD a -instance (Mode f, Mode g) => Mode (f :. g) where-    lift = O . lift . lift-    O a <+> O b = O (a <+> b) -    a *^ O b = O (lift a *^ b) -    O a ^* b = O (a ^* lift b)-    O a ^/ b = O (a ^/ lift b)+instance (Primal f, Mode g, Primal g) => Primal (ComposeMode f g) where+    primal = primal . primal . runComposeMode -instance (Mode f, Mode g) => Lifted (f :. g) where-    showsPrec1 n (O a) = showsPrec1 n a-    O a ==! O b  = a ==! b-    compare1 (O a) (O b) = compare1 a b-    fromInteger1 = O . lift . fromInteger1-    O a +! O b = O (a +! b)-    O a -! O b = O (a -! b)-    O a *! O b = O (a *! b)-    negate1 (O a) = O (negate1 a)-    abs1 (O a) = O (abs1 a)-    signum1 (O a) = O (signum1 a)-    O a /! O b = O (a /! b) -    recip1 (O a) = O (recip1 a)-    fromRational1 = O . lift . fromRational1-    toRational1 (O a) = toRational1 a-    pi1 = O pi1-    exp1 (O a) = O (exp1 a)-    log1 (O a) = O (log1 a) -    sqrt1 (O a) = O (sqrt1 a)-    O a **! O b = O (a **! b)-    logBase1 (O a) (O b) = O (logBase1 a b)-    sin1 (O a) = O (sin1 a)-    cos1 (O a) = O (cos1 a)-    tan1 (O a) = O (tan1 a)-    asin1 (O a) = O (asin1 a)-    acos1 (O a) = O (acos1 a)-    atan1 (O a) = O (atan1 a)-    sinh1 (O a) = O (sinh1 a)-    cosh1 (O a) = O (cosh1 a)-    tanh1 (O a) = O (tanh1 a)-    asinh1 (O a) = O (asinh1 a)-    acosh1 (O a) = O (acosh1 a)-    atanh1 (O a) = O (atanh1 a)-    properFraction1 (O a) = (b, O c) where+instance (Mode f, Mode g) => Mode (ComposeMode f g) where+    lift = ComposeMode . lift . lift+    ComposeMode a <+> ComposeMode b = ComposeMode (a <+> b) +    a *^ ComposeMode b = ComposeMode (lift a *^ b) +    ComposeMode a ^* b = ComposeMode (a ^* lift b)+    ComposeMode a ^/ b = ComposeMode (a ^/ lift b)++instance (Mode f, Mode g) => Lifted (ComposeMode f g) where+    showsPrec1 n (ComposeMode a) = showsPrec1 n a+    ComposeMode a ==! ComposeMode b  = a ==! b+    compare1 (ComposeMode a) (ComposeMode b) = compare1 a b+    fromInteger1 = ComposeMode . lift . fromInteger1+    ComposeMode a +! ComposeMode b = ComposeMode (a +! b)+    ComposeMode a -! ComposeMode b = ComposeMode (a -! b)+    ComposeMode a *! ComposeMode b = ComposeMode (a *! b)+    negate1 (ComposeMode a) = ComposeMode (negate1 a)+    abs1 (ComposeMode a) = ComposeMode (abs1 a)+    signum1 (ComposeMode a) = ComposeMode (signum1 a)+    ComposeMode a /! ComposeMode b = ComposeMode (a /! b) +    recip1 (ComposeMode a) = ComposeMode (recip1 a)+    fromRational1 = ComposeMode . lift . fromRational1+    toRational1 (ComposeMode a) = toRational1 a+    pi1 = ComposeMode pi1+    exp1 (ComposeMode a) = ComposeMode (exp1 a)+    log1 (ComposeMode a) = ComposeMode (log1 a) +    sqrt1 (ComposeMode a) = ComposeMode (sqrt1 a)+    ComposeMode a **! ComposeMode b = ComposeMode (a **! b)+    logBase1 (ComposeMode a) (ComposeMode b) = ComposeMode (logBase1 a b)+    sin1 (ComposeMode a) = ComposeMode (sin1 a)+    cos1 (ComposeMode a) = ComposeMode (cos1 a)+    tan1 (ComposeMode a) = ComposeMode (tan1 a)+    asin1 (ComposeMode a) = ComposeMode (asin1 a)+    acos1 (ComposeMode a) = ComposeMode (acos1 a)+    atan1 (ComposeMode a) = ComposeMode (atan1 a)+    sinh1 (ComposeMode a) = ComposeMode (sinh1 a)+    cosh1 (ComposeMode a) = ComposeMode (cosh1 a)+    tanh1 (ComposeMode a) = ComposeMode (tanh1 a)+    asinh1 (ComposeMode a) = ComposeMode (asinh1 a)+    acosh1 (ComposeMode a) = ComposeMode (acosh1 a)+    atanh1 (ComposeMode a) = ComposeMode (atanh1 a)+    properFraction1 (ComposeMode a) = (b, ComposeMode c) where         (b, c) = properFraction1 a-    truncate1 (O a) = truncate1 a-    round1 (O a) = round1 a-    ceiling1 (O a) = ceiling1 a-    floor1 (O a) = floor1 a-    floatRadix1 (O a) = floatRadix1 a-    floatDigits1 (O a) = floatDigits1 a-    floatRange1 (O a) = floatRange1 a-    decodeFloat1 (O a) = decodeFloat1 a-    encodeFloat1 m e = O (encodeFloat1 m e)-    exponent1 (O a) = exponent1 a-    significand1 (O a) = O (significand1 a)-    scaleFloat1 n (O a) = O (scaleFloat1 n a)-    isNaN1 (O a) = isNaN1 a -    isInfinite1 (O a) = isInfinite1 a-    isDenormalized1 (O a) = isDenormalized1 a-    isNegativeZero1 (O a) = isNegativeZero1 a-    isIEEE1 (O a) = isIEEE1 a-    atan21 (O a) (O b) = O (atan21 a b)-    succ1 (O a) = O (succ1 a)-    pred1 (O a) = O (pred1 a)-    toEnum1 n = O (toEnum1 n)-    fromEnum1 (O a) = fromEnum1 a-    enumFrom1 (O a) = map O $ enumFrom1 a-    enumFromThen1 (O a) (O b) = map O $ enumFromThen1 a b-    enumFromTo1 (O a) (O b) = map O $ enumFromTo1 a b-    enumFromThenTo1 (O a) (O b) (O c) = map O $ enumFromThenTo1 a b c-    minBound1 = O minBound1-    maxBound1 = O maxBound1+    truncate1 (ComposeMode a) = truncate1 a+    round1 (ComposeMode a) = round1 a+    ceiling1 (ComposeMode a) = ceiling1 a+    floor1 (ComposeMode a) = floor1 a+    floatRadix1 (ComposeMode a) = floatRadix1 a+    floatDigits1 (ComposeMode a) = floatDigits1 a+    floatRange1 (ComposeMode a) = floatRange1 a+    decodeFloat1 (ComposeMode a) = decodeFloat1 a+    encodeFloat1 m e = ComposeMode (encodeFloat1 m e)+    exponent1 (ComposeMode a) = exponent1 a+    significand1 (ComposeMode a) = ComposeMode (significand1 a)+    scaleFloat1 n (ComposeMode a) = ComposeMode (scaleFloat1 n a)+    isNaN1 (ComposeMode a) = isNaN1 a +    isInfinite1 (ComposeMode a) = isInfinite1 a+    isDenormalized1 (ComposeMode a) = isDenormalized1 a+    isNegativeZero1 (ComposeMode a) = isNegativeZero1 a+    isIEEE1 (ComposeMode a) = isIEEE1 a+    atan21 (ComposeMode a) (ComposeMode b) = ComposeMode (atan21 a b)+    succ1 (ComposeMode a) = ComposeMode (succ1 a)+    pred1 (ComposeMode a) = ComposeMode (pred1 a)+    toEnum1 n = ComposeMode (toEnum1 n)+    fromEnum1 (ComposeMode a) = fromEnum1 a+    enumFrom1 (ComposeMode a) = map ComposeMode $ enumFrom1 a+    enumFromThen1 (ComposeMode a) (ComposeMode b) = map ComposeMode $ enumFromThen1 a b+    enumFromTo1 (ComposeMode a) (ComposeMode b) = map ComposeMode $ enumFromTo1 a b+    enumFromThenTo1 (ComposeMode a) (ComposeMode b) (ComposeMode c) = map ComposeMode $ enumFromThenTo1 a b c+    minBound1 = ComposeMode minBound1+    maxBound1 = ComposeMode maxBound1  -- deriveNumeric (conT `appT` varT (mkName "f") `appT` varT (mkName "g")) 
Numeric/AD/Newton.hs view
@@ -106,11 +106,11 @@ -- -- > take 10 $ extremum cos 1 -- convert to 0  extremum :: Fractional a => (forall s. Mode s => AD s a -> AD s a) -> a -> [a]-extremum f = findZero (diff (decompose . f . compose))+extremum f = findZero (diff (decomposeMode . f . composeMode)) {-# INLINE extremum #-}  extremumM :: (Monad m, Fractional a) => (forall s. Mode s => AD s a -> m (AD s a)) -> a -> MList m a-extremumM f = findZeroM (diffM (liftM decompose . f . compose))+extremumM f = findZeroM (diffM (liftM decomposeMode . f . composeMode)) {-# INLINE extremumM #-}  -- | The 'gradientDescent' function performs a multivariate
Numeric/AD/Reverse.hs view
@@ -29,6 +29,11 @@     , jacobian'     , jacobianWith     , jacobianWith'+    -- * Hessian+    , hessian+    , hessianM+    , hessianTensor+         -- * Derivatives     , diff     , diff'@@ -57,6 +62,7 @@  import Numeric.AD.Classes import Numeric.AD.Internal+import Numeric.AD.Internal.Composition import Numeric.AD.Internal.Reverse  -- | The 'grad' function calculates the gradient of a non-scalar-to-scalar function with 'Reverse' AD in a single pass.@@ -193,3 +199,20 @@ gradWithM' :: (Traversable f, Monad m, Num a) => (a -> a -> b) -> (forall s. Mode s => f (AD s a) -> m (AD s a)) -> f a -> m (a, f b) gradWithM' g f = unwrapMonad . jacobianWith' g (WrapMonad . f) +-- | Compute the hessian via the jacobian of the gradient. gradient is computed in reverse mode and then the jacobian is computed in reverse mode.+--+-- However, since the @'grad f :: f a -> f a'@ is square this is not as fast as using the forward-mode Jacobian of a reverse mode gradient provided by 'Numeric.AD.hessian' in "Numeric.AD".+hessian :: (Traversable f, Num a) => (forall s. Mode s => f (AD s a) -> AD s a) -> f a -> f (f a)+hessian f = jacobian (grad (decomposeMode . f . fmap composeMode))++-- | Compute the order 3 Hessian tensor on a non-scalar-to-non-scalar function via the forward-mode Jacobian of the mixed-mode Jacobian of the function.+--+-- While this is less efficient than 'Numeric.AD.hessianTensor' from "Numeric.AD" or 'Numeric.AD.Forward.hessianTensor' from "Numeric.AD.Forward", the type signature is more permissive with regards to the output non-scalar, and it may be more efficient if only a few coefficients of the result are consumed.+hessianTensor :: (Traversable f, Functor g, Num a) => (forall s. Mode s => f (AD s a) -> g (AD s a)) -> f a -> g (f (f a))+hessianTensor f = decomposeFunctor . jacobian (ComposeFunctor . jacobian (fmap decomposeMode . f . fmap composeMode))++-- | Compute the hessian via the reverse-mode jacobian of the reverse-mode gradient of a non-scalar-to-scalar monadic action. +--+-- While this is less efficient than 'Numeric.AD.hessianTensor' from "Numeric.AD" or 'Numeric.AD.Forward.hessianTensor' from "Numeric.AD.Forward", the type signature is more permissive with regards to the output non-scalar, and it may be more efficient if only a few coefficients of the result are consumed.+hessianM :: (Traversable f, Monad m, Num a) => (forall s. Mode s => f (AD s a) -> m (AD s a)) -> f a -> m (f (f a))+hessianM f = unwrapMonad . hessianTensor (WrapMonad . f)
ad.cabal view
@@ -1,5 +1,5 @@ Name:         ad-Version:      0.21+Version:      0.22 License:      BSD3 License-File: LICENSE Copyright:    Edward Kmett 2010