Skip to content

Instantly share code, notes, and snippets.

@jdoiwork
Last active August 28, 2019 17:15
Show Gist options
  • Save jdoiwork/6a44b783ebe1240f3723ac93bd1a35af to your computer and use it in GitHub Desktop.
Save jdoiwork/6a44b783ebe1240f3723ac93bd1a35af to your computer and use it in GitHub Desktop.
import Data.Array
import System.Random
import Data.Ratio ((%), Ratio)
type MatrixIndex = (Int, Int)
type MatrixElement = Rational
type MatrixValue = Array MatrixIndex MatrixElement
newtype MatrixDimension = MatrixDimension Int deriving (Show)
data Matrix = Matrix
{ n :: !MatrixDimension
, mat :: !MatrixValue
} deriving (Show)
randomMatrix :: MatrixDimension -> IO Matrix
randomMatrix n@(MatrixDimension n') = Matrix n <$> mat
where
mat :: IO MatrixValue
mat = listArray idx <$> values
idx :: (MatrixIndex, MatrixIndex)
idx = ((1, 1), (n', n'))
values = take (n' ^ 2) <$> randomNumbers
randomNumbers :: IO [Rational]
randomNumbers = do
g <- getStdGen
return $ map ratio $ randomRs (1, 9) g
where
ratio n = n % 1
det :: Matrix -> Rational
det m = go 1 m
where
go a m'@(Matrix (MatrixDimension 1) mat) = a * leftTop m'
go a m'@(Matrix (MatrixDimension n) mat) = go (a * leftTop m') (reduceDimension m')
leftTop :: Matrix -> Rational
leftTop (Matrix _ mat )= mat ! (1, 1)
reduceDimension :: Matrix -> Matrix
reduceDimension m@(Matrix (MatrixDimension n) _) = Matrix (MatrixDimension (n-1)) mat
where
mat = leftZero $ normalizeTop m
normalizeTop :: Matrix -> Matrix
normalizeTop m@(Matrix dim@(MatrixDimension n) mat) = Matrix dim mat'
where
mat' = accum (/) mat $ [((1, x), lt) | x <- [1..n]]
lt = leftTop m
leftZero :: Matrix -> MatrixValue
leftZero (Matrix (MatrixDimension n) mat) = listArray ((1, 1) ,(n', n')) $ zipWith f xs ys
where
n' = n - 1
f (a, x) y = x - a * y
xs = [(mat ! (row, 1), mat ! (row, col)) | row <- [2..n], col <- [2..n]]
ys = concat $ take n' $ repeat [mat ! (1, col) | col <- [2..n]]
leftZero' (Matrix (MatrixDimension n) mat) = ys
where
n' = n - 1
f (a, x) y = x - a * y
xs = [(mat ! (row, 1), mat ! (row, col)) | row <- [2..n], col <- [2..n]]
ys = concat $ repeat [mat ! (1, col) | col <- [2..n]]
main :: IO ()
main = do
ns <- randomMatrix $ MatrixDimension 2
print ""
print ns
print $ det ns
-- print $ normalizeTop ns
-- print $ leftZero $ normalizeTop ns
print "Det Matrix"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment