{-# LANGUAGE Rank2Types, TypeFamilies #-}------------------------------------------------------------------------------- |-- Module : Numeric.AD-- Copyright : (c) Edward Kmett 2010-- License : BSD3-- Maintainer : ekmett@gmail.com-- Stability : experimental-- Portability : GHC only---- Mixed-Mode Automatic Differentiation.---- Each combinator exported from this module chooses an appropriate AD mode.-----------------------------------------------------------------------------moduleNumeric.AD(-- * Gradients (Reverse Mode)grad,grad',gradWith,gradWith'-- * Jacobians (Mixed Mode),jacobian,jacobian',jacobianWith,jacobianWith'-- * Jacobians (Reverse Mode),gradF,gradF',gradWithF,gradWithF'-- * Jacobians (Forward Mode),jacobianT,jacobianWithT-- * Derivatives (Forward Mode),diff,diffF,diff',diffF'-- * Derivatives (Tower),diffs,diffsF,diffs0,diffs0F-- * Directional Derivatives (Forward Mode),du,du',duF,duF'-- * Taylor Series (Tower),taylor,taylor0-- * Maclaurin Series (Tower),maclaurin,maclaurin0-- * Monadic Combinators (Forward Mode),diffM,diffM'-- * Monadic Combinators (Reverse Mode),gradM,gradM',gradWithM,gradWithM'-- * Exposed Types,AD(..),Mode(..))whereimportData.Traversable(Traversable)importData.Foldable(Foldable,foldr')importControl.ApplicativeimportNumeric.AD.Classes(Mode(..))importNumeric.AD.Internal(AD(..),probed,unprobe)importNumeric.AD.Forward(diff,diff',diffF,diffF',du,du',duF,duF',diffM,diffM',jacobianT,jacobianWithT)importNumeric.AD.Tower(diffsF,diffs0F,diffs,diffs0,taylor,taylor0,maclaurin,maclaurin0)importNumeric.AD.Reverse(grad,grad',gradWith,gradWith',gradM,gradM',gradWithM,gradWithM',gradF,gradF',gradWithF,gradWithF')importqualifiedNumeric.AD.ForwardasForwardimportqualifiedNumeric.AD.ReverseasReverse-- | 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::(Traversablef,Traversableg,Numa)=>(foralls.Modes=>f(ADsa)->g(ADsa))->fa->g(fa)jacobianfbs=snd<$>jacobian'fbs{-# INLINE jacobian #-}-- | 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'::(Traversablef,Traversableg,Numa)=>(foralls.Modes=>f(ADsa)->g(ADsa))->fa->g(a,fa)jacobian'fbs|n==0=fmap(\x->(unprobex,bs))as|n>m=Reverse.jacobian'fbs|otherwise=Forward.jacobian'fbswhereas=f(probedbs)n=sizebsm=sizeassize::Foldablef=>fa->Intsize=foldr'(\_b->1+b)0{-# 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@.---- 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::(Traversablef,Traversableg,Numa)=>(a->a->b)->(foralls.Modes=>f(ADsa)->g(ADsa))->fa->g(fb)jacobianWithgfbs=snd<$>jacobianWith'gfbs{-# INLINE jacobianWith #-}-- | @'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@.---- 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'::(Traversablef,Traversableg,Numa)=>(a->a->b)->(foralls.Modes=>f(ADsa)->g(ADsa))->fa->g(a,fb)jacobianWith'gfbs|n==0=fmap(\x->(unprobex,undefined<$>bs))as|n>m=Reverse.jacobianWith'gfbs|otherwise=Forward.jacobianWith'gfbswhereas=f(probedbs)n=sizebsm=sizeassize::Foldablef=>fa->Intsize=foldr'(\_b->1+b)0{-# INLINE jacobianWith' #-}