module Math.Algebras.VectorSpace where
import qualified Data.List as L
import qualified Data.Set as S
infixr 7 *>
infixl 7 <*
infixl 6 <+>
data Vect k b = V [(b,k)] deriving (Eq,Ord)
instance (Num k, Show b) => Show (Vect k b) where
show (V []) = "0"
show (V ts) = concatWithPlus $ map showTerm ts
where showTerm (b,x) | show b == "1" = show x
| show x == "1" = show b
| show x == "-1" = "-" ++ show b
| otherwise = (if isAtomic (show x) then show x else "(" ++ show x ++ ")")
++ show b
concatWithPlus (t1:t2:ts) = if head t2 == '-'
then t1 ++ concatWithPlus (t2:ts)
else t1 ++ '+' : concatWithPlus (t2:ts)
concatWithPlus [t] = t
isAtomic (c:cs) = isAtomic' cs
isAtomic' ('^':'-':cs) = isAtomic' cs
isAtomic' ('+':cs) = False
isAtomic' ('-':cs) = False
isAtomic' (c:cs) = isAtomic' cs
isAtomic' [] = True
zero :: Vect k b
zero = V []
add :: (Ord b, Num k) => Vect k b -> Vect k b -> Vect k b
add (V ts) (V us) = V $ addmerge ts us
(<+>) :: (Ord b, Num k) => Vect k b -> Vect k b -> Vect k b
(<+>) = add
addmerge ((a,x):ts) ((b,y):us) =
case compare a b of
LT -> (a,x) : addmerge ts ((b,y):us)
EQ -> if x+y == 0 then addmerge ts us else (a,x+y) : addmerge ts us
GT -> (b,y) : addmerge ((a,x):ts) us
addmerge ts [] = ts
addmerge [] us = us
neg :: (Num k) => Vect k b -> Vect k b
neg (V ts) = V $ map (\(b,x) -> (b,x)) ts
smultL :: (Num k) => k -> Vect k b -> Vect k b
smultL 0 _ = zero
smultL k (V ts) = V [(ei,k*xi) | (ei,xi) <- ts]
(*>) :: (Num k) => k -> Vect k b -> Vect k b
(*>) = smultL
smultR :: (Num k) => Vect k b -> k -> Vect k b
smultR _ 0 = zero
smultR (V ts) k = V [(ei,xi*k) | (ei,xi) <- ts]
(<*) :: (Num k) => Vect k b -> k -> Vect k b
(<*) = smultR
nf :: (Ord b, Num k) => Vect k b -> Vect k b
nf (V ts) = V $ nf' $ L.sortBy compareFst ts where
nf' ((b1,x1):(b2,x2):ts) =
case compare b1 b2 of
LT -> if x1 == 0 then nf' ((b2,x2):ts) else (b1,x1) : nf' ((b2,x2):ts)
EQ -> if x1+x2 == 0 then nf' ts else nf' ((b1,x1+x2):ts)
GT -> error "nf': not pre-sorted"
nf' [(b,x)] = if x == 0 then [] else [(b,x)]
nf' [] = []
compareFst (b1,x1) (b2,x2) = compare b1 b2
instance Functor (Vect k) where
fmap f (V ts) = V [(f b, x) | (b,x) <- ts]
instance Num k => Monad (Vect k) where
return a = V [(a,1)]
V ts >>= f = V $ concat [ [(b,y*x) | let V us = f a, (b,y) <- us] | (a,x) <- ts]
linear :: (Ord b, Num k) => (a -> Vect k b) -> Vect k a -> Vect k b
linear f v = nf $ v >>= f
newtype EBasis = E Int deriving (Eq,Ord)
instance Show EBasis where show (E i) = "e" ++ show i
e i = return (E i)
e1 = e 1
e2 = e 2
e3 = e 3