summaryrefslogtreecommitdiff
path: root/lib/Data/Packed/Internal
diff options
context:
space:
mode:
authorAlberto Ruiz <aruiz@um.es>2007-09-11 10:25:24 +0000
committerAlberto Ruiz <aruiz@um.es>2007-09-11 10:25:24 +0000
commit834b4837799611fd7fbaa9609ea587e041cb0ca1 (patch)
tree1854b519b6a3dd10e3961796bdfccb52cbc00a4d /lib/Data/Packed/Internal
parent89651db9f2577ba42dbbb91c85565a12f34d0fb2 (diff)
tensor lib moved to easyVision project
Diffstat (limited to 'lib/Data/Packed/Internal')
-rw-r--r--lib/Data/Packed/Internal/Matrix.hs5
-rw-r--r--lib/Data/Packed/Internal/Tensor.hs347
2 files changed, 3 insertions, 349 deletions
diff --git a/lib/Data/Packed/Internal/Matrix.hs b/lib/Data/Packed/Internal/Matrix.hs
index ba32a67..2db4838 100644
--- a/lib/Data/Packed/Internal/Matrix.hs
+++ b/lib/Data/Packed/Internal/Matrix.hs
@@ -9,9 +9,10 @@
9-- Stability : provisional 9-- Stability : provisional
10-- Portability : portable (uses FFI) 10-- Portability : portable (uses FFI)
11-- 11--
12-- Fundamental types 12-- Internal matrix representation
13-- 13--
14----------------------------------------------------------------------------- 14-----------------------------------------------------------------------------
15-- --#hide
15 16
16module Data.Packed.Internal.Matrix where 17module Data.Packed.Internal.Matrix where
17 18
@@ -74,7 +75,7 @@ type Mt t s = Int -> Int -> Ptr t -> s
74-- infixr 6 ::> 75-- infixr 6 ::>
75-- type t ::> s = Mt t s 76-- type t ::> s = Mt t s
76 77
77-- | the inverse of 'fromLists' 78-- | the inverse of 'Data.Packed.Matrix.fromLists'
78toLists :: (Field t) => Matrix t -> [[t]] 79toLists :: (Field t) => Matrix t -> [[t]]
79toLists m = partit (cols m) . toList . cdat $ m 80toLists m = partit (cols m) . toList . cdat $ m
80 81
diff --git a/lib/Data/Packed/Internal/Tensor.hs b/lib/Data/Packed/Internal/Tensor.hs
deleted file mode 100644
index dea1636..0000000
--- a/lib/Data/Packed/Internal/Tensor.hs
+++ /dev/null
@@ -1,347 +0,0 @@
1{-# OPTIONS_GHC -fglasgow-exts #-}
2
3-----------------------------------------------------------------------------
4-- |
5-- Module : Data.Packed.Internal.Tensor
6-- Copyright : (c) Alberto Ruiz 2007
7-- License : GPL-style
8--
9-- Maintainer : Alberto Ruiz <aruiz@um.es>
10-- Stability : provisional
11-- Portability : portable (uses FFI)
12--
13-- support for basic tensor operations
14--
15-----------------------------------------------------------------------------
16
17module Data.Packed.Internal.Tensor where
18
19import Data.Packed.Internal
20import Foreign.Storable
21import Data.List(sort,elemIndex,nub,foldl1',foldl')
22import GSL.Vector
23import Data.Packed.Matrix
24import Data.Packed.Vector
25import LinearAlgebra.Linear
26
27data IdxType = Covariant | Contravariant deriving (Show,Eq)
28
29type IdxName = String
30
31data IdxDesc = IdxDesc { idxDim :: Int,
32 idxType :: IdxType,
33 idxName :: IdxName } deriving Eq
34
35instance Show IdxDesc where
36 show (IdxDesc n t name) = name ++ sym t ++"["++show n++"]"
37 where sym Covariant = "_"
38 sym Contravariant = "^"
39
40
41data Tensor t = T { dims :: [IdxDesc]
42 , ten :: Vector t
43 }
44
45-- | returns the coordinates of a tensor in row - major order
46coords :: Tensor t -> Vector t
47coords = ten
48
49instance (Show a, Field a) => Show (Tensor a) where
50 show T {dims = [], ten = t} = "scalar "++show (t `at` 0)
51 show t = "("++shdims (dims t) ++") "++ showdt t
52
53asMatrix t = reshape (idxDim $ dims t!!1) (ten t)
54
55showdt t | rank t == 1 = show (toList (ten t))
56 | rank t == 2 = ('\n':) . dsp . map (map show) . toLists $ asMatrix $ t
57 | otherwise = concatMap showdt $ parts t (head (names t))
58
59-- | a nice description of the tensor structure
60shdims :: [IdxDesc] -> String
61shdims [] = ""
62shdims [d] = show d
63shdims (d:ds) = show d ++ "><"++ shdims ds
64
65-- | tensor rank (number of indices)
66rank :: Tensor t -> Int
67rank = length . dims
68
69names :: Tensor t -> [IdxName]
70names t = map idxName (dims t)
71
72-- | number of contravariant and covariant indices
73structure :: Tensor t -> (Int,Int)
74structure t = (rank t - n, n) where
75 n = length $ filter isCov (dims t)
76 isCov d = idxType d == Covariant
77
78-- | creates a rank-zero tensor from a scalar
79scalar :: Storable t => t -> Tensor t
80scalar x = T [] (fromList [x])
81
82-- | Creates a tensor from a signed list of dimensions (positive = contravariant, negative = covariant) and a Vector containing the coordinates in row major order.
83tensor :: [Int] -> Vector a -> Tensor a
84tensor dssig vec = T d v `withIdx` seqind where
85 n = product (map abs dssig)
86 v = if dim vec == n then vec else error "wrong arguments for tensor"
87 d = map cr dssig
88 cr n | n > 0 = IdxDesc {idxName = "", idxDim = n, idxType = Contravariant}
89 | n < 0 = IdxDesc {idxName = "", idxDim = -n, idxType = Covariant }
90
91
92tensorFromVector :: IdxType -> Vector t -> Tensor t
93tensorFromVector tp v = T {dims = [IdxDesc (dim v) tp "1"], ten = v}
94
95tensorFromMatrix :: Field t => IdxType -> IdxType -> Matrix t -> Tensor t
96tensorFromMatrix tpr tpc m = T {dims = [IdxDesc (rows m) tpr "1",IdxDesc (cols m) tpc "2"]
97 , ten = cdat m}
98
99
100liftTensor :: (Vector a -> Vector b) -> Tensor a -> Tensor b
101liftTensor f (T d v) = T d (f v)
102
103liftTensor2 :: (Vector a -> Vector b -> Vector c) -> Tensor a -> Tensor b -> Tensor c
104liftTensor2 f (T d1 v1) (T d2 v2) | compat d1 d2 = T d1 (f v1 v2)
105 | otherwise = error "liftTensor2 with incompatible tensors"
106 where compat a b = length a == length b
107
108
109
110
111-- | express the tensor as a matrix with the given index in columns
112findIdx :: (Field t) => IdxName -> Tensor t
113 -> (([IdxDesc], [IdxDesc]), Matrix t)
114findIdx name t = ((d1,d2),m) where
115 (d1,d2) = span (\d -> idxName d /= name) (dims t)
116 c = product (map idxDim d2)
117 m = matrixFromVector RowMajor c (ten t)
118
119-- | express the tensor as a matrix with the given index in rows
120putFirstIdx :: (Field t) => String -> Tensor t -> ([IdxDesc], Matrix t)
121putFirstIdx name t = (nd,m')
122 where ((d1,d2),m) = findIdx name t
123 m' = matrixFromVector RowMajor c $ cdat $ trans m
124 nd = d2++d1
125 c = dim (ten t) `div` (idxDim $ head d2)
126
127
128-- | renames all the indices in the current order (repeated indices may get different names)
129withIdx :: Tensor t -> [IdxName] -> Tensor t
130withIdx (T d v) l = T d' v
131 where d' = zipWith f d l
132 f i n = i {idxName=n}
133
134
135-- | raises or lowers all the indices of a tensor (with euclidean metric)
136raise :: Tensor t -> Tensor t
137raise (T d v) = T (map raise' d) v
138 where raise' idx@IdxDesc {idxType = Covariant } = idx {idxType = Contravariant}
139 raise' idx@IdxDesc {idxType = Contravariant } = idx {idxType = Covariant}
140
141
142-- | index transposition to a desired order. You can specify only a subset of the indices, which will be moved to the front of indices list
143tridx :: (Field t) => [IdxName] -> Tensor t -> Tensor t
144tridx [] t = t
145tridx (name:rest) t = T (d:ds) (join ts) where
146 ((_,d:_),_) = findIdx name t
147 ps = map (tridx rest) (parts t name)
148 ts = map ten ps
149 ds = dims (head ps)
150
151
152
153-- | extracts a given part of a tensor
154part :: (Field t) => Tensor t -> (IdxName, Int) -> Tensor t
155part t (name,k) = if k<0 || k>=l
156 then error $ "part "++show (name,k)++" out of range" -- in "++show t
157 else T {dims = ds, ten = toRows m !! k}
158 where (d:ds,m) = putFirstIdx name t
159 l = idxDim d
160
161-- | creates a list with all parts of a tensor along a given index
162parts :: (Field t) => Tensor t -> IdxName -> [Tensor t]
163parts t name = map f (toRows m)
164 where (d:ds,m) = putFirstIdx name t
165 l = idxDim d
166 f t = T {dims=ds, ten=t}
167
168
169compatIdx :: (Field t1, Field t) => Tensor t1 -> IdxName -> Tensor t -> IdxName -> Bool
170compatIdx t1 n1 t2 n2 = compatIdxAux d1 d2 where
171 d1 = head $ snd $ fst $ findIdx n1 t1
172 d2 = head $ snd $ fst $ findIdx n2 t2
173 compatIdxAux IdxDesc {idxDim = n1, idxType = t1}
174 IdxDesc {idxDim = n2, idxType = t2}
175 = t1 /= t2 && n1 == n2
176
177
178outer' u v = dat (outer u v)
179
180-- | tensor product without without any contractions
181rawProduct :: (Field t, Num t) => Tensor t -> Tensor t -> Tensor t
182rawProduct (T d1 v1) (T d2 v2) = T (d1++d2) (outer' v1 v2)
183
184-- | contraction of the product of two tensors
185contraction2 :: (Field t, Num t) => Tensor t -> IdxName -> Tensor t -> IdxName -> Tensor t
186contraction2 t1 n1 t2 n2 =
187 if compatIdx t1 n1 t2 n2
188 then T (tail d1 ++ tail d2) (cdat m)
189 else error "wrong contraction2"
190 where (d1,m1) = putFirstIdx n1 t1
191 (d2,m2) = putFirstIdx n2 t2
192 m = multiply RowMajor (trans m1) m2
193
194-- | contraction of a tensor along two given indices
195contraction1 :: (Linear Vector t) => Tensor t -> IdxName -> IdxName -> Tensor t
196contraction1 t name1 name2 =
197 if compatIdx t name1 t name2
198 then sumT y
199 else error $ "wrong contraction1: "++(shdims$dims$t)++" "++name1++" "++name2
200 where d = dims (head y)
201 x = (map (flip parts name2) (parts t name1))
202 y = map head $ zipWith drop [0..] x
203
204-- | contraction of a tensor along a repeated index
205contraction1c :: (Linear Vector t) => Tensor t -> IdxName -> Tensor t
206contraction1c t n = contraction1 renamed n' n
207 where n' = n++"'" -- hmmm
208 renamed = withIdx t auxnames
209 auxnames = h ++ (n':r)
210 (h,_:r) = break (==n) (map idxName (dims t))
211
212-- | alternative and inefficient version of contraction2
213contraction2' :: (Linear Vector t) => Tensor t -> IdxName -> Tensor t -> IdxName -> Tensor t
214contraction2' t1 n1 t2 n2 =
215 if compatIdx t1 n1 t2 n2
216 then contraction1 (rawProduct t1 t2) n1 n2
217 else error "wrong contraction'"
218
219-- | applies a sequence of contractions
220contractions :: (Linear Vector t) => Tensor t -> [(IdxName, IdxName)] -> Tensor t
221contractions t pairs = foldl' contract1b t pairs
222 where contract1b t (n1,n2) = contraction1 t n1 n2
223
224-- | applies a sequence of contractions of same index
225contractionsC :: (Linear Vector t) => Tensor t -> [IdxName] -> Tensor t
226contractionsC t is = foldl' contraction1c t is
227
228
229-- | applies a contraction on the first indices of the tensors
230contractionF :: (Linear Vector t) => Tensor t -> Tensor t -> Tensor t
231contractionF t1 t2 = contraction2 t1 n1 t2 n2
232 where n1 = fn t1
233 n2 = fn t2
234 fn = idxName . head . dims
235
236-- | computes all compatible contractions of the product of two tensors that would arise if the index names were equal
237possibleContractions :: (Linear Vector t) => Tensor t -> Tensor t -> [Tensor t]
238possibleContractions t1 t2 = [ contraction2 t1 n1 t2 n2 | n1 <- names t1, n2 <- names t2, compatIdx t1 n1 t2 n2 ]
239
240
241
242desiredContractions2 :: Tensor t -> Tensor t1 -> [(IdxName, IdxName)]
243desiredContractions2 t1 t2 = [ (n1,n2) | n1 <- names t1, n2 <- names t2, n1==n2]
244
245desiredContractions1 :: Tensor t -> [IdxName]
246desiredContractions1 t = [ n1 | (a,n1) <- x , (b,n2) <- x, a/=b, n1==n2]
247 where x = zip [0..] (names t)
248
249-- | tensor product with the convention that repeated indices are contracted.
250mulT :: (Linear Vector t) => Tensor t -> Tensor t -> Tensor t
251mulT t1 t2 = r where
252 t1r = contractionsC t1 (desiredContractions1 t1)
253 t2r = contractionsC t2 (desiredContractions1 t2)
254 cs = desiredContractions2 t1r t2r
255 r = case cs of
256 [] -> rawProduct t1r t2r
257 (n1,n2):as -> contractionsC (contraction2 t1r n1 t2r n2) (map fst as)
258
259-----------------------------------------------------------------
260
261-- | tensor addition (for tensors with the same structure)
262addT :: (Linear Vector a) => Tensor a -> Tensor a -> Tensor a
263addT a b = liftTensor2 add a b
264
265sumT :: (Linear Vector a) => [Tensor a] -> Tensor a
266sumT l = foldl1' addT l
267
268-----------------------------------------------------------------
269
270-- sent to Haskell-Cafe by Sebastian Sylvan
271perms :: [t] -> [[t]]
272perms [x] = [[x]]
273perms xs = [y:ps | (y,ys) <- selections xs , ps <- perms ys]
274 where
275 selections [] = []
276 selections (x:xs) = (x,xs) : [(y,x:ys) | (y,ys) <- selections xs]
277
278interchanges :: (Ord a) => [a] -> Int
279interchanges ls = sum (map (count ls) ls)
280 where count l p = length $ filter (>p) $ take pel l
281 where Just pel = elemIndex p l
282
283signature :: (Num t, Ord a) => [a] -> t
284signature l | length (nub l) < length l = 0
285 | even (interchanges l) = 1
286 | otherwise = -1
287
288
289sym :: (Linear Vector t) => Tensor t -> Tensor t
290sym t = T (dims t) (ten (sym' (withIdx t seqind)))
291 where sym' t = sumT $ map (flip tridx t) (perms (names t))
292 where nms = map idxName . dims
293
294antisym :: (Linear Vector t) => Tensor t -> Tensor t
295antisym t = T (dims t) (ten (antisym' (withIdx t seqind)))
296 where antisym' t = sumT $ map (scsig . flip tridx t) (perms (names t))
297 scsig t = scalar (signature (nms t)) `rawProduct` t
298 where nms = map idxName . dims
299
300-- | the wedge product of two tensors (implemented as the antisymmetrization of the ordinary tensor product).
301wedge :: (Linear Vector t, Fractional t) => Tensor t -> Tensor t -> Tensor t
302wedge a b = antisym (rawProduct (norper a) (norper b))
303 where norper t = rawProduct t (scalar (recip $ fromIntegral $ fact (rank t)))
304
305-- antinorper t = rawProduct t (scalar (fromIntegral $ fact (rank t)))
306
307-- | The euclidean inner product of two completely antisymmetric tensors
308innerAT :: (Fractional t, Field t) => Tensor t -> Tensor t -> t
309innerAT t1 t2 = dot (ten t1) (ten t2) / fromIntegral (fact $ rank t1)
310
311fact :: (Num t, Enum t) => t -> t
312fact n = product [1..n]
313
314seqind' :: [[String]]
315seqind' = map return seqind
316
317seqind :: [String]
318seqind = map show [1..]
319
320-- | completely antisymmetric covariant tensor of dimension n
321leviCivita :: (Linear Vector t) => Int -> Tensor t
322leviCivita n = antisym $ foldl1 rawProduct $ zipWith withIdx auxbase seqind'
323 where auxbase = map tc (toRows (ident n))
324 tc = tensorFromVector Covariant
325
326-- | contraction of leviCivita with a list of vectors (and raise with euclidean metric)
327innerLevi :: (Linear Vector t) => [Tensor t] -> Tensor t
328innerLevi vs = raise $ foldl' contractionF (leviCivita n) vs
329 where n = idxDim . head . dims . head $ vs
330
331
332-- | obtains the dual of a multivector (with euclidean metric)
333dual :: (Linear Vector t, Fractional t) => Tensor t -> Tensor t
334dual t = raise $ leviCivita n `mulT` withIdx t seqind `rawProduct` x
335 where n = idxDim . head . dims $ t
336 x = scalar (recip $ fromIntegral $ fact (rank t))
337
338
339-- | shows only the relevant components of an antisymmetric tensor
340niceAS :: (Field t, Fractional t) => Tensor t -> [(t, [Int])]
341niceAS t = filter ((/=0.0).fst) $ zip vals base
342 where vals = map ((`at` 0).ten.foldl' partF t) (map (map pred) base)
343 base = asBase r n
344 r = length (dims t)
345 n = idxDim . head . dims $ t
346 partF t i = part t (name,i) where name = idxName . head . dims $ t
347 asBase r n = filter (\x-> (x==nub x && x==sort x)) $ sequence $ replicate r [1..n]