\section{Matrix} ======================================================================= This file has been created entirely by Brian D. Moe (Summer 1990) It contains all the "include" statements for the sparse and dense matrix operations. Converted to Haskell by Ian R McLelland and Cordelia V Hall (Nov 1992) ======================================================================= \begin{code} module Matrix (Matrix, Vector, Block , Vec , Block_list , Row_pos, Col_pos, mmult, mvmult, svmult, madd, msub, vadd, vsub, vdot, vouter, mneg, vneg, norm, mkmatrix, mkvector, mergevectors, mupdate, vupdate, msubscript, vsubscript, getrow, getcol, numrows, msize, vsize, showmatrix, showvector) where import AbsDensematrix import Utils \end{code} We have replaced include of "densematrix" with import of AbsDensematrix, which imports Densematrix and exports the named objects with the new names (excluding some). The original include appears in comments in AbsDensematrix (cvh). The beginning of Sparsematrix_kludge, textually inserted because Matrix and Sparsematrix_kludge are now mutually recursive, and it doesn't seem worth maintaining them separately for now (cvh). ================================================================ ================ A SPARSE MATRIX IMPLEMENTATION ================ Written by Brian D. Moe (Summer 1990) Note: mupdate and vupdate have been included by Kamini Shenoi ================================================================ This is a matrix/vector abstract type implementation designed for sparse, block stuctured matrices. Included are several functions specific to solving linear systems for oil reservoir modelling. (e.g. precond & uncondition) Implementation of Types \begin{code} mmult :: Matrix -> Matrix -> Matrix madd :: Matrix -> Matrix -> Matrix msub :: Matrix -> Matrix -> Matrix mvmult :: Matrix -> Vector -> Vector vadd :: Vector -> Vector -> Vector vsub :: Vector -> Vector -> Vector vdot :: Vector -> Vector -> Scalar vouter :: Vector -> Vector -> Matrix norm :: Vector -> Scalar mneg :: Matrix -> Matrix vneg :: Vector -> Vector svmult :: Scalar -> Vector -> Vector mupdate :: Matrix -> (Int,Int) -> Block -> Matrix vupdate :: Vector -> Int -> Vec -> Vector msubscript :: Int -> Int -> Matrix -> Block msubscript' :: Int -> Int -> Matrix -> [Block] vsubscript :: Int -> Vector -> Vec getrow :: Int -> Matrix -> [Block_tuple] getcol :: Int -> Matrix -> [Block_tuple] numrows :: Matrix -> Int msize :: Matrix -> (Int,Int) vsize :: Vector -> Int mkmatrix :: [[(Int,Int,Block)]] -> Matrix mkvector :: [Vec] -> Vector mergevectors :: Vector -> Vector -> Vector showmatrix :: Matrix -> [Char] showvector :: Vector -> [Char] type Row_pos = Int type Col_pos = Int type Block_tuple = (Row_pos, Col_pos, Block) type Block_list = [Block_tuple] type Matrix = Matrix_type type Vector = Vector_type type Matrix_type = [Block_list] type Vector_type = [Vec] type Scalar = Float sadd = (+) mmult m1 m2 = error "unsupported matrix operation" madd m1 m2 = error "unsupported matrix operation" msub m1 m2 = error "unsupported matrix operation" mneg m = map (map negtuple) m where negtuple (r, c, b) = (r, c, bneg b) vadd v1 v2 = map2 vecadd v1 v2 vsub v1 v2 = map2 vecsub v1 v2 vdot v1 v2 = foldl1 sadd (map2 vecdot v1 v2) vouter v1 v2 = error "unsupported vector operation" norm v = foldl1 sadd (map vecnorm v) vneg v = map vecneg v svmult s v = map (svecmult s) v mupdate m (i,j) val = [getrow k m |k <- [0..i-1]] ++ [(f(m!!i))] ++ [getrow l m | l <- [(i+1) .. (numrows m)-1]] where f xs = (take j xs) ++ [(i, (j+1), val)] ++ (drop (j+1) xs) vupdate v i vc = (take i v) ++ [vc] ++ (drop (i+1) v) showmatrix m = concat [ (showrow i)++"\n" | i<-[0..length(m)-1] ] where showrow i = concat [status i j | j<-[0..length(m)-1]] status i j = if exist i j then "#" else "." exist i j = j `elem` (row i) row i = [ col | (r,col,b) <- (m!!i) ] showvector vs = concat (map showvec vs) mkmatrix = id mkvector = id mergevectors = (++) \end{code} ================================================ ================ MISC FUNCTIONS ================ ================================================ Roger Wainwrights's mvmult: (used in mvmult elsewhere) For multiplying a sparse matrix by its vector counterpart. (a list of vectors) mvmult :: Matrix -> Vector -> Vector \begin{code} mvmult rows v = if ok then [ rvdot row v | row <- rows ] else error "Incompatible operands to large mvmult" where ok = (length rows) == (length v) rvdot row v = foldl1 vecadd [bvecmult b (vsubscript c v) | (r,c,b) <- row] \end{code} Notes: okindex checks that the number given won't be out of range for the given list. WARNING: WILL HANG IF LIST IS INFINITE. msubscript' gets the block at a given location in a sparse matrix. msubscript gets the block at a given location in s sparse matrix, even if it isn't present. getrow gets the list of block tuples from the given row of a matrix getcol gets the list of block tuples from the given column of a matrix numrows returns the number of rows of blocks in a sparse matrix. strip_block returns the block part of a block tuple. vsubscript gets a piece of one of those chopped up vectors. \begin{code} okindex :: Int -> [a] -> Bool okindex n m = (0<=n) && (n<=((length m) - 1)) -- testing (irm) iscol :: Int -> Block_tuple -> Bool iscol k (r,c,b) = (k==c) msubscript' r c m = map strip_block (filter (iscol c) (getrow r m)) msubscript r c m = if thingee /= [] then (head thingee) else zero_block r c m where thingee = msubscript' r c m getrow n m = if okindex n m then m !! n else error "getrow: index out of bounds" getcol n m = concat [ filter (iscol n) row | row <- m ] numrows m = length m msize m = (length m,length (head m)) vsize v = length v strip_block :: Block_tuple -> Block strip_block (r,c,b) = b vsubscript n v = if okindex n v then v!!n else error "vsubscript in matrix" \end{code} ========== end of Sparsematrix_kludge ======================== \begin{code} zero_block :: Int -> Int -> Matrix -> Block zero_block i j m = mkblock (rep nrows (rep ncols 0)) where (nrows,junk1) = block_size (head (getrow i m)) (junk2,ncols) = block_size (head (getcol j m)) block_size (r,c,b) = bsize b \end{code}