{-# LANGUAGE MultiParamTypeClasses, FlexibleInstances, NoMonomorphismRestriction #-}
module Math.Algebras.TensorAlgebra where
import Prelude hiding ( (*>) )
import qualified Data.List as L
import Math.Algebras.VectorSpace
import Math.Algebras.TensorProduct
import Math.Algebras.Structures
import Math.Algebra.Field.Base
data TensorAlgebra a = TA Int [a] deriving (Eq,Ord)
instance Show a => Show (TensorAlgebra a) where
show (TA _ []) = "1"
show (TA _ xs) = filter (/= '"') $ concat $ L.intersperse "*" $ map show xs
instance Mon (TensorAlgebra a) where
munit = TA 0 []
mmult (TA i xs) (TA j ys) = TA (i+j) (xs++ys)
instance (Eq k, Num k, Ord a) => Algebra k (TensorAlgebra a) where
unit x = x *> return munit
mult = nf . fmap (\(a,b) -> a `mmult` b)
injectTA :: Num k => Vect k a -> Vect k (TensorAlgebra a)
injectTA = fmap (\a -> TA 1 [a])
injectTA' :: (Eq k, Num k) => a -> Vect k (TensorAlgebra a)
injectTA' = injectTA . return
liftTA :: (Eq k, Num k, Ord b, Show b, Algebra k b) =>
(Vect k a -> Vect k b) -> Vect k (TensorAlgebra a) -> Vect k b
liftTA f = linear (\(TA _ xs) -> product [f (return x) | x <- xs])
liftTA' :: (Eq k, Num k, Ord b, Show b, Algebra k b) =>
(a -> Vect k b) -> Vect k (TensorAlgebra a) -> Vect k b
liftTA' = liftTA . linear
fmapTA :: (Eq k, Num k, Ord b, Show b) =>
(Vect k a -> Vect k b) -> Vect k (TensorAlgebra a) -> Vect k (TensorAlgebra b)
fmapTA f = liftTA (injectTA . f)
fmapTA' :: (Eq k, Num k, Ord b, Show b) =>
(a -> b) -> Vect k (TensorAlgebra a) -> Vect k (TensorAlgebra b)
fmapTA' = fmapTA . fmap
bindTA :: (Eq k, Num k, Ord b, Show b) =>
Vect k (TensorAlgebra a) -> (Vect k a -> Vect k (TensorAlgebra b)) -> Vect k (TensorAlgebra b)
bindTA = flip liftTA
bindTA' :: (Eq k, Num k, Ord b, Show b) =>
Vect k (TensorAlgebra a) -> (a -> Vect k (TensorAlgebra b)) -> Vect k (TensorAlgebra b)
bindTA' = flip liftTA'
data SymmetricAlgebra a = Sym Int [a] deriving (Eq,Ord)
instance Show a => Show (SymmetricAlgebra a) where
show (Sym _ []) = "1"
show (Sym _ xs) = filter (/= '"') $ concat $ L.intersperse "." $ map show xs
instance Ord a => Mon (SymmetricAlgebra a) where
munit = Sym 0 []
mmult (Sym i xs) (Sym j ys) = Sym (i+j) $ L.sort (xs++ys)
instance (Eq k, Num k, Ord a) => Algebra k (SymmetricAlgebra a) where
unit x = x *> return munit
mult = nf . fmap (\(a,b) -> a `mmult` b)
toSym :: (Eq k, Num k, Ord a) =>
Vect k (TensorAlgebra a) -> Vect k (SymmetricAlgebra a)
toSym = linear toSym'
where toSym' (TA i xs) = return $ Sym i (L.sort xs)
injectSym :: Num k => Vect k a -> Vect k (SymmetricAlgebra a)
injectSym = fmap (\a -> Sym 1 [a])
injectSym' :: Num k => a -> Vect k (SymmetricAlgebra a)
injectSym' = injectSym . return
liftSym :: (Eq k, Num k, Ord b, Show b, Algebra k b) =>
(Vect k a -> Vect k b) -> Vect k (SymmetricAlgebra a) -> Vect k b
liftSym f = linear (\(Sym _ xs) -> product [f (return x) | x <- xs])
liftSym' :: (Eq k, Num k, Ord b, Show b, Algebra k b) =>
(a -> Vect k b) -> Vect k (SymmetricAlgebra a) -> Vect k b
liftSym' = liftSym . linear
fmapSym :: (Eq k, Num k, Ord b, Show b) =>
(Vect k a -> Vect k b) -> Vect k (SymmetricAlgebra a) -> Vect k (SymmetricAlgebra b)
fmapSym f = liftSym (injectSym . f)
fmapSym' :: (Eq k, Num k, Ord b, Show b) =>
(a -> b) -> Vect k (SymmetricAlgebra a) -> Vect k (SymmetricAlgebra b)
fmapSym' = fmapSym . fmap
bindSym :: (Eq k, Num k, Ord b, Show b) =>
Vect k (SymmetricAlgebra a) -> (Vect k a -> Vect k (SymmetricAlgebra b)) -> Vect k (SymmetricAlgebra b)
bindSym = flip liftSym
bindSym' :: (Eq k, Num k, Ord b, Show b) =>
Vect k (SymmetricAlgebra a) -> (a -> Vect k (SymmetricAlgebra b)) -> Vect k (SymmetricAlgebra b)
bindSym' = flip liftSym'
data ExteriorAlgebra a = Ext Int [a] deriving (Eq,Ord)
instance Show a => Show (ExteriorAlgebra a) where
show (Ext _ []) = "1"
show (Ext _ xs) = filter (/= '"') $ concat $ L.intersperse "^" $ map show xs
instance (Eq k, Num k, Ord a) => Algebra k (ExteriorAlgebra a) where
unit x = x *> return (Ext 0 [])
mult xy = nf $ xy >>= (\(Ext i xs, Ext j ys) -> signedMerge 1 (0,[]) (i,xs) (j,ys))
where signedMerge s (k,zs) (i,x:xs) (j,y:ys) =
case compare x y of
EQ -> zerov
LT -> signedMerge s (k+1,x:zs) (i-1,xs) (j,y:ys)
GT -> let s' = if even i then s else -s
in signedMerge s' (k+1,y:zs) (i,x:xs) (j-1,ys)
signedMerge s (k,zs) (i,xs) (0,[]) = s *> (return $ Ext (k+i) $ reverse zs ++ xs)
signedMerge s (k,zs) (0,[]) (j,ys) = s *> (return $ Ext (k+j) $ reverse zs ++ ys)
toExt :: (Eq k, Num k, Ord a) =>
Vect k (TensorAlgebra a) -> Vect k (ExteriorAlgebra a)
toExt = linear toExt'
where toExt' (TA i xs) = let (sign,xs') = signedSort 1 True [] xs
in fromInteger sign *> return (Ext i xs')
signedSort sign done ls (r1:r2:rs) =
case compare r1 r2 of
EQ -> (0,[])
LT -> signedSort sign done (r1:ls) (r2:rs)
GT -> signedSort (-sign) False (r2:ls) (r1:rs)
signedSort sign done ls rs =
if done then (sign,reverse ls ++ rs) else signedSort sign True [] (reverse ls ++ rs)
injectExt :: Num k => Vect k a -> Vect k (ExteriorAlgebra a)
injectExt = fmap (\a -> Ext 1 [a])
injectExt' :: Num k => a -> Vect k (ExteriorAlgebra a)
injectExt' = injectExt . return
liftExt :: (Eq k, Num k, Ord b, Show b, Algebra k b) =>
(Vect k a -> Vect k b) -> Vect k (ExteriorAlgebra a) -> Vect k b
liftExt f = linear (\(Ext _ xs) -> product [f (return x) | x <- xs])
liftExt' :: (Eq k, Num k, Ord b, Show b, Algebra k b) =>
(a -> Vect k b) -> Vect k (ExteriorAlgebra a) -> Vect k b
liftExt' = liftExt . linear
fmapExt :: (Eq k, Num k, Ord b, Show b) =>
(Vect k a -> Vect k b) -> Vect k (ExteriorAlgebra a) -> Vect k (ExteriorAlgebra b)
fmapExt f = liftExt (injectExt . f)
fmapExt' :: (Eq k, Num k, Ord b, Show b) =>
(a -> b) -> Vect k (ExteriorAlgebra a) -> Vect k (ExteriorAlgebra b)
fmapExt' = fmapExt . fmap
bindExt :: (Eq k, Num k, Ord b, Show b) =>
Vect k (ExteriorAlgebra a) -> (Vect k a -> Vect k (ExteriorAlgebra b)) -> Vect k (ExteriorAlgebra b)
bindExt = flip liftExt
bindExt' :: (Eq k, Num k, Ord b, Show b) =>
Vect k (ExteriorAlgebra a) -> (a -> Vect k (ExteriorAlgebra b)) -> Vect k (ExteriorAlgebra b)
bindExt' = flip liftExt'
data TensorCoalgebra c = TC Int [c] deriving (Eq,Ord,Show)
instance (Eq k, Num k, Ord c) => Coalgebra k (TensorCoalgebra c) where
counit = unwrap . linear counit'
where counit' (TC 0 []) = return ()
counit' _ = zerov
comult = linear comult'
where comult' (TC d xs) = sumv [return (TC i ls, TC (d-i) rs) | (i,ls,rs) <- L.zip3 [0..] (L.inits xs) (L.tails xs)]
projectTC :: (Eq k, Num k, Ord b) => Vect k (TensorCoalgebra b) -> Vect k b
projectTC = linear projectTC' where projectTC' (TC 1 [b]) = return b; projectTC' _ = zerov
coliftTC :: (Eq k, Num k, Coalgebra k c, Ord d) =>
(Vect k c -> Vect k d) -> Vect k c -> Vect k (TensorCoalgebra d)
coliftTC f = sumf [coliftTC' i f | i <- [0..2] ]
coliftTC' 0 f = linear f0'
where f0' c = counit (return c) *> return (TC 0 [])
coliftTC' 1 f = linear f1'
where f1' c = fmap (\d -> TC 1 [d]) (f $ return c)
coliftTC' n f = linear fn'
where f1' = coliftTC' 1 f
fn1' = coliftTC' (n-1) f
fn' c = fmap (\(TC 1 [x], TC _ xs) -> TC n (x:xs)) $ ( (f1' `tf` fn1') . comult) (return c)
cobindTC :: (Eq k, Num k, Ord c, Ord d) =>
(Vect k (TensorCoalgebra c) -> Vect k d) -> Vect k (TensorCoalgebra c) -> Vect k (TensorCoalgebra d)
cobindTC = coliftTC