| Copyright | (C) 2025 Alexey Tochin |
|---|---|
| License | BSD3 (see the file LICENSE) |
| Maintainer | Alexey Tochin <Alexey.Tochin@gmail.com> |
| Safe Haskell | None |
| Language | Haskell2010 |
Numeric.InfBackprop
Description
| Module providing all functionality of the library. It re-exports all important types and functions from submodules. See the documentation of individual submodules for details.
Synopsis
- type family Tangent a
- type family Dual x
- type Cotangent a = Dual (Tangent a)
- type CT a = Cotangent a
- data RevDiff a b c = MkRevDiff {}
- type RevDiff' a b = RevDiff (CT a) (CT b) b
- type DifferentiableFunc a b = forall t. RevDiff t (CT a) a -> RevDiff t (CT b) b
- initDiff :: a -> RevDiff b b a
- call :: (RevDiff' a a -> RevDiff' a b) -> a -> b
- derivativeOp :: (RevDiff' a a -> RevDiff' a b) -> a -> CT b -> CT a
- constDiff :: Additive a => c -> RevDiff a b c
- scalarArg :: RevDiff a b c -> RevDiff a b c
- scalarVal :: Multiplicative b => RevDiff a b c -> a
- autoArg :: AutoDifferentiableArgument a => RevDiff (DerivativeRoot a) (DerivativeCoarg a) (DerivativeArg a) -> a
- autoVal :: AutoDifferentiableValue a => a -> DerivativeValue a
- stopDiff :: StopDiff a b => a -> b
- simpleDifferentiableFunc :: Multiplicative b => (b -> b) -> (b -> b) -> RevDiff a b b -> RevDiff a b b
- toLensOps :: (RevDiff ca ca a -> RevDiff ca cb b) -> a -> (b, cb -> ca)
- toLens :: (RevDiff b b a -> RevDiff b d c) -> Lens a b c d
- fromLens :: Lens a (CT a) b (CT b) -> RevDiff' a a -> RevDiff' a b
- fromProfunctors :: (forall (p :: Type -> Type -> Type). Costrong p => p (CT a) a -> p (CT b) b) -> DifferentiableFunc a b
- toProfunctors :: Costrong p => DifferentiableFunc a b -> p (CT a) a -> p (CT b) b
- fromVanLaarhoven :: forall a b. (forall (f :: Type -> Type). Functor f => (b -> f (CT b)) -> a -> f (CT a)) -> DifferentiableFunc a b
- toVanLaarhoven :: Functor f => DifferentiableFunc a b -> (b -> f (CT b)) -> a -> f (CT a)
- scalarArgDerivative :: AutoDifferentiableValue c => (RevDiff' a a -> c) -> a -> DerivativeValue c
- customArgDerivative :: AutoDifferentiableValue c => (RevDiff (CT a) (CT a) a -> b) -> (b -> c) -> a -> DerivativeValue c
- customValDerivative :: (DerivativeRoot b ~ CT (DerivativeArg b), DerivativeCoarg b ~ CT (DerivativeArg b), AutoDifferentiableArgument b) => (c -> d) -> (b -> c) -> DerivativeArg b -> d
- scalarValDerivative :: (DerivativeRoot b ~ CT a, DerivativeCoarg b ~ CT a, DerivativeArg b ~ a, Multiplicative (CT c), AutoDifferentiableArgument b) => (b -> RevDiff d (CT c) c) -> a -> d
- simpleDerivative :: forall a b. Multiplicative (CT b) => (RevDiff' a a -> RevDiff' a b) -> a -> CT a
- simpleValueAndDerivative :: forall a b. Multiplicative (CT b) => (RevDiff' a a -> RevDiff' a b) -> a -> (b, CT a)
- customArgValDerivative :: (RevDiff (CT a) (CT a) a -> b) -> (c -> d) -> (b -> c) -> a -> d
- twoArgsDerivative :: (Additive (CT a0), Additive (CT a1), AutoDifferentiableValue b) => (RevDiff' (a0, a1) a0 -> RevDiff' (a0, a1) a1 -> b) -> a0 -> a1 -> DerivativeValue b
- twoArgsDerivativeOverX :: (Additive (CT a0), AutoDifferentiableValue b) => (RevDiff' a0 a0 -> RevDiff' a0 a1 -> b) -> a0 -> a1 -> DerivativeValue b
- twoArgsDerivativeOverY :: (Additive (CT a1), AutoDifferentiableValue b) => (RevDiff' a1 a0 -> RevDiff' a1 a1 -> b) -> a0 -> a1 -> DerivativeValue b
- tupleDerivativeOverX :: (AutoDifferentiableValue b, Additive (CT a0)) => ((RevDiff' a0 a0, RevDiff' a0 a1) -> b) -> (a0, a1) -> DerivativeValue b
- tupleDerivativeOverY :: (Additive (CT a1), AutoDifferentiableValue b) => ((RevDiff' a1 a0, RevDiff' a1 a1) -> b) -> (a0, a1) -> DerivativeValue b
- mkTupleArg :: (Additive b0, Additive b1) => RevDiffArg a b0 c0 d0 -> RevDiffArg a b1 c1 d1 -> RevDiffArg a (b0, b1) (c0, c1) (d0, d1)
- tupleArg :: (Additive b0, Additive b1) => RevDiff a (b0, b1) (c0, c1) -> (RevDiff a b0 c0, RevDiff a b1 c1)
- tupleArgDerivative :: (Additive (CT a0), Additive (CT a1), AutoDifferentiableValue b) => ((RevDiff' (a0, a1) a0, RevDiff' (a0, a1) a1) -> b) -> (a0, a1) -> DerivativeValue b
- mkTupleVal :: (a0 -> b0) -> (a1 -> b1) -> (a0, a1) -> (b0, b1)
- tupleVal :: (Multiplicative b0, Multiplicative b1) => (RevDiff a0 b0 c0, RevDiff a1 b1 c1) -> (a0, a1)
- tupleValDerivative :: (AutoDifferentiableArgument a, Multiplicative c0, Multiplicative c1, DerivativeCoarg a ~ CT (DerivativeArg a), DerivativeRoot a ~ CT (DerivativeArg a)) => (a -> (RevDiff b0 c0 d0, RevDiff b1 c1 d1)) -> DerivativeArg a -> (b0, b1)
- threeArgsToTriple :: Additive a => RevDiff a b0 c0 -> RevDiff a b1 c1 -> RevDiff a b2 c2 -> RevDiff a (b0, b1, b2) (c0, c1, c2)
- threeArgsDerivative :: (AutoDifferentiableValue b, Additive (CT a0), Additive (CT a1), Additive (CT a2)) => (RevDiff' (a0, a1, a2) a0 -> RevDiff' (a0, a1, a2) a1 -> RevDiff' (a0, a1, a2) a2 -> b) -> a0 -> a1 -> a2 -> DerivativeValue b
- derivative3ArgsOverX :: (AutoDifferentiableValue b, Additive (CT a0)) => (RevDiff' a0 a0 -> RevDiff' a0 a1 -> RevDiff' a0 a2 -> b) -> a0 -> a1 -> a2 -> DerivativeValue b
- derivative3ArgsOverY :: (AutoDifferentiableValue b, Additive (CT a1)) => (RevDiff' a1 a0 -> RevDiff' a1 a1 -> RevDiff' a1 a2 -> b) -> a0 -> a1 -> a2 -> DerivativeValue b
- derivative3ArgsOverZ :: (AutoDifferentiableValue b, Additive (CT a2)) => (RevDiff' a2 a0 -> RevDiff' a2 a1 -> RevDiff' a2 a2 -> b) -> a0 -> a1 -> a2 -> DerivativeValue b
- tripleDerivativeOverX :: (AutoDifferentiableValue b, Additive (CT a0)) => ((RevDiff' a0 a0, RevDiff' a0 a1, RevDiff' a0 a2) -> b) -> (a0, a1, a2) -> DerivativeValue b
- tripleDerivativeOverY :: (AutoDifferentiableValue b, Additive (CT a1)) => ((RevDiff' a1 a0, RevDiff' a1 a1, RevDiff' a1 a2) -> b) -> (a0, a1, a2) -> DerivativeValue b
- tripleDerivativeOverZ :: (AutoDifferentiableValue b, Additive (CT a2)) => ((RevDiff' a2 a0, RevDiff' a2 a1, RevDiff' a2 a2) -> b) -> (a0, a1, a2) -> DerivativeValue b
- mkTripleArg :: (Additive b0, Additive b1, Additive b2) => RevDiffArg a b0 c0 d0 -> RevDiffArg a b1 c1 d1 -> RevDiffArg a b2 c2 d2 -> RevDiffArg a (b0, b1, b2) (c0, c1, c2) (d0, d1, d2)
- tripleArg :: (Additive b0, Additive b1, Additive b2) => RevDiff a (b0, b1, b2) (c0, c1, c2) -> (RevDiff a b0 c0, RevDiff a b1 c1, RevDiff a b2 c2)
- tripleArgDerivative :: (Additive (CT a0), Additive (CT a1), Additive (CT a2), AutoDifferentiableValue b) => ((RevDiff' (a0, a1, a2) a0, RevDiff' (a0, a1, a2) a1, RevDiff' (a0, a1, a2) a2) -> b) -> (a0, a1, a2) -> DerivativeValue b
- mkTripleVal :: (a0 -> b0) -> (a1 -> b1) -> (a2 -> b2) -> (a0, a1, a2) -> (b0, b1, b2)
- tripleVal :: (Multiplicative b0, Multiplicative b1, Multiplicative b2) => (RevDiff a0 b0 c0, RevDiff a1 b1 c1, RevDiff a2 b2 c2) -> (a0, a1, a2)
- tripleValDerivative :: (AutoDifferentiableArgument a, Multiplicative c0, Multiplicative c1, Multiplicative c2, DerivativeCoarg a ~ CT (DerivativeArg a), DerivativeRoot a ~ CT (DerivativeArg a)) => (a -> (RevDiff b0 c0 d0, RevDiff b1 c1 d1, RevDiff b2 c2 d2)) -> DerivativeArg a -> (b0, b1, b2)
- mkBoxedVectorArg :: forall b (n :: Nat) a c d. (Additive b, KnownNat n) => RevDiffArg a b c d -> RevDiffArg a (BoxedVector n b) (BoxedVector n c) (BoxedVector n d)
- boxedVectorArg :: forall b (n :: Nat) a c. (Additive b, KnownNat n) => RevDiff a (BoxedVector n b) (BoxedVector n c) -> BoxedVector n (RevDiff a b c)
- boxedVectorArgDerivative :: forall (n :: Nat) b a. (KnownNat n, AutoDifferentiableValue b, Additive (CT a)) => (BoxedVector n (RevDiff' (BoxedVector n a) a) -> b) -> BoxedVector n a -> DerivativeValue b
- mkBoxedVectorVal :: forall a b (n :: Nat). (a -> b) -> BoxedVector n a -> BoxedVector n b
- boxedVectorVal :: forall b (n :: Nat) a c. Multiplicative b => BoxedVector n (RevDiff a b c) -> BoxedVector n a
- boxedVectorValDerivative :: forall a c (n :: Nat) b d. (AutoDifferentiableArgument a, Multiplicative c, DerivativeCoarg a ~ CT (DerivativeArg a), DerivativeRoot a ~ CT (DerivativeArg a)) => (a -> BoxedVector n (RevDiff b c d)) -> DerivativeArg a -> BoxedVector n b
- mkStreamArg :: Additive b => (RevDiff a b c -> d) -> RevDiff a (FiniteSupportStream b) (Stream c) -> Stream d
- streamArg :: Additive b => RevDiff a (FiniteSupportStream b) (Stream c) -> Stream (RevDiff a b c)
- streamArgDerivative :: (AutoDifferentiableValue b, Additive (CT a)) => (Stream (RevDiff' (Stream a) a) -> b) -> Stream a -> DerivativeValue b
- mkStreamVal :: (a -> b) -> Stream a -> Stream b
- streamVal :: Multiplicative b => Stream (RevDiff a b c) -> Stream a
- streamValDerivative :: (AutoDifferentiableArgument a, Multiplicative c, DerivativeCoarg a ~ CT (DerivativeArg a), DerivativeRoot a ~ CT (DerivativeArg a)) => (a -> Stream (RevDiff b c d)) -> DerivativeArg a -> Stream b
- mkFiniteSupportStreamArg :: Additive b => (RevDiff a b c -> d) -> RevDiff a (Stream b) (FiniteSupportStream c) -> FiniteSupportStream d
- finiteSupportStreamArg :: Additive b => RevDiff a (Stream b) (FiniteSupportStream c) -> FiniteSupportStream (RevDiff a b c)
- finiteSupportStreamArgDerivative :: (AutoDifferentiableValue b, Additive (CT a)) => (FiniteSupportStream (RevDiff' (FiniteSupportStream a) a) -> b) -> FiniteSupportStream a -> DerivativeValue b
- mkFiniteSupportStreamVal :: (a -> b) -> FiniteSupportStream a -> FiniteSupportStream b
- finiteSupportStreamVal :: Multiplicative b => FiniteSupportStream (RevDiff a b c) -> FiniteSupportStream a
- finiteSupportStreamValDerivative :: (AutoDifferentiableArgument a, Multiplicative c, DerivativeCoarg a ~ CT (DerivativeArg a), DerivativeRoot a ~ CT (DerivativeArg a)) => (a -> FiniteSupportStream (RevDiff b c d)) -> DerivativeArg a -> FiniteSupportStream b
- maybeArg :: RevDiff a (Maybe b) (Maybe c) -> Maybe (RevDiff a b c)
- mkMaybeArg :: (RevDiff a b c -> d) -> RevDiff a (Maybe b) (Maybe c) -> Maybe d
- maybeArgDerivative :: AutoDifferentiableValue b => (Maybe (RevDiff' (Maybe a) a) -> b) -> Maybe a -> DerivativeValue b
- maybeVal :: Multiplicative b => Maybe (RevDiff a b c) -> Maybe a
- mkMaybeVal :: (a -> b) -> Maybe a -> Maybe b
- maybeValDerivative :: (AutoDifferentiableArgument a, Multiplicative c, DerivativeCoarg a ~ CT (DerivativeArg a), DerivativeRoot a ~ CT (DerivativeArg a)) => (a -> Maybe (RevDiff b c d)) -> DerivativeArg a -> Maybe b
Common
Base
type family Tangent a Source #
Converts a type into its tangent space type.
Instances
| type Tangent SimpleExpr Source # | |
Defined in Numeric.InfBackprop.Core type Tangent SimpleExpr = SimpleExpr | |
| type Tangent Integer Source # | |
Defined in Numeric.InfBackprop.Core | |
| type Tangent Float Source # | |
Defined in Numeric.InfBackprop.Core | |
| type Tangent (Stream a) Source # | |
Defined in Numeric.InfBackprop.Core | |
| type Tangent (FiniteSupportStream a) Source # | |
Defined in Numeric.InfBackprop.Core | |
| type Tangent (Complex a) Source # | |
Defined in Numeric.InfBackprop.Core | |
| type Tangent (Traced a) Source # | |
Defined in Numeric.InfBackprop.Core | |
| type Tangent (Maybe a) Source # | |
Defined in Numeric.InfBackprop.Core | |
| type Tangent [a] Source # | |
Defined in Numeric.InfBackprop.Core | |
| type Tangent (Vec n a) Source # | |
Defined in Numeric.InfBackprop.Core | |
| type Tangent (a0, a1) Source # | |
Defined in Numeric.InfBackprop.Core | |
| type Tangent (RevDiff a b c) Source # | |
| type Tangent (Vector v n a) Source # | |
Defined in Numeric.InfBackprop.Core | |
| type Tangent (a0, a1, a2) Source # | |
Defined in Numeric.InfBackprop.Core | |
Converts a type into its dual space type.
Instances
| type Dual SimpleExpr Source # | |
Defined in Numeric.InfBackprop.Core type Dual SimpleExpr = SimpleExpr | |
| type Dual Integer Source # | |
Defined in Numeric.InfBackprop.Core | |
| type Dual Float Source # | |
Defined in Numeric.InfBackprop.Core | |
| type Dual (Stream a) Source # | |
Defined in Numeric.InfBackprop.Core | |
| type Dual (FiniteSupportStream a) Source # | |
Defined in Numeric.InfBackprop.Core | |
| type Dual (Complex a) Source # | |
Defined in Numeric.InfBackprop.Core | |
| type Dual (SimpleExprF a) Source # | |
Defined in Numeric.InfBackprop.Core | |
| type Dual (Traced a) Source # | |
Defined in Numeric.InfBackprop.Core | |
| type Dual (Maybe a) Source # | |
Defined in Numeric.InfBackprop.Core | |
| type Dual [a] Source # | |
Defined in Numeric.InfBackprop.Core | |
| type Dual (Vec n a) Source # | |
Defined in Numeric.InfBackprop.Core | |
| type Dual (a, b) Source # | |
Defined in Numeric.InfBackprop.Core | |
| type Dual (RevDiff a b c) Source # | |
| type Dual (Vector v n a) Source # | |
Defined in Numeric.InfBackprop.Core | |
| type Dual (a, b, c) Source # | |
Defined in Numeric.InfBackprop.Core | |
Base type for differentiable instances with the backpropagation.
Examples
>>>:{differentiableSin_ :: RevDiff t Float Float -> RevDiff t Float Float differentiableSin_ (MkRevDiff v bp) = MkRevDiff (sin v) (bp . (cos v *)) :}
>>>value $ differentiableSin_ (MkRevDiff 0.0 id)0.0
>>>backprop (differentiableSin_ (MkRevDiff 0.0 id)) 1.01.0
Num typeclass instance
This instance enables the use of standard numeric operations and literals
directly with RevDiff values, simplifying the syntax for
automatic differentiation computations.--
The instance supports Num operations including arithmetic
operators (+), (-), (*), comparison functions (abs, signum), and automatic
conversion from integer literals via fromInteger.
Examples
>>>import Debug.SimpleExpr (variable, SE, simplify)>>>import GHC.Integer (Integer)
>>>x = variable "x"
Using numeric literals in automatic differentiation
This instance allows RevDiff values to be created directly from integer
literals, eliminating the need for explicit conversion functions.
Consider computing the partial derivative:
\[ \left.\frac{\partial}{\partial y} (x \cdot y)\right|_{y=2} \]
Without the Num instance, we would need explicit conversion:
>>>simplify $ twoArgsDerivativeOverY (*) x (stopDiff $ number 2) :: SEx
With the Num instance for RevDiff, this simplifies to:
>>>simplify $ twoArgsDerivativeOverY (*) x (number 2) :: SEx
And combined with the Num instance for SE,
we achieve the most concise form:
>>>simplify $ twoArgsDerivativeOverY (*) x 2x
This progression shows how the typeclass instances work together to enable increasingly natural mathematical notation.
Power function differentiation
The instance enables natural exponentiation syntax with automatic differentiation:
>>>x ** 3 :: SEx^3>>>simplify $ simpleDerivative (** 3) x :: SE3*(x^2)>>>simplify $ simpleDerivative (simpleDerivative (** 3)) x :: SE(2*x)*3
Absolute value and signum functions
The instance provides symbolic differentiation for absolute value and signum:
>>>simplify $ simpleDerivative GHCN.abs (variable "x") :: SEsign(x)
>>>simplify $ simpleDerivative GHCN.signum (variable "x") :: SE0
For numeric evaluation, the second derivative of absolute value at a point gives the expected result:
>>>(simpleDerivative (simpleDerivative GHCN.abs)) (1 :: Float) :: Float0.0
Notice that the signum function returns zero for all values, including zero.
>>>simpleDerivative GHCN.signum (0 :: Float) :: Float0.0
>>>simplify $ (simpleDerivative (simpleDerivative GHCN.abs)) (variable "x") :: SE0
Fractional typeclass instance
Thank to this instance we can use numerical literals like '1.0', '2.0', etc., see the examples below.
Examples
>>>import GHC.Float (Float)>>>import Debug.SimpleExpr (variable, SE, simplify)
>>>f x = 8 / x>>>simpleDerivative f (2.0 :: Float)-2.0>>>simplify $ simpleDerivative f (variable "x") :: SE-((8/x)/x)
Instances
type RevDiff' a b = RevDiff (CT a) (CT b) b Source #
Type alias for common case where the backpropagation is in the cotangent space.
type DifferentiableFunc a b = forall t. RevDiff t (CT a) a -> RevDiff t (CT b) b Source #
Type DifferentiableFunc a b may be associated with the differentiable
functions from a to b.
Composition (.) of
DifferentiableFunc b c and DifferentiableFunc a b is DifferentiableFunc a c
by definition.
See fromProfunctors, toProfunctors, fromVanLaarhoven and fromVanLaarhoven
for illustraing how to use this type.
Examples
>>>:{differentiableCos_ :: DifferentiableFunc Float Float differentiableCos_ (MkRevDiff x bpc) = MkRevDiff (cos x) (bpc . ((negate $ sin x) *)) :}
>>>call differentiableCos_ 0.01.0
>>>simpleDerivative differentiableCos_ 0.0-0.0
initDiff :: a -> RevDiff b b a Source #
Initializes a MkRevDiff instance with given value
and identity backpropagation function.
This is useful for starting the backpropagation chain.
Examples
>>>:{differentiableCos_ :: RevDiff t Float Float -> RevDiff t Float Float differentiableCos_ (MkRevDiff v bp) = MkRevDiff (cos v) (bp . negate . (sin v *)) :}
>>>value $ differentiableCos_ (initDiff 0.0)1.0
>>>backprop (differentiableCos_ (initDiff 0.0)) 1.0-0.0
call :: (RevDiff' a a -> RevDiff' a b) -> a -> b Source #
Converts a differentiable function into a regular function.
Examples
>>>import Debug.SimpleExpr (variable)>>>import Debug.DiffExpr (unarySymbolicFunc)
>>>:{differentiableCos_ :: RevDiff t Float Float -> RevDiff t Float Float differentiableCos_ (MkRevDiff v bp) = MkRevDiff (cos v) (bp . negate . (sin v *)) :}
>>>call differentiableCos_ 0.01.0
>>>x = variable "x">>>f = unarySymbolicFunc "f">>>f xf(x)
>>>call f xf(x)
derivativeOp :: (RevDiff' a a -> RevDiff' a b) -> a -> CT b -> CT a Source #
Converts a differentiable function into into its derivative in the form of multiplicative operator.
Examples
>>>import Debug.SimpleExpr (variable)>>>import Debug.DiffExpr (unarySymbolicFunc)
>>>:{differentiableSin_ :: RevDiff t Float Float -> RevDiff t Float Float differentiableSin_ (MkRevDiff v bp) = MkRevDiff (sin v) (bp . (cos v *)) :}
>>>(derivativeOp differentiableSin_ 0.0) 1.01.0
>>>c = variable "c">>>x = variable "x">>>f = unarySymbolicFunc "f">>>f xf(x)>>>(derivativeOp f x) cf'(x)*c
constDiff :: Additive a => c -> RevDiff a b c Source #
Creates a constant differentiable function. The derivative of a constant function is always zero.
Examples
>>>value (constDiff 42.0 :: RevDiff' Float Float)42.0
>>>backprop (constDiff 42.0 :: RevDiff' Float Float) 1.00.0
scalarArg :: RevDiff a b c -> RevDiff a b c Source #
Scalar (trivial) argument descriptor for differentiable functions.
Examples
>>>import Debug.DiffExpr (unarySymbolicFunc, SymbolicFunc)>>>import Debug.SimpleExpr (variable, SimpleExpr, simplify, SE)
>>>scalarArgDerivative = customArgDerivative scalarArg
>>>t = variable "t">>>:{v :: SymbolicFunc a => a -> BoxedVector 3 a v t = DVGS.fromTuple ( unarySymbolicFunc "v_x" t, unarySymbolicFunc "v_y" t, unarySymbolicFunc "v_z" t ) :}
>>>v tVector [v_x(t),v_y(t),v_z(t)]
>>>v' = simplify . scalarArgDerivative v :: SE -> BoxedVector 3 SE>>>v' tVector [v_x'(t),v_y'(t),v_z'(t)]
scalarVal :: Multiplicative b => RevDiff a b c -> a Source #
Scalar value term.
Examples
>>>:{product :: (Multiplicative a) => (a, a) -> a product (x, y) = x * y :}
>>>product' = customArgValDerivative tupleArg scalarVal product
>>>product' (2 :: Float, 3 :: Float)(3.0,2.0)
>>>import Debug.SimpleExpr (variable, simplify, SimpleExpr)>>>x = variable "x">>>y = variable "y">>>simplify $ product' (x, y) :: (SimpleExpr, SimpleExpr)(y,x)
autoArg :: AutoDifferentiableArgument a => RevDiff (DerivativeRoot a) (DerivativeCoarg a) (DerivativeArg a) -> a Source #
Automatic argument descriptor.
autoVal :: AutoDifferentiableValue a => a -> DerivativeValue a Source #
Automatic value descriptor.
stopDiff :: StopDiff a b => a -> b Source #
Stops differentiation by converting a nested RevDiff type
into a non-differentiable type.
simpleDifferentiableFunc :: Multiplicative b => (b -> b) -> (b -> b) -> RevDiff a b b -> RevDiff a b b Source #
Creates a differentiable function from a function and its derivative. This is a convenience function for defining new differentiable operations.
Examples
>>>:{differentiableCos_ :: RevDiff t Float Float -> RevDiff t Float Float differentiableCos_ = simpleDifferentiableFunc cos (negate . sin) :}
>>>call differentiableCos_ 0.01.0
>>>simpleDerivative differentiableCos_ 0.0-0.0
Relation to lens and profunctors
toLensOps :: (RevDiff ca ca a -> RevDiff ca cb b) -> a -> (b, cb -> ca) Source #
Converts a function into a pair of its value and backpropagation function, which are the lense get and set functions, respectively.
toLens :: (RevDiff b b a -> RevDiff b d c) -> Lens a b c d Source #
Converts a differentiable function into a law-breaking Lens.
This is mutually inverse with fromLens.
Examples
>>>import Optics (Lens', lens, view, set, getting, (%))>>>import Debug.SimpleExpr (variable, SE)
>>>sinLens = toLens sin :: Lens' SE SE>>>x = variable "x">>>c = variable "c">>>(view . getting) sinLens xsin(x)>>>set sinLens c xcos(x)*c>>>squareLens = toLens (^2) :: Lens' SE SE>>>(view . getting) (squareLens % sinLens) xsin(x^2)
fromLens :: Lens a (CT a) b (CT b) -> RevDiff' a a -> RevDiff' a b Source #
Converts a law-breaking Lens into a differentiable function.
This is mutually inverse with toLens.
Examples
>>>import Optics (lens)>>>import Debug.SimpleExpr (variable, SE, simplify)
>>>sinV2 = fromLens $ lens sin (\x -> (cos x *))>>>x = variable "x">>>c = variable "c">>>call sinV2 xsin(x)>>>simplify $ simpleDerivative sinV2 x :: SEcos(x)
fromProfunctors :: (forall (p :: Type -> Type -> Type). Costrong p => p (CT a) a -> p (CT b) b) -> DifferentiableFunc a b Source #
Transorfms profunctor (Costrong) map into a RevDiff map.
Inverse of toProfunctors.
toProfunctors :: Costrong p => DifferentiableFunc a b -> p (CT a) a -> p (CT b) b Source #
Profunctor representation of the RevDiff like for lens map in the spirit of optics.
Inverse of fromProfunctors.
fromVanLaarhoven :: forall a b. (forall (f :: Type -> Type). Functor f => (b -> f (CT b)) -> a -> f (CT a)) -> DifferentiableFunc a b Source #
Converts a Van Laarhoven representation to a function over RevDiff types
Inverse of toVanLaarhoven.
toVanLaarhoven :: Functor f => DifferentiableFunc a b -> (b -> f (CT b)) -> a -> f (CT a) Source #
Converts a function over RevDiff types into a Van Laarhoven representation.
Inverse of fromVanLaarhoven.
Derivative operators
scalarArgDerivative :: AutoDifferentiableValue c => (RevDiff' a a -> c) -> a -> DerivativeValue c Source #
Derivative operator for a function from a scalar to any supported value type.
Examples
>>>import Debug.SimpleExpr (variable, simplify, SE)
>>>:{f :: TrigField a => a -> (a, a) f t = (cos t, sin t) :}
>>>f' = scalarArgDerivative f
>>>f (0 :: Float)(1.0,0.0)>>>f' (0 :: Float)(-0.0,1.0)
>>>t = variable "t">>>f t(cos(t),sin(t))>>>simplify $ scalarArgDerivative f t :: (SE, SE)(-(sin(t)),cos(t))
customArgDerivative :: AutoDifferentiableValue c => (RevDiff (CT a) (CT a) a -> b) -> (b -> c) -> a -> DerivativeValue c Source #
Derivative operator for a function with a specified argument type, but with the value type derived automatically.
Examples
>>>:{sphericToVec :: (TrigField a) => (a, a) -> BoxedVector 3 a sphericToVec (theta, phi) = DVGS.fromTuple (cos theta * cos phi, cos theta * sin phi, sin theta) :}
>>>sphericToVec' = customArgDerivative tupleArg sphericToVec
Here tupleArg indicates that the argument type is a tuple.
>>>sphericToVec' (0 :: Float, 0 :: Float)Vector [(0.0,0.0),(0.0,1.0),(1.0,0.0)]
customValDerivative :: (DerivativeRoot b ~ CT (DerivativeArg b), DerivativeCoarg b ~ CT (DerivativeArg b), AutoDifferentiableArgument b) => (c -> d) -> (b -> c) -> DerivativeArg b -> d Source #
Derivative operator for a function with specified argument type but automatically derived value type.
Examples
>>>:{sphericToVector :: (TrigField a) => (a, a) -> BoxedVector 3 a sphericToVector (theta, phi) = DVGS.fromTuple (cos theta * cos phi, cos theta * sin phi, sin theta) :}
>>>sphericToVector' = customValDerivative boxedVectorVal sphericToVector
The term boxedVectorVal specifies that the output value type is a boxed vector.
>>>sphericToVector' (0 :: Float, 0 :: Float)Vector [(0.0,0.0),(0.0,1.0),(1.0,0.0)]
scalarValDerivative :: (DerivativeRoot b ~ CT a, DerivativeCoarg b ~ CT a, DerivativeArg b ~ a, Multiplicative (CT c), AutoDifferentiableArgument b) => (b -> RevDiff d (CT c) c) -> a -> d Source #
Derivative operator for a function from any supported argument type to a scalar value.
Examples
>>>import Debug.SimpleExpr (variable, simplify, SE)
>>>:{f :: Additive a => (a, a) -> a f (x, y) = x + y :}
>>>f (2 :: Float, 3 :: Float)5.0>>>x = variable "x">>>y = variable "y">>>f (x, y)x+y
>>>:{f' :: (Additive a, Distributive (CT a)) => (a, a) -> (CT a, CT a) f' = scalarValDerivative f :}
>>>f' (2 :: Float, 3 :: Float)(1.0,1.0)>>>simplify $ f' (x, y) :: (SE, SE)(1,1)
simpleDerivative :: forall a b. Multiplicative (CT b) => (RevDiff' a a -> RevDiff' a b) -> a -> CT a Source #
Derivative for a scalar-to-scalar function.
Examples
>>>import Debug.SimpleExpr (variable, simplify, SimpleExpr)>>>import Debug.DiffExpr (unarySymbolicFunc)
>>>simpleDerivative sin (0.0 :: Float)1.0
>>>x = variable "x"
>>>simplify $ simpleDerivative (^ 2) x2*x
>>>f = unarySymbolicFunc "f"
>>>simplify $ simpleDerivative f x :: SimpleExprf'(x)
simpleValueAndDerivative :: forall a b. Multiplicative (CT b) => (RevDiff' a a -> RevDiff' a b) -> a -> (b, CT a) Source #
Returns both the value and the derivative for a scalar-to-scalar function.
Examples
>>>import Debug.SimpleExpr (variable, simplify, SimpleExpr)>>>import Debug.DiffExpr (unarySymbolicFunc)
>>>simpleValueAndDerivative sin (0.0 :: Float)(0.0,1.0)
>>>x = variable "x">>>f = unarySymbolicFunc "f"
>>>simplify $ simpleValueAndDerivative f x :: (SimpleExpr, SimpleExpr)(f(x),f'(x))
customArgValDerivative :: (RevDiff (CT a) (CT a) a -> b) -> (c -> d) -> (b -> c) -> a -> d Source #
Derivative of a function from any type to any type. The type structure of the input and output values must be specified in the first and second arguments, respectively. The output value type of the derivative is infereced automatically.
Examples
>>>:{sphericToVec :: (TrigField a) => (a, a) -> BoxedVector 3 a sphericToVec (theta, phi) = DVGS.fromTuple (cos theta * cos phi, cos theta * sin phi, sin theta) :}
>>>sphericToVec' = customArgValDerivative tupleArg boxedVectorVal sphericToVec
Here tupleArg manifests that the argument type is a tuple.
The second term boxedVectorVal specifies that the output value type is a boxed vector.
>>>sphericToVec' (0 :: Float, 0 :: Float)Vector [(0.0,0.0),(0.0,1.0),(1.0,0.0)]
Differentiable types
Tuple
twoArgsDerivative :: (Additive (CT a0), Additive (CT a1), AutoDifferentiableValue b) => (RevDiff' (a0, a1) a0 -> RevDiff' (a0, a1) a1 -> b) -> a0 -> a1 -> DerivativeValue b Source #
Differentiable operator for functions over two arguments
and any supported by AutoDifferentiableValue value type.
Equivalent to tupleArgDerivative up to the curring.
Examples
>>>import Debug.SimpleExpr (variable, simplify, SE)>>>import Debug.DiffExpr (SymbolicFunc, unarySymbolicFunc)
>>>:{x = variable "x" y = variable "y" f :: SymbolicFunc a => a -> a f = unarySymbolicFunc "f" g :: SymbolicFunc a => a -> a g = unarySymbolicFunc "g" h :: (SymbolicFunc a, Multiplicative a) => a -> a -> a h x y = f x * g y :}
>>>f(x)*g(y)f(x)*g(y)
>>>:{h' :: SE -> SE -> (SE, SE) h' = simplify . twoArgsDerivative h :}
>>>h' x y(f'(x)*g(y),g'(y)*f(x))
>>>:{h'' :: SE -> SE -> ((SE, SE), (SE, SE)) h'' = simplify . twoArgsDerivative (twoArgsDerivative h) :}
>>>h'' x y((f''(x)*g(y),g'(y)*f'(x)),(f'(x)*g'(y),g''(y)*f(x)))
twoArgsDerivativeOverX :: (Additive (CT a0), AutoDifferentiableValue b) => (RevDiff' a0 a0 -> RevDiff' a0 a1 -> b) -> a0 -> a1 -> DerivativeValue b Source #
Differentiable operator for functions over two arguments
with respect to the first argument.
Equivalent to tupleDerivativeOverX up to the curring.
Examples
>>>import Debug.SimpleExpr (variable, simplify, SE)>>>import Debug.DiffExpr (SymbolicFunc, unarySymbolicFunc)
>>>:{x = variable "x" y = variable "y" f :: SymbolicFunc a => a -> a f = unarySymbolicFunc "f" g :: SymbolicFunc a => a -> a g = unarySymbolicFunc "g" h :: (SymbolicFunc a, Multiplicative a) => a -> a -> a h x y = f x * g y :}
>>>f(x)*g(y)f(x)*g(y)
>>>:{h' :: SE -> SE -> SE h' = simplify . twoArgsDerivativeOverX h :}
>>>h' x yf'(x)*g(y)
>>>:{h'' :: SE -> SE -> SE h'' = simplify . twoArgsDerivativeOverX (twoArgsDerivativeOverX h) :}
>>>h'' x yf''(x)*g(y)
twoArgsDerivativeOverY :: (Additive (CT a1), AutoDifferentiableValue b) => (RevDiff' a1 a0 -> RevDiff' a1 a1 -> b) -> a0 -> a1 -> DerivativeValue b Source #
Differentiable operator for functions over two arguments
with respect to the second argument.
Equivalent to tupleDerivativeOverY up to the curring.
tupleDerivativeOverX :: (AutoDifferentiableValue b, Additive (CT a0)) => ((RevDiff' a0 a0, RevDiff' a0 a1) -> b) -> (a0, a1) -> DerivativeValue b Source #
Differentiable operator for functions over tuple argument with respect to the first argument.
Examples
>>>import Debug.SimpleExpr (variable, simplify, SE)>>>import Debug.DiffExpr (SymbolicFunc, unarySymbolicFunc)
>>>:{x = variable "x" y = variable "y" f :: SymbolicFunc a => a -> a f = unarySymbolicFunc "f" g :: SymbolicFunc a => a -> a g = unarySymbolicFunc "g" h :: (SymbolicFunc a, Multiplicative a) => (a, a) -> a h (x, y) = f x * g y :}
>>>f(x)*g(y)f(x)*g(y)
>>>:{h' :: (SE, SE) -> SE h' = simplify . tupleDerivativeOverX h :}
>>>h' (x, y)f'(x)*g(y)
>>>:{h'' :: (SE, SE) -> SE h'' = simplify . tupleDerivativeOverX (tupleDerivativeOverX h) :}
>>>h'' (x, y)f''(x)*g(y)
tupleDerivativeOverY :: (Additive (CT a1), AutoDifferentiableValue b) => ((RevDiff' a1 a0, RevDiff' a1 a1) -> b) -> (a0, a1) -> DerivativeValue b Source #
Differentiable operator for functions over tuple argument with respect to the second argument.
Examples
>>>import Debug.SimpleExpr (variable, simplify, SE)>>>import Debug.DiffExpr (SymbolicFunc, unarySymbolicFunc)
>>>:{x = variable "x" y = variable "y" f :: SymbolicFunc a => a -> a f = unarySymbolicFunc "f" g :: SymbolicFunc a => a -> a g = unarySymbolicFunc "g" h :: (SymbolicFunc a, Multiplicative a) => (a, a) -> a h (x, y) = f x * g y :}
>>>f(x)*g(y)f(x)*g(y)
>>>:{h' :: (SE, SE) -> SE h' = simplify . tupleDerivativeOverY h :}
>>>h' (x, y)g'(y)*f(x)
>>>:{h'' :: (SE, SE) -> SE h'' = simplify . tupleDerivativeOverY (tupleDerivativeOverY h) :}
>>>h'' (x, y)g''(y)*f(x)
mkTupleArg :: (Additive b0, Additive b1) => RevDiffArg a b0 c0 d0 -> RevDiffArg a b1 c1 d1 -> RevDiffArg a (b0, b1) (c0, c1) (d0, d1) Source #
Tuple argument descriptor builder. See this tutorial section for details and examples.
tupleArg :: (Additive b0, Additive b1) => RevDiff a (b0, b1) (c0, c1) -> (RevDiff a b0 c0, RevDiff a b1 c1) Source #
Tuple argument descriptor for differentiable functions.
Transforms a RevDiff instances of a tuple into a tuple of RevDiff instances.
This allows applying differentiable operations to both elements of the tuple.
Examples
>>>import Debug.SimpleExpr (variable, SE, simplify)>>>import Debug.DiffExpr (SymbolicFunc, unarySymbolicFunc)
>>>:{f :: Multiplicative a => (a, a) -> a f (x, y) = x * y :}
>>>:{f' :: (Distributive a, CT a ~ a) => (a, a) -> (a, a) f' = customArgDerivative tupleArg f :}
>>>simplify $ f' (variable "x", variable "y")(y,x)
tupleArgDerivative :: (Additive (CT a0), Additive (CT a1), AutoDifferentiableValue b) => ((RevDiff' (a0, a1) a0, RevDiff' (a0, a1) a1) -> b) -> (a0, a1) -> DerivativeValue b Source #
Differentiable operator for functions with tuple argument
and any supported by AutoDifferentiableValue value type.
This function is equivalent to twoArgsDerivative up to the curring.
Examples
>>>import Debug.SimpleExpr (variable, simplify, SE)>>>import Debug.DiffExpr (SymbolicFunc, unarySymbolicFunc)
>>>:{x = variable "x" y = variable "y" f :: SymbolicFunc a => a -> a f = unarySymbolicFunc "f" g :: SymbolicFunc a => a -> a g = unarySymbolicFunc "g" h :: (SymbolicFunc a, Multiplicative a) => (a, a) -> a h (x, y) = f x * g y :}
>>>f(x)*g(y)f(x)*g(y)
>>>:{h' :: (SE, SE) -> (SE, SE) h' = simplify . tupleArgDerivative h :}
>>>h' (x, y)(f'(x)*g(y),g'(y)*f(x))
>>>:{h'' :: (SE, SE) -> ((SE, SE), (SE, SE)) h'' = simplify . tupleArgDerivative (tupleArgDerivative h) :}
>>>h'' (x, y)((f''(x)*g(y),g'(y)*f'(x)),(f'(x)*g'(y),g''(y)*f(x)))
mkTupleVal :: (a0 -> b0) -> (a1 -> b1) -> (a0, a1) -> (b0, b1) Source #
Tuple differentiable value builder See this tutorial section for details and examples.
tupleVal :: (Multiplicative b0, Multiplicative b1) => (RevDiff a0 b0 c0, RevDiff a1 b1 c1) -> (a0, a1) Source #
Tuple differentiable value descriptor. See this tutorial section for details and examples.
tupleValDerivative :: (AutoDifferentiableArgument a, Multiplicative c0, Multiplicative c1, DerivativeCoarg a ~ CT (DerivativeArg a), DerivativeRoot a ~ CT (DerivativeArg a)) => (a -> (RevDiff b0 c0 d0, RevDiff b1 c1 d1)) -> DerivativeArg a -> (b0, b1) Source #
Differentiable operator for functions with tuple value and any supported by
AutoDifferentiableArgument argument type.
Examples
>>>import Debug.SimpleExpr (variable, simplify, SE)
>>>:{f :: TrigField a => a -> (a, a) f x = (sin x, cos x) :}
>>>f (variable "x")(sin(x),cos(x))
>>>:{f' :: SE -> (SE, SE) f' = simplify . tupleValDerivative f :}
>>>f' (variable "x")(cos(x),-(sin(x)))
Triple
threeArgsToTriple :: Additive a => RevDiff a b0 c0 -> RevDiff a b1 c1 -> RevDiff a b2 c2 -> RevDiff a (b0, b1, b2) (c0, c1, c2) Source #
threeArgsDerivative :: (AutoDifferentiableValue b, Additive (CT a0), Additive (CT a1), Additive (CT a2)) => (RevDiff' (a0, a1, a2) a0 -> RevDiff' (a0, a1, a2) a1 -> RevDiff' (a0, a1, a2) a2 -> b) -> a0 -> a1 -> a2 -> DerivativeValue b Source #
Differentiable operator for functions over three argument.
and any supported by AutoDifferentiableValue value type.
The output is a triple of corresponding partial derivatives.
This function is equivalent to tripleArgDerivative up to the curring.
derivative3ArgsOverX :: (AutoDifferentiableValue b, Additive (CT a0)) => (RevDiff' a0 a0 -> RevDiff' a0 a1 -> RevDiff' a0 a2 -> b) -> a0 -> a1 -> a2 -> DerivativeValue b Source #
Differentiable operator for functions over three argument
with respect to the first argument.
and any supported by AutoDifferentiableValue value type.
derivative3ArgsOverY :: (AutoDifferentiableValue b, Additive (CT a1)) => (RevDiff' a1 a0 -> RevDiff' a1 a1 -> RevDiff' a1 a2 -> b) -> a0 -> a1 -> a2 -> DerivativeValue b Source #
Differentiable operator for functions over three argument
with respect to the second argument.
and any supported by AutoDifferentiableValue value type.
derivative3ArgsOverZ :: (AutoDifferentiableValue b, Additive (CT a2)) => (RevDiff' a2 a0 -> RevDiff' a2 a1 -> RevDiff' a2 a2 -> b) -> a0 -> a1 -> a2 -> DerivativeValue b Source #
Differentiable operator for functions over three argument
with respect to the third argument.
and any supported by AutoDifferentiableValue value type.
tripleDerivativeOverX :: (AutoDifferentiableValue b, Additive (CT a0)) => ((RevDiff' a0 a0, RevDiff' a0 a1, RevDiff' a0 a2) -> b) -> (a0, a1, a2) -> DerivativeValue b Source #
Differentiable operator for functions over triple arguments with respect to the first argument.
tripleDerivativeOverY :: (AutoDifferentiableValue b, Additive (CT a1)) => ((RevDiff' a1 a0, RevDiff' a1 a1, RevDiff' a1 a2) -> b) -> (a0, a1, a2) -> DerivativeValue b Source #
Differentiable operator for functions over triple arguments with respect to the second argument.
tripleDerivativeOverZ :: (AutoDifferentiableValue b, Additive (CT a2)) => ((RevDiff' a2 a0, RevDiff' a2 a1, RevDiff' a2 a2) -> b) -> (a0, a1, a2) -> DerivativeValue b Source #
Differentiable operator for functions over triple arguments with respect to the third argument.
mkTripleArg :: (Additive b0, Additive b1, Additive b2) => RevDiffArg a b0 c0 d0 -> RevDiffArg a b1 c1 d1 -> RevDiffArg a b2 c2 d2 -> RevDiffArg a (b0, b1, b2) (c0, c1, c2) (d0, d1, d2) Source #
Triple argument builder. See this tutorial section for details and examples for the tuple.
tripleArg :: (Additive b0, Additive b1, Additive b2) => RevDiff a (b0, b1, b2) (c0, c1, c2) -> (RevDiff a b0 c0, RevDiff a b1 c1, RevDiff a b2 c2) Source #
Triple argument descriptor for differentiable functions.
Transforms a RevDiff instances of a triple into a triple of RevDiff instances.
This allows applying differentiable operations to each element of the triple.
Examples
>>>import Debug.SimpleExpr (variable, SE, simplify)>>>import Debug.DiffExpr (SymbolicFunc, unarySymbolicFunc)
>>>:{f :: Multiplicative a => (a, a, a) -> a f (x, y, z) = x * y * z :}
>>>:{f' :: (Distributive a, CT a ~ a) => (a, a, a) -> (a, a, a) f' = customArgDerivative tripleArg f :}
>>>simplify $ f' (variable "x", variable "y", variable "z")(y*z,x*z,x*y)
tripleArgDerivative :: (Additive (CT a0), Additive (CT a1), Additive (CT a2), AutoDifferentiableValue b) => ((RevDiff' (a0, a1, a2) a0, RevDiff' (a0, a1, a2) a1, RevDiff' (a0, a1, a2) a2) -> b) -> (a0, a1, a2) -> DerivativeValue b Source #
Differentiable operator for functions with triple argument
and any supported by AutoDifferentiableValue value type.
The output is a triple of corresponding partial derivatives.
This function is equivalent to threeArgsDerivative up to the curring.
Examples
>>>import Debug.SimpleExpr (variable, simplify, SE)>>>import Debug.SimpleExpr.Utils.Algebra (AlgebraicPower, square, MultiplicativeAction)>>>import Debug.DiffExpr (SymbolicFunc)
>>>:{x = variable "x" y = variable "y" z = variable "z" norm :: (AlgebraicPower Integer a, Additive a) => (a, a, a) -> a norm (x, y, z) = square x + square y + square z :}
>>>norm (x, y, z)((x^2)+(y^2))+(z^2)
>>>:{norm' :: (SE, SE, SE) -> (SE, SE, SE) norm' = simplify . tripleArgDerivative norm :}
>>>simplify $ norm' (x, y, z)(2*x,2*y,2*z)
>>>:{norm'' :: (SE, SE, SE) -> ((SE, SE, SE), (SE, SE, SE), (SE, SE, SE)) norm'' = simplify . tripleArgDerivative (tripleArgDerivative norm) :}
>>>norm'' (x, y, z)((2,0,0),(0,2,0),(0,0,2))
mkTripleVal :: (a0 -> b0) -> (a1 -> b1) -> (a2 -> b2) -> (a0, a1, a2) -> (b0, b1, b2) Source #
Triple differentiable value builder See this tutorial section for details and examples for tuple.
tripleVal :: (Multiplicative b0, Multiplicative b1, Multiplicative b2) => (RevDiff a0 b0 c0, RevDiff a1 b1 c1, RevDiff a2 b2 c2) -> (a0, a1, a2) Source #
Triple differentiable value descriptor. See this tutorial section for details and examples.
tripleValDerivative :: (AutoDifferentiableArgument a, Multiplicative c0, Multiplicative c1, Multiplicative c2, DerivativeCoarg a ~ CT (DerivativeArg a), DerivativeRoot a ~ CT (DerivativeArg a)) => (a -> (RevDiff b0 c0 d0, RevDiff b1 c1 d1, RevDiff b2 c2 d2)) -> DerivativeArg a -> (b0, b1, b2) Source #
Differentiable operator for functions with tuple value and any supported by
AutoDifferentiableArgument argument type.
Examples
>>>import Debug.SimpleExpr (variable, simplify, SE)
>>>:{f :: (Multiplicative a, IntegerPower a) => a -> (a, a, a) f x = (one, x^1, x^2) :}
>>>f (variable "x")(1,x^1,x^2)
>>>:{f' :: SE -> (SE, SE, SE) f' = simplify . tripleValDerivative f :}
>>>f' (variable "x")(0,1,2*x)
Boxed Vector
mkBoxedVectorArg :: forall b (n :: Nat) a c d. (Additive b, KnownNat n) => RevDiffArg a b c d -> RevDiffArg a (BoxedVector n b) (BoxedVector n c) (BoxedVector n d) Source #
BoxedVector argument descriptor builder.
boxedVectorArg :: forall b (n :: Nat) a c. (Additive b, KnownNat n) => RevDiff a (BoxedVector n b) (BoxedVector n c) -> BoxedVector n (RevDiff a b c) Source #
Boxed vector argument descriptor for differentiable functions.
Transforms a RevDiff instances of a boxed vector into a boxed vectror
of RevDiff instances.
This allows applying differentiable operations to each element of the boxed Vector.
Examples
>>>import Debug.SimpleExpr (variable, SE, simplify)>>>import Debug.DiffExpr (SymbolicFunc, unarySymbolicFunc)
>>>:{f :: Additive a => BoxedVector 3 a -> a f = boxedVectorSum :}
>>>:{f' :: (Distributive a, CT a ~ a) => BoxedVector 3 a -> BoxedVector 3 a f' = customArgDerivative boxedVectorArg f :}
>>>simplify $ f' (DVGS.fromTuple (variable "x", variable "y", variable "z"))Vector [1,1,1]
boxedVectorArgDerivative :: forall (n :: Nat) b a. (KnownNat n, AutoDifferentiableValue b, Additive (CT a)) => (BoxedVector n (RevDiff' (BoxedVector n a) a) -> b) -> BoxedVector n a -> DerivativeValue b Source #
Differentiable operator for functions with boxed array argument
and any supported by AutoDifferentiableValue value type.
The output is a boxed array of corresponding partial derivatives (i.e. gradient).
Examples
>>>import Debug.SimpleExpr (variable, simplify, SE)>>>import Debug.DiffExpr (SymbolicFunc)>>>import Numeric.InfBackprop.Utils.SizedVector (BoxedVector, boxedVectorSum)>>>import Debug.SimpleExpr.Utils.Algebra (AlgebraicPower, (^))
>>>:{x = variable "x" y = variable "y" z = variable "z" r = DVGS.fromTuple (x, y, z) :: BoxedVector 3 SE norm2 :: (AlgebraicPower Integer a, Additive a) => BoxedVector 3 a -> a norm2 v = boxedVectorSum (v^2) :}
>>>simplify $ norm2 r((x^2)+(y^2))+(z^2)
>>>:{norm2' :: BoxedVector 3 SE -> BoxedVector 3 SE norm2' = simplify . boxedVectorArgDerivative norm2 :}
>>>norm2' rVector [2*x,2*y,2*z]
>>>:{norm2'' :: BoxedVector 3 SE -> BoxedVector 3 (BoxedVector 3 SE) norm2'' = simplify . boxedVectorArgDerivative (boxedVectorArgDerivative norm2) :}
>>>norm2'' rVector [Vector [2,0,0],Vector [0,2,0],Vector [0,0,2]]
mkBoxedVectorVal :: forall a b (n :: Nat). (a -> b) -> BoxedVector n a -> BoxedVector n b Source #
BoxedVector differentiable value builder
See this tutorial section
for details and examples.
boxedVectorVal :: forall b (n :: Nat) a c. Multiplicative b => BoxedVector n (RevDiff a b c) -> BoxedVector n a Source #
Boxed array differentiable value descriptor. See this tutorial section for details and examples.
Examples
>>>import Debug.SimpleExpr (variable, SE, simplify)>>>import Debug.DiffExpr (unarySymbolicFunc, SymbolicFunc)
>>>:{v :: SymbolicFunc a => a -> BoxedVector 3 a v t = DVGS.fromTuple ( unarySymbolicFunc "v_x" t, unarySymbolicFunc "v_y" t, unarySymbolicFunc "v_z" t ) :}
>>>t = variable "t">>>v tVector [v_x(t),v_y(t),v_z(t)]
>>>v' = simplify . customValDerivative boxedVectorVal v :: SE -> BoxedVector 3 SE>>>v' tVector [v_x'(t),v_y'(t),v_z'(t)]
boxedVectorValDerivative :: forall a c (n :: Nat) b d. (AutoDifferentiableArgument a, Multiplicative c, DerivativeCoarg a ~ CT (DerivativeArg a), DerivativeRoot a ~ CT (DerivativeArg a)) => (a -> BoxedVector n (RevDiff b c d)) -> DerivativeArg a -> BoxedVector n b Source #
Differentiable operator for functions with BoxedVector argument
and any supported by AutoDifferentiableValue value type.
The output is a BoxedVector instamce of corresponding drivatives.
Examples
>>>import Debug.SimpleExpr (variable, SE, simplify)>>>import Debug.DiffExpr (unarySymbolicFunc, SymbolicFunc)
>>>:{v :: SymbolicFunc a => a -> BoxedVector 3 a v t = DVGS.fromTuple ( unarySymbolicFunc "v_x" t, unarySymbolicFunc "v_y" t, unarySymbolicFunc "v_z" t ) :}
>>>t = variable "t">>>v tVector [v_x(t),v_y(t),v_z(t)]
>>>v' = simplify . boxedVectorValDerivative v :: SE -> BoxedVector 3 SE>>>v' tVector [v_x'(t),v_y'(t),v_z'(t)]
Stream
mkStreamArg :: Additive b => (RevDiff a b c -> d) -> RevDiff a (FiniteSupportStream b) (Stream c) -> Stream d Source #
Stream argument builder. See this tutorial section for details and examples for the tuple.
streamArg :: Additive b => RevDiff a (FiniteSupportStream b) (Stream c) -> Stream (RevDiff a b c) Source #
Stream argument descriptor for differentiable functions.
Transforms a RevDiff instances of a stream into a stream of RevDiff instances.
This allows applying differentiable operations to each element of the Stream.
Examples
>>>import Debug.SimpleExpr (variable, SE, simplify)>>>import GHC.Base ((<>))
>>>:{f :: Additive a => Stream a -> a f = NumHask.sum . Data.Stream.take 4 :: Additive a => Data.Stream.Stream a -> a :}
>>>:{f' :: (Distributive a, CT a ~ a) => Stream a -> FiniteSupportStream a f' = customArgDerivative streamArg f :}
>>>s = Data.Stream.fromList [variable ("s_" <> show n) | n <- [0 :: Int ..]] :: Data.Stream.Stream SE>>>simplify $ f' s[1,1,1,1,0,0,0,...
streamArgDerivative :: (AutoDifferentiableValue b, Additive (CT a)) => (Stream (RevDiff' (Stream a) a) -> b) -> Stream a -> DerivativeValue b Source #
Differentiable operator for functions with Stream argument
and any supported by AutoDifferentiableValue value type.
The output is a boxed array of corresponding partial derivatives (i.e. gradient).
Examples
>>>import GHC.Base ((<>))>>>import Debug.SimpleExpr (variable, simplify, SE)>>>import Debug.DiffExpr (SymbolicFunc)>>>import Data.Stream (Stream, fromList, take)
>>>s = fromList [variable ("s_" <> show n) | n <- [0 :: Int ..]] :: Stream SE
>>>take4Sum = NumHask.sum . take 4 :: Additive a => Stream a -> a>>>simplify $ take4Sum s :: SEs_0+(s_1+(s_2+s_3))
>>>:{take4Sum' :: (Distributive a, CT a ~ a) => Stream a -> FiniteSupportStream (CT a) take4Sum' = streamArgDerivative take4Sum :}
>>>simplify $ take4Sum' s[1,1,1,1,0,0,0,...
>>>:{take4Sum'' :: (Distributive a, CT a ~ a) => Stream a -> FiniteSupportStream (FiniteSupportStream (CT a)) take4Sum'' = streamArgDerivative (streamArgDerivative take4Sum) :}
>>>simplify $ take4Sum'' s[[0,0,0,...,[0,0,0,...,[0,0,0,...,...
mkStreamVal :: (a -> b) -> Stream a -> Stream b Source #
Stream differentiable value builder See this tutorial section for details and examples.
streamVal :: Multiplicative b => Stream (RevDiff a b c) -> Stream a Source #
Stream value structure for differentiable functions.
Examples
>>>import GHC.Base ((<>))>>>import Data.Stream (Stream, fromList, take)>>>import Debug.SimpleExpr (variable, SE, simplify)>>>import Debug.DiffExpr (unarySymbolicFunc, SymbolicFunc)
>>>:{s :: SymbolicFunc a => a -> Stream a s t = fromList [unarySymbolicFunc ("s_" <> show n) t | n <- [0..]] :}
>>>t = variable "t">>>take 5 (s t)[s_0(t),s_1(t),s_2(t),s_3(t),s_4(t)]
>>>:{s' :: SE -> Stream SE s' = simplify . customValDerivative streamVal s :}
>>>take 5 (s' t)[s_0'(t),s_1'(t),s_2'(t),s_3'(t),s_4'(t)]
streamValDerivative :: (AutoDifferentiableArgument a, Multiplicative c, DerivativeCoarg a ~ CT (DerivativeArg a), DerivativeRoot a ~ CT (DerivativeArg a)) => (a -> Stream (RevDiff b c d)) -> DerivativeArg a -> Stream b Source #
Derivative operator for a function from any supported argument type to a Stream.
FiniteSupportStream
mkFiniteSupportStreamArg :: Additive b => (RevDiff a b c -> d) -> RevDiff a (Stream b) (FiniteSupportStream c) -> FiniteSupportStream d Source #
Finite support stream argument descriptor builder. See this tutorial section for details and examples. It is expected that the argument function is linear or at least maps zero to zero.
finiteSupportStreamArg :: Additive b => RevDiff a (Stream b) (FiniteSupportStream c) -> FiniteSupportStream (RevDiff a b c) Source #
Finite support stream argument descriptor for differentiable functions.
Transforms a RevDiff instances of a finite support stream into
a finite support stream of RevDiff instances.
Examples
>>>import Debug.SimpleExpr (variable, SE, simplify)>>>import Data.FiniteSupportStream (unsafeFromList, toVector)
>>>:{f :: Additive a => FiniteSupportStream a -> a f = NumHask.sum . toVector :}
>>>f (unsafeFromList [1, 2, 3])6
>>>:{f' :: (Distributive a, CT a ~ a) => FiniteSupportStream a -> Stream a f' = customArgDerivative finiteSupportStreamArg f :}
>>>Data.Stream.take 5 $ f' (unsafeFromList [1, 2, 3])[1,1,1,0,0]
finiteSupportStreamArgDerivative :: (AutoDifferentiableValue b, Additive (CT a)) => (FiniteSupportStream (RevDiff' (FiniteSupportStream a) a) -> b) -> FiniteSupportStream a -> DerivativeValue b Source #
Differentiable operator for functions that take a FiniteSupportStream argument
and return any value type supported by AutoDifferentiableValue.
The output is a stream of corresponding partial derivatives,
computing the gradient of the function with respect to each stream element.
See also
"Tangent and Cotangent Spaces" tutorial section
for the connection beetwen streams and finite support streams.
Examples
>>>import Debug.SimpleExpr (variable, simplify, SE)>>>import Debug.DiffExpr (SymbolicFunc)>>>import Data.Stream (Stream, take)>>>import Data.FiniteSupportStream (FiniteSupportStream, unsafeFromList, toVector)>>>import NumHask (sum)
Define a finite support stream with support length 4 containing 4 symbolic variables.
>>>s = unsafeFromList [variable "s_0", variable "s_1", variable "s_2", variable "s_3"] :: FiniteSupportStream SE>>>s[s_0,s_1,s_2,s_3,0,0,0,...
Now we'll define a function that sums all elements of a finite support stream.
>>>finiteSupportStreamSum = sum . toVector :: Additive a => FiniteSupportStream a -> a>>>simplify $ finiteSupportStreamSum s :: SEs_0+(s_1+(s_2+s_3))
We compute the gradient of this function.
>>>:{finiteSupportStreamSum' :: (Distributive a, CT a ~ a) => FiniteSupportStream a -> Stream (CT a) finiteSupportStreamSum' = finiteSupportStreamArgDerivative finiteSupportStreamSum :}
Let's compute the gradient at point s. It is an infinite stream and we take first 7 elements:
>>>take 7 $ simplify $ finiteSupportStreamSum' s[1,1,1,1,0,0,0]
As expected, the gradient is a stream with 1's in the first four positions (corresponding to our four variables and the fixed support length 4) and 0's elsewhere:
We can compute the second derivative (Hessian matrix) that is stream of streams in our case.
>>>:{finiteSupportStreamSum'' :: (Distributive a, CT a ~ a) => FiniteSupportStream a -> Stream (Stream (CT a)) finiteSupportStreamSum'' = finiteSupportStreamArgDerivative (finiteSupportStreamArgDerivative finiteSupportStreamSum) :}
All second derivatives should all be zero. We take first 7 rows and 4 columns of the inifinite Hessian matrix:
>>>take 7 $ fmap (take 4) $ simplify $ finiteSupportStreamSum'' s[[0,0,0,0],[0,0,0,0],[0,0,0,0],[0,0,0,0],[0,0,0,0],[0,0,0,0],[0,0,0,0]]
mkFiniteSupportStreamVal :: (a -> b) -> FiniteSupportStream a -> FiniteSupportStream b Source #
Finite support stream differentiable value builder See this tutorial section for details and examples. It is expected that the argument function is linear or at least maps zero to zero.
finiteSupportStreamVal :: Multiplicative b => FiniteSupportStream (RevDiff a b c) -> FiniteSupportStream a Source #
Finite support stream value structure for differentiable functions.
Examples
>>>import Debug.SimpleExpr (variable, SE, simplify)>>>import Debug.DiffExpr (unarySymbolicFunc, SymbolicFunc)>>>import Data.FiniteSupportStream (unsafeFromList, FiniteSupportStream)
>>>:{fss :: (Multiplicative a, IntegerPower a) => a -> FiniteSupportStream a fss t = unsafeFromList [t^3, t^2, t, one] :}
>>>t = variable "t">>>fss t[t^3,t^2,t,1,0,0,0,...
>>>:{fss' :: SE -> FiniteSupportStream SE fss' = simplify . customValDerivative finiteSupportStreamVal fss :}
>>>(fss' t)[3*(t^2),2*t,1,0,0,0,...
finiteSupportStreamValDerivative :: (AutoDifferentiableArgument a, Multiplicative c, DerivativeCoarg a ~ CT (DerivativeArg a), DerivativeRoot a ~ CT (DerivativeArg a)) => (a -> FiniteSupportStream (RevDiff b c d)) -> DerivativeArg a -> FiniteSupportStream b Source #
Derivative operator for a function from any supported argument type to
a FiniteSupportStream instance.
Examples
>>>import Debug.SimpleExpr (variable, SE, simplify)>>>import Debug.DiffExpr (unarySymbolicFunc, SymbolicFunc)>>>import Data.FiniteSupportStream (unsafeFromList, FiniteSupportStream)
>>>:{fss :: (Multiplicative a, IntegerPower a) => a -> FiniteSupportStream a fss t = unsafeFromList [t^3, t^2, t, one] :}
>>>t = variable "t">>>fss t[t^3,t^2,t,1,0,0,0,...
>>>:{fss' :: SE -> FiniteSupportStream SE fss' = simplify . finiteSupportStreamValDerivative fss :}
>>>fss' t[3*(t^2),2*t,1,0,0,0,...
Maybe
maybeArg :: RevDiff a (Maybe b) (Maybe c) -> Maybe (RevDiff a b c) Source #
Argument descriptor for differentiable functions with optional argument.
Transforms a RevDiff instances of an otional type into
an optional of RevDiff instances.
This allows applying differentiable operations to the optiona value.
Argument descriptor for differentiable functions with optional (Maybe) values.
Transforms a RevDiff instance containing an optional type into an optional
RevDiff instance. This transformation enables applying differentiable
operations to values that may or may not be present, while preserving
gradient flow when values exist.
When the wrapped value is `Just x`, the function extracts the value and
wraps it in a new RevDiff instance with appropriately transformed
backpropagation. When the value is Nothing, the result is Nothing,
effectively short-circuiting the computation.
Examples
>>>:{f :: Additive a => Maybe a -> a f (Just x) = x f Nothing = zero :}
>>>customArgDerivative maybeArg f (Just 3 :: Maybe Float) :: Maybe FloatJust 1.0
maybeArgDerivative :: AutoDifferentiableValue b => (Maybe (RevDiff' (Maybe a) a) -> b) -> Maybe a -> DerivativeValue b Source #
Differentiable operator for functions that take a Maybe (a value or none) argument
and return any value type supported by AutoDifferentiableValue.
The output is Maybe of corresponding derivatives over the inner type.
Examples
>>>import Debug.SimpleExpr (variable, simplify, SE)>>>import Debug.DiffExpr (SymbolicFunc)>>>import qualified GHC.Num as GHCN
>>>:{maybeF :: TrigField a => Maybe a -> a maybeF (Just x) = sin x maybeF Nothing = zero :}
>>>maybeF (Just 0.0 :: Maybe Float)0.0
>>>maybeF (Nothing :: Maybe Float)0.0
>>>maybeArgDerivative maybeF (Just 0.0 :: Maybe Float)Just 1.0
>>>maybeArgDerivative maybeF (Nothing :: Maybe Float)Just 0.0
maybeVal :: Multiplicative b => Maybe (RevDiff a b c) -> Maybe a Source #
Maybe value structure for differentiable functions.
Extracts the derivative with respect to the original function for Maybe types.
Examples
>>>:{class SafeRecip a where safeRecip :: a -> Maybe a instance SafeRecip Float where safeRecip x = if x == 0.0 then Nothing else Just (recip x) instance (SafeRecip b, Subtractive b, Multiplicative b, IntegerPower b) => SafeRecip (RevDiff a b b) where safeRecip (MkRevDiff v bp) = fmap (\r -> MkRevDiff r (bp . negate . (r^2 *))) (safeRecip v) :}
>>>safeRecip (2.0 :: Float) :: Maybe FloatJust 0.5>>>safeRecip (0.0 :: Float) :: Maybe FloatNothing
>>>customValDerivative maybeVal safeRecip (2.0 :: Float)Just (-0.25)>>>customValDerivative maybeVal safeRecip (0.0 :: Float)Nothing
mkMaybeVal :: (a -> b) -> Maybe a -> Maybe b Source #
Maybe differentiable value builder. Creates a mapping function for Maybe types. See this tutorial section for details and examples.
maybeValDerivative :: (AutoDifferentiableArgument a, Multiplicative c, DerivativeCoarg a ~ CT (DerivativeArg a), DerivativeRoot a ~ CT (DerivativeArg a)) => (a -> Maybe (RevDiff b c d)) -> DerivativeArg a -> Maybe b Source #
Derivative operator for functions with Maybe arguments. This allows computing derivatives of functions that returns Maybe values as output, handling the case when the value is Nothing appropriately.
Examples
>>>:{class SafeRecip a where safeRecip :: a -> Maybe a instance SafeRecip Float where safeRecip x = if x == 0.0 then Nothing else Just (recip x) instance (SafeRecip b, Subtractive b, Multiplicative b, IntegerPower b) => SafeRecip (RevDiff a b b) where safeRecip (MkRevDiff v bp) = fmap (\r -> MkRevDiff r (bp . negate . (r^2 *))) (safeRecip v) :}
>>>safeRecip (2.0 :: Float) :: Maybe FloatJust 0.5>>>safeRecip (0.0 :: Float) :: Maybe FloatNothing
>>>maybeValDerivative safeRecip (2.0 :: Float)Just (-0.25)>>>maybeValDerivative safeRecip (0.0 :: Float)Nothing