packages feed

ad 0.19 → 0.20

raw patch · 3 files changed

+84/−10 lines, 3 filesdep +mlistPVP ok

version bump matches the API change (PVP)

Dependencies added: mlist

API changes (from Hackage documentation)

+ Numeric.AD.Internal: Pair :: a -> b -> Pair a b
+ Numeric.AD.Internal: data Pair a b
+ Numeric.AD.Internal: instance (Eq a, Eq b) => Eq (Pair a b)
+ Numeric.AD.Internal: instance (Ord a, Ord b) => Ord (Pair a b)
+ Numeric.AD.Internal: instance (Read a, Read b) => Read (Pair a b)
+ Numeric.AD.Internal: instance (Show a, Show b) => Show (Pair a b)
+ Numeric.AD.Internal: instance Foldable (Pair a)
+ Numeric.AD.Internal: instance Functor (Pair a)
+ Numeric.AD.Internal: instance Traversable (Pair a)
+ Numeric.AD.Newton: extremumM :: (Monad m, Fractional a) => (forall s. (Mode s) => AD s a -> m (AD s a)) -> a -> MList m a
+ Numeric.AD.Newton: findZeroM :: (Monad m, Fractional a) => (forall s. (Mode s) => AD s a -> m (AD s a)) -> a -> MList m a
+ Numeric.AD.Newton: fixedPointM :: (Monad m, Fractional a) => (forall s. (Mode s) => AD s a -> m (AD s a)) -> a -> MList m a
+ Numeric.AD.Newton: gradientAscent :: (Traversable f, Fractional a, Ord a) => (forall s. (Mode s) => f (AD s a) -> AD s a) -> f a -> [f a]
+ Numeric.AD.Newton: gradientAscentM :: (Traversable f, Monad m, Fractional a, Ord a) => (forall s. (Mode s) => f (AD s a) -> m (AD s a)) -> f a -> MList m (f a)
+ Numeric.AD.Newton: gradientDescentM :: (Traversable f, Monad m, Fractional a, Ord a) => (forall s. (Mode s) => f (AD s a) -> m (AD s a)) -> f a -> MList m (f a)
+ Numeric.AD.Newton: inverseM :: (Monad m, Fractional a) => (forall s. (Mode s) => AD s a -> m (AD s a)) -> a -> a -> MList m a

Files

Numeric/AD/Internal.hs view
@@ -1,4 +1,4 @@-{-# LANGUAGE GeneralizedNewtypeDeriving, TemplateHaskell, FlexibleContexts, FlexibleInstances, MultiParamTypeClasses #-}+{-# LANGUAGE GeneralizedNewtypeDeriving, TemplateHaskell, FlexibleContexts, FlexibleInstances, MultiParamTypeClasses, DeriveFunctor, DeriveFoldable, DeriveTraversable #-} ----------------------------------------------------------------------------- -- | -- Module      :  Numeric.AD.Internal@@ -18,6 +18,7 @@     , unprobe     , probed     , unprobed+    , Pair(..)     ) where  import Control.Applicative@@ -26,6 +27,8 @@ import Data.Monoid import Data.Traversable (Traversable, mapAccumL) import Data.Foldable (Foldable, toList)++data Pair a b = Pair a b deriving (Eq, Ord, Show, Read, Functor, Foldable, Traversable)  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)
Numeric/AD/Newton.hs view
@@ -1,4 +1,4 @@-{-# LANGUAGE Rank2Types, BangPatterns #-}+{-# LANGUAGE Rank2Types, BangPatterns, ScopedTypeVariables #-} ----------------------------------------------------------------------------- -- | -- Module      :  Numeric.AD.Newton@@ -14,23 +14,32 @@     (     -- * Newton's Method (Forward AD)       findZero+    , findZeroM     , inverse+    , inverseM     , fixedPoint+    , fixedPointM     , extremum-    -- * Gradient Descent (Reverse AD)+    , extremumM+    -- * Gradient Ascent/Descent (Reverse AD)     , gradientDescent+    , gradientDescentM+    , gradientAscent+    , gradientAscentM     -- * Exposed Types     , AD(..)     , Mode(..)     ) where  import Prelude hiding (all)+import Control.Monad (liftM)+import Data.MList import Numeric.AD.Classes import Numeric.AD.Internal import Data.Foldable (all) import Data.Traversable (Traversable)-import Numeric.AD.Forward (diff, diff')-import Numeric.AD.Reverse (gradWith')+import Numeric.AD.Forward (diff, diff', diffM, diffM')+import Numeric.AD.Reverse (gradWith', gradWithM') import Numeric.AD.Internal.Composition  -- | The 'findZero' function finds a zero of a scalar function using@@ -45,35 +54,65 @@ --  > 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') = diff' f x in x - y/y') x0+findZero f = go+    where+        go x = x : go (x - y/y') +            where+                (y,y') = diff' f x {-# INLINE findZero #-} +findZeroM :: (Monad m, Fractional a) => (forall s. Mode s => AD s a -> m (AD s a)) -> a -> MList m a+findZeroM f x0 = MList (go x0)+    where+        go x = return $ +               MCons x $ +               MList $ do+                (y,y') <- diffM' f x+                go (x - y/y')+{-# INLINE findZeroM #-}+ -- | 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+-- > take 10 $ inverseNewton sqrt 1 (sqrt 10)  -- converges 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  #-} +inverseM :: (Monad m, Fractional a) => (forall s. Mode s => AD s a -> m (AD s a)) -> a -> a -> MList m a+inverseM f x0 y = findZeroM (\x -> subtract (lift y) `liftM` f x) x0+{-# INLINE inverseM  #-}+ -- | 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.)+-- +-- > take 10 $ fixedPoint cos 1 -- converges to 0.7390851332151607 fixedPoint :: Fractional a => (forall s. Mode s => AD s a -> AD s a) -> a -> [a] fixedPoint f = findZero (\x -> f x - x) {-# INLINE fixedPoint #-} +fixedPointM :: (Monad m, Fractional a) => (forall s. Mode s => AD s a -> m (AD s a)) -> a -> MList m a+fixedPointM f = findZeroM (\x -> subtract x `liftM` f x)+{-# INLINE fixedPointM #-}+ -- | 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.)+--+-- > 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 x0 = findZero (diff (decompose . f . compose)) x0+extremum f = findZero (diff (decompose . f . compose)) {-# 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))+{-# INLINE extremumM #-}+ -- | 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@@ -96,5 +135,36 @@                 zeroGrad = all (\(_,g) -> g == 0)                 x1 = fmap (\(xi,gxi) -> xi - eta * gxi) xgx                 (fx1, xgx1) = gradWith' (,) f x1- {-# INLINE gradientDescent #-}++gradientAscent :: (Traversable f, Fractional a, Ord a) => (forall s. Mode s => f (AD s a) -> AD s a) -> f a -> [f a]+gradientAscent f = gradientDescent (negate . f)+{-# INLINE gradientAscent #-}++-- monadic gradient descent+gradientDescentM :: (Traversable f, Monad m, Fractional a, Ord a) => (forall s. Mode s => f (AD s a) -> m (AD s a)) -> f a -> MList m (f a)+gradientDescentM f x0 = MList $ do+        (fx0, xgx0) <- gradWithM' (,) f x0+        go x0 fx0 xgx0 0.1 (0 :: Int)+    where+        go x fx xgx !eta !i+            | eta == 0  = return MNil -- step size is 0+            | otherwise = do+                (fx1, xgx1) <- gradWithM' (,) f x1+                case () of+                 _ | fx1 > fx     -> go x fx xgx (eta/2) 0 -- we stepped too far+                   | zeroGrad xgx -> return MNil -- gradient is 0+                   | otherwise    -> return $ +                                     MCons x1 $ +                                     MList $+                                     if i == 10+                                     then go x1 fx1 xgx1 (eta*2) 0+                                     else go x1 fx1 xgx1 eta (i+1)+            where+                x1 = fmap (\(xi,gxi) -> xi - eta * gxi) xgx+                zeroGrad = all (\(_,g) -> g == 0)+{-# INLINE gradientDescentM #-}++gradientAscentM :: (Traversable f, Monad m, Fractional a, Ord a) => (forall s. Mode s => f (AD s a) -> m (AD s a)) -> f a -> MList m (f a)+gradientAscentM f = gradientDescentM (liftM negate . f)+{-# INLINE gradientAscentM #-}
ad.cabal view
@@ -1,5 +1,5 @@ Name:         ad-Version:      0.19+Version:      0.20 License:      BSD3 License-File: LICENSE Copyright:    Edward Kmett 2010@@ -21,6 +21,7 @@     data-reify >= 0.5 && < 0.6,      containers >= 0.2 && < 0.4,     template-haskell >= 2.4 && < 2.5,+    mlist >= 0.0.2 && <= 0.1,     array >= 0.2 && < 0.4  Exposed-Modules: