{-# LANGUAGE MultiParamTypeClasses,FlexibleInstances,FlexibleContexts,FunctionalDependencies,UndecidableInstances,RankNTypes,ExplicitForAll,ScopedTypeVariables,NoMonomorphismRestriction,OverlappingInstances,EmptyDataDecls,RecordWildCards,TypeFamilies,TemplateHaskell,TypeSynonymInstances #-} -- | This module provides the GTA framework on binary (and -- leaf-valued) trees, such as definitions of the data structures -- and their algebras, generators, aggregators, etc. module GTA.Data.BinTree (LVTree (NodeLV, LeafLV), LVTreeAlgebra(LVTreeAlgebra, nodeLV, leafLV), LVTreeMapFs (LVTreeMapFs, leafLVF), BinTree(BinNode,BinLeaf), BinTreeAlgebra(BinTreeAlgebra, binNode, binLeaf), BinTreeMapFs (BinTreeMapFs, binLeafF, binNodeF), lvtrees, subtreeSelectsWithRoot, subtreeSelects, selects, assignTrans, assignTrees, count, maxsum, maxsumsolution, LVTreeSemiring, BinTreeSemiring) where import GTA.Core import GTA.Util.GenericSemiringStructureTemplate import Data.List -- leaf-valued binary tree data LVTree a = NodeLV (LVTree a) (LVTree a) | LeafLV a deriving (Eq, Ord, Read) -- The following definitions can be generated automatically by @genAllDecl ''LVTree@ -- They are written by hand here for writing comments. -- algebra of LVTree data LVTreeAlgebra b a = LVTreeAlgebra { nodeLV :: a -> a -> a, leafLV :: b -> a } -- a set of functions for 'map' data LVTreeMapFs b b' = LVTreeMapFs { leafLVF :: b -> b' } -- type parameters are algebra, free algebra, and functions for 'map' instance GenericSemiringStructure (LVTreeAlgebra b) (LVTree b) (LVTreeMapFs b) where freeAlgebra = LVTreeAlgebra {..} where nodeLV = NodeLV leafLV = LeafLV pairAlgebra lvta1 lvta2 = LVTreeAlgebra {..} where nodeLV (l1, l2) (r1, r2) = (nodeLV1 l1 r1, nodeLV2 l2 r2) leafLV a = (leafLV1 a, leafLV2 a) (nodeLV1, leafLV1) = let LVTreeAlgebra {..} = lvta1 in (nodeLV, leafLV) (nodeLV2, leafLV2) = let LVTreeAlgebra {..} = lvta2 in (nodeLV, leafLV) makeAlgebra (CommutativeMonoid {..}) lvta frec fsingle = LVTreeAlgebra {..} where nodeLV l r = foldr oplus identity [fsingle (nodeLV' l' r') | l' <- frec l, r' <- frec r] leafLV a = fsingle (leafLV' a) (nodeLV', leafLV') = let LVTreeAlgebra {..} = lvta in (nodeLV, leafLV) foldingAlgebra op iop (LVTreeMapFs {..}) = LVTreeAlgebra {..} where nodeLV l r = l `op` r leafLV a = leafLVF a hom (LVTreeAlgebra {..}) = h where h (NodeLV l r) = nodeLV (h l) (h r) h (LeafLV a) = leafLV a -- renaming type LVTreeSemiring a s = GenericSemiring (LVTreeAlgebra a) s {- -- generalized version of the matrix chain DP algorithm O(n^3) generates a bag of trees from a list. The left-to-right traversal of each tree is equivalent to the input list. -} lvtrees :: [a] -> LVTreeSemiring a s -> s lvtrees x bts = head (head (lvtrees' x bts)) lvtrees' :: [a] -> LVTreeSemiring a s -> [[s]] lvtrees' x (GenericSemiring{..}) = let CommutativeMonoid {..} = monoid LVTreeAlgebra {..} = algebra ls = map f x bigOplus = foldr oplus identity f a = leafLV a f' l r = [nodeLV l r] n = length x merge ts k = let vs = transpose (map (\(i, y) -> drop i y) (zip [1..k] ts)) hs = map reverse (transpose ts) ns = zipWith mrg hs vs in ns:ts mrg h v = bigOplus (concat (zipWith f' h v)) in foldl merge [ls] [1..(n-1)] -- binary tree with different types for nodes and leaves data BinTree n l = BinNode n (BinTree n l) (BinTree n l) | BinLeaf l deriving (Eq, Ord, Read) -- The following definitions can be generated automatically by @genAllDecl ''BinTree@ -- They are written by hand here for writing comments. -- algebra of BinTree data BinTreeAlgebra n l a = BinTreeAlgebra { binNode :: n -> a -> a -> a, binLeaf :: l -> a } -- a set of functions for 'map' data BinTreeMapFs n l b' = BinTreeMapFs { binNodeF :: n -> b', binLeafF :: l -> b' } -- type parameters are algebra, free algebra, and functions for 'map' instance GenericSemiringStructure (BinTreeAlgebra n l) (BinTree n l) (BinTreeMapFs n l) where freeAlgebra = BinTreeAlgebra {..} where binNode = BinNode binLeaf = BinLeaf pairAlgebra lvta1 lvta2 = BinTreeAlgebra {..} where binNode a (l1, l2) (r1, r2) = (binNode1 a l1 r1, binNode2 a l2 r2) binLeaf a = (binLeaf1 a, binLeaf2 a) (binNode1, binLeaf1) = let BinTreeAlgebra {..} = lvta1 in (binNode, binLeaf) (binNode2, binLeaf2) = let BinTreeAlgebra {..} = lvta2 in (binNode, binLeaf) makeAlgebra (CommutativeMonoid {..}) lvta frec fsingle = BinTreeAlgebra {..} where binNode a l r = foldr oplus identity [fsingle (binNode' a l' r') | l' <- frec l, r' <- frec r] binLeaf a = fsingle (binLeaf' a) (binNode', binLeaf') = let BinTreeAlgebra {..} = lvta in (binNode, binLeaf) foldingAlgebra op iop (BinTreeMapFs {..}) = BinTreeAlgebra {..} where binNode a l r = binNodeF a `op` l `op` r binLeaf a = binLeafF a hom (BinTreeAlgebra {..}) = h where h (BinNode a l r) = binNode a (h l) (h r) h (BinLeaf a) = binLeaf a -- renaming type BinTreeSemiring n l a = GenericSemiring (BinTreeAlgebra n l) a -- BinTree-semiring for counting count :: Num a => BinTreeSemiring n l a count = sumproductBy (BinTreeMapFs {binLeafF = const 1, binNodeF = const 1}) -- shotcuts to maxsum of marked trees markedT :: forall a. Num a => BinTreeMapFs (Bool, a) (Bool, a) (AddIdentity a) markedT = BinTreeMapFs {binNodeF=f, binLeafF=f} where f (m,a) = AddIdentity (if m then a else 0) maxsum :: (Num a, Ord a) => BinTreeSemiring (Bool, a) (Bool, a) (AddIdentity a) maxsum = maxsumBy markedT maxsumsolution :: (Num a, Ord a) => BinTreeSemiring (Bool, a) (Bool, a) (AddIdentity a, Bag (BinTree (Bool, a) (Bool, a))) maxsumsolution = maxsumsolutionBy markedT -- predicate for rooted suBinTrees (i.e., those including the original root) data RtStClass = Rtd | Emp | NG deriving (Show, Eq, Ord, Read) rtst :: forall t t1. BinTreeAlgebra (Bool, t1) (Bool, t) RtStClass rtst = BinTreeAlgebra {..} where binNode (True, _) l r = case (l, r) of (Rtd, Rtd) -> Rtd (Rtd, Emp) -> Rtd (Rtd, NG) -> NG (Emp, Rtd) -> Rtd (Emp, Emp) -> Rtd (Emp, NG) -> NG (NG , Rtd) -> NG (NG , Emp) -> NG (NG , NG) -> NG binNode (False, _) l r = case (l, r) of (Rtd, Rtd) -> NG (Rtd, Emp) -> NG (Rtd, NG) -> NG (Emp, Rtd) -> NG (Emp, Emp) -> Emp (Emp, NG) -> NG (NG , Rtd) -> NG (NG , Emp) -> NG (NG , NG) -> NG binLeaf (m, _) = if m then Rtd else Emp -- predicate for all suBinTrees data StClass = RtdST -- suBinTree including the root | IsoST -- isolated suBinTree | Empty -- empty | Other -- other NGs deriving (Show, Eq, Ord, Read) st :: forall t t1. BinTreeAlgebra (Bool, t1) (Bool, t) StClass st = BinTreeAlgebra {..} where binNode (True, _) l r = case (l, r) of (RtdST, RtdST) -> RtdST (RtdST, IsoST) -> Other (RtdST, Empty) -> RtdST (RtdST, Other) -> Other (IsoST, RtdST) -> Other (IsoST, IsoST) -> Other (IsoST, Empty) -> Other (IsoST, Other) -> Other (Empty, RtdST) -> RtdST (Empty, IsoST) -> Other (Empty, Empty) -> RtdST (Empty, Other) -> Other (Other, RtdST) -> Other (Other, IsoST) -> Other (Other, Empty) -> Other (Other, Other) -> Other binNode (False, _) l r = case (l, r) of (RtdST, RtdST) -> Other (RtdST, IsoST) -> Other (RtdST, Empty) -> IsoST (RtdST, Other) -> Other (IsoST, RtdST) -> Other (IsoST, IsoST) -> Other (IsoST, Empty) -> Other (IsoST, Other) -> Other (Empty, RtdST) -> IsoST (Empty, IsoST) -> IsoST (Empty, Empty) -> Empty (Empty, Other) -> Other (Other, RtdST) -> Other (Other, IsoST) -> Other (Other, Empty) -> Other (Other, Other) -> Other binLeaf (m, _) = if m then RtdST else Empty {- This is BinTreeSemiring-polymorphic LVTreeSemiring. We can use this kind of A-semirnig-polymorphic B-semiring to change the intermediate data structure from B to A -} assignTrans :: [b] -> [c] -> BinTreeSemiring c (b, a) s -> LVTreeSemiring a s assignTrans msl msn bts = GenericSemiring {monoid=monoid'',algebra=algebra''} where (monoid'', algebra') = let GenericSemiring {..} = bts in (monoid, algebra) BinTreeAlgebra {..} = algebra' CommutativeMonoid {..} = monoid'' bigOplus = foldr oplus identity algebra'' = LVTreeAlgebra {..} where nodeLV l r = bigOplus [binNode m l r | m <- msn] leafLV a = bigOplus [binLeaf (m, a) | m <- msl] ---generators {- generating a bag of trees from a list. The left-to-right traversal of each tree is equivalent to the input list, ignoring the assigned marks. -} assignTrees :: [b] -> [c] -> [a] -> BinTreeSemiring c (b, a) s -> s assignTrees msl msn x = lvtrees x >=< assignTrans msl msn -- polymorphic generator for all selections selects :: BinTree n l -> BinTreeSemiring (Bool,n) (Bool,l) a -> a selects t bts = selects' t where BinTreeAlgebra {..} = algebra bts CommutativeMonoid {..} = monoid bts selects' (BinNode a l r) = let l' = selects' l; r' = selects' r in binNode (True, a) l' r' `oplus` binNode (False, a) l' r' selects' (BinLeaf a) = (binLeaf (True, a)) `oplus` (binLeaf (False, a)) subtreeSelectsWithRoot :: BinTree n l -> BinTreeSemiring (Bool,n) (Bool,l) a -> a subtreeSelectsWithRoot t = selects t >== (/=NG)<.>rtst subtreeSelects :: BinTree n l -> BinTreeSemiring (Bool,n) (Bool,l) a -> a subtreeSelects t = selects t >== (/=Other)<.>st