downhill 0.3.0.0 → 0.4.0.0
raw patch · 9 files changed
+216/−70 lines, 9 filesdep −template-haskelldep −th-abstractionPVP ok
version bump matches the API change (PVP)
Dependencies removed: template-haskell, th-abstraction
API changes (from Hackage documentation)
- Downhill.BVar: instance (Data.VectorSpace.VectorSpace v, Downhill.Grad.HasGrad v, Downhill.Grad.Grad v GHC.Types.~ v, Downhill.Grad.Tang v GHC.Types.~ v, Downhill.Linear.Expr.BasicVector (Downhill.Grad.MScalar v), Downhill.Grad.Grad (Downhill.Grad.MScalar v) GHC.Types.~ Downhill.Grad.MScalar v, Data.VectorSpace.InnerSpace v, Downhill.Grad.HasGrad (Downhill.Grad.MScalar v)) => Data.VectorSpace.InnerSpace (Downhill.BVar.BVar r v)
- Downhill.BVar: instance (Data.VectorSpace.VectorSpace v, Downhill.Grad.HasGrad v, Downhill.Grad.Tang v GHC.Types.~ v, Downhill.Linear.Expr.BasicVector (Downhill.Grad.MScalar v), Downhill.Grad.Grad (Downhill.Grad.MScalar v) GHC.Types.~ Downhill.Grad.MScalar v) => Data.VectorSpace.VectorSpace (Downhill.BVar.BVar r v)
- Downhill.BVar.Num: instance GHC.Num.Num a => Downhill.Grad.HasGrad (Downhill.BVar.Num.AsNum a)
- Downhill.BVar.Traversable: instance Downhill.Grad.HasGrad a => Downhill.Grad.HasGrad (Downhill.BVar.Traversable.TraversableVar f a)
- Downhill.Grad: class (Dual (Tang p) (Grad p), BasicVector (Grad p), Scalar (Tang p) ~ Scalar (Grad p)) => HasGrad p where {
- Downhill.Grad: instance (Downhill.Grad.HasGrad a, Downhill.Grad.HasGrad b, Downhill.Grad.HasGrad c, Downhill.Grad.MScalar b GHC.Types.~ Downhill.Grad.MScalar a, Downhill.Grad.MScalar c GHC.Types.~ Downhill.Grad.MScalar a) => Downhill.Grad.HasGrad (a, b, c)
- Downhill.Grad: instance (Downhill.Grad.HasGrad a, Downhill.Grad.HasGrad b, Downhill.Grad.MScalar b GHC.Types.~ Downhill.Grad.MScalar a) => Downhill.Grad.HasGrad (a, b)
- Downhill.Grad: instance Downhill.Grad.HasGrad GHC.Num.Integer.Integer
- Downhill.Grad: instance Downhill.Grad.HasGrad GHC.Types.Double
- Downhill.Grad: instance Downhill.Grad.HasGrad GHC.Types.Float
+ Downhill.BVar: instance (Data.VectorSpace.VectorSpace v, Downhill.Grad.HasGrad v, Downhill.Grad.Tang v GHC.Types.~ v, Downhill.Grad.HasGrad (Downhill.Grad.MScalar v), Downhill.Grad.Grad (Data.VectorSpace.Scalar v) GHC.Types.~ Data.VectorSpace.Scalar v) => Data.VectorSpace.VectorSpace (Downhill.BVar.BVar r v)
+ Downhill.BVar: instance (Data.VectorSpace.VectorSpace v, Downhill.Grad.HasGrad v, Downhill.Grad.Tang v GHC.Types.~ v, Downhill.Grad.HilbertSpace (Downhill.Grad.Tang v) (Downhill.Grad.Grad v), Downhill.Linear.Expr.BasicVector (Downhill.Grad.MScalar v), Downhill.Grad.Grad (Downhill.Grad.MScalar v) GHC.Types.~ Downhill.Grad.MScalar v, Data.VectorSpace.InnerSpace v, Downhill.Grad.HasGrad (Downhill.Grad.MScalar v)) => Data.VectorSpace.InnerSpace (Downhill.BVar.BVar r v)
+ Downhill.BVar: instance (Downhill.Grad.HasGrad (Data.VectorSpace.Scalar v), Downhill.Grad.HasGrad v, Downhill.Grad.HasGrad dv, Downhill.Grad.Dual v dv, Downhill.Grad.Grad dv GHC.Types.~ v, Downhill.Grad.Grad v GHC.Types.~ dv, Downhill.Grad.Tang v GHC.Types.~ v, Downhill.Grad.Tang dv GHC.Types.~ dv, Downhill.Grad.Grad (Data.VectorSpace.Scalar dv) GHC.Types.~ Data.VectorSpace.Scalar dv) => Downhill.Grad.Dual (Downhill.BVar.BVar r v) (Downhill.BVar.BVar r dv)
+ Downhill.BVar: instance (Downhill.Grad.HasGrad (Downhill.Grad.MScalar p), Downhill.Grad.HasGrad (Downhill.Grad.Tang p), Downhill.Grad.HasGrad (Downhill.Grad.Grad p), Downhill.Grad.Grad (Downhill.Grad.Grad p) GHC.Types.~ Downhill.Grad.Tang p, Downhill.Grad.Tang (Downhill.Grad.Grad p) GHC.Types.~ Downhill.Grad.Grad p, Downhill.Grad.Tang (Downhill.Grad.Tang p) GHC.Types.~ Downhill.Grad.Tang p, Downhill.Grad.Grad (Downhill.Grad.Tang p) GHC.Types.~ Downhill.Grad.Grad p, Downhill.Grad.Grad (Downhill.Grad.MScalar p) GHC.Types.~ Downhill.Grad.MScalar p, Data.VectorSpace.Scalar (Downhill.Grad.Grad p) GHC.Types.~ Data.VectorSpace.Scalar (Downhill.Grad.Tang p), Downhill.Grad.Manifold p) => Downhill.Grad.Manifold (Downhill.BVar.BVar r p)
+ Downhill.BVar: instance (Downhill.Grad.HilbertSpace v dv, Downhill.Grad.HasGrad (Data.VectorSpace.Scalar v), Downhill.Grad.HasGrad v, Downhill.Grad.HasGrad dv, Downhill.Grad.Grad dv GHC.Types.~ v, Downhill.Grad.Grad v GHC.Types.~ dv, Downhill.Grad.Tang v GHC.Types.~ v, Downhill.Grad.Tang dv GHC.Types.~ dv, Downhill.Grad.Grad (Data.VectorSpace.Scalar dv) GHC.Types.~ Data.VectorSpace.Scalar dv) => Downhill.Grad.HilbertSpace (Downhill.BVar.BVar r v) (Downhill.BVar.BVar r dv)
+ Downhill.BVar.Num: instance GHC.Num.Num a => Downhill.Grad.Manifold (Downhill.BVar.Num.AsNum a)
+ Downhill.BVar.Traversable: instance Downhill.Grad.Manifold a => Downhill.Grad.Manifold (Downhill.BVar.Traversable.TraversableVar f a)
+ Downhill.BVar.Traversable: instance Downhill.Grad.Manifold v => Downhill.Grad.Manifold (Downhill.BVar.Traversable.IntmapVector f v)
+ Downhill.Grad: class Dual v dv => HilbertSpace v dv
+ Downhill.Grad: class (Dual (Tang p) (Grad p), Scalar (Tang p) ~ Scalar (Grad p)) => Manifold p where {
+ Downhill.Grad: coriesz :: HilbertSpace v dv => dv -> v
+ Downhill.Grad: instance (Downhill.Grad.HasGrad a, Downhill.Grad.HasGrad b, Downhill.Grad.HasGrad c, Downhill.Grad.MScalar b GHC.Types.~ Downhill.Grad.MScalar a, Downhill.Grad.MScalar c GHC.Types.~ Downhill.Grad.MScalar a) => Downhill.Grad.Manifold (a, b, c)
+ Downhill.Grad: instance (Downhill.Grad.HasGrad a, Downhill.Grad.HasGrad b, Downhill.Grad.MScalar b GHC.Types.~ Downhill.Grad.MScalar a) => Downhill.Grad.Manifold (a, b)
+ Downhill.Grad: instance Downhill.Grad.Manifold GHC.Num.Integer.Integer
+ Downhill.Grad: instance Downhill.Grad.Manifold GHC.Types.Double
+ Downhill.Grad: instance Downhill.Grad.Manifold GHC.Types.Float
+ Downhill.Grad: riesz :: HilbertSpace v dv => v -> dv
+ Downhill.Grad: type HasGrad p = (Manifold p, BasicVector (Grad p))
Files
- CHANGELOG.md +3/−0
- downhill.cabal +1/−3
- src/Downhill/BVar.hs +81/−26
- src/Downhill/BVar/Num.hs +2/−2
- src/Downhill/BVar/Traversable.hs +6/−2
- src/Downhill/Grad.hs +19/−11
- src/Downhill/Metric.hs +1/−1
- test/DownhillTest/Bilinear.hs +101/−23
- test/DownhillTest/Traversable.hs +2/−2
CHANGELOG.md view
@@ -1,5 +1,8 @@ # Revision history for downhill +## 0.4.0.0+* `Manifold` class+ ## 0.2.0.0 * `MetricTensor` is no longer required to be a `VectorSpace` * `T2`, `T3` pattern synonyms for `BVar`
downhill.cabal view
@@ -1,7 +1,7 @@ cabal-version: 2.4 name: downhill-version: 0.3.0.0+version: 0.4.0.0 synopsis: Reverse mode automatic differentiation homepage: https://andriusstank.github.io/downhill/ description:@@ -39,9 +39,7 @@ build-depends: base >= 4.12.0.0 && <4.18, containers >= 0.6.5 && < 0.7, reflection >= 2.1.6 && < 2.2,- template-haskell >= 2.16.0 && < 2.20, transformers >= 0.5.6 && < 0.7,- th-abstraction >= 0.4.3 && < 0.5, unordered-containers >= 0.2.14 && < 0.3, vector-space >= 0.16 && < 0.17, hs-source-dirs: src
src/Downhill/BVar.hs view
@@ -6,13 +6,13 @@ {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE GADTs #-} {-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE PatternSynonyms #-} {-# LANGUAGE PolyKinds #-} {-# LANGUAGE RankNTypes #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE TypeFamilies #-} {-# LANGUAGE TypeOperators #-} {-# LANGUAGE UndecidableInstances #-}-{-# LANGUAGE PatternSynonyms #-} {-# LANGUAGE ViewPatterns #-} module Downhill.BVar@@ -20,9 +20,10 @@ var, constant, backprop,+ -- * Pattern synonyms pattern T2,- pattern T3+ pattern T3, ) where @@ -32,23 +33,25 @@ import Data.VectorSpace ( AdditiveGroup (..), InnerSpace ((<.>)),- VectorSpace ((*^)),+ VectorSpace (Scalar, (*^)), )-import qualified Data.VectorSpace as VectorSpace import Downhill.Grad ( Dual (evalGrad),- HasGrad (Grad, Tang),- HasGradAffine, MScalar+ HasGrad,+ HasGradAffine,+ HilbertSpace (coriesz, riesz),+ MScalar,+ Manifold (Grad, Tang), ) import Downhill.Linear.BackGrad ( BackGrad (..), realNode, ) import qualified Downhill.Linear.Backprop as BP-import Downhill.Linear.Expr (BasicVector, Expr (ExprVar))-import Downhill.Linear.Lift (lift2_dense)-import Prelude hiding (id, (.))+import Downhill.Linear.Expr (BasicVector (..), Expr (ExprVar))+import Downhill.Linear.Lift (lift1_dense, lift2_dense) import qualified Downhill.Linear.Prelude as Linear+import Prelude hiding (id, (.)) -- | Variable is a value paired with derivative. data BVar r a = BVar@@ -103,8 +106,8 @@ ( VectorSpace v, HasGrad v, Tang v ~ v,- BasicVector (MScalar v),- Grad (MScalar v) ~ MScalar v+ HasGrad (MScalar v),+ Grad (Scalar v) ~ Scalar v ) => VectorSpace (BVar r v) where@@ -121,11 +124,60 @@ BVar y0 dy .+^ BVar z0 dz = BVar (y0 .+^ z0) (dy ^+^ dz) BVar y0 dy .-. BVar z0 dz = BVar (y0 .-. z0) (dy ^-^ dz) +-- maybe move all those equality constraints to Dual class? instance+ ( HasGrad (Scalar v),+ HasGrad v,+ HasGrad dv,+ Dual v dv,+ Grad dv ~ v,+ Grad v ~ dv,+ Tang v ~ v,+ Tang dv ~ dv,+ Grad (Scalar dv) ~ Scalar dv+ ) =>+ Dual (BVar r v) (BVar r dv)+ where+ evalGrad (BVar dv d_dv) (BVar v d_v) = BVar (evalGrad dv v) (lift2_dense (*^ v) (*^ dv) d_dv d_v)++instance+ ( HasGrad (MScalar p),+ HasGrad (Tang p),+ HasGrad (Grad p),+ Grad (Grad p) ~ Tang p,+ Tang (Grad p) ~ Grad p,+ Tang (Tang p) ~ Tang p,+ Grad (Tang p) ~ Grad p,+ Grad (MScalar p) ~ MScalar p,+ Scalar (Grad p) ~ Scalar (Tang p),+ Manifold p+ ) =>+ Manifold (BVar r p)+ where+ type Tang (BVar r p) = BVar r (Tang p)+ type Grad (BVar r p) = BVar r (Grad p)++instance+ ( HilbertSpace v dv,+ HasGrad (Scalar v),+ HasGrad v,+ HasGrad dv,+ Grad dv ~ v,+ Grad v ~ dv,+ Tang v ~ v,+ Tang dv ~ dv,+ Grad (Scalar dv) ~ Scalar dv+ ) =>+ HilbertSpace (BVar r v) (BVar r dv)+ where+ riesz (BVar v dv) = BVar (riesz v) (lift1_dense riesz dv)+ coriesz (BVar v dv) = BVar (coriesz v) (lift1_dense coriesz dv)++instance ( VectorSpace v, HasGrad v,- Grad v ~ v, Tang v ~ v,+ HilbertSpace (Tang v) (Grad v), BasicVector (MScalar v), Grad (MScalar v) ~ MScalar v, InnerSpace v,@@ -136,9 +188,9 @@ BVar u du <.> BVar v dv = BVar (u <.> v) (lift2_dense bpU bpV du dv) where bpU :: MScalar v -> Grad v- bpU dz = dz *^ v+ bpU dz = dz *^ riesz v bpV :: MScalar v -> Grad v- bpV dz = dz *^ u+ bpV dz = dz *^ riesz u -- | A variable with derivative of zero. constant :: forall r a. (BasicVector (Grad a), AdditiveGroup (Grad a)) => a -> BVar r a@@ -148,27 +200,30 @@ var :: a -> BVar (Grad a) a var x = BVar x (realNode ExprVar) ---backprop :: forall a p. (HasGrad p, BasicVector a) => BVar a p -> GradBuilder p -> a---backprop (BVar _y0 x) = BP.backprop x- -- | Reverse mode differentiation.------ backprop :: forall r a. (HasGrad a, BasicVector r) => BVar r a -> Grad a -> r backprop (BVar _y0 x) = BP.backprop x - splitPair :: (BasicVector (Grad a), BasicVector (Grad b)) => BVar r (a, b) -> (BVar r a, BVar r b) splitPair (BVar (a, b) (Linear.T2 da db)) = (BVar a da, BVar b db) pattern T2 :: forall r a b. (BasicVector (Grad a), BasicVector (Grad b)) => BVar r a -> BVar r b -> BVar r (a, b)-pattern T2 a b <- (splitPair -> (a, b))- where T2 (BVar a da) (BVar b db) = BVar (a, b) (Linear.T2 da db)+pattern T2 a b <-+ (splitPair -> (a, b))+ where+ T2 (BVar a da) (BVar b db) = BVar (a, b) (Linear.T2 da db) splitTriple :: (BasicVector (Grad a), BasicVector (Grad b), BasicVector (Grad c)) => BVar r (a, b, c) -> (BVar r a, BVar r b, BVar r c) splitTriple (BVar (a, b, c) (Linear.T3 da db dc)) = (BVar a da, BVar b db, BVar c dc) -pattern T3 :: forall r a b c. (BasicVector (Grad a), BasicVector (Grad b), BasicVector (Grad c))- => BVar r a -> BVar r b -> BVar r c -> BVar r (a, b, c)-pattern T3 a b c <- (splitTriple -> (a, b, c))- where T3 (BVar a da) (BVar b db) (BVar c dc) = BVar (a, b, c) (Linear.T3 da db dc)+pattern T3 ::+ forall r a b c.+ (BasicVector (Grad a), BasicVector (Grad b), BasicVector (Grad c)) =>+ BVar r a ->+ BVar r b ->+ BVar r c ->+ BVar r (a, b, c)+pattern T3 a b c <-+ (splitTriple -> (a, b, c))+ where+ T3 (BVar a da) (BVar b db) (BVar c dc) = BVar (a, b, c) (Linear.T3 da db dc)
src/Downhill/BVar/Num.hs view
@@ -34,7 +34,7 @@ import qualified Downhill.BVar as BVar import Downhill.Grad ( Dual (evalGrad),- HasGrad (Grad, Tang)+ Manifold (Grad, Tang) ) import Downhill.Linear.Expr (BasicVector (..)) import Downhill.Metric (MetricTensor (evalMetric))@@ -49,7 +49,7 @@ instance Num a => Dual (AsNum a) (AsNum a) where evalGrad = (*) -instance Num a => HasGrad (AsNum a) where+instance Num a => Manifold (AsNum a) where type Grad (AsNum a) = AsNum a type Tang (AsNum a) = AsNum a
src/Downhill/BVar/Traversable.hs view
@@ -63,7 +63,7 @@ import Downhill.BVar (BVar (BVar, bvarGrad, bvarValue), backprop, var) import Downhill.Grad ( Dual (evalGrad),- HasGrad (Grad, Tang)+ Manifold (Grad, Tang), HasGrad ) import Downhill.Linear.BackGrad (BackGrad (BackGrad), castBackGrad, realNode) import Downhill.Linear.Expr@@ -92,13 +92,17 @@ evalMetric (TraversableMetric m) (IntmapVector da) = IntmapVector (IntMap.map (evalMetric @p @g m) da) -instance HasGrad a => HasGrad (TraversableVar f a) where+instance Manifold a => Manifold (TraversableVar f a) where type Tang (TraversableVar f a) = IntmapVector f (Tang a) type Grad (TraversableVar f a) = IntmapVector f (Grad a) -- | @IntmapVector@ serves as a gradient of 'TraversableVar'. newtype IntmapVector (f :: Type -> Type) v = IntmapVector {unIntmapVector :: IntMap v} deriving (Show)++instance Manifold v => Manifold (IntmapVector f v) where+ type Tang (IntmapVector f v) = IntmapVector f (Tang v)+ type Grad (IntmapVector f v) = IntmapVector f (Grad v) instance AdditiveGroup a => AdditiveGroup (IntmapVector f a) where zeroV = IntmapVector IntMap.empty
src/Downhill/Grad.hs view
@@ -13,8 +13,8 @@ {-# LANGUAGE UndecidableInstances #-} module Downhill.Grad- ( Dual (..),- HasGrad (..), MScalar,+ ( Dual (..), HilbertSpace(..),+ Manifold(..), HasGrad, MScalar, GradBuilder, HasGradAffine, )@@ -41,16 +41,20 @@ default evalGrad :: (GDual (Scalar v) (Rep v) (Rep dv), Generic dv, Generic v) => dv -> v -> Scalar v evalGrad dv v = gevalGrad (from dv) (from v) +-- | u <.> v = evalDual (riesz u) v+-- | du <.> dv = evalDual du (coriesz dv)+class Dual v dv => HilbertSpace v dv where+ riesz :: v -> dv+ coriesz :: dv -> v++ type MScalar p = Scalar (Tang p) --- | Differentiable functions don't need to be constrained to vector spaces, they--- can be defined on other smooth manifolds, too. class ( Dual (Tang p) (Grad p),- BasicVector (Grad p), Scalar (Tang p) ~ Scalar (Grad p) ) =>- HasGrad p+ Manifold p where -- | Tangent space. type Tang p :: Type@@ -58,6 +62,10 @@ -- | Cotangent space. type Grad p :: Type +-- | Differentiable functions don't need to be constrained to vector spaces, they+-- can be defined on other smooth manifolds, too.+type HasGrad p = (Manifold p, BasicVector (Grad p))+ type GradBuilder v = VecBuilder (Grad v) type HasGradAffine p =@@ -72,7 +80,7 @@ instance Dual Integer Integer where evalGrad = (*) -instance HasGrad Integer where+instance Manifold Integer where type Tang Integer = Integer type Grad Integer = Integer @@ -87,7 +95,7 @@ HasGrad b, MScalar b ~ MScalar a ) =>- HasGrad (a, b)+ Manifold (a, b) where type Grad (a, b) = (Grad a, Grad b) type Tang (a, b) = (Tang a, Tang b)@@ -99,7 +107,7 @@ MScalar b ~ MScalar a, MScalar c ~ MScalar a ) =>- HasGrad (a, b, c)+ Manifold (a, b, c) where type Grad (a, b, c) = (Grad a, Grad b, Grad c) type Tang (a, b, c) = (Tang a, Tang b, Tang c)@@ -107,14 +115,14 @@ instance Dual Float Float where evalGrad = (*) -instance HasGrad Float where+instance Manifold Float where type Grad Float = Float type Tang Float = Float instance Dual Double Double where evalGrad = (*) -instance HasGrad Double where+instance Manifold Double where type Grad Double = Double type Tang Double = Double
src/Downhill/Metric.hs view
@@ -14,7 +14,7 @@ where import Data.VectorSpace ((^+^))-import Downhill.Grad (Dual (evalGrad), HasGrad (Grad, Tang), MScalar)+import Downhill.Grad (Dual (evalGrad), Manifold(..), MScalar) -- | @MetricTensor@ converts gradients to vectors. --
test/DownhillTest/Bilinear.hs view
@@ -1,40 +1,73 @@-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE RankNTypes #-}-{-# LANGUAGE TypeApplications #-}-{-# LANGUAGE DerivingVia #-} {-# LANGUAGE DeriveGeneric #-}-{-# LANGUAGE UndecidableInstances #-}-{-# LANGUAGE TemplateHaskell #-}-{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE DerivingVia #-}+{-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE TypeApplications #-} {-# LANGUAGE TypeOperators #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE UndecidableInstances #-} module DownhillTest.Bilinear where import Data.AffineSpace ((.+^))-import Data.VectorSpace (AdditiveGroup, VectorSpace ((*^), Scalar), (^+^))+import Data.VectorSpace (AdditiveGroup, VectorSpace (Scalar, (*^)), (^+^)) import Downhill.BVar (BVar (bvarValue)) import qualified Downhill.BVar as BVar-import Downhill.Grad (Dual (evalGrad), HasGrad (Grad), MScalar)+import Downhill.Grad (Dual (evalGrad), HasGrad, MScalar, Manifold (Grad))+import Downhill.Linear.Expr (BasicVector, DenseVector (DenseVector))+import GHC.Base (VecElem (DoubleElemRep))+import GHC.Generics (Generic) import Hedgehog ( Gen, Property,+ PropertyT, forAll, property, (===), )-import Test.Tasty (TestTree, testGroup)-import Test.Tasty.Hedgehog (testProperty, testPropertyNamed)-import GHC.Base (VecElem(DoubleElemRep))-import Hedgehog.Internal.Show (Value(Integer))-import qualified Hedgehog.Internal.Show as Gen import qualified Hedgehog.Gen as Gen+import Hedgehog.Internal.Show (Value (Integer))+import qualified Hedgehog.Internal.Show as Gen import qualified Hedgehog.Range as Range-import GHC.Generics (Generic)-import Downhill.Linear.Expr (BasicVector, DenseVector (DenseVector))+import Test.Tasty (TestTree, testGroup)+import Test.Tasty.Hedgehog (testProperty, testPropertyNamed) +testLinear ::+ forall m r u z.+ ( Show u,+ HasGrad u,+ Show (Grad z),+ HasGrad z,+ Eq z,+ AdditiveGroup u,+ Show z,+ AdditiveGroup z,+ Dual (Grad u) u,+ Eq (Scalar u),+ Show (Scalar u),+ Scalar u ~ Scalar z,+ Dual (Grad z) z,+ Show (MScalar z),+ Monad m+ ) =>+ (u -> z) ->+ (forall r. BVar r u -> BVar r z) ->+ Gen u ->+ Gen (Grad z) ->+ PropertyT m ()+testLinear f bf genU genDZ = do+ u <- forAll genU+ dz <- forAll genDZ+ let z = f u+ bu = BVar.var u+ bz = bf bu+ du = BVar.backprop bz dz+ bvarValue bz === z -- check that `f` and `bf` is the same function+ evalGrad u du === evalGrad z dz+ testBilinear :: ( Show u, Show v,@@ -51,7 +84,10 @@ Show (Scalar u), Scalar u ~ Scalar z, Scalar v ~ Scalar z,- Dual (Grad z) z, Show (MScalar z), Dual (Grad v) v) =>+ Dual (Grad z) z,+ Show (MScalar z),+ Dual (Grad v) v+ ) => (u -> v -> z) -> (forall r. BVar r u -> BVar r v -> BVar r z) -> Gen u ->@@ -70,10 +106,52 @@ evalGrad u du === evalGrad z dz evalGrad v dv === evalGrad z dz +testBilinear' ::+ ( Show u,+ Show v,+ HasGrad u,+ HasGrad v,+ Show (Grad z),+ HasGrad z,+ Eq z,+ AdditiveGroup u,+ Show z,+ AdditiveGroup z,+ Dual (Grad u) u,+ Eq (Scalar u),+ Show (Scalar u),+ Scalar u ~ Scalar z,+ Scalar v ~ Scalar z,+ Dual (Grad z) z,+ Show (MScalar z),+ Dual (Grad v) v+ ) =>+ (u -> v -> z) ->+ (forall r. BVar r u -> BVar r v -> BVar r z) ->+ Gen u ->+ Gen v ->+ Gen (Grad z) ->+ Property+testBilinear' f bf genU genV genDZ = property $ do+ u <- forAll genU+ v <- forAll genV+ dz <- forAll genDZ+ let z = f u v+ BVar.T2 bu bv = BVar.var (u, v)+ bz = bf bu bv+ (du, dv) = BVar.backprop bz dz+ bvarValue bz === z -- check that `f` and `bf` is the same function+ evalGrad u du === evalGrad z dz+ evalGrad v dv === evalGrad z dz++ testLinear (\x -> f x v) (\bx -> bf bx (BVar.constant v)) genU genDZ+ testLinear (\x -> f u x) (\bx -> bf (BVar.constant u) bx) genV genDZ+ data Vector = Vector Integer Integer- deriving Generic+ deriving (Generic) instance AdditiveGroup Vector+ instance VectorSpace Vector bilinearIntMulProperty :: Property@@ -84,10 +162,10 @@ genInt :: Gen Integer genInt = Gen.integral (Range.linear (-100) 100) - bilinearTests :: TestTree bilinearTests =- testGroup "Bilinear operations"- [ testPropertyNamed "Scalar multiplication" "bilinearIntMulProperty" bilinearIntMulProperty- -- TODO: scalar-vector product, inner product- ]+ testGroup+ "Bilinear operations"+ [ testPropertyNamed "Scalar multiplication" "bilinearIntMulProperty" bilinearIntMulProperty+ -- TODO: scalar-vector product, inner product+ ]
test/DownhillTest/Traversable.hs view
@@ -8,7 +8,7 @@ import Downhill.BVar.Traversable (TraversableVar (TraversableVar), backpropTraversable, splitTraversable) import Downhill.BVar (BVar (BVar), backprop, var)-import Downhill.Grad (HasGrad (Grad))+import Downhill.Grad (Manifold (Grad), HasGrad) import Test.Tasty (TestTree) import Test.Tasty.HUnit (testCase, (@?=)) @@ -18,7 +18,7 @@ } deriving (Eq, Functor, Foldable, Traversable, Show) -deriving via (TraversableVar MyRecord a) instance HasGrad a => HasGrad (MyRecord a)+deriving via (TraversableVar MyRecord a) instance Manifold a => Manifold (MyRecord a) test_r :: MyRecord Integer test_r = MyRecord (10, 11) [12, 13, 14]