Matrices in Haskell II

What’s the use of a matrix if you can’t find its characteristic polynomial? So, a very primitive haskell type for polynomials:

 
import MyPermutations
import MyMatrices
 
type Polynomial = [Int]
 
polySum :: Polynomial -> Polynomial -> Polynomial
polySum p q = if (length p >= length q) 
	then zipWith (+) p (q ++ [0,0..])
	else zipWith (+) q (p ++ [0,0..])
 
polyProduct :: Polynomial -> Polynomial -> Polynomial
polyProduct p q = map (polyProduct' p q) [0..((length p) + (length q) - 2)]
 
polyProduct' :: Polynomial -> Polynomial -> Int -> Int
polyProduct' p q k = sum [ ((p++[0,0..])!!i) * ((q++[0,0..])!!(k-i)) | 
                                         i <- [0..k] ]
 
.

Its not too much effort to generalize matrices with integer entries to matrices with polynomial entries:

 
type MatrixPoly = [[Polynomial]]
 
polyMatTranspose :: MatrixPoly -> MatrixPoly
polyMatTranspose ([]:xs) = []
polyMatTranspose xs = (map head xs):(polyMatTranspose (map tail xs))
 
polyMatProduct :: MatrixPoly -> MatrixPoly -> MatrixPoly
polyMatProduct m1 m2 = polyMatProduct' m1 (polyMatTranspose m2)
 
polyMatProduct' :: MatrixPoly -> MatrixPoly -> MatrixPoly
polyMatProduct' [] m = []
polyMatProduct' (r:rs) m = (polyFindRow' r m):(polyMatProduct' rs m)
 
polyFindRow' :: [Polynomial] -> MatrixPoly -> [Polynomial]
polyFindRow' r m = map (foldr (polySum) [0]) (map (zipWith (polyProduct) r) m)
 
polyDeterminant :: MatrixPoly -> Polynomial
polyDeterminant m = foldr (polySum) [0] (map (polyDetTerm m) 
                                           (allPermutedLists (length m)))
 
polyDetTerm :: MatrixPoly -> PermutedList -> Polynomial
polyDetTerm m p = map (\x -> (-1)^(sign p) * x) (polyDetTerm' m p)
 
polyDetTerm' :: MatrixPoly -> PermutedList -> Polynomial
polyDetTerm' _ [] = [1]
polyDetTerm' (m:ms) (p:ps) = polyProduct (m!!(p-1)) (polyDetTerm' ms ps)
 
polyMinor :: MatrixPoly -> [Int] -> [Int] -> MatrixPoly
polyMinor m rows cols = [ [ (m!!(i-1))!!(j-1) | j <- cols ] | i <- rows ] 
 
almostPolyMatInverse :: MatrixPoly -> MatrixPoly
almostPolyMatInverse m =  [ [ polyDeterminant $ polyMinor m (foo n i) (foo n j) 
                                        |  i <- [1..n] ] | j <- [1..n]]
	where n = length m
 
.

Finally:

 
charpoly :: Matrix -> Polynomial
charpoly m = polyDeterminant $ matPolyAdd (matToPolyMat m) 
      (diagonalPolyMat (take (length m) (repeat [0,-1])))
 
matToPolyMat :: Matrix -> MatrixPoly
matToPolyMat = map (map (\x -> [x])) 
 
matPolyAdd :: MatrixPoly -> MatrixPoly -> MatrixPoly
matPolyAdd = zipWith (zipWith (polySum))
 
diagonalPolyMat :: [Polynomial] -> MatrixPoly
diagonalPolyMat xs = diagonalPolyMat' (length xs) 1 xs
 
diagonalPolyMat' :: Int -> Int -> [Polynomial] -> MatrixPoly
diagonalPolyMat' _ _ [] = []
diagonalPolyMat' n k (x:xs) = ((take (k-1) (repeat [0])) ++ [x] 
         ++ (take (n-k) (repeat [0]))):(diagonalPolyMat' n (k+1) xs)
 
.

Leave a Reply