on master help sign in
Network scale autodiff test
f9b5379Huw Campbell
examples/main/gan-mnist.hs+1−1
@@ -11,7 +11,7 @@
11-- of numbers similar to those in MNIST.
11-- of numbers similar to those in MNIST.
12--
12--
13-- It demonstrates a different usage of the library. Within about 15
13-- It demonstrates a different usage of the library. Within about 15
14−-- minutes hour it was producing examples like this:
14+-- minutes it was producing examples like this:
15--
15--
16-- --.
16-- --.
17-- .=-.--..#=###
17-- .=-.--..#=###
grenade.cabal+1
@@ -137,6 +137,7 @@ test-suite test
137 , random
137 , random
138 , ad
138 , ad
139 , reflection
139 , reflection
140+ , vector
140
141
141
142
142benchmark bench
143benchmark bench
test/Test/Grenade/Layers/Convolution.hs+8−6
@@ -19,11 +19,12 @@ import Grenade.Core
19import Grenade.Layers.Convolution
19import Grenade.Layers.Convolution
20
20
21import Hedgehog
21import Hedgehog
22+import Hedgehog.Gen ( Gen )
22import qualified Hedgehog.Gen as Gen
23import qualified Hedgehog.Gen as Gen
23
24
24−import Test.Jack.Hmatrix
25+import Test.Hedgehog.Hmatrix
25−import Test.Jack.TypeLits
26+import Test.Hedgehog.TypeLits
26−import Test.Jack.Compat
27+import Test.Hedgehog.Compat
27
28
28data OpaqueConvolution :: * where
29data OpaqueConvolution :: * where
29 OpaqueConvolution :: Convolution channels filters kernelRows kernelColumns strideRows strideColumns -> OpaqueConvolution
30 OpaqueConvolution :: Convolution channels filters kernelRows kernelColumns strideRows strideColumns -> OpaqueConvolution
@@ -39,10 +40,11 @@ genConvolution :: ( KnownNat channels
39 , KnownNat strideColumns
40 , KnownNat strideColumns
40 , KnownNat kernelFlattened
41 , KnownNat kernelFlattened
41 , kernelFlattened ~ (kernelRows * kernelColumns * channels)
42 , kernelFlattened ~ (kernelRows * kernelColumns * channels)
43+ , Monad m
42− ) => Jack (Convolution channels filters kernelRows kernelColumns strideRows strideColumns)
44+ ) => Gen m (Convolution channels filters kernelRows kernelColumns strideRows strideColumns)
43genConvolution = Convolution <$> uniformSample <*> uniformSample
45genConvolution = Convolution <$> uniformSample <*> uniformSample
44
46
45−genOpaqueOpaqueConvolution :: Jack OpaqueConvolution
47+genOpaqueOpaqueConvolution :: Monad m => Gen m OpaqueConvolution
46genOpaqueOpaqueConvolution = do
48genOpaqueOpaqueConvolution = do
47 channels <- genNat
49 channels <- genNat
48 filters <- genNat
50 filters <- genNat
@@ -58,7 +60,7 @@ genOpaqueOpaqueConvolution = do
58 p2 = natDict pkc
60 p2 = natDict pkc
59 p3 = natDict pch
61 p3 = natDict pch
60 in case p1 %* p2 %* p3 of
62 in case p1 %* p2 %* p3 of
61− Dict -> OpaqueConvolution <$> (genConvolution :: Jack (Convolution ch fl kr kc sr sc))
63+ Dict -> OpaqueConvolution <$> (genConvolution :: Monad n => Gen n (Convolution ch fl kr kc sr sc))
62
64
63prop_conv_net_witness = property $
65prop_conv_net_witness = property $
64 blindForAll genOpaqueOpaqueConvolution >>= \onet ->
66 blindForAll genOpaqueOpaqueConvolution >>= \onet ->
test/Test/Grenade/Layers/FullyConnected.hs+3−3
@@ -17,8 +17,8 @@ import Grenade.Layers.FullyConnected
17
17
18import Hedgehog
18import Hedgehog
19
19
20−import Test.Jack.Compat
20+import Test.Hedgehog.Compat
21−import Test.Jack.Hmatrix
21+import Test.Hedgehog.Hmatrix
22
22
23data OpaqueFullyConnected :: * where
23data OpaqueFullyConnected :: * where
24 OpaqueFullyConnected :: (KnownNat i, KnownNat o) => FullyConnected i o -> OpaqueFullyConnected
24 OpaqueFullyConnected :: (KnownNat i, KnownNat o) => FullyConnected i o -> OpaqueFullyConnected
@@ -26,7 +26,7 @@ data OpaqueFullyConnected :: * where
26instance Show OpaqueFullyConnected where
26instance Show OpaqueFullyConnected where
27 show (OpaqueFullyConnected n) = show n
27 show (OpaqueFullyConnected n) = show n
28
28
29−genOpaqueFullyConnected :: Jack OpaqueFullyConnected
29+genOpaqueFullyConnected :: Monad m => Gen m OpaqueFullyConnected
30genOpaqueFullyConnected = do
30genOpaqueFullyConnected = do
31 input :: Integer <- choose 2 100
31 input :: Integer <- choose 2 100
32 output :: Integer <- choose 1 100
32 output :: Integer <- choose 1 100
test/Test/Grenade/Layers/Internal/Convolution.hs+1−1
@@ -17,7 +17,7 @@ import qualified Hedgehog.Gen as Gen
17import qualified Hedgehog.Range as Range
17import qualified Hedgehog.Range as Range
18
18
19import qualified Test.Grenade.Layers.Internal.Reference as Reference
19import qualified Test.Grenade.Layers.Internal.Reference as Reference
20−import Test.Jack.Compat
20+import Test.Hedgehog.Compat
21
21
22prop_im2col_col2im_symmetrical_with_kernel_stride =
22prop_im2col_col2im_symmetrical_with_kernel_stride =
23 let factors n = [x | x <- [1..n], n `mod` x == 0]
23 let factors n = [x | x <- [1..n], n `mod` x == 0]
test/Test/Grenade/Layers/Internal/Pooling.hs+1−1
@@ -17,7 +17,7 @@ import qualified Hedgehog.Gen as Gen
17import qualified Hedgehog.Range as Range
17import qualified Hedgehog.Range as Range
18
18
19import qualified Test.Grenade.Layers.Internal.Reference as Reference
19import qualified Test.Grenade.Layers.Internal.Reference as Reference
20−import Test.Jack.Compat
20+import Test.Hedgehog.Compat
21
21
22prop_poolForwards_poolBackwards_behaves_as_reference =
22prop_poolForwards_poolBackwards_behaves_as_reference =
23 let ok extent kernel = [stride | stride <- [1..extent], (extent - kernel) `mod` stride == 0]
23 let ok extent kernel = [stride | stride <- [1..extent], (extent - kernel) `mod` stride == 0]
test/Test/Grenade/Layers/Nonlinear.hs+3−5
@@ -20,9 +20,9 @@ import GHC.TypeLits
20
20
21import Hedgehog
21import Hedgehog
22
22
23−import Test.Jack.Compat
23+import Test.Hedgehog.Compat
24−import Test.Jack.Hmatrix
24+import Test.Hedgehog.Hmatrix
25−import Test.Jack.TypeLits
25+import Test.Hedgehog.TypeLits
26
26
27import Numeric.LinearAlgebra.Static ( norm_Inf )
27import Numeric.LinearAlgebra.Static ( norm_Inf )
28
28
@@ -68,8 +68,6 @@ prop_softmax_grad = property $
68 in assert ((case numericalGradient - ret of
68 in assert ((case numericalGradient - ret of
69 (S1D x) -> norm_Inf x < 0.0001) :: Bool)
69 (S1D x) -> norm_Inf x < 0.0001) :: Bool)
70
70
71−
72−
73tests :: IO Bool
71tests :: IO Bool
74tests = $$(checkConcurrent)
72tests = $$(checkConcurrent)
75
73
test/Test/Grenade/Layers/PadCrop.hs+1−1
@@ -19,7 +19,7 @@ import Hedgehog
19
19
20import Numeric.LinearAlgebra.Static ( norm_Inf )
20import Numeric.LinearAlgebra.Static ( norm_Inf )
21
21
22−import Test.Jack.Hmatrix
22+import Test.Hedgehog.Hmatrix
23
23
24prop_pad_crop :: Property
24prop_pad_crop :: Property
25prop_pad_crop =
25prop_pad_crop =
test/Test/Grenade/Layers/Pooling.hs+4−2
@@ -13,7 +13,9 @@ import GHC.TypeLits
13import Grenade.Layers.Pooling
13import Grenade.Layers.Pooling
14
14
15import Hedgehog
15import Hedgehog
16+import Hedgehog.Gen ( Gen )
17+
16−import Test.Jack.Compat
18+import Test.Hedgehog.Compat
17
19
18data OpaquePooling :: * where
20data OpaquePooling :: * where
19 OpaquePooling :: (KnownNat kh, KnownNat kw, KnownNat sh, KnownNat sw) => Pooling kh kw sh sw -> OpaquePooling
21 OpaquePooling :: (KnownNat kh, KnownNat kw, KnownNat sh, KnownNat sw) => Pooling kh kw sh sw -> OpaquePooling
@@ -21,7 +23,7 @@ data OpaquePooling :: * where
21instance Show OpaquePooling where
23instance Show OpaquePooling where
22 show (OpaquePooling n) = show n
24 show (OpaquePooling n) = show n
23
25
24−genOpaquePooling :: Jack OpaquePooling
26+genOpaquePooling :: Monad m => Gen m OpaquePooling
25genOpaquePooling = do
27genOpaquePooling = do
26 Just kernelHeight <- someNatVal <$> choose 2 15
28 Just kernelHeight <- someNatVal <$> choose 2 15
27 Just kernelWidth <- someNatVal <$> choose 2 15
29 Just kernelWidth <- someNatVal <$> choose 2 15
test/Test/Grenade/Recurrent/Layers/LSTM.hs+3−4
@@ -11,6 +11,7 @@
11module Test.Grenade.Recurrent.Layers.LSTM where
11module Test.Grenade.Recurrent.Layers.LSTM where
12
12
13import Hedgehog
13import Hedgehog
14+import Hedgehog.Gen ( Gen )
14import Hedgehog.Internal.Source
15import Hedgehog.Internal.Source
15import Hedgehog.Internal.Show
16import Hedgehog.Internal.Show
16import Hedgehog.Internal.Property ( failWith, Diff (..) )
17import Hedgehog.Internal.Property ( failWith, Diff (..) )
@@ -26,10 +27,9 @@ import qualified Numeric.LinearAlgebra.Static as S
26
27
27
28
28import qualified Test.Grenade.Recurrent.Layers.LSTM.Reference as Reference
29import qualified Test.Grenade.Recurrent.Layers.LSTM.Reference as Reference
29−import Test.Jack.Hmatrix
30+import Test.Hedgehog.Hmatrix
30−import Test.Jack.Compat
31
31
32−genLSTM :: forall i o. (KnownNat i, KnownNat o) => Jack (LSTM i o)
32+genLSTM :: forall i o m. (KnownNat i, KnownNat o, Monad m) => Gen m (LSTM i o)
33genLSTM = do
33genLSTM = do
34 let w = uniformSample
34 let w = uniformSample
35 u = uniformSample
35 u = uniformSample
@@ -121,6 +121,5 @@ prop_lstm_reference_backwards_cell =
121 failWith (Just $ Diff "Failed (" "- lhs" "~/~" "+ rhs" ")" diff) ""
121 failWith (Just $ Diff "Failed (" "- lhs" "~/~" "+ rhs" ")" diff) ""
122infix 4 ~~~
122infix 4 ~~~
123
123
124−
125tests :: IO Bool
124tests :: IO Bool
126tests = $$(checkConcurrent)
125tests = $$(checkConcurrent)
test/Test/Hedgehog/Compat.hsnew file+39
@@ -0,0 +1,39 @@
1+{-# LANGUAGE RankNTypes #-}
2+module Test.Hedgehog.Compat where
3+
4+import Control.Monad.Trans.Class (MonadTrans(..))
5+
6+import Data.Typeable ( typeOf )
7+
8+import Hedgehog.Gen ( Gen )
9+import qualified Hedgehog.Gen as Gen
10+import qualified Hedgehog.Range as Range
11+import Hedgehog.Internal.Property
12+import Hedgehog.Internal.Source
13+import Hedgehog.Internal.Show
14+
15+(...) :: (c -> d) -> (a -> b -> c) -> a -> b -> d
16+(...) = (.) . (.)
17+{-# INLINE (...) #-}
18+
19+choose :: ( Monad m, Integral a ) => a -> a -> Gen m a
20+choose = Gen.integral ... Range.constant
21+
22+-- | Generates a random input for the test by running the provided generator.
23+blindForAll :: Monad m => Gen m a -> Test m a
24+blindForAll = Test . lift . lift
25+
26+-- | Generates a random input for the test by running the provided generator.
27+semiBlindForAll :: (Monad m, Show a, HasCallStack) => Gen m a -> Test m a
28+semiBlindForAll gen = do
29+ x <- Test . lift $ lift gen
30+ writeLog $ Input (getCaller callStack) (typeOf ()) (showPretty x)
31+ return x
32+
33+
34+-- | Generates a random input for the test by running the provided generator.
35+forAllRender :: (Monad m, HasCallStack) => ( a -> String ) -> Gen m a -> Test m a
36+forAllRender render gen = do
37+ x <- Test . lift $ lift gen
38+ writeLog $ Input (getCaller callStack) (typeOf ()) (render x)
39+ return x
test/Test/Jack/Hmatrix.hs → test/Test/Hedgehog/Hmatrix.hsrenamed+11−5
@@ -3,29 +3,35 @@
3{-# LANGUAGE ScopedTypeVariables #-}
3{-# LANGUAGE ScopedTypeVariables #-}
4{-# LANGUAGE GADTs #-}
4{-# LANGUAGE GADTs #-}
5
5
6−module Test.Jack.Hmatrix where
6+module Test.Hedgehog.Hmatrix where
7
7
8import Grenade
8import Grenade
9import Data.Singletons
9import Data.Singletons
10
10
11+import Hedgehog.Gen ( Gen )
11import qualified Hedgehog.Gen as Gen
12import qualified Hedgehog.Gen as Gen
12import qualified Hedgehog.Range as Range
13import qualified Hedgehog.Range as Range
13
14
14import GHC.TypeLits
15import GHC.TypeLits
15
16
16import qualified Numeric.LinearAlgebra.Static as HStatic
17import qualified Numeric.LinearAlgebra.Static as HStatic
17−import Test.Jack.Compat
18
18
19−randomVector :: forall n. KnownNat n => Jack (HStatic.R n)
19+randomVector :: forall m n. ( Monad m, KnownNat n ) => Gen m (HStatic.R n)
20randomVector = (\s -> HStatic.randomVector s HStatic.Uniform * 2 - 1) <$> Gen.int Range.linearBounded
20randomVector = (\s -> HStatic.randomVector s HStatic.Uniform * 2 - 1) <$> Gen.int Range.linearBounded
21
21
22−uniformSample :: forall m n. (KnownNat m, KnownNat n) => Jack (HStatic.L m n)
22+uniformSample :: forall mm m n. ( Monad mm, KnownNat m, KnownNat n ) => Gen mm (HStatic.L m n)
23uniformSample = (\s -> HStatic.uniformSample s (-1) 1 ) <$> Gen.int Range.linearBounded
23uniformSample = (\s -> HStatic.uniformSample s (-1) 1 ) <$> Gen.int Range.linearBounded
24
24
25-- | Generate random data of the desired shape
25-- | Generate random data of the desired shape
26−genOfShape :: forall x. ( SingI x ) => Jack (S x)
26+genOfShape :: forall m x. ( Monad m, SingI x ) => Gen m (S x)
27genOfShape =
27genOfShape =
28 case (sing :: Sing x) of
28 case (sing :: Sing x) of
29 D1Sing -> S1D <$> randomVector
29 D1Sing -> S1D <$> randomVector
30 D2Sing -> S2D <$> uniformSample
30 D2Sing -> S2D <$> uniformSample
31 D3Sing -> S3D <$> uniformSample
31 D3Sing -> S3D <$> uniformSample
32+
33+
34+nice :: S shape -> String
35+nice (S1D x) = show . HStatic.extract $ x
36+nice (S2D x) = show . HStatic.extract $ x
37+nice (S3D x) = show . HStatic.extract $ x
test/Test/Hedgehog/Network.hsnew file+203
@@ -0,0 +1,203 @@
1+{-# LANGUAGE CPP #-}
2+{-# LANGUAGE RankNTypes #-}
3+{-# LANGUAGE DataKinds #-}
4+{-# LANGUAGE ScopedTypeVariables #-}
5+{-# LANGUAGE PolyKinds #-}
6+{-# LANGUAGE GADTs #-}
7+{-# LANGUAGE TypeOperators #-}
8+{-# LANGUAGE TemplateHaskell #-}
9+{-# LANGUAGE FlexibleContexts #-}
10+module Test.Hedgehog.Network where
11+
12+import Control.Monad.ST ( runST )
13+
14+import Data.Constraint
15+#if __GLASGOW_HASKELL__ < 800
16+import Data.Proxy
17+#endif
18+import qualified Data.Vector.Storable as VS
19+import qualified Data.Vector.Storable.Mutable as VS ( write )
20+import Data.Singletons
21+import Data.Singletons.Prelude.List
22+-- import Data.Type.Equality
23+
24+import Hedgehog
25+import Hedgehog.Gen ( Gen )
26+import qualified Hedgehog.Gen as Gen
27+import Hedgehog.Internal.Source
28+import Hedgehog.Internal.Property ( failWith )
29+
30+import Grenade
31+
32+import GHC.TypeLits
33+import GHC.TypeLits.Witnesses
34+import Test.Hedgehog.Compat
35+import Test.Hedgehog.TypeLits
36+import Test.Hedgehog.Hmatrix
37+import Test.Grenade.Layers.Convolution
38+
39+import Numeric.LinearAlgebra ( flatten )
40+import Numeric.LinearAlgebra.Static ( size , extract, norm_Inf )
41+import Unsafe.Coerce
42+
43+data SomeNetwork :: * where
44+ SomeNetwork :: ( SingI shapes, SingI (Head shapes), SingI (Last shapes), Show (Network layers shapes) ) => Network layers shapes -> SomeNetwork
45+
46+instance Show SomeNetwork where
47+ show (SomeNetwork net) = show net
48+
49+-- | Generate a random network of a random type
50+--
51+-- This is slightly insane
52+genNetwork :: Monad m => Gen m SomeNetwork
53+genNetwork =
54+ Gen.recursive Gen.choice [
55+ do SomeSing ( r :: Sing final ) <- genShape
56+ withSingI r $
57+ pure (SomeNetwork (NNil :: Network '[] '[ final ] ))
58+ ] [
59+ do SomeNetwork ( rest :: Network layers shapes ) <- genNetwork
60+ case ( sing :: Sing shapes ) of
61+ SNil -> Gen.discard
62+ SCons ( r :: Sing h ) ( _ :: Sing hs ) ->
63+ withSingI r $ Gen.choice [
64+ pure (SomeNetwork (Logit :~> rest :: Network ( Logit ': layers ) ( h ': h ': hs )))
65+ , pure (SomeNetwork (Tanh :~> rest :: Network ( Tanh ': layers ) ( h ': h ': hs )))
66+ , case r of
67+ D1Sing ->
68+ Gen.choice [
69+ pure (SomeNetwork (Relu :~> rest :: Network ( Relu ': layers ) ( h ': h ': hs )))
70+ , pure (SomeNetwork (Elu :~> rest :: Network ( Elu ': layers ) ( h ': h ': hs )))
71+ , pure (SomeNetwork (Softmax :~> rest :: Network ( Softmax ': layers ) ( h ': h ': hs )))
72+ ]
73+ D2Sing ->
74+ Gen.choice [
75+ pure (SomeNetwork (Relu :~> rest :: Network ( Relu ': layers ) ( h ': h ': hs )))
76+ , pure (SomeNetwork (Elu :~> rest :: Network ( Elu ': layers ) ( h ': h ': hs )))
77+ , do -- Build a convolution layer with one filter output
78+ -- Figure out some kernel sizes which work for this layer
79+ -- There must be a better way than this...
80+ let dumb :: S h = 0
81+ case dumb of
82+ S2D x -> do
83+ let (rs, cs) = size x
84+ let output_r = fromIntegral rs
85+ let output_c = fromIntegral cs
86+
87+ let ok extent kernel = [stride | stride <- [ 1 .. extent ], (extent - kernel) `mod` stride == 0]
88+
89+ -- Get some kernels which will fit
90+ kernel_r <- choose 1 output_r
91+ kernel_c <- choose 1 output_c
92+
93+ -- Build up some strides which also fit
94+ stride_r <- Gen.element $ ok output_r kernel_r
95+ stride_c <- Gen.element $ ok output_c kernel_c
96+
97+ -- Determine the input size
98+ let input_r = (output_r - 1) * stride_r + kernel_r
99+ let input_c = (output_c - 1) * stride_c + kernel_c
100+
101+ -- Remake types for input
102+ case ( someNatVal input_r, someNatVal input_c, someNatVal output_r, someNatVal output_c, someNatVal kernel_r, someNatVal kernel_c, someNatVal stride_r, someNatVal stride_c ) of
103+ ( Just (SomeNat (_ :: Proxy inRows)), Just (SomeNat (_ :: Proxy inCols)),
104+ Just (SomeNat (_ :: Proxy outRows)), Just (SomeNat (_ :: Proxy outCols)),
105+ Just (SomeNat (pkr :: Proxy kernelRows)), Just (SomeNat (pkc :: Proxy kernelCols)),
106+ Just (SomeNat (_ :: Proxy strideRows)), Just (SomeNat (_ :: Proxy strideCols))) ->
107+ let p1 = natDict pkr
108+ p2 = natDict pkc
109+ in case ( p1 %* p2
110+ -- Fake it till you make it.
111+ , (unsafeCoerce (Dict :: Dict ()) :: Dict ( ( 'D2 outRows outCols ) ~ h ))
112+ , (unsafeCoerce (Dict :: Dict ()) :: Dict (((outRows - 1) * strideRows) ~ (inRows - kernelRows)))
113+ , (unsafeCoerce (Dict :: Dict ()) :: Dict (((outCols - 1) * strideCols) ~ (inCols - kernelCols)))) of
114+ (Dict, Dict, Dict, Dict) -> do
115+ conv <- genConvolution
116+ pure (SomeNetwork (conv :~> rest :: Network ( Convolution 1 1 kernelRows kernelCols strideRows strideCols ': layers ) ( ('D2 inRows inCols) ': h ': hs )))
117+ _ -> Gen.discard
118+ ]
119+ D3Sing ->
120+ Gen.choice [
121+ pure (SomeNetwork (Relu :~> rest :: Network ( Relu ': layers ) ( h ': h ': hs )))
122+ , pure (SomeNetwork (Elu :~> rest :: Network ( Elu ': layers ) ( h ': h ': hs )))
123+ ]
124+ ]
125+ ]
126+
127+-- Test a partial derivative numerically for a random network and input
128+prop_auto_diff :: Property
129+prop_auto_diff = property $ do
130+ SomeNetwork (network :: Network layers shapes) <- forAll genNetwork
131+ (input :: S (Head shapes)) <- forAllRender nice genOfShape
132+ (target :: S (Last shapes)) <- forAllRender nice oneUp
133+ (tested :: S (Head shapes)) <- forAllRender nice oneUp
134+
135+ let (tapes, output) = runNetwork network input
136+ let (_, bgrad) = runGradient network tapes target
137+ let inputDiff = input + tested * 0.00001
138+ let expected = maxVal ( bgrad * tested )
139+ let (_, outputDiff) = runNetwork network inputDiff
140+ let result = maxVal ( outputDiff * target - output * target ) / 0.00001
141+
142+ result ~~~ expected
143+
144+ where
145+
146+-- Make a shape where all are 0 except for 1 value, which is 1.
147+oneUp :: forall shape m. ( Monad m, SingI shape ) => Gen m (S shape)
148+oneUp =
149+ case ( sing :: Sing shape ) of
150+ D1Sing -> let x = 0 :: S ( shape )
151+ in case x of
152+ ( S1D x' ) -> do
153+ let ex = extract x'
154+ let len = VS.length ex
155+ ix <- choose 0 (len - 1)
156+ let nx = runST $ do ex' <- VS.thaw ex
157+ VS.write ex' ix 1.0
158+ VS.freeze ex'
159+ maybe Gen.discard pure . fromStorable $ nx
160+
161+ D2Sing -> let x = 0 :: S ( shape )
162+ in case x of
163+ ( S2D x' ) -> do
164+ let ex = flatten ( extract x' )
165+ let len = VS.length ex
166+ ix <- choose 0 (len - 1)
167+ let nx = runST $ do ex' <- VS.thaw ex
168+ VS.write ex' ix 1
169+ VS.freeze ex'
170+ maybe Gen.discard pure . fromStorable $ nx
171+
172+ D3Sing -> let x = 0 :: S ( shape )
173+ in case x of
174+ ( S3D x' ) -> do
175+ let ex = flatten ( extract x' )
176+ let len = VS.length ex
177+ ix <- choose 0 (len - 1)
178+ let nx = runST $ do ex' <- VS.thaw ex
179+ VS.write ex' ix 1
180+ VS.freeze ex'
181+ maybe Gen.discard pure . fromStorable $ nx
182+
183+maxVal :: S shape -> Double
184+maxVal ( S1D x ) = norm_Inf x
185+maxVal ( S2D x ) = norm_Inf x
186+maxVal ( S3D x ) = norm_Inf x
187+
188+(~~~) :: (Monad m, HasCallStack) => Double -> Double -> Test m ()
189+(~~~) x y =
190+ if (x - y) < 1e-5 then
191+ success
192+ else
193+ withFrozenCallStack $
194+ failWith Nothing $ unlines [
195+ "━━━ Not Simliar ━━━"
196+ , show x
197+ , show y
198+ ]
199+infix 4 ~~~
200+
201+
202+tests :: IO Bool
203+tests = $$(checkConcurrent)
test/Test/Jack/TypeLits.hs → test/Test/Hedgehog/TypeLits.hsrenamed+10−7
@@ -3,7 +3,9 @@
3{-# LANGUAGE DataKinds #-}
3{-# LANGUAGE DataKinds #-}
4{-# LANGUAGE ScopedTypeVariables #-}
4{-# LANGUAGE ScopedTypeVariables #-}
5{-# LANGUAGE PolyKinds #-}
5{-# LANGUAGE PolyKinds #-}
6+{-# LANGUAGE TypeOperators #-}
7+{-# LANGUAGE GADTs #-}
6−module Test.Jack.TypeLits where
8+module Test.Hedgehog.TypeLits where
7
9
8import Data.Constraint
10import Data.Constraint
9#if __GLASGOW_HASKELL__ < 800
11#if __GLASGOW_HASKELL__ < 800
@@ -11,15 +13,16 @@ import Data.Proxy
11#endif
13#endif
12import Data.Singletons
14import Data.Singletons
13
15
16+import Hedgehog.Gen ( Gen )
14import qualified Hedgehog.Gen as Gen
17import qualified Hedgehog.Gen as Gen
15
18
16import Grenade
19import Grenade
17
20
18import GHC.TypeLits
21import GHC.TypeLits
19import GHC.TypeLits.Witnesses
22import GHC.TypeLits.Witnesses
20−import Test.Jack.Compat
23+import Test.Hedgehog.Compat
21
24
22−genNat :: Jack SomeNat
25+genNat :: Monad m => Gen m SomeNat
23genNat = do
26genNat = do
24 Just n <- someNatVal <$> choose 1 10
27 Just n <- someNatVal <$> choose 1 10
25 return n
28 return n
@@ -30,7 +33,7 @@ type Shape' = ('KProxy :: KProxy Shape)
30type Shape' = Shape
33type Shape' = Shape
31#endif
34#endif
32
35
33−genShape :: Jack (SomeSing Shape')
36+genShape :: Monad m => Gen m (SomeSing Shape')
34genShape
37genShape
35 = Gen.choice [
38 = Gen.choice [
36 genD1
39 genD1
@@ -38,20 +41,20 @@ genShape
38 , genD3
41 , genD3
39 ]
42 ]
40
43
41−genD1 :: Jack (SomeSing Shape')
44+genD1 :: Monad m => Gen m (SomeSing Shape')
42genD1 = do
45genD1 = do
43 n <- genNat
46 n <- genNat
44 return $ case n of
47 return $ case n of
45 SomeNat (_ :: Proxy x) -> SomeSing (sing :: Sing ('D1 x))
48 SomeNat (_ :: Proxy x) -> SomeSing (sing :: Sing ('D1 x))
46
49
47−genD2 :: Jack (SomeSing Shape')
50+genD2 :: Monad m => Gen m (SomeSing Shape')
48genD2 = do
51genD2 = do
49 n <- genNat
52 n <- genNat
50 m <- genNat
53 m <- genNat
51 return $ case (n, m) of
54 return $ case (n, m) of
52 (SomeNat (_ :: Proxy x), SomeNat (_ :: Proxy y)) -> SomeSing (sing :: Sing ('D2 x y))
55 (SomeNat (_ :: Proxy x), SomeNat (_ :: Proxy y)) -> SomeSing (sing :: Sing ('D2 x y))
53
56
54−genD3 :: Jack (SomeSing Shape')
57+genD3 :: Monad m => Gen m (SomeSing Shape')
55genD3 = do
58genD3 = do
56 n <- genNat
59 n <- genNat
57 m <- genNat
60 m <- genNat
test/Test/Jack/Compat.hsdeleted−22
@@ -1,22 +0,0 @@
1−{-# LANGUAGE RankNTypes #-}
2−module Test.Jack.Compat where
3−
4−import Control.Monad.Trans.Class (MonadTrans(..))
5−
6−import Hedgehog
7−import qualified Hedgehog.Gen as Gen
8−import qualified Hedgehog.Range as Range
9−import Hedgehog.Internal.Property ( Test (..) )
10−
11−type Jack x = forall m. Monad m => Gen m x
12−
13−(...) :: (c -> d) -> (a -> b -> c) -> a -> b -> d
14−(...) = (.) . (.)
15−{-# INLINE (...) #-}
16−
17−choose :: Integral a => a -> a -> Jack a
18−choose = Gen.integral ... Range.constant
19−
20−-- | Generates a random input for the test by running the provided generator.
21−blindForAll :: Monad m => Gen m a -> Test m a
22−blindForAll = Test . lift . lift
test/test.hs+3
@@ -10,6 +10,7 @@ import qualified Test.Grenade.Layers.Internal.Convolution
10import qualified Test.Grenade.Layers.Internal.Pooling
10import qualified Test.Grenade.Layers.Internal.Pooling
11
11
12import qualified Test.Grenade.Recurrent.Layers.LSTM
12import qualified Test.Grenade.Recurrent.Layers.LSTM
13+import qualified Test.Hedgehog.Network
13
14
14import System.Exit
15import System.Exit
15import System.IO
16import System.IO
@@ -27,6 +28,8 @@ main =
27 , Test.Grenade.Layers.Internal.Pooling.tests
28 , Test.Grenade.Layers.Internal.Pooling.tests
28
29
29 , Test.Grenade.Recurrent.Layers.LSTM.tests
30 , Test.Grenade.Recurrent.Layers.LSTM.tests
31+
32+ , Test.Hedgehog.Network.tests
30 ]
33 ]
31
34
32disorderMain :: [IO Bool] -> IO ()
35disorderMain :: [IO Bool] -> IO ()