ad 0.15 → 0.17
raw patch · 10 files changed
+306/−284 lines, 10 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
- Numeric.AD: diff2 :: (Num a) => (forall s. (Mode s) => AD s a -> AD s a) -> a -> (a, a)
- Numeric.AD: diff2FU :: (Traversable f, Num a) => (forall s. (Mode s) => f (AD s a) -> AD s a) -> f a -> (a, f a)
- Numeric.AD: diff2UF :: (Functor f, Num a) => (forall s. (Mode s) => AD s a -> f (AD s a)) -> a -> f (a, a)
- Numeric.AD: diff2UU :: (Num a) => (forall s. (Mode s) => AD s a -> AD s a) -> a -> (a, a)
- Numeric.AD: diffFU :: (Traversable f, Num a) => (forall s. (Mode s) => f (AD s a) -> AD s a) -> f a -> f a
- Numeric.AD: diffUF :: (Functor f, Num a) => (forall s. (Mode s) => AD s a -> f (AD s a)) -> a -> f a
- Numeric.AD: diffUU :: (Num a) => (forall s. (Mode s) => AD s a -> AD s a) -> a -> a
- Numeric.AD: diffs0UF :: (Functor f, Num a) => (forall s. (Mode s) => AD s a -> f (AD s a)) -> a -> f [a]
- Numeric.AD: diffs0UU :: (Num a) => (forall s. (Mode s) => AD s a -> AD s a) -> a -> [a]
- Numeric.AD: diffsUF :: (Functor f, Num a) => (forall s. (Mode s) => AD s a -> f (AD s a)) -> a -> f [a]
- Numeric.AD: diffsUU :: (Num a) => (forall s. (Mode s) => AD s a -> AD s a) -> a -> [a]
- Numeric.AD: grad2 :: (Traversable f, Num a) => (forall s. (Mode s) => f (AD s a) -> AD s a) -> f a -> (a, f a)
- Numeric.AD: gradWith2 :: (Traversable f, Num a) => (a -> a -> b) -> (forall s. (Mode s) => f (AD s a) -> AD s a) -> f a -> (a, f b)
- Numeric.AD: 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)
- Numeric.AD: jacobianWith2 :: (Traversable f, Traversable g, Num a) => (a -> a -> b) -> (forall s. (Mode s) => f (AD s a) -> g (AD s a)) -> f a -> g (a, f b)
- Numeric.AD.Directed: diff2 :: (Num a) => Direction -> (forall s. (Mode s) => AD s a -> AD s a) -> a -> (a, a)
- Numeric.AD.Directed: diff2UU :: (Num a) => Direction -> (forall s. (Mode s) => AD s a -> AD s a) -> a -> (a, a)
- Numeric.AD.Directed: diffUU :: (Num a) => Direction -> (forall s. (Mode s) => AD s a -> AD s a) -> a -> a
- Numeric.AD.Directed: grad2 :: (Traversable f, Num a) => Direction -> (forall s. (Mode s) => f (AD s a) -> AD s a) -> f a -> (a, f a)
- Numeric.AD.Directed: jacobian2 :: (Traversable f, Traversable g, Num a) => Direction -> (forall s. (Mode s) => f (AD s a) -> g (AD s a)) -> f a -> g (a, f a)
- Numeric.AD.Forward: diff2 :: (Num a) => (forall s. (Mode s) => AD s a -> AD s a) -> a -> (a, a)
- Numeric.AD.Forward: diff2MU :: (Functor f, Num a) => (forall s. (Mode s) => f (AD s a) -> AD s a) -> f (a, a) -> (a, a)
- Numeric.AD.Forward: diff2UF :: (Functor f, Num a) => (forall s. (Mode s) => AD s a -> f (AD s a)) -> a -> f (a, a)
- Numeric.AD.Forward: diff2UU :: (Num a) => (forall s. (Mode s) => AD s a -> AD s a) -> a -> (a, a)
- Numeric.AD.Forward: diffMU :: (Functor f, Num a) => (forall s. (Mode s) => f (AD s a) -> AD s a) -> f (a, a) -> a
- Numeric.AD.Forward: diffUF :: (Functor f, Num a) => (forall s. (Mode s) => AD s a -> f (AD s a)) -> a -> f a
- Numeric.AD.Forward: diffUU :: (Num a) => (forall s. (Mode s) => AD s a -> AD s a) -> a -> a
- Numeric.AD.Forward: grad2 :: (Traversable f, Num a) => (forall s. (Mode s) => f (AD s a) -> AD s a) -> f a -> (a, f a)
- Numeric.AD.Forward: gradWith2 :: (Traversable f, Num a) => (a -> a -> b) -> (forall s. (Mode s) => f (AD s a) -> AD s a) -> f a -> (a, f b)
- Numeric.AD.Forward: 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)
- Numeric.AD.Forward: jacobianWith2 :: (Traversable f, Traversable g, Num a) => (a -> a -> b) -> (forall s. (Mode s) => f (AD s a) -> g (AD s a)) -> f a -> g (a, f b)
- Numeric.AD.Internal.Forward: bind2 :: (Traversable f, Num a) => (f (AD Forward a) -> b) -> f a -> (b, f b)
- Numeric.AD.Internal.Forward: bindWith2 :: (Traversable f, Num a) => (a -> b -> c) -> (f (AD Forward a) -> b) -> f a -> (b, f c)
- Numeric.AD.Internal.Reverse: derivative2 :: (Num a) => AD Reverse a -> (a, a)
- Numeric.AD.Internal.Tower: d2 :: (Num a) => [a] -> (a, a)
- Numeric.AD.Reverse: diff2 :: (Num a) => (forall s. (Mode s) => AD s a -> AD s a) -> a -> (a, a)
- Numeric.AD.Reverse: diff2FU :: (Traversable f, Num a) => (forall s. (Mode s) => f (AD s a) -> AD s a) -> f a -> (a, f a)
- Numeric.AD.Reverse: diff2UF :: (Functor f, Num a) => (forall s. (Mode s) => AD s a -> f (AD s a)) -> a -> f (a, a)
- Numeric.AD.Reverse: diff2UU :: (Num a) => (forall s. (Mode s) => AD s a -> AD s a) -> a -> (a, a)
- Numeric.AD.Reverse: diffFU :: (Traversable f, Num a) => (forall s. (Mode s) => f (AD s a) -> AD s a) -> f a -> f a
- Numeric.AD.Reverse: diffUF :: (Functor f, Num a) => (forall s. (Mode s) => AD s a -> f (AD s a)) -> a -> f a
- Numeric.AD.Reverse: diffUU :: (Num a) => (forall s. (Mode s) => AD s a -> AD s a) -> a -> a
- Numeric.AD.Reverse: grad2 :: (Traversable f, Num a) => (forall s. (Mode s) => f (AD s a) -> AD s a) -> f a -> (a, f a)
- Numeric.AD.Reverse: gradWith2 :: (Traversable f, Num a) => (a -> a -> b) -> (forall s. (Mode s) => f (AD s a) -> AD s a) -> f a -> (a, f b)
- Numeric.AD.Reverse: 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)
- Numeric.AD.Reverse: jacobianWith2 :: (Traversable f, Functor g, Num a) => (a -> a -> b) -> (forall s. (Mode s) => f (AD s a) -> g (AD s a)) -> f a -> g (a, f b)
- Numeric.AD.Tower: diff2 :: (Num a) => (forall s. (Mode s) => AD s a -> AD s a) -> a -> (a, a)
- Numeric.AD.Tower: diff2UU :: (Num a) => (forall s. (Mode s) => AD s a -> AD s a) -> a -> (a, a)
- Numeric.AD.Tower: diffUU :: (Num a) => (forall s. (Mode s) => AD s a -> AD s a) -> a -> a
- Numeric.AD.Tower: diffs0UF :: (Functor f, Num a) => (forall s. (Mode s) => AD s a -> f (AD s a)) -> a -> f [a]
- Numeric.AD.Tower: diffs0UU :: (Num a) => (forall s. (Mode s) => AD s a -> AD s a) -> a -> [a]
- Numeric.AD.Tower: diffsUF :: (Functor f, Num a) => (forall s. (Mode s) => AD s a -> f (AD s a)) -> a -> f [a]
- Numeric.AD.Tower: diffsUU :: (Num a) => (forall s. (Mode s) => AD s a -> AD s a) -> a -> [a]
+ Numeric.AD: diff' :: (Num a) => (forall s. (Mode s) => AD s a -> AD s a) -> a -> (a, a)
+ Numeric.AD: diffF :: (Functor f, Num a) => (forall s. (Mode s) => AD s a -> f (AD s a)) -> a -> f a
+ Numeric.AD: diffF' :: (Functor f, Num a) => (forall s. (Mode s) => AD s a -> f (AD s a)) -> a -> f (a, a)
+ Numeric.AD: diffM :: (Monad m, Num a) => (forall s. (Mode s) => AD s a -> m (AD s a)) -> a -> m a
+ Numeric.AD: diffM' :: (Monad m, Num a) => (forall s. (Mode s) => AD s a -> m (AD s a)) -> a -> m (a, a)
+ Numeric.AD: diffs0F :: (Functor f, Num a) => (forall s. (Mode s) => AD s a -> f (AD s a)) -> a -> f [a]
+ Numeric.AD: diffsF :: (Functor f, Num a) => (forall s. (Mode s) => AD s a -> f (AD s a)) -> a -> f [a]
+ Numeric.AD: du :: (Functor f, Num a) => (forall s. (Mode s) => f (AD s a) -> AD s a) -> f (a, a) -> a
+ Numeric.AD: du' :: (Functor f, Num a) => (forall s. (Mode s) => f (AD s a) -> AD s a) -> f (a, a) -> (a, a)
+ Numeric.AD: duF :: (Functor f, Functor g, Num a) => (forall s. (Mode s) => f (AD s a) -> g (AD s a)) -> f (a, a) -> g a
+ Numeric.AD: duF' :: (Functor f, Functor g, Num a) => (forall s. (Mode s) => f (AD s a) -> g (AD s a)) -> f (a, a) -> g (a, a)
+ Numeric.AD: grad' :: (Traversable f, Num a) => (forall s. (Mode s) => f (AD s a) -> AD s a) -> f a -> (a, f a)
+ Numeric.AD: gradM :: (Traversable f, Monad m, Num a) => (forall s. (Mode s) => f (AD s a) -> m (AD s a)) -> f a -> m (f a)
+ Numeric.AD: gradM' :: (Traversable f, Monad m, Num a) => (forall s. (Mode s) => f (AD s a) -> m (AD s a)) -> f a -> m (a, f a)
+ Numeric.AD: gradWith' :: (Traversable f, Num a) => (a -> a -> b) -> (forall s. (Mode s) => f (AD s a) -> AD s a) -> f a -> (a, f b)
+ Numeric.AD: 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 (f b)
+ Numeric.AD: 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)
+ Numeric.AD: jacobian' :: (Traversable f, Traversable g, Num a) => (forall s. (Mode s) => f (AD s a) -> g (AD s a)) -> f a -> g (a, f a)
+ Numeric.AD: jacobianWith' :: (Traversable f, Traversable g, Num a) => (a -> a -> b) -> (forall s. (Mode s) => f (AD s a) -> g (AD s a)) -> f a -> g (a, f b)
+ Numeric.AD: maclaurin :: (Fractional a) => (forall s. (Mode s) => AD s a -> AD s a) -> a -> [a]
+ Numeric.AD: maclaurin0 :: (Fractional a) => (forall s. (Mode s) => AD s a -> AD s a) -> a -> [a]
+ Numeric.AD.Directed: diff' :: (Num a) => Direction -> (forall s. (Mode s) => AD s a -> AD s a) -> a -> (a, a)
+ Numeric.AD.Directed: grad' :: (Traversable f, Num a) => Direction -> (forall s. (Mode s) => f (AD s a) -> AD s a) -> f a -> (a, f a)
+ Numeric.AD.Directed: jacobian' :: (Traversable f, Traversable g, Num a) => Direction -> (forall s. (Mode s) => f (AD s a) -> g (AD s a)) -> f a -> g (a, f a)
+ Numeric.AD.Forward: diff' :: (Num a) => (forall s. (Mode s) => AD s a -> AD s a) -> a -> (a, a)
+ Numeric.AD.Forward: diffF :: (Functor f, Num a) => (forall s. (Mode s) => AD s a -> f (AD s a)) -> a -> f a
+ Numeric.AD.Forward: diffF' :: (Functor f, Num a) => (forall s. (Mode s) => AD s a -> f (AD s a)) -> a -> f (a, a)
+ Numeric.AD.Forward: diffM :: (Monad m, Num a) => (forall s. (Mode s) => AD s a -> m (AD s a)) -> a -> m a
+ Numeric.AD.Forward: diffM' :: (Monad m, Num a) => (forall s. (Mode s) => AD s a -> m (AD s a)) -> a -> m (a, a)
+ Numeric.AD.Forward: du :: (Functor f, Num a) => (forall s. (Mode s) => f (AD s a) -> AD s a) -> f (a, a) -> a
+ Numeric.AD.Forward: du' :: (Functor f, Num a) => (forall s. (Mode s) => f (AD s a) -> AD s a) -> f (a, a) -> (a, a)
+ Numeric.AD.Forward: duF :: (Functor f, Functor g, Num a) => (forall s. (Mode s) => f (AD s a) -> g (AD s a)) -> f (a, a) -> g a
+ Numeric.AD.Forward: duF' :: (Functor f, Functor g, Num a) => (forall s. (Mode s) => f (AD s a) -> g (AD s a)) -> f (a, a) -> g (a, a)
+ Numeric.AD.Forward: grad' :: (Traversable f, Num a) => (forall s. (Mode s) => f (AD s a) -> AD s a) -> f a -> (a, f a)
+ Numeric.AD.Forward: gradWith' :: (Traversable f, Num a) => (a -> a -> b) -> (forall s. (Mode s) => f (AD s a) -> AD s a) -> f a -> (a, f b)
+ Numeric.AD.Forward: jacobian' :: (Traversable f, Traversable g, Num a) => (forall s. (Mode s) => f (AD s a) -> g (AD s a)) -> f a -> g (a, f a)
+ Numeric.AD.Forward: jacobianWith' :: (Traversable f, Traversable g, Num a) => (a -> a -> b) -> (forall s. (Mode s) => f (AD s a) -> g (AD s a)) -> f a -> g (a, f b)
+ Numeric.AD.Internal.Forward: bind' :: (Traversable f, Num a) => (f (AD Forward a) -> b) -> f a -> (b, f b)
+ Numeric.AD.Internal.Forward: bindWith' :: (Traversable f, Num a) => (a -> b -> c) -> (f (AD Forward a) -> b) -> f a -> (b, f c)
+ Numeric.AD.Internal.Reverse: derivative' :: (Num a) => AD Reverse a -> (a, a)
+ Numeric.AD.Internal.Tower: d' :: (Num a) => [a] -> (a, a)
+ Numeric.AD.Reverse: diff' :: (Num a) => (forall s. (Mode s) => AD s a -> AD s a) -> a -> (a, a)
+ Numeric.AD.Reverse: diffF :: (Functor f, Num a) => (forall s. (Mode s) => AD s a -> f (AD s a)) -> a -> f a
+ Numeric.AD.Reverse: diffF' :: (Functor f, Num a) => (forall s. (Mode s) => AD s a -> f (AD s a)) -> a -> f (a, a)
+ Numeric.AD.Reverse: diffM :: (Monad m, Num a) => (forall s. (Mode s) => AD s a -> m (AD s a)) -> a -> m a
+ Numeric.AD.Reverse: diffM' :: (Monad m, Num a) => (forall s. (Mode s) => AD s a -> m (AD s a)) -> a -> m (a, a)
+ Numeric.AD.Reverse: grad' :: (Traversable f, Num a) => (forall s. (Mode s) => f (AD s a) -> AD s a) -> f a -> (a, f a)
+ Numeric.AD.Reverse: gradM :: (Traversable f, Monad m, Num a) => (forall s. (Mode s) => f (AD s a) -> m (AD s a)) -> f a -> m (f a)
+ Numeric.AD.Reverse: gradM' :: (Traversable f, Monad m, Num a) => (forall s. (Mode s) => f (AD s a) -> m (AD s a)) -> f a -> m (a, f a)
+ Numeric.AD.Reverse: gradWith' :: (Traversable f, Num a) => (a -> a -> b) -> (forall s. (Mode s) => f (AD s a) -> AD s a) -> f a -> (a, f b)
+ Numeric.AD.Reverse: 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 (f b)
+ Numeric.AD.Reverse: 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)
+ Numeric.AD.Reverse: jacobian' :: (Traversable f, Functor g, Num a) => (forall s. (Mode s) => f (AD s a) -> g (AD s a)) -> f a -> g (a, f a)
+ Numeric.AD.Reverse: jacobianWith' :: (Traversable f, Functor g, Num a) => (a -> a -> b) -> (forall s. (Mode s) => f (AD s a) -> g (AD s a)) -> f a -> g (a, f b)
+ Numeric.AD.Tower: diff' :: (Num a) => (forall s. (Mode s) => AD s a -> AD s a) -> a -> (a, a)
+ Numeric.AD.Tower: diffs0F :: (Functor f, Num a) => (forall s. (Mode s) => AD s a -> f (AD s a)) -> a -> f [a]
+ Numeric.AD.Tower: diffs0M :: (Monad m, Num a) => (forall s. (Mode s) => AD s a -> m (AD s a)) -> a -> m [a]
+ Numeric.AD.Tower: diffsF :: (Functor f, Num a) => (forall s. (Mode s) => AD s a -> f (AD s a)) -> a -> f [a]
+ Numeric.AD.Tower: diffsM :: (Monad m, Num a) => (forall s. (Mode s) => AD s a -> m (AD s a)) -> a -> m [a]
Files
- Numeric/AD.hs +60/−43
- Numeric/AD/Directed.hs +31/−42
- Numeric/AD/Forward.hs +80/−65
- Numeric/AD/Internal/Forward.hs +6/−6
- Numeric/AD/Internal/Reverse.hs +6/−6
- Numeric/AD/Internal/Tower.hs +6/−6
- Numeric/AD/Newton.hs +6/−6
- Numeric/AD/Reverse.hs +72/−66
- Numeric/AD/Tower.hs +38/−43
- ad.cabal +1/−1
Numeric/AD.hs view
@@ -16,41 +16,49 @@ module Numeric.AD ( -- * Gradients- grad, grad2- , gradWith, gradWith2+ grad, grad'+ , gradWith, gradWith' -- * Jacobians- , jacobian, jacobian2- , jacobianWith, jacobianWith2-- -- * Synonyms- , diff- , diff2- , diffs- , diffs0+ , jacobian, jacobian'+ , jacobianWith, jacobianWith' -- * Derivatives (Forward)- , diffUU- , diffUF-- , diff2UU- , diff2UF+ , diff+ , diffF - -- * Derivatives (Reverse)- , diffFU- , diff2FU+ , diff'+ , diffF' -- * Derivatives (Tower)- , diffsUU- , diffsUF+ , diffs+ , diffsF - , diffs0UU- , diffs0UF+ , diffs0+ , diffs0F + -- * Directional Derivatives (Forward)+ , du+ , du'+ , duF+ , duF'+ -- * Taylor Series (Tower) , taylor , taylor0+ , maclaurin+ , maclaurin0 + -- * Monadic Combinators (Forward)+ , diffM+ , diffM'++ -- * Monadic Combinators (Reverse)+ , gradM+ , gradM'+ , gradWithM+ , gradWithM'+ -- * Exposed Types , AD(..) , Mode(..)@@ -61,50 +69,59 @@ import Control.Applicative import Numeric.AD.Classes (Mode(..)) 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.Reverse (diffFU, diff2FU, grad, grad2, gradWith, gradWith2)+import Numeric.AD.Forward (diff, diff', diffF, diffF', du, du', duF, duF', diffM, diffM') +import Numeric.AD.Tower (diffsF, diffs0F , diffs, diffs0, taylor, taylor0, maclaurin, maclaurin0)+import Numeric.AD.Reverse (grad, grad', gradWith, gradWith', gradM, gradM', gradWithM, gradWithM') import qualified Numeric.AD.Forward as Forward import qualified Numeric.AD.Reverse as Reverse --- | Calculate the Jacobian of a non-scalar-to-non-scalar function, automatically choosing between forward and reverse mode AD based on the number of inputs and outputs+-- | Calculate the Jacobian of a non-scalar-to-non-scalar function, automatically choosing between forward and reverse mode AD based on the number of inputs and outputs.+--+-- If you need to support functions where the output is only a 'Functor' or 'Monad', consider 'Numeric.AD.Reverse.jacobian' or 'Numeric.AD.Reverse.gradM' from "Numeric.AD.Reverse". 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 bs = snd <$> jacobian2 f bs+jacobian f bs = snd <$> jacobian' f bs {-# INLINE jacobian #-} --- | Calculate the answer and Jacobian of a non-scalar-to-non-scalar function, automatically choosing between forward- and reverse- mode AD based on the relative, number of inputs and outputs. If you need to support functions where the output is only a 'Functor', consider using 'jacobianT' from "Numeric.AD.Forward" or 'jacobian2' from "Numeric.AD.Reverse" directly.-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 bs | n == 0 = fmap (\x -> (unprobe x, bs)) as- | n > m = Reverse.jacobian2 f bs- | otherwise = Forward.jacobian2 f bs+-- | Calculate both the answer and Jacobian of a non-scalar-to-non-scalar function, automatically choosing between forward- and reverse- mode AD based on the relative, number of inputs and outputs.+--+-- If you need to support functions where the output is only a 'Functor' or 'Monad', consider 'Numeric.AD.Reverse.jacobian'' or 'Numeric.AD.Reverse.gradM'' from "Numeric.AD.Reverse".+jacobian' :: (Traversable f, Traversable g, Num a) => (forall s. Mode s => f (AD s a) -> g (AD s a)) -> f a -> g (a, f a)+jacobian' f bs | n == 0 = fmap (\x -> (unprobe x, bs)) as+ | n > m = Reverse.jacobian' f bs+ | otherwise = Forward.jacobian' f bs where as = f (probed bs) n = size bs m = size as size :: Foldable f => f a -> Int size = foldr' (\_ b -> 1 + b) 0-{-# INLINE jacobian2 #-}+{-# INLINE jacobian' #-} -- | @'jacobianWith' g f@ calculates the Jacobian of a non-scalar-to-non-scalar function, automatically choosing between forward and reverse mode AD based on the number of inputs and outputs.--- --- The resulting Jacobian matrix is then recombined element-wise with the input using @g@. +--+-- The resulting Jacobian matrix is then recombined element-wise with the input using @g@.+--+-- If you need to support functions where the output is only a 'Functor' or 'Monad', consider 'Numeric.AD.Reverse.jacobianWith' or 'Numeric.AD.Reverse.gradWithM' from "Numeric.AD.Reverse". jacobianWith :: (Traversable f, Traversable g, Num a) => (a -> a -> b) -> (forall s. Mode s => f (AD s a) -> g (AD s a)) -> f a -> g (f b)-jacobianWith g f bs = snd <$> jacobianWith2 g f bs+jacobianWith g f bs = snd <$> jacobianWith' g f bs {-# INLINE jacobianWith #-} --- | @'jacobianWith2' g f@ calculates the answer and Jacobian of a non-scalar-to-non-scalar function, automatically choosing between forward and reverse mode AD based on the number of inputs and outputs.+-- | @'jacobianWith'' g f@ calculates the answer and Jacobian of a non-scalar-to-non-scalar function, automatically choosing between forward and reverse mode AD based on the number of inputs and outputs. ----- The resulting Jacobian matrix is then recombined element-wise with the input using @g@. -jacobianWith2 :: (Traversable f, Traversable g, Num a) => (a -> a -> b) -> (forall s. Mode s => f (AD s a) -> g (AD s a)) -> f a -> g (a, f b)-jacobianWith2 g f bs +-- The resulting Jacobian matrix is then recombined element-wise with the input using @g@.+--+-- If you need to support functions where the output is only a 'Functor' or 'Monad', consider 'Numeric.AD.Reverse.jacobianWith'' or 'Numeric.AD.Reverse.gradWithM'' from "Numeric.AD.Reverse".+jacobianWith' :: (Traversable f, Traversable g, Num a) => (a -> a -> b) -> (forall s. Mode s => f (AD s a) -> g (AD s a)) -> f a -> g (a, f b)+jacobianWith' g f bs | n == 0 = fmap (\x -> (unprobe x, undefined <$> bs)) as- | n > m = Reverse.jacobianWith2 g f bs- | otherwise = Forward.jacobianWith2 g f bs+ | n > m = Reverse.jacobianWith' g f bs+ | otherwise = Forward.jacobianWith' g f bs where as = f (probed bs) n = size bs m = size as size :: Foldable f => f a -> Int size = foldr' (\_ b -> 1 + b) 0-{-# INLINE jacobianWith2 #-}+{-# INLINE jacobianWith' #-}+
Numeric/AD/Directed.hs view
@@ -14,18 +14,15 @@ module Numeric.AD.Directed (- -- * Derivatives- diffUU- , diff2UU- -- * Common access patterns- , diff- , diff2+ -- * Gradients+ grad+ , grad' -- * Jacobians , jacobian- , jacobian2- -- * Gradients- , grad- , grad2+ , jacobian'+ -- * Derivatives+ , diff+ , diff' -- * Exposed Types , Direction(..) , Mode(..)@@ -51,53 +48,45 @@ | 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-diffUU Forward = F.diffUU-diffUU Reverse = R.diffUU-diffUU Tower = T.diffUU-diffUU Mixed = F.diffUU-{-# INLINE diffUU #-}--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-diff2UU Mixed = F.diff2UU-{-# INLINE diff2UU #-}- diff :: Num a => Direction -> (forall s. Mode s => AD s a -> AD s a) -> a -> a-diff = diffUU+diff Forward = F.diff+diff Reverse = R.diff+diff Tower = T.diff+diff Mixed = F.diff {-# INLINE diff #-} -diff2 :: Num a => Direction -> (forall s. Mode s => AD s a -> AD s a) -> a -> (a, a)-diff2 = diff2UU-{-# INLINE diff2 #-}+diff' :: Num a => Direction -> (forall s. Mode s => AD s a -> AD s a) -> a -> (a, a)+diff' Forward = F.diff'+diff' Reverse = R.diff'+diff' Tower = T.diff'+diff' Mixed = F.diff'+{-# INLINE diff' #-} jacobian :: (Traversable f, Traversable g, Num a) => Direction -> (forall s. Mode s => f (AD s a) -> g (AD s a)) -> f a -> g (f a) jacobian Forward = F.jacobian jacobian Reverse = R.jacobian-jacobian Tower = error "jacobian Tower: unimplemented"+jacobian Tower = F.jacobian -- error "jacobian Tower: unimplemented" jacobian Mixed = M.jacobian {-# INLINE jacobian #-} -jacobian2 :: (Traversable f, Traversable g, Num a) => Direction -> (forall s. Mode s => f (AD s a) -> g (AD s a)) -> f a -> g (a, f a)-jacobian2 Forward = F.jacobian2-jacobian2 Reverse = R.jacobian2-jacobian2 Tower = error "jacobian2 Tower: unimplemented"-jacobian2 Mixed = M.jacobian2-{-# INLINE jacobian2 #-}+jacobian' :: (Traversable f, Traversable g, Num a) => Direction -> (forall s. Mode s => f (AD s a) -> g (AD s a)) -> f a -> g (a, f a)+jacobian' Forward = F.jacobian'+jacobian' Reverse = R.jacobian'+jacobian' Tower = F.jacobian' -- error "jacobian' Tower: unimplemented"+jacobian' Mixed = M.jacobian'+{-# INLINE jacobian' #-} grad :: (Traversable f, Num a) => Direction -> (forall s. Mode s => f (AD s a) -> AD s a) -> f a -> f a grad Forward = F.grad grad Reverse = R.grad-grad Tower = error "grad Tower: unimplemented"+grad Tower = F.grad -- error "grad Tower: unimplemented" grad Mixed = M.grad {-# INLINE grad #-} -grad2 :: (Traversable f, Num a) => Direction -> (forall s. Mode s => f (AD s a) -> AD s a) -> f a -> (a, f a)-grad2 Forward = F.grad2-grad2 Reverse = R.grad2-grad2 Tower = error "grad2 Tower: unimplemented"-grad2 Mixed = M.grad2-{-# INLINE grad2 #-}+grad' :: (Traversable f, Num a) => Direction -> (forall s. Mode s => f (AD s a) -> AD s a) -> f a -> (a, f a)+grad' Forward = F.grad'+grad' Reverse = R.grad'+grad' Tower = F.grad' -- error "grad' Tower: unimplemented"+grad' Mixed = M.grad'+{-# INLINE grad' #-}
Numeric/AD/Forward.hs view
@@ -16,27 +16,30 @@ ( -- * Gradient grad- , grad2+ , grad' , gradWith- , gradWith2+ , gradWith' -- * Jacobian , jacobian- , jacobian2- , jacobianT+ , jacobian' , jacobianWith- , jacobianWith2+ , jacobianWith'+ -- * Transposed Jacobian+ , jacobianT , jacobianWithT -- * Derivatives- , diffUU- , diff2UU- , diffUF- , diff2UF- -- * Directional Derivatives- , diffMU - , diff2MU- -- * Synonyms , diff- , diff2+ , diff'+ , diffF+ , diffF'+ -- * Directional Derivatives+ , du+ , du'+ , duF+ , duF'+ -- * Monadic Combinators+ , diffM+ , diffM' -- * Exposed Types , AD(..) , Mode(..)@@ -44,103 +47,115 @@ import Data.Traversable (Traversable) import Control.Applicative+import Control.Monad (liftM) import Numeric.AD.Classes import Numeric.AD.Internal import Numeric.AD.Internal.Forward -diffMU :: (Functor f, Num a) => (forall s. Mode s => f (AD s a) -> AD s a) -> f (a, a) -> a-diffMU f = tangent . f . fmap (uncurry bundle)-{-# INLINE diffMU #-}+du :: (Functor f, Num a) => (forall s. Mode s => f (AD s a) -> AD s a) -> f (a, a) -> a+du f = tangent . f . fmap (uncurry bundle)+{-# INLINE du #-} -diff2MU :: (Functor f, Num a) => (forall s. Mode s => f (AD s a) -> AD s a) -> f (a, a) -> (a, a)-diff2MU f = unbundle . f . fmap (uncurry bundle)-{-# INLINE diff2MU #-}+du' :: (Functor f, Num a) => (forall s. Mode s => f (AD s a) -> AD s a) -> f (a, a) -> (a, a)+du' f = unbundle . f . fmap (uncurry bundle)+{-# INLINE du' #-} --- | The 'diff2' function calculates the first derivative of scalar-to-scalar function by 'Forward' 'AD'+duF :: (Functor f, Functor g, Num a) => (forall s. Mode s => f (AD s a) -> g (AD s a)) -> f (a, a) -> g a+duF f = fmap tangent . f . fmap (uncurry bundle)+{-# INLINE duF #-}++duF' :: (Functor f, Functor g, Num a) => (forall s. Mode s => f (AD s a) -> g (AD s a)) -> f (a, a) -> g (a, a)+duF' f = fmap unbundle . f . fmap (uncurry bundle)+{-# INLINE duF' #-}++-- | The 'diff' function calculates the first derivative of a scalar-to-scalar function by forward-mode 'AD'+--+-- > diff sin == cos diff :: Num a => (forall s. Mode s => AD s a -> AD s a) -> a -> a-diff = diffUU+diff f a = tangent $ apply f a {-# 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 = diff2UU-{-# INLINE diff2 #-}+-- | The 'd'UU' function calculates the result and first derivative of scalar-to-scalar function by F'orward' 'AD'+-- +-- > d' sin == sin &&& cos+-- > d' f = f &&& d f+diff' :: Num a => (forall s. Mode s => AD s a -> AD s a) -> a -> (a, a)+diff' f a = unbundle $ apply f a+{-# INLINE diff' #-} --- | The 'diffUU' function calculates the first derivative of a scalar-to-scalar function by 'Forward' 'AD'-diffUU :: Num a => (forall s. Mode s => AD s a -> AD s a) -> a -> a-diffUU f a = tangent $ apply f a-{-# INLINE diffUU #-}+-- | The 'diffF' function calculates the first derivative of scalar-to-nonscalar function by F'orward' 'AD'+diffF :: (Functor f, Num a) => (forall s. Mode s => AD s a -> f (AD s a)) -> a -> f a+diffF f a = tangent <$> apply f a+{-# INLINE diffF #-} --- | 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 f a = unbundle $ apply f a-{-# INLINE diff2UU #-}+-- | The 'diffF'' function calculates the result and first derivative of a scalar-to-non-scalar function by F'orward' 'AD'+diffF' :: (Functor f, Num a) => (forall s. Mode s => AD s a -> f (AD s a)) -> a -> f (a, a)+diffF' f a = unbundle <$> apply f a+{-# INLINE diffF' #-} --- | The 'diffUF' function calculates the first derivative of scalar-to-nonscalar function by 'Forward' 'AD'-diffUF :: (Functor f, Num a) => (forall s. Mode s => AD s a -> f (AD s a)) -> a -> f a-diffUF f a = tangent <$> apply f a-{-# INLINE diffUF #-}+-- | The 'dUM' function calculates the first derivative of scalar-to-scalar monadic function by F'orward' 'AD'+diffM :: (Monad m, Num a) => (forall s. Mode s => AD s a -> m (AD s a)) -> a -> m a+diffM f a = tangent `liftM` apply f a+{-# INLINE diffM #-} --- | 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 f a = unbundle <$> apply f a-{-# INLINE diff2UF #-}+-- | The 'd'UM' function calculates the result and first derivative of a scalar-to-scalar monadic function by F'orward' 'AD'+diffM' :: (Monad m, Num a) => (forall s. Mode s => AD s a -> m (AD s a)) -> a -> m (a, a)+diffM' f a = unbundle `liftM` apply f a+{-# INLINE diffM' #-} -- | A fast, simple transposed Jacobian computed with forward-mode AD. jacobianT :: (Traversable f, Functor g, Num a) => (forall s. Mode s => f (AD s a) -> g (AD s a)) -> f a -> f (g a) jacobianT f = bind (fmap tangent . f)--- jacobianT f as = fmap tangent <$> bind f as {-# INLINE jacobianT #-} -- | A fast, simple transposed Jacobian computed with forward-mode AD. jacobianWithT :: (Traversable f, Functor g, Num a) => (a -> a -> b) -> (forall s. Mode s => f (AD s a) -> g (AD s a)) -> f a -> f (g b)-jacobianWithT g f = bindWith g' f - where g' a ga = g a . tangent <$> ga +jacobianWithT g f = bindWith g' f+ where g' a ga = g a . tangent <$> ga {-# INLINE jacobianWithT #-} 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+ (p, t) = bind' (fmap tangent . f) as {-# INLINE jacobian #-} jacobianWith :: (Traversable f, Traversable g, Num a) => (a -> a -> b) -> (forall s. Mode s => f (AD s a) -> g (AD s a)) -> f a -> g (f b) jacobianWith g f as = transposeWith (const id) t p where- (p, t) = bindWith2 g' f as- g' a ga = g a . tangent <$> ga + (p, t) = bindWith' g' f as+ g' a ga = g a . tangent <$> ga {-# INLINE jacobianWith #-} -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+jacobian' :: (Traversable f, Traversable g, Num a) => (forall s. Mode s => f (AD s a) -> g (AD s a)) -> f a -> g (a, f a)+jacobian' f as = transposeWith row t p where- (p, t) = bind2 f as+ (p, t) = bind' f as row x as' = (primal x, tangent <$> as')-{-# INLINE jacobian2 #-}+{-# INLINE jacobian' #-} -jacobianWith2 :: (Traversable f, Traversable g, Num a) => (a -> a -> b) -> (forall s. Mode s => f (AD s a) -> g (AD s a)) -> f a -> g (a, f b)-jacobianWith2 g f as = transposeWith row t p+jacobianWith' :: (Traversable f, Traversable g, Num a) => (a -> a -> b) -> (forall s. Mode s => f (AD s a) -> g (AD s a)) -> f a -> g (a, f b)+jacobianWith' g f as = transposeWith row t p where- (p, t) = bindWith2 g' f as+ (p, t) = bindWith' g' f as row x as' = (primal x, as')- g' a ga = g a . tangent <$> ga -{-# INLINE jacobianWith2 #-}+ g' a ga = g a . tangent <$> ga+{-# INLINE jacobianWith' #-} grad :: (Traversable f, Num a) => (forall s. Mode s => f (AD s a) -> AD s a) -> f a -> f a grad f = bind (tangent . f) {-# INLINE grad #-} --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)+grad' :: (Traversable f, Num a) => (forall s. Mode s => f (AD s a) -> AD s a) -> f a -> (a, f a)+grad' f as = (primal b, tangent <$> bs) where- (b, bs) = bind2 f as-{-# INLINE grad2 #-}+ (b, bs) = bind' f as+{-# INLINE grad' #-} gradWith :: (Traversable f, Num a) => (a -> a -> b) -> (forall s. Mode s => f (AD s a) -> AD s a) -> f a -> f b gradWith g f = bindWith g (tangent . f) {-# INLINE gradWith #-} -gradWith2 :: (Traversable f, Num a) => (a -> a -> b) -> (forall s. Mode s => f (AD s a) -> AD s a) -> f a -> (a, f b)-gradWith2 g f = bindWith2 g (tangent . f)-{-# INLINE gradWith2 #-}+gradWith' :: (Traversable f, Num a) => (a -> a -> b) -> (forall s. Mode s => f (AD s a) -> AD s a) -> f a -> (a, f b)+gradWith' g f = bindWith' g (tangent . f)+{-# INLINE gradWith' #-}
Numeric/AD/Internal/Forward.hs view
@@ -20,9 +20,9 @@ , unbundle , apply , bind- , bind2+ , bind' , bindWith- , bindWith2+ , bindWith' , transposeWith ) where @@ -96,8 +96,8 @@ outer !i _ = (i + 1, f $ snd $ mapAccumL (inner i) 0 as) 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+bind' :: (Traversable f, Num a) => (f (AD Forward a) -> b) -> f a -> (b, f b)+bind' 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)@@ -110,8 +110,8 @@ outer !i a = (i + 1, g a $ f $ snd $ mapAccumL (inner i) 0 as) inner !i !j a = (j + 1, bundle a $ if i == j then 1 else 0) -bindWith2 :: (Traversable f, Num a) => (a -> b -> c) -> (f (AD Forward a) -> b) -> f a -> (b, f c)-bindWith2 g f as = dropIx $ mapAccumL outer (0 :: Int, b0) as+bindWith' :: (Traversable f, Num a) => (a -> b -> c) -> (f (AD Forward a) -> b) -> f a -> (b, f c)+bindWith' g f as = dropIx $ mapAccumL outer (0 :: Int, b0) as where outer (!i, _) a = let b = f $ snd $ mapAccumL (inner i) (0 :: Int) as in ((i + 1, b), g a b) inner !i !j a = (j + 1, bundle a $ if i == j then 1 else 0)
Numeric/AD/Internal/Reverse.hs view
@@ -24,7 +24,7 @@ , partialArray , partialMap , derivative- , derivative2+ , derivative' , Var(..) , bind , unbind@@ -118,9 +118,9 @@ derivative = sum . map snd . partials {-# INLINE derivative #-} -derivative2 :: Num a => AD Reverse a -> (a, a)-derivative2 r = (primal r, derivative r)-{-# INLINE derivative2 #-}+derivative' :: Num a => AD Reverse a -> (a, a)+derivative' r = (primal r, derivative r)+{-# INLINE derivative' #-} -- | back propagate sensitivities along a tape. backPropagate :: Num a => (Vertex -> (Tape a Int, Int, [Int])) -> STArray s Int a -> Vertex -> ST s ()@@ -204,10 +204,10 @@ unbind xs ys = fmap (\v -> ys ! varId v) xs unbindWith :: (Functor f, Var v, Num a) => (a -> b -> c) -> f (v a) -> Array Int b -> f c-unbindWith f xs ys = fmap (\v -> f (primal v) (ys ! varId v)) xs +unbindWith f xs ys = fmap (\v -> f (primal v) (ys ! varId v)) xs unbindMap :: (Functor f, Var v, Num a) => f (v a) -> IntMap a -> f a unbindMap xs ys = fmap (\v -> findWithDefault 0 (varId v) ys) xs unbindMapWithDefault :: (Functor f, Var v, Num a) => b -> (a -> b -> c) -> f (v a) -> IntMap b -> f c-unbindMapWithDefault z f xs ys = fmap (\v -> f (primal v) $ findWithDefault z (varId v) ys) xs +unbindMapWithDefault z f xs ys = fmap (\v -> f (primal v) $ findWithDefault z (varId v) ys) xs
Numeric/AD/Internal/Tower.hs view
@@ -14,7 +14,7 @@ ( Tower(..) , zeroPad , d- , d2+ , d' , tangents , bundle , apply@@ -39,11 +39,11 @@ d _ = 0 {-# INLINE d #-} -d2 :: Num a => [a] -> (a, a)-d2 (a:da:_) = (a, da)-d2 (a:_) = (a, 0)-d2 _ = (0, 0)-{-# INLINE d2 #-}+d' :: Num a => [a] -> (a, a)+d' (a:da:_) = (a, da)+d' (a:_) = (a, 0)+d' _ = (0, 0)+{-# INLINE d' #-} tangents :: Tower a -> Tower a tangents (Tower []) = Tower []
Numeric/AD/Newton.hs view
@@ -29,8 +29,8 @@ import Numeric.AD.Internal import Data.Foldable (all) import Data.Traversable (Traversable)-import Numeric.AD.Forward (diff, diff2)-import Numeric.AD.Reverse (gradWith2)+import Numeric.AD.Forward (diff, diff')+import Numeric.AD.Reverse (gradWith') -- | The 'findZero' function finds a zero of a scalar function using -- Newton's method; its output is a stream of increasingly accurate@@ -44,7 +44,7 @@ -- > 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+findZero f x0 = iterate (\x -> let (y,y') = diff' f x in x - y/y') x0 {-# INLINE findZero #-} -- | The 'inverseNewton' function inverts a scalar function using@@ -83,7 +83,7 @@ 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 xgx0 0.1 (0 :: Int) where- (fx0, xgx0) = gradWith2 (,) f x0+ (fx0, xgx0) = gradWith' (,) f x0 go x fx xgx !eta !i | eta == 0 = [] -- step size is 0 | fx1 > fx = go x fx xgx (eta/2) 0 -- we stepped too far@@ -94,6 +94,6 @@ where zeroGrad = all (\(_,g) -> g == 0) x1 = fmap (\(xi,gxi) -> xi - eta * gxi) xgx- (fx1, xgx1) = gradWith2 (,) f x1- + (fx1, xgx1) = gradWith' (,) f x1+ {-# INLINE gradientDescent #-}
Numeric/AD/Reverse.hs view
@@ -21,30 +21,33 @@ ( -- * Gradient grad- , grad2+ , grad' , gradWith- , gradWith2+ , gradWith' -- * Jacobian , jacobian- , jacobian2+ , jacobian' , jacobianWith- , jacobianWith2+ , jacobianWith' -- * Derivatives- , diffUU- , diff2UU- , diffFU- , diff2FU- , diffUF- , diff2UF- -- * Synonyms , diff- , diff2+ , diff'+ , diffF+ , diffF'+ -- * Monadic Combinators+ , diffM+ , diffM'+ , gradM+ , gradM'+ , gradWithM+ , gradWithM' -- * Exposed Types , AD(..) , Mode(..) ) where -import Control.Applicative ((<$>))+import Control.Monad (liftM)+import Control.Applicative (WrappedMonad(..),(<$>)) import Data.Traversable (Traversable) import Numeric.AD.Classes@@ -57,32 +60,32 @@ where (vs,bds) = bind as {-# INLINE grad #-} --- | The 'grad2' function calculates the result and gradient of a non-scalar-to-scalar function with 'Reverse' AD in a single pass.-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)+-- | The 'grad'' function calculates the result and gradient of a non-scalar-to-scalar function with 'Reverse' AD in a single pass.+grad' :: (Traversable f, Num a) => (forall s. Mode s => f (AD s a) -> AD s a) -> f a -> (a, f a)+grad' f as = (primal r, unbind vs $ partialArray bds r) where (vs, bds) = bind as r = f vs-{-# INLINE grad2 #-}+{-# INLINE grad' #-} -- | @'grad' g f@ function calculates the gradient of a non-scalar-to-scalar function @f@ with reverse-mode AD in a single pass. -- The gradient is combined element-wise with the argument using the function @g@. ----- > grad == gradWith (\_ dx -> dx) +-- > grad == gradWith (\_ dx -> dx) -- > id == gradWith const gradWith :: (Traversable f, Num a) => (a -> a -> b) -> (forall s. Mode s => f (AD s a) -> AD s a) -> f a -> f b gradWith g f as = unbindWith g vs (partialArray bds $ f vs) where (vs,bds) = bind as {-# INLINE gradWith #-} --- | @'grad2' g f@ calculates the result and gradient of a non-scalar-to-scalar function @f@ with 'Reverse' AD in a single pass+-- | @'grad'' g f@ calculates the result and gradient of a non-scalar-to-scalar function @f@ with 'Reverse' AD in a single pass -- the gradient is combined element-wise with the argument using the function @g@.--- --- > grad2 == gradWith2 (\_ dx -> dx)-gradWith2 :: (Traversable f, Num a) => (a -> a -> b) -> (forall s. Mode s => f (AD s a) -> AD s a) -> f a -> (a, f b)-gradWith2 g f as = (primal r, unbindWith g vs $ partialArray bds r)+--+-- > grad' == gradWith' (\_ dx -> dx)+gradWith' :: (Traversable f, Num a) => (a -> a -> b) -> (forall s. Mode s => f (AD s a) -> AD s a) -> f a -> (a, f b)+gradWith' g f as = (primal r, unbindWith g vs $ partialArray bds r) where (vs, bds) = bind as r = f vs-{-# INLINE gradWith2 #-}+{-# INLINE gradWith' #-} -- | 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)@@ -90,18 +93,18 @@ (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,+-- | The 'jacobian'' 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+jacobian' :: (Traversable f, Functor g, Num a) => (forall s. Mode s => f (AD s a) -> g (AD s a)) -> f a -> g (a, f a)+jacobian' f as = row <$> f vs where (vs, bds) = bind as row a = (primal a, unbind vs (partialArray bds a))-{-# INLINE jacobian2 #-}+{-# INLINE jacobian' #-} -- | 'jacobianWith g f' calculates the jacobian of a non-scalar-to-non-scalar function @f@ with reverse AD lazily in @m@ passes for @m@ outputs. -- -- Instead of returning the Jacobian matrix, the elements of the matrix are combined with the input using the @g@.--- +-- -- > jacobian == jacobianWith (\_ dx -> dx) -- > jacobianWith const == (\f x -> const x <$> f x) --@@ -110,55 +113,58 @@ (vs, bds) = bind as {-# INLINE jacobianWith #-} --- | 'jacobianWith2 g f' calculates both the result and the Jacobian of a nonscalar-to-nonscalar function @f@, using @m@ invocations of reverse AD,+-- | 'jacobianWith' g f' calculates both the result and the Jacobian of a nonscalar-to-nonscalar function @f@, using @m@ invocations of reverse AD, -- where @m@ is the output dimensionality. Applying @fmap snd@ to the result will recover the result of 'jacobianWith'--- +-- -- Instead of returning the Jacobian matrix, the elements of the matrix are combined with the input using the @g@. ----- > jacobian2 == jacobianWith2 (\_ dx -> dx)+-- > jacobian' == jacobianWith' (\_ dx -> dx) ---jacobianWith2 :: (Traversable f, Functor g, Num a) => (a -> a -> b) -> (forall s. Mode s => f (AD s a) -> g (AD s a)) -> f a -> g (a, f b)-jacobianWith2 g f as = row <$> f vs where+jacobianWith' :: (Traversable f, Functor g, Num a) => (a -> a -> b) -> (forall s. Mode s => f (AD s a) -> g (AD s a)) -> f a -> g (a, f b)+jacobianWith' g f as = row <$> f vs where (vs, bds) = bind as row a = (primal a, unbindWith g vs (partialArray bds a))-{-# INLINE jacobianWith2 #-}--diffUU :: Num a => (forall s. Mode s => AD s a -> AD s a) -> a -> a-diffUU f a = derivative $ f (var a 0)-{-# INLINE diffUU #-}+{-# INLINE jacobianWith' #-} -diffUF :: (Functor f, Num a) => (forall s. Mode s => AD s a -> f (AD s a)) -> a -> f a-diffUF f a = derivative <$> f (var a 0)-{-# INLINE diffUF #-}+diff :: Num a => (forall s. Mode s => AD s a -> AD s a) -> a -> a+diff f a = derivative $ f (var a 0)+{-# INLINE diff #-} --- | The 'diff2UU' function calculates the value and derivative, as a+-- | The 'd'' function calculates the value and derivative, as a -- pair, of a scalar-to-scalar function.-diff2UU :: Num a => (forall s. Mode s => AD s a -> AD s a) -> a -> (a, a)-diff2UU f a = derivative2 $ f (var a 0)-{-# INLINE diff2UU #-}+diff' :: Num a => (forall s. Mode s => AD s a -> AD s a) -> a -> (a, a)+diff' f a = derivative' $ f (var a 0)+{-# INLINE diff' #-} -diff2UF :: (Functor f, Num a) => (forall s. Mode s => AD s a -> f (AD s a)) -> a -> f (a, a)-diff2UF f a = derivative2 <$> f (var a 0)-{-# INLINE diff2UF #-}+diffF :: (Functor f, Num a) => (forall s. Mode s => AD s a -> f (AD s a)) -> a -> f a+diffF f a = derivative <$> f (var a 0)+{-# INLINE diffF #-} -diffFU :: (Traversable f, Num a) => (forall s. Mode s => f (AD s a) -> AD s a) -> f a -> f a-diffFU f as = unbind vs $ partialArray bds (f vs)- where (vs, bds) = bind as-{-# INLINE diffFU #-}+diffF' :: (Functor f, Num a) => (forall s. Mode s => AD s a -> f (AD s a)) -> a -> f (a, a)+diffF' f a = derivative' <$> f (var a 0)+{-# INLINE diffF' #-} -diff2FU :: (Traversable f, Num a) => (forall s. Mode s => f (AD s a) -> AD s a) -> f a -> (a, f a)-diff2FU f as = (primal result, unbind vs $ partialArray bds result)- where (vs, bds) = bind as- result = f vs-{-# INLINE diff2FU #-}+-- * Monadic Combinators --- | 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-{-# INLINE diff #-}+diffM :: (Monad m, Num a) => (forall s. Mode s => AD s a -> m (AD s a)) -> a -> m a+diffM f a = liftM derivative $ f (var a 0)+{-# INLINE diffM #-} --- | The 'diff2' function is a synonym for 'diff2UU'.-diff2 :: Num a => (forall s. Mode s => AD s a -> AD s a) -> a -> (a, a)-diff2 = diff2UU-{-# INLINE diff2 #-}+diffM' :: (Monad m, Num a) => (forall s. Mode s => AD s a -> m (AD s a)) -> a -> m (a, a)+diffM' f a = liftM derivative' $ f (var a 0)+{-# INLINE diffM' #-}++gradM :: (Traversable f, Monad m, Num a) => (forall s. Mode s => f (AD s a) -> m (AD s a)) -> f a -> m (f a)+gradM f = unwrapMonad . jacobian (WrapMonad . f)+{-# INLINE gradM #-}++gradM' :: (Traversable f, Monad m, Num a) => (forall s. Mode s => f (AD s a) -> m (AD s a)) -> f a -> m (a, f a)+gradM' f = unwrapMonad . jacobian' (WrapMonad . f)+{-# INLINE gradM' #-}++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 (f b)+gradWithM g f = unwrapMonad . jacobianWith g (WrapMonad . f)++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)
Numeric/AD/Tower.hs view
@@ -15,54 +15,56 @@ module Numeric.AD.Tower ( -- * Taylor Series- taylor, taylor0- , maclaurin, maclaurin0+ taylor+ , taylor0+ -- * Maclaurin Series+ , maclaurin+ , maclaurin0 -- * Derivatives- , diffUU- , diff2UU- , diffsUU- , diffs0UU- , diffsUF- , diffs0UF- -- * Synonyms- , diffs, diffs0- , diff, diff2+ , diff+ , diff'+ , diffs+ , diffs0+ , diffsF+ , diffs0F+ -- * Monadic Combinators+ , diffsM+ , diffs0M -- * Exposed Types , Mode(..) , AD(..) ) where --- TODO: argminNaiveGradient-+import Control.Monad (liftM) import Control.Applicative ((<$>)) import Numeric.AD.Classes import Numeric.AD.Internal 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-{-# INLINE diffsUU #-}--diffs0UU :: Num a => (forall s. Mode s => AD s a -> AD s a) -> a -> [a]-diffs0UU f a = zeroPad (diffsUU f a)-{-# INLINE diffs0UU #-}--diffs0UF :: (Functor f, Num a) => (forall s. Mode s => AD s a -> f (AD s a)) -> a -> f [a]-diffs0UF f a = (zeroPad . getADTower) <$> apply f a-{-# INLINE diffs0UF #-}--diffsUF :: (Functor f, Num a) => (forall s. Mode s => AD s a -> f (AD s a)) -> a -> f [a]-diffsUF f a = getADTower <$> apply f a-{-# INLINE diffsUF #-}- diffs :: Num a => (forall s. Mode s => AD s a -> AD s a) -> a -> [a]-diffs = diffsUU+diffs f a = getADTower $ apply f a {-# INLINE diffs #-} diffs0 :: Num a => (forall s. Mode s => AD s a -> AD s a) -> a -> [a]-diffs0 = diffs0UU+diffs0 f a = zeroPad (diffs f a) {-# INLINE diffs0 #-} +diffsF :: (Functor f, Num a) => (forall s. Mode s => AD s a -> f (AD s a)) -> a -> f [a]+diffsF f a = getADTower <$> apply f a+{-# INLINE diffsF #-}++diffs0F :: (Functor f, Num a) => (forall s. Mode s => AD s a -> f (AD s a)) -> a -> f [a]+diffs0F f a = (zeroPad . getADTower) <$> apply f a+{-# INLINE diffs0F #-}++diffsM :: (Monad m, Num a) => (forall s. Mode s => AD s a -> m (AD s a)) -> a -> m [a]+diffsM f a = getADTower `liftM` apply f a+{-# INLINE diffsM #-}++diffs0M :: (Monad m, Num a) => (forall s. Mode s => AD s a -> m (AD s a)) -> a -> m [a]+diffs0M f a = (zeroPad . getADTower) `liftM` apply f a+{-# INLINE diffs0M #-}+ taylor :: Fractional a => (forall s. Mode s => AD s a -> AD s a) -> a -> a -> [a] taylor f x dx = go 1 1 (diffs f x) where@@ -81,18 +83,11 @@ 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-{-# 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-{-# INLINE diff2UU #-}- diff :: Num a => (forall s. Mode s => AD s a -> AD s a) -> a -> a-diff = diffUU+diff f a = d $ diffs f a {-# INLINE diff #-} -diff2 :: Num a => (forall s. Mode s => AD s a -> AD s a) -> a -> (a, a)-diff2 = diff2UU-{-# INLINE diff2 #-}+diff' :: Num a => (forall s. Mode s => AD s a -> AD s a) -> a -> (a, a)+diff' f a = d' $ diffs f a+{-# INLINE diff' #-}+
ad.cabal view
@@ -1,5 +1,5 @@ Name: ad-Version: 0.15+Version: 0.17 License: BSD3 License-File: LICENSE Copyright: Edward Kmett 2010