GTALib-0.0.6: src/GTA/Data/ConsList.hs
{-# LANGUAGE MultiParamTypeClasses,FlexibleInstances,FlexibleContexts,FunctionalDependencies,UndecidableInstances,RankNTypes,ExplicitForAll,ScopedTypeVariables,NoMonomorphismRestriction,OverlappingInstances,EmptyDataDecls,RecordWildCards,TypeFamilies,TemplateHaskell #-}
{-
Definitions for applying the generic GTA framework to cons lists.
(we can make a concise, specialized GTA framework for cons-lists, but...)
-}
-- | This module provides the GTA framework on cons lists, such as
-- definitions of the data structure and its algebra, generators,
-- aggregators, etc.
module GTA.Data.ConsList (ConsList(Cons, Nil), ConsListAlgebra(ConsListAlgebra, cons, nil), consize, deconsize, segs, inits, tails, subs, assigns, assignsBy, paths, mapC, count, maxsum, maxsumsolution, maxsumWith, maxsumKWith, maxsumsolutionXKWith, maxsumsolutionXWith, maxsumsolutionWith, maxsumsolutionKWith, maxprodWith, maxprodKWith, maxprodsolutionXKWith, maxprodsolutionXWith, maxprodsolutionWith, maxprodsolutionKWith, crossCons, emptyBag, bagOfNil, bagUnion, ConsSemiring, foldr',ConsListMapFs(consF),mapMap,perms) where
import GTA.Core
import GTA.Util.GenericSemiringStructureTemplate
import GTA.Data.BinTree (BinTree (..))
import qualified Data.IntSet as IntSet
-- cons list = the usual list in FP
data ConsList a = Cons a (ConsList a)
| Nil
-- deriving (Show, Eq, Ord, Read)
-- to use the GTA framework
-- The following definitions can be generated automatically by @genAllDecl ''ConsList@
-- They are written by hand here for writing comments.
-- algebra of ConsList
data ConsListAlgebra b a = ConsListAlgebra {
cons :: b -> a -> a,
nil :: a
}
-- a set of functions for 'map'
data ConsListMapFs b b' = ConsListMapFs {
consF :: b -> b'
}
-- type parameters are algebra, free algebra, and functions for 'map'
instance GenericSemiringStructure (ConsListAlgebra b) (ConsList b) (ConsListMapFs b) where
freeAlgebra = ConsListAlgebra {..} where
cons = Cons
nil = Nil
pairAlgebra cla1 cla2 = ConsListAlgebra {..} where
cons a (r1, r2) = (cons1 a r1, cons2 a r2)
nil = (nil1, nil2)
(cons1, nil1) = let ConsListAlgebra {..} = cla1 in (cons, nil)
(cons2, nil2) = let ConsListAlgebra {..} = cla2 in (cons, nil)
makeAlgebra (CommutativeMonoid {..}) cla frec fsingle = ConsListAlgebra {..} where
cons a r = foldr oplus identity [fsingle (cons' a r') | r' <- frec r]
nil = fsingle nil'
(cons', nil') = let ConsListAlgebra {..} = cla in (cons, nil)
foldingAlgebra op iop (ConsListMapFs {..}) = ConsListAlgebra {..} where
cons a r = consF a `op` r
nil = iop
hom (ConsListAlgebra {..}) = h where
h (Cons a r) = cons a (h r)
h Nil = nil
-- stupid consize function
consize :: forall a. [a] -> ConsList a
consize = foldr Cons Nil
-- stupid deconsize function
deconsize :: forall a. ConsList a -> [a]
deconsize = hom (ConsListAlgebra{cons=(:),nil=[]})
--this hom is of GenericSemiringStructure, namely, foldr
instance Show a => Show (ConsList a) where
showsPrec d x = showsPrec d (deconsize x)
instance Read a => Read (ConsList a) where
readsPrec d x = map (\(y, s)->(consize y, s)) (readsPrec d x)
instance Eq a => Eq (ConsList a) where
(==) x y = deconsize x == deconsize y
instance Ord a => Ord (ConsList a) where
compare x y = compare (deconsize x) (deconsize y)
-- short-cut to ConsListAlgebra
foldr' :: forall a s.(a -> s -> s) -> s -> ConsListAlgebra a s
foldr' f e = ConsListAlgebra {cons = f, nil = e}
-- renaming
type ConsSemiring a s= GenericSemiring (ConsListAlgebra a) s
segs :: [a] -> ConsSemiring a s -> s
segs x (GenericSemiring {..}) =
let (s, i) = foldr cons' nil' x
in i `oplus` s
where cons' a (s, i) = (i `oplus` s, cons a (nil `oplus` i))
nil' = (nil, identity)
ConsListAlgebra {..} = algebra
CommutativeMonoid {..} = monoid
inits :: [a] -> ConsSemiring a s -> s
inits x (GenericSemiring {..}) = foldr cons' nil x
where cons' a i = nil `oplus` cons a i
ConsListAlgebra {..} = algebra
CommutativeMonoid {..} = monoid
tails :: [a] -> ConsSemiring a s -> s
tails x (GenericSemiring {..}) =
let (t, _) = foldr cons' nil' x
in t
where cons' a (t, w) = let aw = cons a w
in ( aw `oplus` t, aw)
nil' = (nil, nil)
ConsListAlgebra {..} = algebra
CommutativeMonoid {..} = monoid
subs :: [a] -> ConsSemiring a s -> s
subs x (GenericSemiring {..}) = foldr cons' nil x
where cons' a y = cons a y `oplus` y
ConsListAlgebra {..} = algebra
CommutativeMonoid {..} = monoid
assigns :: [m] -> [a] -> ConsSemiring (m,a) s -> s
assigns ms x (GenericSemiring {..}) = foldr cons' nil x
where cons' a y = foldr oplus identity [cons (m, a) y | m <- ms]
ConsListAlgebra {..} = algebra
CommutativeMonoid {..} = monoid
assignsBy :: (a -> [m]) -> [a] -> ConsSemiring (m,a) s -> s
assignsBy f x (GenericSemiring {..}) = foldr cons' nil x
where cons' a y = foldr oplus identity [cons (m, a) y | m <- f a]
ConsListAlgebra {..} = algebra
CommutativeMonoid {..} = monoid
perms :: [a] -> ConsSemiring a s -> s
perms x = assigns (zip [1..n] x) [1..n] `transformBy` mapMap fst `filterBy` spans n `transformBy` mapMap snd
where n = length x
spans n = ok <.> foldr' f e where
e = IntSet.empty
f (v,_) x = IntSet.insert v x
ok x = IntSet.size x == n
{- this generates lists from a tree, while CYK geenerates trees from a list -}
paths :: BinTree a a -> ConsSemiring a s -> s
paths x (GenericSemiring {..}) = paths' x
where paths' (BinNode a l r) = cons a (paths' l `oplus` paths' r)
paths' (BinLeaf a) = cons a nil
ConsListAlgebra {..} = algebra
CommutativeMonoid {..} = monoid
-- useful function to map
mapC :: forall b a. (b -> a) -> ConsListMapFs b a
mapC f = ConsListMapFs {..} where consF = f
-- ConsList-semiring for counting
count :: Num a => ConsSemiring b a
count = sumproductBy (ConsListMapFs {consF = const 1})
{- simplified aggregators -}
maxsum :: (Ord a, Num a) => ConsSemiring a (AddIdentity a)
maxsum = maxsumBy (ConsListMapFs {consF = addIdentity})
maxsumsolution :: (Ord a, Num a) => ConsSemiring a (AddIdentity a, Bag (ConsList a))
maxsumsolution = maxsumsolutionBy (ConsListMapFs {consF = addIdentity})
maxsumWith :: (Ord a, Num a) => (b -> a) -> ConsSemiring b (AddIdentity a)
maxsumWith f = maxsumBy (mapC (addIdentity.f))
maxsumKWith :: (Ord a, Num a) => Int -> (b -> a) -> ConsSemiring b ([AddIdentity a])
maxsumKWith k f = maxsumKBy k (mapC (addIdentity.f))
maxsumsolutionXKWith :: (Ord a, Num a) =>
ConsSemiring c b -> Int -> (c -> a) -> ConsSemiring c [(AddIdentity a, b)]
maxsumsolutionXKWith s k f = maxsumsolutionXKBy s k (mapC (addIdentity.f))
maxsumsolutionXWith :: (Ord a, Num a) =>
ConsSemiring c b -> (c -> a) -> ConsSemiring c (AddIdentity a, b)
maxsumsolutionXWith s f = maxsumsolutionXBy s (mapC (addIdentity.f))
maxsumsolutionWith :: (Ord a, Num a) => (b -> a) -> ConsSemiring b (AddIdentity a, Bag (ConsList b))
maxsumsolutionWith f = maxsumsolutionBy (mapC (addIdentity.f))
maxsumsolutionKWith :: (Ord a, Num a) => Int -> (b -> a) -> ConsSemiring b [(AddIdentity a, Bag (ConsList b))]
maxsumsolutionKWith k f = maxsumsolutionKBy k (mapC (addIdentity.f))
maxprodWith :: (Ord a, Num a) => (b -> a) -> ConsSemiring b (AddIdentity a)
maxprodWith f = maxprodBy (mapC (addIdentity.f))
maxprodKWith :: (Ord a, Num a) => Int -> (b -> a) -> ConsSemiring b ([AddIdentity a])
maxprodKWith k f = maxprodKBy k (mapC (addIdentity.f))
maxprodsolutionXKWith :: (Ord a, Num a) =>
ConsSemiring c b -> Int -> (c -> a) -> ConsSemiring c [(AddIdentity a, b)]
maxprodsolutionXKWith s k f = maxprodsolutionXKBy s k (mapC (addIdentity.f))
maxprodsolutionXWith :: (Ord a, Num a) =>
ConsSemiring c b -> (c -> a) -> ConsSemiring c (AddIdentity a, b)
maxprodsolutionXWith s f = maxprodsolutionXBy s (mapC (addIdentity.f))
maxprodsolutionWith :: (Ord a, Num a) => (b -> a) -> ConsSemiring b (AddIdentity a, Bag (ConsList b))
maxprodsolutionWith f = maxprodsolutionBy (mapC (addIdentity.f))
maxprodsolutionKWith :: (Ord a, Num a) => Int -> (b -> a) -> ConsSemiring b [(AddIdentity a, Bag (ConsList b))]
maxprodsolutionKWith k f = maxprodsolutionKBy k (mapC (addIdentity.f))
--- useful functions to design generators: constructors of bags of lists
crossCons :: a -> Bag (ConsList a) -> Bag (ConsList a)
crossCons = cons (algebra freeSemiring)
bagOfNil :: Bag (ConsList a)
bagOfNil = nil (algebra freeSemiring)
emptyBag :: Bag (ConsList a)
emptyBag = let GenericSemiring{..} = freeSemiring :: GenericSemiring (ConsListAlgebra a) (Bag (ConsList a))
in identity monoid
bagUnion :: Bag (ConsList a) -> Bag (ConsList a) -> Bag (ConsList a)
bagUnion = let GenericSemiring{..} = freeSemiring :: GenericSemiring (ConsListAlgebra a) (Bag (ConsList a))
in oplus monoid
mapMap :: (b -> b') -> GenericSemiring (ConsListAlgebra b') a -> GenericSemiring (ConsListAlgebra b) a
mapMap f (GenericSemiring {..}) =
GenericSemiring {algebra=algebra',monoid=monoid} where
ConsListAlgebra{..} = algebra
algebra' = ConsListAlgebra{cons=cons.f,nil=nil}