ad 4.3.1 → 4.3.2
raw patch · 10 files changed
+225/−24 lines, 10 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
+ Numeric.AD.Halley: extremumNoEq :: Fractional a => (forall s. AD s (On (Forward (Tower a))) -> AD s (On (Forward (Tower a)))) -> a -> [a]
+ Numeric.AD.Halley: findZeroNoEq :: Fractional a => (forall s. AD s (Tower a) -> AD s (Tower a)) -> a -> [a]
+ Numeric.AD.Halley: fixedPointNoEq :: Fractional a => (forall s. AD s (Tower a) -> AD s (Tower a)) -> a -> [a]
+ Numeric.AD.Halley: inverseNoEq :: Fractional a => (forall s. AD s (Tower a) -> AD s (Tower a)) -> a -> a -> [a]
+ Numeric.AD.Newton: extremumNoEq :: Fractional a => (forall s. AD s (On (Forward (Forward a))) -> AD s (On (Forward (Forward a)))) -> a -> [a]
+ Numeric.AD.Newton: findZeroNoEq :: Fractional a => (forall s. AD s (Forward a) -> AD s (Forward a)) -> a -> [a]
+ Numeric.AD.Newton: fixedPointNoEq :: Fractional a => (forall s. AD s (Forward a) -> AD s (Forward a)) -> a -> [a]
+ Numeric.AD.Newton: inverseNoEq :: Fractional a => (forall s. AD s (Forward a) -> AD s (Forward a)) -> a -> a -> [a]
+ Numeric.AD.Newton.Double: extremumNoEq :: (forall s. AD s (On (Forward ForwardDouble)) -> AD s (On (Forward ForwardDouble))) -> Double -> [Double]
+ Numeric.AD.Newton.Double: findZeroNoEq :: (forall s. AD s ForwardDouble -> AD s ForwardDouble) -> Double -> [Double]
+ Numeric.AD.Newton.Double: fixedPointNoEq :: (forall s. AD s ForwardDouble -> AD s ForwardDouble) -> Double -> [Double]
+ Numeric.AD.Newton.Double: inverseNoEq :: (forall s. AD s ForwardDouble -> AD s ForwardDouble) -> Double -> Double -> [Double]
+ Numeric.AD.Rank1.Halley: extremumNoEq :: Fractional a => (On (Forward (Tower a)) -> On (Forward (Tower a))) -> a -> [a]
+ Numeric.AD.Rank1.Halley: findZeroNoEq :: Fractional a => (Tower a -> Tower a) -> a -> [a]
+ Numeric.AD.Rank1.Halley: fixedPointNoEq :: Fractional a => (Tower a -> Tower a) -> a -> [a]
+ Numeric.AD.Rank1.Halley: inverseNoEq :: Fractional a => (Tower a -> Tower a) -> a -> a -> [a]
+ Numeric.AD.Rank1.Newton: extremumNoEq :: Fractional a => (On (Forward (Forward a)) -> On (Forward (Forward a))) -> a -> [a]
+ Numeric.AD.Rank1.Newton: findZeroNoEq :: Fractional a => (Forward a -> Forward a) -> a -> [a]
+ Numeric.AD.Rank1.Newton: fixedPointNoEq :: Fractional a => (Forward a -> Forward a) -> a -> [a]
+ Numeric.AD.Rank1.Newton: inverseNoEq :: Fractional a => (Forward a -> Forward a) -> a -> a -> [a]
+ Numeric.AD.Rank1.Newton.Double: extremumNoEq :: (On (Forward ForwardDouble) -> On (Forward ForwardDouble)) -> Double -> [Double]
+ Numeric.AD.Rank1.Newton.Double: findZeroNoEq :: (ForwardDouble -> ForwardDouble) -> Double -> [Double]
+ Numeric.AD.Rank1.Newton.Double: fixedPointNoEq :: (ForwardDouble -> ForwardDouble) -> Double -> [Double]
+ Numeric.AD.Rank1.Newton.Double: inverseNoEq :: (ForwardDouble -> ForwardDouble) -> Double -> Double -> [Double]
Files
- CHANGELOG.markdown +4/−0
- README.markdown +1/−0
- ad.cabal +3/−1
- src/Numeric/AD/Halley.hs +31/−0
- src/Numeric/AD/Internal/Combinators.hs +9/−0
- src/Numeric/AD/Newton.hs +36/−4
- src/Numeric/AD/Newton/Double.hs +28/−0
- src/Numeric/AD/Rank1/Halley.hs +39/−7
- src/Numeric/AD/Rank1/Newton.hs +39/−6
- src/Numeric/AD/Rank1/Newton/Double.hs +35/−6
CHANGELOG.markdown view
@@ -1,3 +1,7 @@+4.3.2+-----+* Added `NoEq` versions of several combinators that can be used when `Eq` isn't available on the numeric type involved.+ 4.3.1 ----- * Further improvements have been made in the performance of `Sparse` mode, at least asymptotically, when used on functions with many variables.
README.markdown view
@@ -121,6 +121,7 @@ * `s` means the function returns all higher derivatives in a list or f-branching `Stream` * `T` means the result is transposed with respect to the traditional formulation (usually to avoid paying for transposing back) * `0` means that the resulting derivative list is padded with 0s at the end.+ * `NoEq` means that an infinite list of converging values is returned rather than truncating the list when they become constant Contact Information -------------------
ad.cabal view
@@ -1,5 +1,5 @@ name: ad-version: 4.3.1+version: 4.3.2 license: BSD3 license-File: LICENSE copyright: (c) Edward Kmett 2010-2015,@@ -70,6 +70,8 @@ * @T@ means the result is transposed with respect to the traditional formulation. . * @0@ means that the resulting derivative list is padded with 0s at the end.+ .+ * @NoEq@ means that an infinite list of converging values is returned rather than truncating the list when they become constant source-repository head type: git
src/Numeric/AD/Halley.hs view
@@ -19,9 +19,13 @@ ( -- * Halley's Method (Tower AD) findZero+ , findZeroNoEq , inverse+ , inverseNoEq , fixedPoint+ , fixedPointNoEq , extremum+ , extremumNoEq ) where import Prelude@@ -50,6 +54,13 @@ findZero f = Rank1.findZero (runAD.f.AD) {-# INLINE findZero #-} +-- | The 'findZeroNoEq' function behaves the same as 'findZero' except that it+-- doesn't truncate the list once the results become constant. This means it+-- can be used with types without an 'Eq' instance.+findZeroNoEq :: Fractional a => (forall s. AD s (Tower a) -> AD s (Tower a)) -> a -> [a]+findZeroNoEq f = Rank1.findZeroNoEq (runAD.f.AD)+{-# INLINE findZeroNoEq #-}+ -- | The 'inverse' function inverts a scalar function using -- Halley's method; its output is a stream of increasingly accurate -- results. (Modulo the usual caveats.) If the stream becomes constant@@ -61,6 +72,13 @@ inverse f = Rank1.inverse (runAD.f.AD) {-# INLINE inverse #-} +-- | The 'inverseNoEq' function behaves the same as 'inverse' except that it+-- doesn't truncate the list once the results become constant. This means it+-- can be used with types without an 'Eq' instance.+inverseNoEq :: Fractional a => (forall s. AD s (Tower a) -> AD s (Tower a)) -> a -> a -> [a]+inverseNoEq f = Rank1.inverseNoEq (runAD.f.AD)+{-# INLINE inverseNoEq #-}+ -- | The 'fixedPoint' function find a fixedpoint of a scalar -- function using Halley's method; its output is a stream of -- increasingly accurate results. (Modulo the usual caveats.)@@ -74,6 +92,12 @@ fixedPoint f = Rank1.fixedPoint (runAD.f.AD) {-# INLINE fixedPoint #-} +-- | The 'fixedPointNoEq' function behaves the same as 'fixedPoint' except that+-- it doesn't truncate the list once the results become constant. This means it+-- can be used with types without an 'Eq' instance.+fixedPointNoEq :: Fractional a => (forall s. AD s (Tower a) -> AD s (Tower a)) -> a -> [a]+fixedPointNoEq f = Rank1.fixedPointNoEq (runAD.f.AD)+{-# INLINE fixedPointNoEq #-} -- | The 'extremum' function finds an extremum of a scalar -- function using Halley's method; produces a stream of increasingly@@ -85,3 +109,10 @@ extremum :: (Fractional a, Eq a) => (forall s. AD s (On (Forward (Tower a))) -> AD s (On (Forward (Tower a)))) -> a -> [a] extremum f = Rank1.extremum (runAD.f.AD) {-# INLINE extremum #-}++-- | The 'extremumNoEq' function behaves the same as 'extremum' except that it+-- doesn't truncate the list once the results become constant. This means it+-- can be used with types without an 'Eq' instance.+extremumNoEq :: Fractional a => (forall s. AD s (On (Forward (Tower a))) -> AD s (On (Forward (Tower a)))) -> a -> [a]+extremumNoEq f = Rank1.extremumNoEq (runAD.f.AD)+{-# INLINE extremumNoEq #-}
src/Numeric/AD/Internal/Combinators.hs view
@@ -16,6 +16,7 @@ , zipWithDefaultT , withPrimal , fromBy+ , takeWhileDifferent ) where #if __GLASGOW_HASKELL__ < 710@@ -44,3 +45,11 @@ -- | Used internally to define various 'Enum' combinators. fromBy :: Jacobian t => t -> t -> Int -> Scalar t -> t fromBy a delta n x = binary (\_ _ -> x) 1 (fromIntegral n) a delta++-- | Used internally to implement functions which truncate lists after the+-- stream of results converge+takeWhileDifferent :: Eq a => [a] -> [a]+takeWhileDifferent (x1:x2:xs) = if x1 == x2+ then [x1]+ else x1 : takeWhileDifferent (x2:xs)+takeWhileDifferent xs = xs
src/Numeric/AD/Newton.hs view
@@ -23,9 +23,13 @@ ( -- * Newton's Method (Forward AD) findZero+ , findZeroNoEq , inverse+ , inverseNoEq , fixedPoint+ , fixedPointNoEq , extremum+ , extremumNoEq -- * Gradient Ascent/Descent (Reverse AD) , gradientDescent, constrainedDescent, CC(..), eval , gradientAscent@@ -72,6 +76,13 @@ findZero f = Rank1.findZero (runAD.f.AD) {-# INLINE findZero #-} +-- | The 'findZeroNoEq' function behaves the same as 'findZero' except that it+-- doesn't truncate the list once the results become constant. This means it+-- can be used with types without an 'Eq' instance.+findZeroNoEq :: Fractional a => (forall s. AD s (Forward a) -> AD s (Forward a)) -> a -> [a]+findZeroNoEq f = Rank1.findZeroNoEq (runAD.f.AD)+{-# INLINE findZeroNoEq #-}+ -- | The 'inverse' function inverts a scalar function using -- Newton's method; its output is a stream of increasingly accurate -- results. (Modulo the usual caveats.) If the stream becomes@@ -85,6 +96,13 @@ inverse f = Rank1.inverse (runAD.f.AD) {-# INLINE inverse #-} +-- | The 'inverseNoEq' function behaves the same as 'inverse' except that it+-- doesn't truncate the list once the results become constant. This means it+-- can be used with types without an 'Eq' instance.+inverseNoEq :: Fractional a => (forall s. AD s (Forward a) -> AD s (Forward a)) -> a -> a -> [a]+inverseNoEq f = Rank1.inverseNoEq (runAD.f.AD)+{-# INLINE inverseNoEq #-}+ -- | 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.)@@ -98,6 +116,13 @@ fixedPoint f = Rank1.fixedPoint (runAD.f.AD) {-# INLINE fixedPoint #-} +-- | The 'fixedPointNoEq' function behaves the same as 'fixedPoint' except that+-- it doesn't truncate the list once the results become constant. This means it+-- can be used with types without an 'Eq' instance.+fixedPointNoEq :: Fractional a => (forall s. AD s (Forward a) -> AD s (Forward a)) -> a -> [a]+fixedPointNoEq f = Rank1.fixedPointNoEq (runAD.f.AD)+{-# INLINE fixedPointNoEq #-}+ -- | 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.) If the stream@@ -109,6 +134,13 @@ extremum f = Rank1.extremum (runAD.f.AD) {-# INLINE extremum #-} +-- | The 'extremumNoEq' function behaves the same as 'extremum' except that it+-- doesn't truncate the list once the results become constant. This means it+-- can be used with types without an 'Eq' instance.+extremumNoEq :: Fractional a => (forall s. AD s (On (Forward (Forward a))) -> AD s (On (Forward (Forward a)))) -> a -> [a]+extremumNoEq f = Rank1.extremumNoEq (runAD.f.AD)+{-# INLINE extremumNoEq #-}+ -- | 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@@ -223,15 +255,15 @@ -- | The 'stochasticGradientDescent' function approximates -- the true gradient of the constFunction by a gradient at--- a single example. As the algorithm sweeps through the training +-- a single example. As the algorithm sweeps through the training -- set, it performs the update for each training example. -- -- It uses reverse mode automatic differentiation to compute the gradient -- The learning rate is constant through out, and is set to 0.001-stochasticGradientDescent :: (Traversable f, Fractional a, Ord a) - => (forall s. Reifies s Tape => f (Scalar a) -> f (Reverse s a) -> Reverse s a) +stochasticGradientDescent :: (Traversable f, Fractional a, Ord a)+ => (forall s. Reifies s Tape => f (Scalar a) -> f (Reverse s a) -> Reverse s a) -> [f (Scalar a)]- -> f a + -> f a -> [f a] stochasticGradientDescent errorSingle d0 x0 = go xgx0 0.001 dLeft where
src/Numeric/AD/Newton/Double.hs view
@@ -17,9 +17,13 @@ ( -- * Newton's Method (Forward AD) findZero+ , findZeroNoEq , inverse+ , inverseNoEq , fixedPoint+ , fixedPointNoEq , extremum+ , extremumNoEq -- * Gradient Ascent/Descent (Reverse AD) , conjugateGradientDescent , conjugateGradientAscent@@ -51,6 +55,12 @@ findZero f = Rank1.findZero (runAD.f.AD) {-# INLINE findZero #-} +-- | The 'findZeroNoEq' function behaves the same as 'findZero' except that it+-- doesn't truncate the list once the results become constant.+findZeroNoEq :: (forall s. AD s ForwardDouble -> AD s ForwardDouble) -> Double -> [Double]+findZeroNoEq f = Rank1.findZeroNoEq (runAD.f.AD)+{-# INLINE findZeroNoEq #-}+ -- | The 'inverse' function inverts a scalar function using -- Newton's method; its output is a stream of increasingly accurate -- results. (Modulo the usual caveats.) If the stream becomes@@ -64,6 +74,12 @@ inverse f = Rank1.inverse (runAD.f.AD) {-# INLINE inverse #-} +-- | The 'inverseNoEq' function behaves the same as 'inverse' except that it+-- doesn't truncate the list once the results become constant.+inverseNoEq :: (forall s. AD s ForwardDouble -> AD s ForwardDouble) -> Double -> Double -> [Double]+inverseNoEq f = Rank1.inverseNoEq (runAD.f.AD)+{-# INLINE inverseNoEq #-}+ -- | 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.)@@ -77,6 +93,12 @@ fixedPoint f = Rank1.fixedPoint (runAD.f.AD) {-# INLINE fixedPoint #-} +-- | The 'fixedPointNoEq' function behaves the same as 'fixedPoint' except that+-- doesn't truncate the list once the results become constant.+fixedPointNoEq :: (forall s. AD s ForwardDouble -> AD s ForwardDouble) -> Double -> [Double]+fixedPointNoEq f = Rank1.fixedPointNoEq (runAD.f.AD)+{-# INLINE fixedPointNoEq #-}+ -- | 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.) If the stream@@ -87,6 +109,12 @@ extremum :: (forall s. AD s (On (Forward ForwardDouble)) -> AD s (On (Forward ForwardDouble))) -> Double -> [Double] extremum f = Rank1.extremum (runAD.f.AD) {-# INLINE extremum #-}++-- | The 'extremumNoEq' function behaves the same as 'extremum' except that it+-- doesn't truncate the list once the results become constant.+extremumNoEq :: (forall s. AD s (On (Forward ForwardDouble)) -> AD s (On (Forward ForwardDouble))) -> Double -> [Double]+extremumNoEq f = Rank1.extremumNoEq (runAD.f.AD)+{-# INLINE extremumNoEq #-} -- | Perform a conjugate gradient descent using reverse mode automatic differentiation to compute the gradient, and using forward-on-forward mode for computing extrema. --
src/Numeric/AD/Rank1/Halley.hs view
@@ -18,9 +18,13 @@ ( -- * Halley's Method (Tower AD) findZero+ , findZeroNoEq , inverse+ , inverseNoEq , fixedPoint+ , fixedPointNoEq , extremum+ , extremumNoEq ) where import Prelude hiding (all)@@ -30,6 +34,7 @@ import Numeric.AD.Mode import Numeric.AD.Rank1.Tower (diffs0) import Numeric.AD.Rank1.Forward (diff)+import Numeric.AD.Internal.Combinators (takeWhileDifferent) -- $setup -- >>> import Data.Complex@@ -47,16 +52,23 @@ -- >>> last $ take 10 $ findZero ((+1).(^2)) (1 :+ 1) -- 0.0 :+ 1.0 findZero :: (Fractional a, Eq a) => (Tower a -> Tower a) -> a -> [a]-findZero f = go where- go x = x : if x == xn then [] else go xn where+findZero f = takeWhileDifferent . findZeroNoEq f+{-# INLINE findZero #-}++-- | The 'findZeroNoEq' function behaves the same as 'findZero' except that it+-- doesn't truncate the list once the results become constant. This means it+-- can be used with types without an 'Eq' instance.+findZeroNoEq :: Fractional a => (Tower a -> Tower a) -> a -> [a]+findZeroNoEq f = iterate go where+ go x = xn where (y:y':y'':_) = diffs0 f x xn = x - 2*y*y'/(2*y'*y'-y*y'') -- 9.606671960457536 bits error -- = x - recip (y'/y - y''/ y') -- "improved error" = 6.640625e-2 bits -- = x - y' / (y'/y/y' - y''/2) -- "improved error" = 1.4 #ifdef HERBIE-{-# ANN findZero "NoHerbie" #-}+{-# ANN findZeroNoEq "NoHerbie" #-} #endif-{-# INLINE findZero #-}+{-# INLINE findZeroNoEq #-} -- | The 'inverse' function inverts a scalar function using -- Halley's method; its output is a stream of increasingly accurate@@ -66,9 +78,16 @@ -- Note: the @take 10 $ inverse sqrt 1 (sqrt 10)@ example that works for Newton's method -- fails with Halley's method because the preconditions do not hold! inverse :: (Fractional a, Eq a) => (Tower a -> Tower a) -> a -> a -> [a]-inverse f x0 y = findZero (\x -> f x - auto y) x0+inverse f x0 = takeWhileDifferent . inverseNoEq f x0 {-# INLINE inverse #-} +-- | The 'inverseNoEq' function behaves the same as 'inverse' except that it+-- doesn't truncate the list once the results become constant. This means it+-- can be used with types without an 'Eq' instance.+inverseNoEq :: Fractional a => (Tower a -> Tower a) -> a -> a -> [a]+inverseNoEq f x0 y = findZeroNoEq (\x -> f x - auto y) x0+{-# INLINE inverseNoEq #-}+ -- | The 'fixedPoint' function find a fixedpoint of a scalar -- function using Halley's method; its output is a stream of -- increasingly accurate results. (Modulo the usual caveats.)@@ -79,9 +98,15 @@ -- >>> last $ take 10 $ fixedPoint cos 1 -- 0.7390851332151607 fixedPoint :: (Fractional a, Eq a) => (Tower a -> Tower a) -> a -> [a]-fixedPoint f = findZero (\x -> f x - x)+fixedPoint f = takeWhileDifferent . fixedPointNoEq f {-# INLINE fixedPoint #-} +-- | The 'fixedPointNoEq' function behaves the same as 'fixedPoint' except that+-- it doesn't truncate the list once the results become constant. This means it+-- can be used with types without an 'Eq' instance.+fixedPointNoEq :: Fractional a => (Tower a -> Tower a) -> a -> [a]+fixedPointNoEq f = findZeroNoEq (\x -> f x - x)+{-# INLINE fixedPointNoEq #-} -- | The 'extremum' function finds an extremum of a scalar -- function using Halley's method; produces a stream of increasingly@@ -91,5 +116,12 @@ -- >>> take 10 $ extremum cos 1 -- [1.0,0.29616942658570555,4.59979519460002e-3,1.6220740159042513e-8,0.0] extremum :: (Fractional a, Eq a) => (On (Forward (Tower a)) -> On (Forward (Tower a))) -> a -> [a]-extremum f = findZero (diff (off . f . On))+extremum f = takeWhileDifferent . extremumNoEq f {-# INLINE extremum #-}++-- | The 'extremumNoEq' function behaves the same as 'extremum' except that it+-- doesn't truncate the list once the results become constant. This means it+-- can be used with types without an 'Eq' instance.+extremumNoEq :: Fractional a => (On (Forward (Tower a)) -> On (Forward (Tower a))) -> a -> [a]+extremumNoEq f = findZeroNoEq (diff (off . f . On))+{-# INLINE extremumNoEq #-}
src/Numeric/AD/Rank1/Newton.hs view
@@ -17,9 +17,13 @@ ( -- * Newton's Method (Forward) findZero+ , findZeroNoEq , inverse+ , inverseNoEq , fixedPoint+ , fixedPointNoEq , extremum+ , extremumNoEq -- * Gradient Ascent/Descent (Kahn) , gradientDescent , gradientAscent@@ -34,6 +38,7 @@ import Numeric.AD.Rank1.Forward (Forward, diff, diff') import Numeric.AD.Rank1.Kahn as Kahn (Kahn, gradWith') import Numeric.AD.Internal.On+import Numeric.AD.Internal.Combinators (takeWhileDifferent) -- $setup -- >>> import Data.Complex@@ -51,11 +56,18 @@ -- >>> last $ take 10 $ findZero ((+1).(^2)) (1 :+ 1) -- 0.0 :+ 1.0 findZero :: (Fractional a, Eq a) => (Forward a -> Forward a) -> a -> [a]-findZero f = go where- go x = x : if x == xn then [] else go xn where+findZero f = takeWhileDifferent . findZeroNoEq f+{-# INLINE findZero #-}++-- | The 'findZeroNoEq' function behaves the same as 'findZero' except that it+-- doesn't truncate the list once the results become constant. This means it+-- can be used with types without an 'Eq' instance.+findZeroNoEq :: Fractional a => (Forward a -> Forward a) -> a -> [a]+findZeroNoEq f = iterate go where+ go x = xn where (y,y') = diff' f x xn = x - y/y'-{-# INLINE findZero #-}+{-# INLINE findZeroNoEq #-} -- | The 'inverse' function inverts a scalar function using -- Newton's method; its output is a stream of increasingly accurate@@ -67,9 +79,16 @@ -- >>> last $ take 10 $ inverse sqrt 1 (sqrt 10) -- 10.0 inverse :: (Fractional a, Eq a) => (Forward a -> Forward a) -> a -> a -> [a]-inverse f x0 y = findZero (\x -> f x - auto y) x0+inverse f x0 = takeWhileDifferent . inverseNoEq f x0 {-# INLINE inverse #-} +-- | The 'inverseNoEq' function behaves the same as 'inverse' except that it+-- doesn't truncate the list once the results become constant. This means it+-- can be used with types without an 'Eq' instance.+inverseNoEq :: Fractional a => (Forward a -> Forward a) -> a -> a -> [a]+inverseNoEq f x0 y = findZeroNoEq (\x -> f x - auto y) x0+{-# INLINE inverseNoEq #-}+ -- | 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.)@@ -80,9 +99,16 @@ -- >>> last $ take 10 $ fixedPoint cos 1 -- 0.7390851332151607 fixedPoint :: (Fractional a, Eq a) => (Forward a -> Forward a) -> a -> [a]-fixedPoint f = findZero (\x -> f x - x)+fixedPoint f = takeWhileDifferent . fixedPointNoEq f {-# INLINE fixedPoint #-} +-- | The 'fixedPointNoEq' function behaves the same as 'fixedPoint' except that+-- it doesn't truncate the list once the results become constant. This means it+-- can be used with types without an 'Eq' instance.+fixedPointNoEq :: Fractional a => (Forward a -> Forward a) -> a -> [a]+fixedPointNoEq f = findZeroNoEq (\x -> f x - x)+{-# INLINE fixedPointNoEq #-}+ -- | 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.) If the stream@@ -91,8 +117,15 @@ -- >>> last $ take 10 $ extremum cos 1 -- 0.0 extremum :: (Fractional a, Eq a) => (On (Forward (Forward a)) -> On (Forward (Forward a))) -> a -> [a]-extremum f = findZero (diff (off . f . On))+extremum f = takeWhileDifferent . extremumNoEq f {-# INLINE extremum #-}++-- | The 'extremumNoEq' function behaves the same as 'extremum' except that it+-- doesn't truncate the list once the results become constant. This means it+-- can be used with types without an 'Eq' instance.+extremumNoEq :: Fractional a => (On (Forward (Forward a)) -> On (Forward (Forward a))) -> a -> [a]+extremumNoEq f = findZeroNoEq (diff (off . f . On))+{-# INLINE extremumNoEq #-} -- | The 'gradientDescent' function performs a multivariate -- optimization, based on the naive-gradient-descent in the file
src/Numeric/AD/Rank1/Newton/Double.hs view
@@ -17,9 +17,13 @@ ( -- * Newton's Method (Forward) findZero+ , findZeroNoEq , inverse+ , inverseNoEq , fixedPoint+ , fixedPointNoEq , extremum+ , extremumNoEq ) where import Prelude hiding (all, mapM)@@ -28,6 +32,7 @@ import qualified Numeric.AD.Rank1.Forward as Forward import Numeric.AD.Rank1.Forward.Double (ForwardDouble, diff') import Numeric.AD.Internal.On+import Numeric.AD.Internal.Combinators (takeWhileDifferent) -- | The 'findZero' function finds a zero of a scalar function using -- Newton's method; its output is a stream of increasingly accurate@@ -39,11 +44,17 @@ -- >>> take 10 $ findZero (\x->x^2-4) 1 -- [1.0,2.5,2.05,2.000609756097561,2.0000000929222947,2.000000000000002,2.0] findZero :: (ForwardDouble -> ForwardDouble) -> Double -> [Double]-findZero f = go where- go x = x : if x == xn then [] else go xn where+findZero f = takeWhileDifferent . findZeroNoEq f+{-# INLINE findZero #-}++-- | The 'findZeroNoEq' function behaves the same as 'findZero' except that it+-- doesn't truncate the list once the results become constant.+findZeroNoEq :: (ForwardDouble -> ForwardDouble) -> Double -> [Double]+findZeroNoEq f = iterate go where+ go x = xn where (y,y') = diff' f x xn = x - y/y'-{-# INLINE findZero #-}+{-# INLINE findZeroNoEq #-} -- | The 'inverse' function inverts a scalar function using -- Newton's method; its output is a stream of increasingly accurate@@ -55,9 +66,15 @@ -- >>> last $ take 10 $ inverse sqrt 1 (sqrt 10) -- 10.0 inverse :: (ForwardDouble -> ForwardDouble) -> Double -> Double -> [Double]-inverse f x0 y = findZero (\x -> f x - auto y) x0+inverse f x0 = takeWhileDifferent . inverseNoEq f x0 {-# INLINE inverse #-} +-- | The 'inverseNoEq' function behaves the same as 'inverse' except that it+-- doesn't truncate the list once the results become constant.+inverseNoEq :: (ForwardDouble -> ForwardDouble) -> Double -> Double -> [Double]+inverseNoEq f x0 y = findZeroNoEq (\x -> f x - auto y) x0+{-# INLINE inverseNoEq #-}+ -- | 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.)@@ -68,9 +85,15 @@ -- >>> last $ take 10 $ fixedPoint cos 1 -- 0.7390851332151607 fixedPoint :: (ForwardDouble -> ForwardDouble) -> Double -> [Double]-fixedPoint f = findZero (\x -> f x - x)+fixedPoint f = takeWhileDifferent . fixedPointNoEq f {-# INLINE fixedPoint #-} +-- | The 'fixedPointNoEq' function behaves the same as 'fixedPoint' except that+-- doesn't truncate the list once the results become constant.+fixedPointNoEq :: (ForwardDouble -> ForwardDouble) -> Double -> [Double]+fixedPointNoEq f = findZeroNoEq (\x -> f x - x)+{-# INLINE fixedPointNoEq #-}+ -- | 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.) If the stream@@ -79,5 +102,11 @@ -- >>> last $ take 10 $ extremum cos 1 -- 0.0 extremum :: (On (Forward ForwardDouble) -> On (Forward ForwardDouble)) -> Double -> [Double]-extremum f = findZero (Forward.diff (off . f . On))+extremum f = takeWhileDifferent . extremumNoEq f {-# INLINE extremum #-}++-- | The 'extremumNoEq' function behaves the same as 'extremum' except that it+-- doesn't truncate the list once the results become constant.+extremumNoEq :: (On (Forward ForwardDouble) -> On (Forward ForwardDouble)) -> Double -> [Double]+extremumNoEq f = findZeroNoEq (Forward.diff (off . f . On))+{-# INLINE extremumNoEq #-}