packages feed

data-reify-cse (empty) → 0.0.1

raw patch · 4 files changed

+151/−0 lines, 4 filesdep +basedep +containersdep +data-reifysetup-changed

Dependencies added: base, containers, data-reify

Files

+ LICENSE view
@@ -0,0 +1,28 @@+Copyright (c) Sebastiaan Visser 2008++All rights reserved.++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions+are met:+1. Redistributions of source code must retain the above copyright+   notice, this list of conditions and the following disclaimer.+2. Redistributions in binary form must reproduce the above copyright+   notice, this list of conditions and the following disclaimer in the+   documentation and/or other materials provided with the distribution.+3. Neither the name of the author nor the names of his contributors+   may be used to endorse or promote products derived from this software+   without specific prior written permission.++THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE+ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS+OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT+LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY+OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF+SUCH DAMAGE.+
+ Setup.lhs view
@@ -0,0 +1,6 @@+#! /usr/bin/env runhaskell++>import Distribution.Simple++>main = defaultMain+
+ data-reify-cse.cabal view
@@ -0,0 +1,18 @@+Name:             data-reify-cse+Version:          0.0.1+Description:      Common Sub-Expression Elimination for graphs generated by Data.Reify.+Synopsis:         Common Sub-Expression Elimination for graphs generated by Data.Reify.+Category:         Data, Language+License:          BSD3+License-file:     LICENSE+Author:           Sebastiaan Visser+Maintainer:       sfvisser@cs.uu.nl+Cabal-Version:    >= 1.6+Build-Type:       Simple+Build-Depends:    base ==3.*, containers ==0.2.*, data-reify ==0.4.*++GHC-Options:      -Wall+Extensions:       CPP+HS-Source-Dirs:   src+Exposed-modules:  Data.Reify.Graph.CSE+
+ src/Data/Reify/Graph/CSE.hs view
@@ -0,0 +1,99 @@+-- |+-- Module: Data.Reify.Graph.CSE+-- Copyright: (c) 2009 Sebastiaan Visser+-- License: BSD3+--+-- Maintainer: Sebastiaan Visser <sfvisser@cs.uu.nl>+-- Stability: unstable+-- Portability: ghc+--+-- This module implements common sub-expression elimination for graphs+-- generated by the Data.Reify package. The algorithm performs a simple+-- fixed point iteration and is not optimized for speed.+--+-- As an illustration, take this simple datatype representing an embedded+-- language containing primitives and function application.  The datatype+-- abstracts away from the recursive points which is common when using the+-- 'Data.Reify' package.  A fixed point combinator can be used to tie the knot.+--+-- >data Val f = App f f | Prim String+-- >  deriving (Eq, Ord, Show)+-- >+-- >newtype Fix f = In { out :: f (Fix f) }+--+-- No we can add some useful instances and make the fixed point combinator an+-- instance of the 'Data.Reify' 'MuRef' class.+--+-- >instance Functor Val      ...+-- >instance Foldable Val     ...+-- >instance Traversable Val  ...+-- >+-- >instance Traversable a => MuRef (Fix a) where+-- >  type DeRef (Fix a) = a+-- >  mapDeRef f = traverse f . out+--+-- When we now take the following example term in our embedded language we can+-- see that the `cse` function can eliminate common terms without changing the+-- semantics. Evidently, we assume our language is referential transparent language.+--+-- >myTerm :: Fix Val+-- >myTerm = In $ (Prim "2" `add` Prim "5") `mul` (Prim "2" `add` Prim "5")+-- >  where add a b = Prim "+" `app` a `app` b+-- >        mul a b = Prim "*" `app` a `app` b+-- >        app a b = App (In a) (In b)+--+-- The term @fmap cse $ reifyGraph myTerm@ yields an optimized graph compared+-- to the normal result of `reifyGraph`.+--+-- >with CSE:       without CSE:+-- >+-- >(1,App 2 9)     (1,App 2 9)+-- >(2,App 3 9)     (9,App 10 13)+-- >(10,App 6 7)    (13,Prim "5")+-- >(9,App 10 8)    (10,App 11 12)+-- >(3,Prim "*")    (12,Prim "2")+-- >(6,Prim "+")    (11,Prim "+")+-- >(7,Prim "2")    (2,App 3 4)+-- >(8,Prim "5")    (4,App 5 8)+-- >                (8,Prim "5")+-- >                (5,App 6 7)+-- >                (7,Prim "2")+-- >                (6,Prim "+")+-- >                (3,Prim "*")++{-# LANGUAGE TypeFamilies #-}+module Data.Reify.Graph.CSE (cse) where++import Data.Map (Map, toList, fromListWith, filter, update, mapKeysWith)+import Data.Reify+import Prelude hiding (filter)+import qualified Data.Map as Map++{- | Perform CSE on the input graph. -} ++cse :: (Ord (f Unique), Functor f) => Graph f -> Graph f+cse (Graph xs root) =+  let swapped = map (\(a, b) -> (head b, a)) . toList . eliminate $ xs+  in Graph swapped root++groupById :: Ord k => [(a, k)] -> Map k [a]+groupById = fromListWith (++) . map (\(a, b) -> (b, [a]))++fixpoint :: Eq a => (a -> a) -> a -> a+fixpoint f a = let b = f a in if b == a then a else fixpoint f b++eliminate :: (Eq a, Functor f, Ord (f a)) => [(a, f a)] -> Map (f a) [a]+eliminate = fixpoint eliminate1 . groupById++eliminate1 :: (Eq a, Functor f, Ord (f a)) => Map (f a) [a] -> Map (f a) [a]+eliminate1 g =+  case toList $ filter ((>1) . length) g of+    (term, ids):_ -> update (elimKey ids) term . mapKeysWith (++) (elimVal ids) $ g+    _ -> g++elimVal :: (Eq a, Functor f) => [a] -> f a -> f a+elimVal i = fmap (\a -> if a `elem` i then head i else a)++elimKey :: [a] -> b -> Maybe [a]+elimKey = const . Just . take 1+