From bff396138cbd07936f6457341458bcae93a93989 Mon Sep 17 00:00:00 2001 From: Ian-Woo Kim Date: Sat, 28 May 2022 09:50:43 -0700 Subject: [PATCH 01/13] start grad-descent example --- examples/categorifier-c-examples.cabal | 34 ++++++++++++++++++++++++++ examples/grad-descent/F.hs | 27 ++++++++++++++++++++ examples/grad-descent/Main.hs | 9 +++++++ 3 files changed, 70 insertions(+) create mode 100644 examples/grad-descent/F.hs create mode 100644 examples/grad-descent/Main.hs diff --git a/examples/categorifier-c-examples.cabal b/examples/categorifier-c-examples.cabal index 037ec0c..aa5b1ec 100644 --- a/examples/categorifier-c-examples.cabal +++ b/examples/categorifier-c-examples.cabal @@ -278,3 +278,37 @@ executable th-compile , categorifier-unconcat-category , categorifier-unconcat-integration default-language: Haskell2010 + +executable grad-descent + hs-source-dirs: grad-descent + main-is: Main.hs + other-modules: + F + ghc-options: + -O0 + -fexpose-all-unfoldings + -fmax-simplifier-iterations=0 + -fno-ignore-interface-pragmas + -fno-omit-interface-pragmas + -Wall + -fplugin Categorifier + -fplugin-opt Categorifier:hierarchy:Categorifier.Hierarchy.UnconCat.hierarchy + -fplugin-opt Categorifier:hierarchy:Categorifier.Hierarchy.ConCat.functionHierarchy + -fplugin-opt Categorifier:hierarchy:Categorifier.Hierarchy.ConCatExtensions.hierarchy + build-depends: + base + , ghc-prim + , concat-classes + , categorifier-c + , categorifier-c-test-lib + , categorifier-category + , categorifier-client + , categorifier-concat-extensions-category + , categorifier-concat-extensions-integration + , categorifier-concat-integration + , categorifier-plugin + , categorifier-unconcat-category + , categorifier-unconcat-integration + , ad + , reflection + default-language: Haskell2010 diff --git a/examples/grad-descent/F.hs b/examples/grad-descent/F.hs new file mode 100644 index 0000000..d6932e2 --- /dev/null +++ b/examples/grad-descent/F.hs @@ -0,0 +1,27 @@ +{-# LANGUAGE FlexibleContexts #-} +{-# LANGUAGE RankNTypes #-} +{-# LANGUAGE ScopedTypeVariables #-} + +module F + ( rosenbrock, + dRosenbrock, + ) +where + +import Data.Reflection (Reifies) +import Numeric.AD (grad) +import Numeric.AD.Internal.Reverse (Tape) +import Numeric.AD.Mode.Reverse (Reverse) + +rosenbrock :: RealFloat a => (a, a) -> (a, a) -> a +rosenbrock (a, b) (x, y) = (a - x) ^ 2 + b * (y - x ^ 2) ^ 2 + +dRosenbrock :: (Double, Double) -> (Double, Double) -> (Double, Double) +dRosenbrock (a, b) (x, y) = + let rosenbrock' :: forall s. Reifies s Tape => [Reverse s Double] -> Reverse s Double + rosenbrock' [x', y'] = + let a' = realToFrac a + b' = realToFrac b + in rosenbrock (a', b') (x', y') + [dx, dy] = grad rosenbrock' [x, y] + in (dx, dy) diff --git a/examples/grad-descent/Main.hs b/examples/grad-descent/Main.hs new file mode 100644 index 0000000..feba5b9 --- /dev/null +++ b/examples/grad-descent/Main.hs @@ -0,0 +1,9 @@ +module Main where + +import F (dRosenbrock, rosenbrock) + +main :: IO () +main = do + print (rosenbrock (1, 100) (0, 0)) + + print (dRosenbrock (1, 100) (0, 0)) From 5c37fc2adacfa1b43c867e819bc7f91d89d00dad Mon Sep 17 00:00:00 2001 From: Ian-Woo Kim Date: Sat, 28 May 2022 10:00:53 -0700 Subject: [PATCH 02/13] naive gd. --- examples/grad-descent/F.hs | 4 ++-- examples/grad-descent/Main.hs | 18 +++++++++++++++--- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/examples/grad-descent/F.hs b/examples/grad-descent/F.hs index d6932e2..8069dba 100644 --- a/examples/grad-descent/F.hs +++ b/examples/grad-descent/F.hs @@ -23,5 +23,5 @@ dRosenbrock (a, b) (x, y) = let a' = realToFrac a b' = realToFrac b in rosenbrock (a', b') (x', y') - [dx, dy] = grad rosenbrock' [x, y] - in (dx, dy) + [dfdx, dfdy] = grad rosenbrock' [x, y] + in (dfdx, dfdy) diff --git a/examples/grad-descent/Main.hs b/examples/grad-descent/Main.hs index feba5b9..4e680ac 100644 --- a/examples/grad-descent/Main.hs +++ b/examples/grad-descent/Main.hs @@ -1,9 +1,21 @@ module Main where +import Data.List (iterate) import F (dRosenbrock, rosenbrock) +gamma = 0.01 + +step f df (x0, y0) = + let (dfdx, dfdy) = df (x0, y0) + (x1, y1) = (x0 - gamma * dfdx, y0 - gamma * dfdy) + in (x1, y1) + main :: IO () main = do - print (rosenbrock (1, 100) (0, 0)) - - print (dRosenbrock (1, 100) (0, 0)) + let f = rosenbrock (1, 100) + df = dRosenbrock (1, 100) + (x0, y0) = (0, 0) + (x1, y1) = step f df (x0, y0) + (x2, y2) = step f df (x1, y1) + hist = take 10 $ iterate (step f df) (0, 0) + print hist From 4397bda1f8978006a8bfaaa8076ee36116a14193 Mon Sep 17 00:00:00 2001 From: Ian-Woo Kim Date: Sat, 28 May 2022 14:03:05 -0700 Subject: [PATCH 03/13] categorify rosenbrock and dRosenbrock (not working due to unsafePerformIO prob) --- examples/grad-descent/F.hs | 84 +++++++++++++++++++++++++++++++++-- examples/grad-descent/Main.hs | 36 +++++++++++---- 2 files changed, 108 insertions(+), 12 deletions(-) diff --git a/examples/grad-descent/F.hs b/examples/grad-descent/F.hs index 8069dba..a8fe249 100644 --- a/examples/grad-descent/F.hs +++ b/examples/grad-descent/F.hs @@ -1,27 +1,103 @@ +{-# LANGUAGE DeriveGeneric #-} {-# LANGUAGE FlexibleContexts #-} +{-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE RankNTypes #-} {-# LANGUAGE ScopedTypeVariables #-} +{-# LANGUAGE TemplateHaskell #-} +{-# LANGUAGE TypeFamilies #-} +{-# LANGUAGE TypeOperators #-} +{-# LANGUAGE UndecidableInstances #-} module F - ( rosenbrock, + ( Input (..), + Output (..), + rosenbrock, dRosenbrock, + wrap_rosenbrockF, + -- wrap_dRosenbrockF, ) where +import qualified Categorifier.C.CExpr.Cat as C +import Categorifier.C.CExpr.Cat.TargetOb (TargetOb) +import Categorifier.C.CTypes.CGeneric (CGeneric) +import qualified Categorifier.C.CTypes.CGeneric as CG +import Categorifier.C.CTypes.GArrays (GArrays) +import Categorifier.C.KTypes.C (C) +-- import Categorifier.C.KTypes.KLiteral (kliteral) +import qualified Categorifier.Categorify as Categorify +import Categorifier.Client (deriveHasRep) +import Data.Int (Int32) import Data.Reflection (Reifies) +import Data.Word (Word64) +import GHC.Generics (Generic) import Numeric.AD (grad) import Numeric.AD.Internal.Reverse (Tape) import Numeric.AD.Mode.Reverse (Reverse) -rosenbrock :: RealFloat a => (a, a) -> (a, a) -> a +rosenbrock :: RealFrac a => (a, a) -> (a, a) -> a rosenbrock (a, b) (x, y) = (a - x) ^ 2 + b * (y - x ^ 2) ^ 2 -dRosenbrock :: (Double, Double) -> (Double, Double) -> (Double, Double) +dRosenbrock :: forall a. RealFrac a => (a, a) -> (a, a) -> (a, a) dRosenbrock (a, b) (x, y) = - let rosenbrock' :: forall s. Reifies s Tape => [Reverse s Double] -> Reverse s Double + let rosenbrock' :: forall s. Reifies s Tape => [Reverse s a] -> Reverse s a rosenbrock' [x', y'] = let a' = realToFrac a b' = realToFrac b in rosenbrock (a', b') (x', y') [dfdx, dfdy] = grad rosenbrock' [x, y] in (dfdx, dfdy) + +data Input = Input + { iA :: C Double, + iB :: C Double, + iX :: C Double, + iY :: C Double + } + deriving (Generic, Show) + +deriveHasRep ''Input + +instance CGeneric Input + +instance GArrays C Input + +type instance TargetOb Input = TargetOb (CG.Rep Input ()) + +newtype Output = Output + {oF :: C Double} + deriving (Generic, Show) + +deriveHasRep ''Output + +instance CGeneric Output + +instance GArrays C Output + +type instance TargetOb Output = TargetOb (CG.Rep Output ()) + +data Output2 = Output2 + { oDFDX :: C Double, + oDFDY :: C Double + } + deriving (Generic, Show) + +deriveHasRep ''Output2 + +instance CGeneric Output2 + +instance GArrays C Output2 + +type instance TargetOb Output2 = TargetOb (CG.Rep Output2 ()) + +rosenbrockF :: Input -> Output +rosenbrockF (Input a b x y) = Output $ rosenbrock (a, b) (x, y) + +dRosenbrockF :: Input -> Output2 +dRosenbrockF (Input a b x y) = + let (dfdx, dfdy) = dRosenbrock (a, b) (x, y) + in Output2 dfdx dfdy + +$(Categorify.function 'rosenbrockF [t|C.Cat|] []) + +-- $(Categorify.function 'dRosenbrockF [t|C.Cat|] []) diff --git a/examples/grad-descent/Main.hs b/examples/grad-descent/Main.hs index 4e680ac..c3649c1 100644 --- a/examples/grad-descent/Main.hs +++ b/examples/grad-descent/Main.hs @@ -1,10 +1,29 @@ +{-# LANGUAGE OverloadedStrings #-} +{-# LANGUAGE TemplateHaskell #-} +{-# LANGUAGE TypeApplications #-} + module Main where +import Categorifier.C.Codegen.FFI.TH (embedFunction) import Data.List (iterate) -import F (dRosenbrock, rosenbrock) +import F + ( Input (..), + Output (..), + dRosenbrock, + rosenbrock, + wrap_rosenbrockF, + ) + +$(embedFunction "rosenbrock" wrap_rosenbrockF) +gamma :: Double gamma = 0.01 +step :: + ((Double, Double) -> Double) -> + ((Double, Double) -> (Double, Double)) -> + (Double, Double) -> + (Double, Double) step f df (x0, y0) = let (dfdx, dfdy) = df (x0, y0) (x1, y1) = (x0 - gamma * dfdx, y0 - gamma * dfdy) @@ -12,10 +31,11 @@ step f df (x0, y0) = main :: IO () main = do - let f = rosenbrock (1, 100) - df = dRosenbrock (1, 100) - (x0, y0) = (0, 0) - (x1, y1) = step f df (x0, y0) - (x2, y2) = step f df (x1, y1) - hist = take 10 $ iterate (step f df) (0, 0) - print hist + let f = rosenbrock (1, 10) + df = dRosenbrock (1, 10) + hist = take 1500 $ iterate (step f df) (0.1, 0.4) + mapM_ print hist + + z <- hs_rosenbrock (Input 1 10 0.1 0.4) + let z' = f (0.1, 0.4) + print (z, z') From c280ccb70e0e46e80da83c9afe7f6a3e7eca2780 Mon Sep 17 00:00:00 2001 From: Ian-Woo Kim Date: Sun, 29 May 2022 10:05:37 -0700 Subject: [PATCH 04/13] try to categorify dRosenbrock --- examples/categorifier-c-examples.cabal | 5 ++ examples/grad-descent/F.hs | 85 +++++++++++++++++++--- examples/grad-descent/Main.hs | 11 ++- examples/multiple-c-functions/Main.hs | 2 +- examples/separate-categorification/G.hs | 2 +- examples/separate-categorification/Main.hs | 2 +- 6 files changed, 91 insertions(+), 16 deletions(-) diff --git a/examples/categorifier-c-examples.cabal b/examples/categorifier-c-examples.cabal index aa5b1ec..cea3a35 100644 --- a/examples/categorifier-c-examples.cabal +++ b/examples/categorifier-c-examples.cabal @@ -87,6 +87,10 @@ executable separate-categorification G ghc-options: -O0 + -fforce-recomp + -ddump-simpl + -ddump-splices + -dsuppress-all -fexpose-all-unfoldings -fmax-simplifier-iterations=0 -fno-ignore-interface-pragmas @@ -286,6 +290,7 @@ executable grad-descent F ghc-options: -O0 + -ddump-splices -fexpose-all-unfoldings -fmax-simplifier-iterations=0 -fno-ignore-interface-pragmas diff --git a/examples/grad-descent/F.hs b/examples/grad-descent/F.hs index a8fe249..6cd624c 100644 --- a/examples/grad-descent/F.hs +++ b/examples/grad-descent/F.hs @@ -1,9 +1,12 @@ +{-# LANGUAGE DataKinds #-} {-# LANGUAGE DeriveGeneric #-} {-# LANGUAGE FlexibleContexts #-} +{-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE RankNTypes #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE TemplateHaskell #-} +{-# LANGUAGE TypeApplications #-} {-# LANGUAGE TypeFamilies #-} {-# LANGUAGE TypeOperators #-} {-# LANGUAGE UndecidableInstances #-} @@ -11,6 +14,8 @@ module F ( Input (..), Output (..), + Param (..), + XY (..), rosenbrock, dRosenbrock, wrap_rosenbrockF, @@ -24,10 +29,11 @@ import Categorifier.C.CTypes.CGeneric (CGeneric) import qualified Categorifier.C.CTypes.CGeneric as CG import Categorifier.C.CTypes.GArrays (GArrays) import Categorifier.C.KTypes.C (C) --- import Categorifier.C.KTypes.KLiteral (kliteral) +import Categorifier.C.KTypes.Function (kFunctionCall) import qualified Categorifier.Categorify as Categorify import Categorifier.Client (deriveHasRep) import Data.Int (Int32) +import Data.Proxy (Proxy (..)) import Data.Reflection (Reifies) import Data.Word (Word64) import GHC.Generics (Generic) @@ -48,11 +54,39 @@ dRosenbrock (a, b) (x, y) = [dfdx, dfdy] = grad rosenbrock' [x, y] in (dfdx, dfdy) +----------- + +data Param = Param + { paramA :: C Double, + paramB :: C Double + } + deriving (Generic, Show) + +deriveHasRep ''Param + +instance CGeneric Param + +instance GArrays C Param + +type instance TargetOb Param = TargetOb (CG.Rep Param ()) + +data XY = XY + { xyX :: C Double, + xyY :: C Double + } + deriving (Generic, Show) + +deriveHasRep ''XY + +instance CGeneric XY + +instance GArrays C XY + +type instance TargetOb XY = TargetOb (CG.Rep XY ()) + data Input = Input - { iA :: C Double, - iB :: C Double, - iX :: C Double, - iY :: C Double + { iParam :: Param, + iCoord :: XY } deriving (Generic, Show) @@ -76,6 +110,23 @@ instance GArrays C Output type instance TargetOb Output = TargetOb (CG.Rep Output ()) +rosenbrockF :: Input -> Output +rosenbrockF (Input (Param a b) (XY x y)) = Output $ rosenbrock (a, b) (x, y) + +data Input2 = Input2 + { i2X :: C Double, + i2Y :: C Double + } + deriving (Generic, Show) + +deriveHasRep ''Input2 + +instance CGeneric Input2 + +instance GArrays C Input2 + +type instance TargetOb Input2 = TargetOb (CG.Rep Input2 ()) + data Output2 = Output2 { oDFDX :: C Double, oDFDY :: C Double @@ -90,14 +141,24 @@ instance GArrays C Output2 type instance TargetOb Output2 = TargetOb (CG.Rep Output2 ()) -rosenbrockF :: Input -> Output -rosenbrockF (Input a b x y) = Output $ rosenbrock (a, b) (x, y) +-------------------------------------- + +dRosenbrock_ :: Param -> XY -> XY +dRosenbrock_ (Param a b) (XY x y) = + let rosenbrock' :: forall s. Reifies s Tape => [Reverse s (C Double)] -> Reverse s (C Double) + rosenbrock' [x', y'] = + let a' = realToFrac a + b' = realToFrac b + in rosenbrock (a', b') (x', y') + [dfdx, dfdy] = grad rosenbrock' [x, y] + in XY dfdx dfdy -dRosenbrockF :: Input -> Output2 -dRosenbrockF (Input a b x y) = - let (dfdx, dfdy) = dRosenbrock (a, b) (x, y) - in Output2 dfdx dfdy +dRosenbrockF :: Param -> XY -> XY +dRosenbrockF p = + kFunctionCall (Proxy @C) "dRosenbrock_" (dRosenbrock_ p) $(Categorify.function 'rosenbrockF [t|C.Cat|] []) --- $(Categorify.function 'dRosenbrockF [t|C.Cat|] []) +$(Categorify.function 'dRosenbrockF [t|C.Cat|] []) + +-- wrap_dRosenbrockF = id diff --git a/examples/grad-descent/Main.hs b/examples/grad-descent/Main.hs index c3649c1..8381261 100644 --- a/examples/grad-descent/Main.hs +++ b/examples/grad-descent/Main.hs @@ -9,13 +9,18 @@ import Data.List (iterate) import F ( Input (..), Output (..), + Param (..), + XY (..), dRosenbrock, rosenbrock, wrap_rosenbrockF, + -- wrap_dRosenbrockF, ) $(embedFunction "rosenbrock" wrap_rosenbrockF) +-- $(embedFunction "dRosenbrock" wrap_dRosenbrockF) + gamma :: Double gamma = 0.01 @@ -36,6 +41,10 @@ main = do hist = take 1500 $ iterate (step f df) (0.1, 0.4) mapM_ print hist - z <- hs_rosenbrock (Input 1 10 0.1 0.4) + z <- hs_rosenbrock (Input (Param 1 10) (XY 0.1 0.4)) let z' = f (0.1, 0.4) print (z, z') + +-- out3 <- +-- _ +-- print out3 diff --git a/examples/multiple-c-functions/Main.hs b/examples/multiple-c-functions/Main.hs index a87976e..98436c3 100644 --- a/examples/multiple-c-functions/Main.hs +++ b/examples/multiple-c-functions/Main.hs @@ -8,4 +8,4 @@ import F (fCategorified) -- This generates /tmp/multiple_c_functions.c, which contains two -- C functions: `multiple_c_functions` (the main function), and `g`. main :: IO () -main = writeCFiles "/tmp" "multiple_c_functions" fCategorified +main = writeCFiles "." "multiple_c_functions" fCategorified diff --git a/examples/separate-categorification/G.hs b/examples/separate-categorification/G.hs index 37b4881..038453d 100644 --- a/examples/separate-categorification/G.hs +++ b/examples/separate-categorification/G.hs @@ -13,6 +13,6 @@ import Data.Int (Int32) import Data.Word (Word64) g :: C Int32 -> C Word64 -g x = if odd x then fromIntegral x + 5 else 42 +g x = if odd x then fromIntegral x + 5 else 43 Categorify.separately 'g [t|C.Cat|] [] diff --git a/examples/separate-categorification/Main.hs b/examples/separate-categorification/Main.hs index 80ea0d5..f0fdd80 100644 --- a/examples/separate-categorification/Main.hs +++ b/examples/separate-categorification/Main.hs @@ -7,4 +7,4 @@ import F (fCategorified) -- This generates /tmp/separate_categorification.c main :: IO () -main = writeCFiles "/tmp" "separate_categorification" fCategorified +main = writeCFiles "." "separate_categorification" fCategorified From 1c6d627152c965c39af4ab5fa01a6999577eca6d Mon Sep 17 00:00:00 2001 From: Ian-Woo Kim Date: Sun, 29 May 2022 15:41:49 -0700 Subject: [PATCH 05/13] add missing dep for kFunctionCall --- examples/categorifier-c-examples.cabal | 3 +++ 1 file changed, 3 insertions(+) diff --git a/examples/categorifier-c-examples.cabal b/examples/categorifier-c-examples.cabal index cea3a35..f6f6e86 100644 --- a/examples/categorifier-c-examples.cabal +++ b/examples/categorifier-c-examples.cabal @@ -300,11 +300,14 @@ executable grad-descent -fplugin-opt Categorifier:hierarchy:Categorifier.Hierarchy.UnconCat.hierarchy -fplugin-opt Categorifier:hierarchy:Categorifier.Hierarchy.ConCat.functionHierarchy -fplugin-opt Categorifier:hierarchy:Categorifier.Hierarchy.ConCatExtensions.hierarchy + -fplugin-opt Categorifier:maker-map:Categorifier.Core.MakerMap.baseMakerMapFun + -fplugin-opt Categorifier:maker-map:Categorifier.C.MakerMap.cMakerMapFun build-depends: base , ghc-prim , concat-classes , categorifier-c + , categorifier-c-maker-map , categorifier-c-test-lib , categorifier-category , categorifier-client From d3b5127c45cae9cd15a6c733f9be41c40dec9c5e Mon Sep 17 00:00:00 2001 From: Ian-Woo Kim Date: Mon, 30 May 2022 17:05:37 -0700 Subject: [PATCH 06/13] first working auto-diff example! --- examples/categorifier-c-examples.cabal | 5 + examples/grad-descent/F.hs | 132 +++++++++++++--------- examples/grad-descent/Main.hs | 57 +++++++--- test-lib/Categorifier/C/Codegen/FFI/TH.hs | 39 ++++++- 4 files changed, 164 insertions(+), 69 deletions(-) diff --git a/examples/categorifier-c-examples.cabal b/examples/categorifier-c-examples.cabal index f6f6e86..f108f9f 100644 --- a/examples/categorifier-c-examples.cabal +++ b/examples/categorifier-c-examples.cabal @@ -302,13 +302,18 @@ executable grad-descent -fplugin-opt Categorifier:hierarchy:Categorifier.Hierarchy.ConCatExtensions.hierarchy -fplugin-opt Categorifier:maker-map:Categorifier.Core.MakerMap.baseMakerMapFun -fplugin-opt Categorifier:maker-map:Categorifier.C.MakerMap.cMakerMapFun + -fplugin-opt Categorifier:autointerpreter:Categorifier.C.UnconCat.tryAutoInterpret + -optc-Wno-implicit-function-declaration + -fprint-potential-instances build-depends: base , ghc-prim , concat-classes , categorifier-c + , categorifier-c-hk-classes , categorifier-c-maker-map , categorifier-c-test-lib + , categorifier-c-unconcat , categorifier-category , categorifier-client , categorifier-concat-extensions-category diff --git a/examples/grad-descent/F.hs b/examples/grad-descent/F.hs index 6cd624c..a2672e3 100644 --- a/examples/grad-descent/F.hs +++ b/examples/grad-descent/F.hs @@ -5,32 +5,36 @@ {-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE RankNTypes #-} {-# LANGUAGE ScopedTypeVariables #-} +{-# LANGUAGE StandaloneDeriving #-} {-# LANGUAGE TemplateHaskell #-} {-# LANGUAGE TypeApplications #-} {-# LANGUAGE TypeFamilies #-} {-# LANGUAGE TypeOperators #-} {-# LANGUAGE UndecidableInstances #-} -module F - ( Input (..), +module F where + +{- ( Input (..), Output (..), Param (..), XY (..), rosenbrock, dRosenbrock, wrap_rosenbrockF, - -- wrap_dRosenbrockF, - ) -where + wrap_dRosenbrockF, + ) -} import qualified Categorifier.C.CExpr.Cat as C -import Categorifier.C.CExpr.Cat.TargetOb (TargetOb) +import Categorifier.C.CExpr.Cat.TargetOb (TargetOb, TargetObTC1) +import Categorifier.C.CExpr.Types.Core (CExpr) import Categorifier.C.CTypes.CGeneric (CGeneric) import qualified Categorifier.C.CTypes.CGeneric as CG import Categorifier.C.CTypes.GArrays (GArrays) import Categorifier.C.KTypes.C (C) import Categorifier.C.KTypes.Function (kFunctionCall) +import Categorifier.C.KTypes.KType1 (KType1) import qualified Categorifier.Categorify as Categorify +import qualified Categorifier.Category as Category import Categorifier.Client (deriveHasRep) import Data.Int (Int32) import Data.Proxy (Proxy (..)) @@ -56,6 +60,7 @@ dRosenbrock (a, b) (x, y) = ----------- +{- data Param = Param { paramA :: C Double, paramB :: C Double @@ -69,21 +74,56 @@ instance CGeneric Param instance GArrays C Param type instance TargetOb Param = TargetOb (CG.Rep Param ()) +-} -data XY = XY - { xyX :: C Double, - xyY :: C Double +data XY f = XY + { xyX :: f Double, + xyY :: f Double } - deriving (Generic, Show) + deriving (Generic) + +deriving instance Show (XY C) deriveHasRep ''XY -instance CGeneric XY +instance CGeneric (XY f) + +instance GArrays f (XY f) + +type instance TargetOb (XY f) = XY (TargetObTC1 f) + +dummy :: (KType1 f) => XY f -> XY f +dummy (XY x y) = + let f [x', y'] = x' * x' + y' * y' + [dfdx, dfdy] = grad f [x, y] + in XY dfdx dfdy + +-- $(Categorify.separately 'dummy [t|C.Cat|] [pure [t|C|]]) + +$(Categorify.separately 'dummy [t|C.Cat|] [pure [t|C|]]) -instance GArrays C XY +-- wrap_dummy :: KType1 f => C.Cat (XY f) (XY f) +-- wrap_dummy :: C.Cat (XY C) (XY C) +-- wrap_dummy :: XY C -> XY C +-- wrap_dummy = dummy -- Categorify.expression dummy -type instance TargetOb XY = TargetOb (CG.Rep XY ()) +-- instance Category.NativeCat (->) "F.dummy" (XY C) (XY C) where +-- nativeK = wrap_dummy +-- dummy_ :: XY C -> XY C +-- dummy_ = kFunctionCall (Proxy @C) "dummy" dummy + +-- $(Categorify.separately 'dummy_ [t|C.Cat|] []) + +-- if x > 0 then x + 5 else 42 + +-- kFunctionCall (Proxy @C) "g" $ + +-- type instance TargetOb (XY C) = TargetOb (CG.Rep (XY C) ()) + +-- type instance TargetOb (XY C) = Float + +{- data Input = Input { iParam :: Param, iCoord :: XY @@ -113,52 +153,42 @@ type instance TargetOb Output = TargetOb (CG.Rep Output ()) rosenbrockF :: Input -> Output rosenbrockF (Input (Param a b) (XY x y)) = Output $ rosenbrock (a, b) (x, y) -data Input2 = Input2 - { i2X :: C Double, - i2Y :: C Double - } - deriving (Generic, Show) - -deriveHasRep ''Input2 - -instance CGeneric Input2 - -instance GArrays C Input2 - -type instance TargetOb Input2 = TargetOb (CG.Rep Input2 ()) - -data Output2 = Output2 - { oDFDX :: C Double, - oDFDY :: C Double - } - deriving (Generic, Show) +-------------------------------------- -deriveHasRep ''Output2 +dRosenbrock_ {- Param -> -} :: (KType f) -> XY f -> XY f +dRosenbrock_ {- (Param a b) -} (XY x y) = + let rosenbrock' :: forall s. Reifies s Tape => [Reverse s (C Double)] -> Reverse s (C Double) + rosenbrock' [x', y'] = x' + y' + {- let a' = 1 -- realToFrac a + b' = 10 -- realToFrac b + in rosenbrock (a', b') (x', y') -} + [dfdx, dfdy] = grad rosenbrock' [x, y] + in XY dfdx dfdy +-} -instance CGeneric Output2 +-- dummy_ :: XY C -> XY C +-- dummy_ xy = kFunctionCall (Proxy @C) "dummy" dummy xy -instance GArrays C Output2 +{- +dRosenbrockF {- Param -> -} :: + XY -> XY +dRosenbrockF (XY x y) = + let p = Param 1 10 + in -- x' = gg x + -- kFunctionCall (Proxy @C) "dRosenbrock_c" dummy (XY x y) -type instance TargetOb Output2 = TargetOb (CG.Rep Output2 ()) + -- dummy 2 (XY x y) + -- kFunctionCall (Proxy @C) "dRosenbrock_c" dRosenbrock_ (XY x y) +-} --------------------------------------- +{- dummydRosenbrock_ p -} -dRosenbrock_ :: Param -> XY -> XY -dRosenbrock_ (Param a b) (XY x y) = - let rosenbrock' :: forall s. Reifies s Tape => [Reverse s (C Double)] -> Reverse s (C Double) - rosenbrock' [x', y'] = - let a' = realToFrac a - b' = realToFrac b - in rosenbrock (a', b') (x', y') - [dfdx, dfdy] = grad rosenbrock' [x, y] - in XY dfdx dfdy +-- $(Categorify.function 'rosenbrockF [t|C.Cat|] []) -dRosenbrockF :: Param -> XY -> XY -dRosenbrockF p = - kFunctionCall (Proxy @C) "dRosenbrock_" (dRosenbrock_ p) +-- $(Categorify.function 'dRosenbrockF [t|C.Cat|] []) -$(Categorify.function 'rosenbrockF [t|C.Cat|] []) +-- $(Categorify.function 'dummy_ [t|C.Cat|] []) -$(Categorify.function 'dRosenbrockF [t|C.Cat|] []) +-- $(Categorify.separately 'dRosenbrock_ [t|C.Cat|] []) -- wrap_dRosenbrockF = id diff --git a/examples/grad-descent/Main.hs b/examples/grad-descent/Main.hs index 8381261..effbc0c 100644 --- a/examples/grad-descent/Main.hs +++ b/examples/grad-descent/Main.hs @@ -1,25 +1,43 @@ +{-# LANGUAGE ForeignFunctionInterface #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE TemplateHaskell #-} {-# LANGUAGE TypeApplications #-} module Main where -import Categorifier.C.Codegen.FFI.TH (embedFunction) +import Categorifier.C.Codegen.FFI.ArraysCC (fromArraysCC) +import Categorifier.C.Codegen.FFI.Spec (SBVFunCall) +import Categorifier.C.Codegen.FFI.TH (embedFunction, embedFunctionCTemp) +import Categorifier.C.Generate (writeCFiles) +import Categorifier.C.KTypes.C (C) import Data.List (iterate) +import Data.Proxy (Proxy (..)) import F - ( Input (..), + +{- ( Input (..), Output (..), Param (..), XY (..), dRosenbrock, rosenbrock, + wrap_dRosenbrockF, wrap_rosenbrockF, - -- wrap_dRosenbrockF, ) - +-} +{- $(embedFunction "rosenbrock" wrap_rosenbrockF) --- $(embedFunction "dRosenbrock" wrap_dRosenbrockF) +$(embedFunction "dRosenbrock" wrap_dRosenbrockF) +-} + +$(embedFunctionCTemp "dummy" wrap_dummy) + +{- +foreign import ccall safe "dummy" c_dummy :: SBVFunCall + +hs_dummy :: XY C -> IO (XY C) +hs_dummy input = fromArraysCC (Proxy @(XY C -> XY C)) c_dummy input +-} gamma :: Double gamma = 0.01 @@ -36,15 +54,20 @@ step f df (x0, y0) = main :: IO () main = do - let f = rosenbrock (1, 10) - df = dRosenbrock (1, 10) - hist = take 1500 $ iterate (step f df) (0.1, 0.4) - mapM_ print hist - - z <- hs_rosenbrock (Input (Param 1 10) (XY 0.1 0.4)) - let z' = f (0.1, 0.4) - print (z, z') - --- out3 <- --- _ --- print out3 + {- + writeCFiles "/tmp" "dRosenbrock" wrap_dRosenbrockF + + let f = rosenbrock (1, 10) + df = dRosenbrock (1, 10) + hist = take 10 {- 1500 -} $ iterate (step f df) (0.1, 0.4) + mapM_ print hist + + z <- hs_rosenbrock (Input (Param 1 10) (XY 0.1 0.4)) + let z' = f (0.1, 0.4) + print (z, z') + + out3 <- hs_dRosenbrock (XY 0.1 0.4) + print out3 + -} + out3 <- hs_dummy (XY 0.1 0.4) + print out3 diff --git a/test-lib/Categorifier/C/Codegen/FFI/TH.hs b/test-lib/Categorifier/C/Codegen/FFI/TH.hs index 656c691..dac532e 100644 --- a/test-lib/Categorifier/C/Codegen/FFI/TH.hs +++ b/test-lib/Categorifier/C/Codegen/FFI/TH.hs @@ -8,7 +8,11 @@ -- Data.Text.Prettyprint.Doc.Render.Text is deprecated. {-# OPTIONS_GHC -fno-warn-deprecations #-} -module Categorifier.C.Codegen.FFI.TH (embedFunction) where +module Categorifier.C.Codegen.FFI.TH + ( embedFunction, + embedFunctionCTemp, + ) +where import qualified Categorifier.C.CExpr.Cat as C import Categorifier.C.CExpr.Cat.TargetOb (TargetOb) @@ -89,3 +93,36 @@ embedFunction name f = do let hsfunDef = FunD funName [Clause [VarP (TH.mkName "input")] (NormalB body) []] -- pure [cfunFfi, hsfunSig, hsfunDef] + +-- temporary +embedFunctionCTemp :: + forall i o. + (Typeable i, Typeable o, PolyVec CExpr (TargetOb i), PolyVec CExpr (TargetOb o), PolyVec C i) => + Text -> + (i `C.Cat` o) -> + Q [Dec] +embedFunctionCTemp name f = do + -- generate C FFI + let cname = "c_" <> name + cnameName = TH.mkName (T.unpack cname) + codeC <- + TH.runIO $ do + x <- generateCExprFunction name (inputDims $ Proxy @i) (arraysFun f) + case x of + Left err -> Exception.impureThrow err + Right (CExpr.FunctionText _ srcText) -> + pure $ Prettyprint.renderStrict $ CExpr.layoutOptions srcText + TH.addForeignSource LangC (T.unpack codeC) + cfunFfi <- + ForeignD . ImportF CCall Safe (T.unpack name) cnameName <$> [t|SBVFunCall|] + -- generate high-level haskell + inputTy <- AppT (ConT (TH.mkName (getTypeName (Proxy @i)))) <$> [t|C|] -- for now + outputTy <- AppT (ConT (TH.mkName (getTypeName (Proxy @o)))) <$> [t|C|] -- for now + let funName = TH.mkName (T.unpack ("hs_" <> name)) + hsfunSig <- + SigD funName <$> [t|$(pure inputTy) -> IO $(pure outputTy)|] + body <- + [|fromArraysCC (Proxy @($(pure inputTy) -> $(pure outputTy))) $(pure (VarE cnameName)) input|] + let hsfunDef = FunD funName [Clause [VarP (TH.mkName "input")] (NormalB body) []] + -- + pure [cfunFfi, hsfunSig, hsfunDef] From 2d84812eca83be714acfd7ace7c9ad19b7845ef0 Mon Sep 17 00:00:00 2001 From: Ian-Woo Kim Date: Mon, 30 May 2022 17:44:12 -0700 Subject: [PATCH 07/13] make comparison of gradient descent between Haskell and codegen C --- examples/grad-descent/F.hs | 141 +++++++++++++++------------------- examples/grad-descent/Main.hs | 77 +++++++++---------- 2 files changed, 100 insertions(+), 118 deletions(-) diff --git a/examples/grad-descent/F.hs b/examples/grad-descent/F.hs index a2672e3..8c95a1b 100644 --- a/examples/grad-descent/F.hs +++ b/examples/grad-descent/F.hs @@ -42,39 +42,23 @@ import Data.Reflection (Reifies) import Data.Word (Word64) import GHC.Generics (Generic) import Numeric.AD (grad) -import Numeric.AD.Internal.Reverse (Tape) -import Numeric.AD.Mode.Reverse (Reverse) +import Numeric.AD.Internal.Reverse (Reverse (Lift), Tape) -rosenbrock :: RealFrac a => (a, a) -> (a, a) -> a -rosenbrock (a, b) (x, y) = (a - x) ^ 2 + b * (y - x ^ 2) ^ 2 - -dRosenbrock :: forall a. RealFrac a => (a, a) -> (a, a) -> (a, a) -dRosenbrock (a, b) (x, y) = - let rosenbrock' :: forall s. Reifies s Tape => [Reverse s a] -> Reverse s a - rosenbrock' [x', y'] = - let a' = realToFrac a - b' = realToFrac b - in rosenbrock (a', b') (x', y') - [dfdx, dfdy] = grad rosenbrock' [x, y] - in (dfdx, dfdy) - ------------ - -{- -data Param = Param - { paramA :: C Double, - paramB :: C Double +data Param f = Param + { paramA :: f Double, + paramB :: f Double } - deriving (Generic, Show) + deriving (Generic) + +deriving instance Show (Param C) deriveHasRep ''Param -instance CGeneric Param +instance CGeneric (Param f) -instance GArrays C Param +instance GArrays f (Param f) -type instance TargetOb Param = TargetOb (CG.Rep Param ()) --} +type instance TargetOb (Param f) = Param (TargetObTC1 f) data XY f = XY { xyX :: f Double, @@ -92,80 +76,79 @@ instance GArrays f (XY f) type instance TargetOb (XY f) = XY (TargetObTC1 f) -dummy :: (KType1 f) => XY f -> XY f -dummy (XY x y) = - let f [x', y'] = x' * x' + y' * y' - [dfdx, dfdy] = grad f [x, y] - in XY dfdx dfdy - --- $(Categorify.separately 'dummy [t|C.Cat|] [pure [t|C|]]) - -$(Categorify.separately 'dummy [t|C.Cat|] [pure [t|C|]]) - --- wrap_dummy :: KType1 f => C.Cat (XY f) (XY f) --- wrap_dummy :: C.Cat (XY C) (XY C) --- wrap_dummy :: XY C -> XY C --- wrap_dummy = dummy -- Categorify.expression dummy - --- instance Category.NativeCat (->) "F.dummy" (XY C) (XY C) where --- nativeK = wrap_dummy - --- dummy_ :: XY C -> XY C --- dummy_ = kFunctionCall (Proxy @C) "dummy" dummy +data Input f = Input + { iParam :: Param f, + iCoord :: XY f + } + deriving (Generic) --- $(Categorify.separately 'dummy_ [t|C.Cat|] []) +deriving instance Show (Input C) --- if x > 0 then x + 5 else 42 +deriveHasRep ''Input --- kFunctionCall (Proxy @C) "g" $ +instance CGeneric (Input f) --- type instance TargetOb (XY C) = TargetOb (CG.Rep (XY C) ()) +instance GArrays f (Input f) --- type instance TargetOb (XY C) = Float +type instance TargetOb (Input f) = Input (TargetObTC1 f) -{- -data Input = Input - { iParam :: Param, - iCoord :: XY - } - deriving (Generic, Show) +newtype Output f = Output + {oF :: f Double} + deriving (Generic) -deriveHasRep ''Input +deriving instance Show (Output C) -instance CGeneric Input +deriveHasRep ''Output -instance GArrays C Input +instance CGeneric (Output f) -type instance TargetOb Input = TargetOb (CG.Rep Input ()) +instance GArrays f (Output f) -newtype Output = Output - {oF :: C Double} - deriving (Generic, Show) +type instance TargetOb (Output f) = Output (TargetObTC1 f) -deriveHasRep ''Output +rosenbrock :: Num a => (a, a) -> (a, a) -> a +rosenbrock (a, b) (x, y) = (a - x) ^ 2 + b * (y - x ^ 2) ^ 2 -instance CGeneric Output +dRosenbrock :: forall a. Num a => (a, a) -> (a, a) -> (a, a) +dRosenbrock (a, b) (x, y) = + let rosenbrock' :: forall s. Reifies s Tape => [Reverse s a] -> Reverse s a + rosenbrock' [x', y'] = + let a' = Lift a + b' = Lift b + in rosenbrock (a', b') (x', y') + [dfdx, dfdy] = grad rosenbrock' [x, y] + in (dfdx, dfdy) -instance GArrays C Output +rosenbrockF :: KType1 f => Input f -> Output f +rosenbrockF (Input (Param a b) (XY x y)) = Output $ rosenbrock (a, b) (x, y) -type instance TargetOb Output = TargetOb (CG.Rep Output ()) +dRosenbrockF :: forall f. (KType1 f) => Input f -> XY f +dRosenbrockF (Input (Param a b) (XY x y)) = + let (dfdx, dfdy) = dRosenbrock (a, b) (x, y) + in XY dfdx dfdy -rosenbrockF :: Input -> Output -rosenbrockF (Input (Param a b) (XY x y)) = Output $ rosenbrock (a, b) (x, y) +$(Categorify.separately 'rosenbrockF [t|C.Cat|] [pure [t|C|]]) --------------------------------------- +$(Categorify.separately 'dRosenbrockF [t|C.Cat|] [pure [t|C|]]) -dRosenbrock_ {- Param -> -} :: (KType f) -> XY f -> XY f -dRosenbrock_ {- (Param a b) -} (XY x y) = - let rosenbrock' :: forall s. Reifies s Tape => [Reverse s (C Double)] -> Reverse s (C Double) - rosenbrock' [x', y'] = x' + y' - {- let a' = 1 -- realToFrac a - b' = 10 -- realToFrac b - in rosenbrock (a', b') (x', y') -} +{- + let rosenbrock' :: forall s. Reifies s Tape => [Reverse s a] -> Reverse s a + rosenbrock' [x', y'] = + let a' = Lift a + b' = Lift b + in rosenbrock (a', b') (x', y') + [dfdx, dfdy] = grad rosenbrock' [x, y] + in (dfdx, dfdy) +-} +{- + let rosenbrock' :: forall s. Reifies s Tape => [Reverse s (f Double)] -> Reverse s (f Double) + rosenbrock' [x', y'] = + let a' = realToFrac a + b' = realToFrac b + in rosenbrock (a', b') (x', y') [dfdx, dfdy] = grad rosenbrock' [x, y] in XY dfdx dfdy -} - -- dummy_ :: XY C -> XY C -- dummy_ xy = kFunctionCall (Proxy @C) "dummy" dummy xy diff --git a/examples/grad-descent/Main.hs b/examples/grad-descent/Main.hs index effbc0c..163f6f2 100644 --- a/examples/grad-descent/Main.hs +++ b/examples/grad-descent/Main.hs @@ -9,12 +9,12 @@ import Categorifier.C.Codegen.FFI.ArraysCC (fromArraysCC) import Categorifier.C.Codegen.FFI.Spec (SBVFunCall) import Categorifier.C.Codegen.FFI.TH (embedFunction, embedFunctionCTemp) import Categorifier.C.Generate (writeCFiles) -import Categorifier.C.KTypes.C (C) +import Categorifier.C.KTypes.C (C (unsafeC)) +import Categorifier.C.KTypes.KLiteral (kliteral) import Data.List (iterate) import Data.Proxy (Proxy (..)) import F - -{- ( Input (..), + ( Input (..), Output (..), Param (..), XY (..), @@ -23,51 +23,50 @@ import F wrap_dRosenbrockF, wrap_rosenbrockF, ) --} -{- -$(embedFunction "rosenbrock" wrap_rosenbrockF) - -$(embedFunction "dRosenbrock" wrap_dRosenbrockF) --} - -$(embedFunctionCTemp "dummy" wrap_dummy) -{- -foreign import ccall safe "dummy" c_dummy :: SBVFunCall +$(embedFunctionCTemp "rosenbrockF" wrap_rosenbrockF) -hs_dummy :: XY C -> IO (XY C) -hs_dummy input = fromArraysCC (Proxy @(XY C -> XY C)) c_dummy input --} +$(embedFunctionCTemp "dRosenbrockF" wrap_dRosenbrockF) gamma :: Double gamma = 0.01 step :: - ((Double, Double) -> Double) -> - ((Double, Double) -> (Double, Double)) -> + ((Double, Double) -> IO Double) -> + ((Double, Double) -> IO (Double, Double)) -> (Double, Double) -> - (Double, Double) -step f df (x0, y0) = - let (dfdx, dfdy) = df (x0, y0) - (x1, y1) = (x0 - gamma * dfdx, y0 - gamma * dfdy) - in (x1, y1) + IO (Double, Double) +step f df (x0, y0) = do + (dfdx, dfdy) <- df (x0, y0) + let (x1, y1) = (x0 - gamma * dfdx, y0 - gamma * dfdy) + pure (x1, y1) + +iterateNM :: (Monad m) => Int -> (a -> m a) -> a -> m [a] +iterateNM n f x0 = go n f x0 id + where + go k f x acc + | k > 0 = do + y <- f x + go (k - 1) f y (acc . (y :)) + | otherwise = pure (acc []) main :: IO () main = do - {- - writeCFiles "/tmp" "dRosenbrock" wrap_dRosenbrockF - - let f = rosenbrock (1, 10) - df = dRosenbrock (1, 10) - hist = take 10 {- 1500 -} $ iterate (step f df) (0.1, 0.4) - mapM_ print hist - - z <- hs_rosenbrock (Input (Param 1 10) (XY 0.1 0.4)) - let z' = f (0.1, 0.4) - print (z, z') + let (x0, y0) = (0.1, 0.4) + -- pure haskell + putStrLn "pure haskell" + let f = pure . rosenbrock (1, 10) + df = pure . dRosenbrock (1, 10) + histH <- iterateNM 10 (step f df) (x0, y0) + mapM_ print histH - out3 <- hs_dRosenbrock (XY 0.1 0.4) - print out3 - -} - out3 <- hs_dummy (XY 0.1 0.4) - print out3 + -- C + putStrLn "codegen C" + let g (x, y) = do + Output z <- hs_rosenbrockF (Input (Param 1 10) (XY (kliteral x) (kliteral y))) + pure (unsafeC z) + dg (x, y) = do + XY x' y' <- hs_dRosenbrockF (Input (Param 1 10) (XY (kliteral x) (kliteral y))) + pure (unsafeC x', unsafeC y') + histC <- iterateNM 10 (step g dg) (x0, y0) + mapM_ print histC From bca18d313ae413a8720a33d34237f44fb127427e Mon Sep 17 00:00:00 2001 From: Ian-Woo Kim Date: Mon, 30 May 2022 17:50:04 -0700 Subject: [PATCH 08/13] clean up stale code --- examples/grad-descent/F.hs | 53 +++----------------------------------- 1 file changed, 4 insertions(+), 49 deletions(-) diff --git a/examples/grad-descent/F.hs b/examples/grad-descent/F.hs index 8c95a1b..001ab5f 100644 --- a/examples/grad-descent/F.hs +++ b/examples/grad-descent/F.hs @@ -12,9 +12,8 @@ {-# LANGUAGE TypeOperators #-} {-# LANGUAGE UndecidableInstances #-} -module F where - -{- ( Input (..), +module F + ( Input (..), Output (..), Param (..), XY (..), @@ -22,7 +21,8 @@ module F where dRosenbrock, wrap_rosenbrockF, wrap_dRosenbrockF, - ) -} + ) +where import qualified Categorifier.C.CExpr.Cat as C import Categorifier.C.CExpr.Cat.TargetOb (TargetOb, TargetObTC1) @@ -130,48 +130,3 @@ dRosenbrockF (Input (Param a b) (XY x y)) = $(Categorify.separately 'rosenbrockF [t|C.Cat|] [pure [t|C|]]) $(Categorify.separately 'dRosenbrockF [t|C.Cat|] [pure [t|C|]]) - -{- - let rosenbrock' :: forall s. Reifies s Tape => [Reverse s a] -> Reverse s a - rosenbrock' [x', y'] = - let a' = Lift a - b' = Lift b - in rosenbrock (a', b') (x', y') - [dfdx, dfdy] = grad rosenbrock' [x, y] - in (dfdx, dfdy) --} -{- - let rosenbrock' :: forall s. Reifies s Tape => [Reverse s (f Double)] -> Reverse s (f Double) - rosenbrock' [x', y'] = - let a' = realToFrac a - b' = realToFrac b - in rosenbrock (a', b') (x', y') - [dfdx, dfdy] = grad rosenbrock' [x, y] - in XY dfdx dfdy --} --- dummy_ :: XY C -> XY C --- dummy_ xy = kFunctionCall (Proxy @C) "dummy" dummy xy - -{- -dRosenbrockF {- Param -> -} :: - XY -> XY -dRosenbrockF (XY x y) = - let p = Param 1 10 - in -- x' = gg x - -- kFunctionCall (Proxy @C) "dRosenbrock_c" dummy (XY x y) - - -- dummy 2 (XY x y) - -- kFunctionCall (Proxy @C) "dRosenbrock_c" dRosenbrock_ (XY x y) --} - -{- dummydRosenbrock_ p -} - --- $(Categorify.function 'rosenbrockF [t|C.Cat|] []) - --- $(Categorify.function 'dRosenbrockF [t|C.Cat|] []) - --- $(Categorify.function 'dummy_ [t|C.Cat|] []) - --- $(Categorify.separately 'dRosenbrock_ [t|C.Cat|] []) - --- wrap_dRosenbrockF = id From 29e98a88cb40ff4db08dbfd7ae6d5f4e242905ac Mon Sep 17 00:00:00 2001 From: Ian-Woo Kim Date: Mon, 30 May 2022 17:55:32 -0700 Subject: [PATCH 09/13] undo some temporary changes --- examples/multiple-c-functions/Main.hs | 2 +- examples/separate-categorification/G.hs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/multiple-c-functions/Main.hs b/examples/multiple-c-functions/Main.hs index 98436c3..a87976e 100644 --- a/examples/multiple-c-functions/Main.hs +++ b/examples/multiple-c-functions/Main.hs @@ -8,4 +8,4 @@ import F (fCategorified) -- This generates /tmp/multiple_c_functions.c, which contains two -- C functions: `multiple_c_functions` (the main function), and `g`. main :: IO () -main = writeCFiles "." "multiple_c_functions" fCategorified +main = writeCFiles "/tmp" "multiple_c_functions" fCategorified diff --git a/examples/separate-categorification/G.hs b/examples/separate-categorification/G.hs index 038453d..37b4881 100644 --- a/examples/separate-categorification/G.hs +++ b/examples/separate-categorification/G.hs @@ -13,6 +13,6 @@ import Data.Int (Int32) import Data.Word (Word64) g :: C Int32 -> C Word64 -g x = if odd x then fromIntegral x + 5 else 43 +g x = if odd x then fromIntegral x + 5 else 42 Categorify.separately 'g [t|C.Cat|] [] From 080a640766fee9ad2e00e5fa0fb0af74f5f29050 Mon Sep 17 00:00:00 2001 From: Ian-Woo Kim Date: Tue, 31 May 2022 15:42:52 -0700 Subject: [PATCH 10/13] remove embedFunctionCTemp as we use lift-type --- examples/grad-descent/Main.hs | 6 ++-- test-lib/Categorifier/C/Codegen/FFI/TH.hs | 39 +---------------------- 2 files changed, 4 insertions(+), 41 deletions(-) diff --git a/examples/grad-descent/Main.hs b/examples/grad-descent/Main.hs index 163f6f2..31c0157 100644 --- a/examples/grad-descent/Main.hs +++ b/examples/grad-descent/Main.hs @@ -7,7 +7,7 @@ module Main where import Categorifier.C.Codegen.FFI.ArraysCC (fromArraysCC) import Categorifier.C.Codegen.FFI.Spec (SBVFunCall) -import Categorifier.C.Codegen.FFI.TH (embedFunction, embedFunctionCTemp) +import Categorifier.C.Codegen.FFI.TH (embedFunction) import Categorifier.C.Generate (writeCFiles) import Categorifier.C.KTypes.C (C (unsafeC)) import Categorifier.C.KTypes.KLiteral (kliteral) @@ -24,9 +24,9 @@ import F wrap_rosenbrockF, ) -$(embedFunctionCTemp "rosenbrockF" wrap_rosenbrockF) +$(embedFunction "rosenbrockF" wrap_rosenbrockF) -$(embedFunctionCTemp "dRosenbrockF" wrap_dRosenbrockF) +$(embedFunction "dRosenbrockF" wrap_dRosenbrockF) gamma :: Double gamma = 0.01 diff --git a/test-lib/Categorifier/C/Codegen/FFI/TH.hs b/test-lib/Categorifier/C/Codegen/FFI/TH.hs index dac532e..656c691 100644 --- a/test-lib/Categorifier/C/Codegen/FFI/TH.hs +++ b/test-lib/Categorifier/C/Codegen/FFI/TH.hs @@ -8,11 +8,7 @@ -- Data.Text.Prettyprint.Doc.Render.Text is deprecated. {-# OPTIONS_GHC -fno-warn-deprecations #-} -module Categorifier.C.Codegen.FFI.TH - ( embedFunction, - embedFunctionCTemp, - ) -where +module Categorifier.C.Codegen.FFI.TH (embedFunction) where import qualified Categorifier.C.CExpr.Cat as C import Categorifier.C.CExpr.Cat.TargetOb (TargetOb) @@ -93,36 +89,3 @@ embedFunction name f = do let hsfunDef = FunD funName [Clause [VarP (TH.mkName "input")] (NormalB body) []] -- pure [cfunFfi, hsfunSig, hsfunDef] - --- temporary -embedFunctionCTemp :: - forall i o. - (Typeable i, Typeable o, PolyVec CExpr (TargetOb i), PolyVec CExpr (TargetOb o), PolyVec C i) => - Text -> - (i `C.Cat` o) -> - Q [Dec] -embedFunctionCTemp name f = do - -- generate C FFI - let cname = "c_" <> name - cnameName = TH.mkName (T.unpack cname) - codeC <- - TH.runIO $ do - x <- generateCExprFunction name (inputDims $ Proxy @i) (arraysFun f) - case x of - Left err -> Exception.impureThrow err - Right (CExpr.FunctionText _ srcText) -> - pure $ Prettyprint.renderStrict $ CExpr.layoutOptions srcText - TH.addForeignSource LangC (T.unpack codeC) - cfunFfi <- - ForeignD . ImportF CCall Safe (T.unpack name) cnameName <$> [t|SBVFunCall|] - -- generate high-level haskell - inputTy <- AppT (ConT (TH.mkName (getTypeName (Proxy @i)))) <$> [t|C|] -- for now - outputTy <- AppT (ConT (TH.mkName (getTypeName (Proxy @o)))) <$> [t|C|] -- for now - let funName = TH.mkName (T.unpack ("hs_" <> name)) - hsfunSig <- - SigD funName <$> [t|$(pure inputTy) -> IO $(pure outputTy)|] - body <- - [|fromArraysCC (Proxy @($(pure inputTy) -> $(pure outputTy))) $(pure (VarE cnameName)) input|] - let hsfunDef = FunD funName [Clause [VarP (TH.mkName "input")] (NormalB body) []] - -- - pure [cfunFfi, hsfunSig, hsfunDef] From 0b9ad8457028ec1e5adb0c453754477e4fcca18a Mon Sep 17 00:00:00 2001 From: Ian-Woo Kim Date: Tue, 31 May 2022 15:46:53 -0700 Subject: [PATCH 11/13] remove debug flags --- examples/categorifier-c-examples.cabal | 4 ---- 1 file changed, 4 deletions(-) diff --git a/examples/categorifier-c-examples.cabal b/examples/categorifier-c-examples.cabal index f108f9f..10e0ed0 100644 --- a/examples/categorifier-c-examples.cabal +++ b/examples/categorifier-c-examples.cabal @@ -87,10 +87,6 @@ executable separate-categorification G ghc-options: -O0 - -fforce-recomp - -ddump-simpl - -ddump-splices - -dsuppress-all -fexpose-all-unfoldings -fmax-simplifier-iterations=0 -fno-ignore-interface-pragmas From ce98ea03fbbddf3a77832bdff1ff3b98a8628811 Mon Sep 17 00:00:00 2001 From: Ian-Woo Kim Date: Tue, 31 May 2022 18:10:32 -0700 Subject: [PATCH 12/13] lint fix --- examples/grad-descent/Main.hs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/examples/grad-descent/Main.hs b/examples/grad-descent/Main.hs index 31c0157..c271910 100644 --- a/examples/grad-descent/Main.hs +++ b/examples/grad-descent/Main.hs @@ -46,8 +46,8 @@ iterateNM n f x0 = go n f x0 id where go k f x acc | k > 0 = do - y <- f x - go (k - 1) f y (acc . (y :)) + y <- f x + go (k - 1) f y (acc . (y :)) | otherwise = pure (acc []) main :: IO () @@ -58,7 +58,7 @@ main = do let f = pure . rosenbrock (1, 10) df = pure . dRosenbrock (1, 10) histH <- iterateNM 10 (step f df) (x0, y0) - mapM_ print histH + traverse_ print histH -- C putStrLn "codegen C" @@ -69,4 +69,4 @@ main = do XY x' y' <- hs_dRosenbrockF (Input (Param 1 10) (XY (kliteral x) (kliteral y))) pure (unsafeC x', unsafeC y') histC <- iterateNM 10 (step g dg) (x0, y0) - mapM_ print histC + traverse_ print histC From b7c2acc460160bfd6727830429a068dfecf79820 Mon Sep 17 00:00:00 2001 From: Ian-Woo Kim Date: Tue, 31 May 2022 19:07:54 -0700 Subject: [PATCH 13/13] remove warnings --- examples/grad-descent/Main.hs | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/examples/grad-descent/Main.hs b/examples/grad-descent/Main.hs index c271910..b88e548 100644 --- a/examples/grad-descent/Main.hs +++ b/examples/grad-descent/Main.hs @@ -5,14 +5,10 @@ module Main where -import Categorifier.C.Codegen.FFI.ArraysCC (fromArraysCC) -import Categorifier.C.Codegen.FFI.Spec (SBVFunCall) import Categorifier.C.Codegen.FFI.TH (embedFunction) -import Categorifier.C.Generate (writeCFiles) import Categorifier.C.KTypes.C (C (unsafeC)) import Categorifier.C.KTypes.KLiteral (kliteral) -import Data.List (iterate) -import Data.Proxy (Proxy (..)) +import Data.Foldable (traverse_) import F ( Input (..), Output (..), @@ -36,18 +32,18 @@ step :: ((Double, Double) -> IO (Double, Double)) -> (Double, Double) -> IO (Double, Double) -step f df (x0, y0) = do +step _f df (x0, y0) = do (dfdx, dfdy) <- df (x0, y0) let (x1, y1) = (x0 - gamma * dfdx, y0 - gamma * dfdy) pure (x1, y1) iterateNM :: (Monad m) => Int -> (a -> m a) -> a -> m [a] -iterateNM n f x0 = go n f x0 id +iterateNM n f x0 = go n x0 id where - go k f x acc + go k x acc | k > 0 = do - y <- f x - go (k - 1) f y (acc . (y :)) + y <- f x + go (k - 1) y (acc . (y :)) | otherwise = pure (acc []) main :: IO ()