module Numeric.LinearAlgebra.Multivector (
Multivector, coords,
scalar, vector, e, (/\), (-|), (\/), rever, full, rotor,
apply,
grade, maxGrade, maxDim,
fromTensor
) where
import Numeric.LinearAlgebra.HMatrix(toList,reshape,(<\>),atIndex)
import Numeric.LinearAlgebra.Array.Internal hiding (scalar,coords)
import Numeric.LinearAlgebra.Array.Display (showBases)
import Numeric.LinearAlgebra.Tensor hiding (scalar,vector)
import qualified Numeric.LinearAlgebra.Array.Internal as Array
import Data.List
import Control.Monad(filterM)
import Data.Function(on)
import qualified Data.Map as Map
powerset = filterM (const [True, False])
base :: Int -> [[Int]]
base k = sortBy (compare `on` length) (powerset [1..k])
base' k = map (\b -> MV [(1,b)]) (base k)
data Multivector = MV { coords :: [(Double,[Int])] } deriving Eq
instance Show Multivector where
show = showMV
maxGrade :: Multivector -> Int
maxGrade (MV l) = maximum . map (length.snd) $ l
grade :: Int -> Multivector -> Multivector
grade k (MV l) = MV $ filter ((k==).length.snd) l
maxDim :: Multivector -> Int
maxDim (MV [(_,[])]) = 0
maxDim (MV l) = maximum . concat . map snd $ l
rever :: Multivector -> Multivector
rever (MV l) = MV (map r l) where
r (c,b) = (c*fromIntegral s ,b)
where s = signum (1)^(k*(k1)`div`2) :: Int
k = length b
showMV :: Multivector -> String
showMV (MV x) = showBases x
scalar :: Double -> Multivector
scalar s = MV [(s,[])]
vector :: [Double] -> Multivector
vector v = MV $ simplify $ zip v (map (:[]) [1..])
r1 :: [Int] -> [(Int,[Int])]
r1 [] = []
r1 l = (m,elemIndices m l):(r1 (filter (/=m) l))
where m = minimum l
r2 :: [(Int, [Int])] -> (Double, [Int])
r2 = foldl' g (1,[])
where g (k,l) (x,ps) = (k*s,l++t)
where t = if even (length ps) then [] else [x]
s = product (map f ps')
where f z = if even z then 1 else 1
ps' = zipWith (subtract) ps [0..]
r3 :: [(Int, [Int])] -> (Double, [Int])
r3 = foldl' g (1,[])
where g (k,l) (x,ps) = (k*s,l++[x])
where s = if length ps > 1 then 0 else if even (head ps) then 1 else 1
simplify = chop . grp . sortBy (compare `on` snd)
where grp [] = []
grp [a] = [a]
grp ((c1,b1):(c2,b2):rest)
| b1 == b2 = grp ( (c1+c2,b1) : rest)
| otherwise = (c1,b1): grp ((c2,b2):rest)
zero (c,_) = abs c < 1E-8
chop = cz . filter (not.zero)
cz [] = [(0,[])]
cz x = x
gs (MV l1) (MV l2) = MV $ simplify (l1++l2)
gp (MV l1) (MV l2) = MV $ simplify [g x y | x<-l1, y <-l2]
where g (c1,b1) (c2,b2) = (k*c1*c2,b3) where (k,b3) = gpr b1 b2
ge (MV l1) (MV l2) = MV $ simplify [g x y | x<-l1, y <-l2]
where g (c1,b1) (c2,b2) = (k*c1*c2,b3) where (k,b3) = epr b1 b2
gi (MV l1) (MV l2) = sum [g x y | x<-l1, y <-l2]
where g (c1,[]) (c2,is) = MV [(c1*c2,is)]
g _ (_,[]) = 0
g (c1,[i]) (c2,[j]) = if i==j then MV [(c1*c2,[])] else 0
g (c1,[i]) (c2,j:js) = (g (c1,[i]) (c2,[j]) /\ MV [(1,js)])
(MV [(c2,[j])] /\ g (c1,[i]) (1,js))
g (c1,i:is) b = gi (MV [(c1,[i])]) (gi (MV[(1,is)]) (MV [b]))
instance Num Multivector where
(+) = gs
(*) = gp
negate (MV l) = MV (map neg l) where neg (k,b) = (k,b)
abs _ = error "abs of multivector not yet defined"
signum _ = error "signum of multivector not yet defined"
fromInteger x = MV [(fromInteger x,[])]
instance Fractional Multivector where
fromRational x = MV [(fromRational x,[])]
recip (MV [(x,[])]) = MV [(recip x,[])]
recip x = mvrecip x
e :: Int -> Multivector
e k = MV [(1,[k])]
(/\) :: Multivector -> Multivector -> Multivector
infixl 7 /\
(/\) = ge
(-|) :: Multivector -> Multivector -> Multivector
infixl 7 -|
(-|) = gi
full :: Int -> Multivector
full k = MV [(1,[1 .. k])]
(\/) :: Multivector -> Multivector -> Multivector
infixl 7 \/
(\/) a b = (b -| rever (full k)) -| a
where k = max (maxDim a) (maxDim b)
normVec v = sqrt x where MV [(x,[])] = v * v
unitary v = v / scalar (normVec v)
rotor :: Int
-> Double
-> Multivector
-> Multivector
rotor k phi axis = scalar (cos (phi/2)) scalar (sin (phi/2)) * (unitary axis*full k)
gprules k = Map.fromList [(x, Map.fromList [(y,(r2.r1)(x++y)) | y<-base k] )| x<-base k]
eprules k = Map.fromList [(x, Map.fromList [(y,(r3.r1)(x++y)) | y<-base k] )| x<-base k]
gpr a b = g Map.! a Map.! b
where g = gprules 6
epr a b = g Map.! a Map.! b
where g = eprules 6
expand k = g
where g (MV l) = foldl1' (zipWith (+)) $ map f l
basepos b = m Map.! b
m = baseraw k
f (c,b) = en pk (basepos b) c
pk = 2^k
baseraw q = Map.fromList $ zip (base q) [0..]
en n q v = replicate q 0 ++ v : replicate (nq1) 0
compact k t = sum $ zipWith (*) (map scalar $ toList (Array.coords t)) (base' k)
gatensor k = listTensor [pk,pk,pk] (concat . concat $ gacoords)
where pk = 2^k
gacoords = [[ f (x * y) | y<-b] | x<-b]
b = base' k
f = expand k
tmv k x = listTensor [2^k] (expand k x)
mat rowidx t = reshape c $ Array.coords t'
where c = iDim $ last (dims t')
t' = reorder (rowidx: (namesR t\\[rowidx])) t
pmat k b = mat "k" $ g!"ijk" * tb!"j"
where g = gatensor k
tb = tmv k b
divi k a b = compact k $ listTensor [2^k] (toList $ pmat k b <\> Array.coords (tmv k a))
mvrecip b = divi (maxDim b) 1 b
fromTensor :: Tensor Double -> Multivector
fromTensor t = MV $ filter ((/=0.0).fst) $ zip vals basis
where vals = map ((`atIndex` 0). Array.coords .foldl' partF t) (map (map pred) basis)
r = length (dims t)
n = iDim . head . dims $ t
partF s i = part s (name,i) where name = iName . head . dims $ s
basis = filter (\x-> (x==nub x && x==sort x)) $ sequence $ replicate r [1..n]
part t (name,i) = parts t name !! i
apply :: (Int -> Multivector) -> Multivector -> Multivector
apply f t = sum $ map g (coords t) where
g (x,[]) = scalar x
g (x,es) = scalar x * foldl1' (/\) (map f es)