Guest User

Untitled

a guest
May 27th, 2018
98
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 9.83 KB | None | 0 0
  1. --module MI where
  2.  
  3. import HUnit
  4. import Control.Arrow
  5. import Monad
  6.  
  7. data Frac = Frac Integer Integer
  8. -- Frac Frac
  9. -- | FracInt Int
  10. -- | FracSqrt Int
  11.  
  12. instance Show Frac where
  13. show (Frac a 1) = show a
  14. show (Frac 0 _) = "0"
  15. show (Frac a b) = show a ++ "/" ++ show b
  16. -- show (FracInt 0) = "0"
  17. -- show (FracInt a) = show a
  18. -- show (FracSqrt a) = "[a]"
  19.  
  20. instance Eq Frac where
  21. (==) (Frac a b) (Frac a' b') = a == a' && b == b'
  22. -- (==) (FracInt a) (FracInt b) = a == b
  23. -- (==) (FracInt _) (FracSqrt _) = False
  24. -- (==) a@(FracSqrt _) b@(FracInt _) = b == a
  25. -- (==) (FracSqrt a) (FracSqrt b) = a == b
  26.  
  27. instance Num Frac where
  28. (+) (Frac a b) (Frac a' b') = (a*b'+b*a')%(b'*b)
  29. -- (+) (FracInt a) (FracInt b) = FracInt (a + b)
  30. -- (+) (FracSqrt a) (FracSqrt b) = error "undefined"
  31. -- (+) (FracInt a) (FracSqrt b) = error "undefined"
  32.  
  33. (*) (Frac a b) (Frac a' b') = (a*a')%(b*b')
  34. -- (*) (FracInt a) (FracInt b) = FracInt (a * b)
  35. -- (*) (FracInt a) b@(FracSqrt _) = (FracSqrt (a*a))*b
  36. -- (*) a@(FracSqrt _) b@(FracInt _) = b * a
  37. -- (*) (FracSqrt a) (FracSqrt b) = FracSqrt (a * b)
  38.  
  39. abs (Frac a b) = (abs a)%(abs b)
  40. -- abs (FracInt a) = FracInt $ abs a
  41. -- abs a@(FracSqrt _) = a
  42.  
  43. fromInteger = (%1)
  44.  
  45. signum (Frac a b) = fromInteger ((signum a)*(signum b))
  46. -- signum (FracInt a) = FracInt $ signum a
  47. -- signum (FracSqrt _) = 1
  48.  
  49. negate (Frac a b) = (-a)%b
  50. -- negate (FracInt a) = FracInt $ negate a
  51. -- negate a@(FracSqrt _) = Frac a (FracInt (-1))
  52.  
  53. data Matrix = Matrix [[Frac]]
  54. deriving Show
  55.  
  56. --instance Show Matrix where
  57. -- show (Matrix rows) = concatMap (\cells -> concatMap show cells) rows
  58.  
  59. instance Eq Matrix where
  60. (==) (Matrix rows) (Matrix rows') =
  61. foldl (&&) True (zipWith (==) rows rows')
  62.  
  63. dim :: Matrix -> (Int, Int)
  64. dim (Matrix []) = (0,0)
  65. dim (Matrix rows) = ((length rows), (length (rows!!0)))
  66.  
  67. dimRow :: Matrix -> Int
  68. dimRow = length . mUnpack
  69.  
  70. dimCol :: Matrix -> Int
  71. dimCol (Matrix []) = 0
  72. dimCol m = (length . (!!0) . mUnpack) m
  73.  
  74. sameDim :: Matrix -> Matrix -> Bool
  75. sameDim a b = (dim a) == (dim b)
  76.  
  77. transpose :: Matrix -> Matrix
  78. transpose = Matrix . (foldr (zipWith (:)) (repeat [])) . mUnpack
  79.  
  80. instance Num Matrix where
  81. (+) a b | not $ sameDim a b =
  82. error ("+: Matrices must have the same dimension, given "
  83. ++ show a ++ show b)
  84. (+) (Matrix rows) (Matrix rows') =
  85. Matrix $ map (uncurry $ zipWith (+))
  86. (zip rows rows')
  87. (-) a b | not $ sameDim a b =
  88. error ("-: Matrices must have the same dimension, given "
  89. ++ show a ++ show b)
  90. (-) a b = a + (negate b)
  91.  
  92. (*) m1 m2 =
  93. if (fst $ dim m1) == 1 && (snd $ dim m2) == 1 then
  94. Matrix [[sum $ zipWith (*)
  95. ((mUnpack m1)!!0)
  96. ((mUnpack $ transpose m2)!!0)]]
  97. else
  98. mRowMap (\row -> mColMap ((mRowHead row) *) m2) m1
  99. abs = error "undefined operation"
  100. fromInteger i = Matrix [[fromInteger i]]
  101. signum = error "undefined operation"
  102. negate (Matrix rows) = Matrix (map (\cells -> map negate cells) rows)
  103.  
  104. (%) :: Integer -> Integer -> Frac
  105. (%) _ 0 = error "Divisor can't be 0"
  106. (%) a b =
  107. Frac (sig*((abs a) `div` g)) ((abs b) `div` g)
  108. where g = gcd a b
  109. sig = (signum a)*(signum b)
  110.  
  111. --matrix' :: [[Frac]]
  112. --matrix' = [[1,2,3],
  113. -- [4,5,6],
  114. -- [7,8,9]]
  115. --
  116. --rh :: [[Frac]]
  117. --rh = [[1,0,0],
  118. -- [0,1,0],
  119. -- [0,0,1]]
  120. --
  121. scale :: Frac -> Matrix -> Matrix
  122. scale n m = Matrix $ map (map (*n)) (mUnpack m)
  123.  
  124. cDiv :: Frac -> Frac -> Frac
  125. cDiv (Frac a b) (Frac a' b') = (a*b')%(b*a')
  126.  
  127. -- Gets a row matrix out of a matrix
  128. mRow :: Int -> Matrix -> Matrix
  129. mRow i (Matrix rows) = Matrix [rows!!i]
  130.  
  131. mCell :: (Int,Int) -> Matrix -> Frac
  132. mCell (row,col) (Matrix rows) = rows!!row!!col
  133.  
  134. emptyMatrix :: Matrix
  135. emptyMatrix = Matrix [[]]
  136.  
  137. mColAppend :: Matrix -> Matrix -> Matrix
  138. mColAppend m1 m2 | m2 == emptyMatrix = m1
  139. mColAppend m1 m2 | m1 == emptyMatrix = m2
  140. mColAppend (Matrix r1) (Matrix r2) = Matrix $ zipWith (++) r1 r2
  141.  
  142. mRowAppend :: Matrix -> Matrix -> Matrix
  143. mRowAppend m1 m2 | m2 == emptyMatrix = m1
  144. mRowAppend m1 m2 | m1 == emptyMatrix = m2
  145. mRowAppend (Matrix r1) (Matrix r2) = Matrix (r1++r2)
  146.  
  147. mUnpack :: Matrix -> [[Frac]]
  148. mUnpack (Matrix rows) = rows
  149.  
  150. mRowHead :: Matrix -> Matrix
  151. mRowHead = mRow 0
  152.  
  153. mRowTail :: Matrix -> Matrix
  154. mRowTail = Matrix . tail . mUnpack
  155.  
  156. mColHead :: Matrix -> Matrix
  157. mColHead = Matrix . (map (take 1)) . mUnpack
  158.  
  159. mColTail :: Matrix -> Matrix
  160. mColTail = Matrix . (map tail) . mUnpack
  161.  
  162. mRowMap :: (Matrix -> Matrix) -> Matrix -> Matrix
  163. mRowMap f (Matrix rows) =
  164. foldl mRowAppend emptyMatrix
  165. (map (\row -> f (Matrix [row])) rows)
  166.  
  167. mColMap :: (Matrix -> Matrix) -> Matrix -> Matrix
  168. mColMap = onTranspose . mRowMap . onTranspose
  169. where onTranspose f = transpose . f . transpose
  170. -- where onTranspose = (transpose .) . (. transpose)
  171. -- Alternative:
  172. --mColMap f m = transpose $ mRowMap (transpose.f.transpose) (transpose m)
  173. -- Alternative:
  174. -- if mColHead m == emptyMatrix then
  175. -- emptyMatrix
  176. -- else
  177. -- (f $ mColHead m) `mColAppend` (mColMap f (mColTail m))
  178.  
  179. (-|-) :: Matrix -> Matrix -> Frac
  180. (-|-) m1 m2 | not $ sameDim m1 m2 = error "Matrices must both be mx1"
  181. (-|-) m1 _ | (snd $ dim m1) /= 1 = error "Matrices must be mx1"
  182. (-|-) m1 m2 =
  183. sum $ zipWith (*) (f m1) (f m2)
  184. where f m = (mUnpack $ transpose m) !! 0
  185.  
  186. identityMatrix :: Int -> Matrix
  187. identityMatrix 0 = Matrix [[]]
  188. identityMatrix n =
  189. mRowAppend
  190. (Matrix [1 : replicate (n-1) 0])
  191. (mColAppend
  192. (Matrix $ replicate (n-1) [0])
  193. (identityMatrix (n-1)))
  194.  
  195. --identityMatrix n =
  196. -- foldl
  197. -- (\m n ->
  198. -- (mRowAppend
  199. -- (Matrix [1 : replicate (n-1) [0]])
  200. -- (mColAppend
  201. -- (Matrix $ replicate (n-1) [0])
  202. -- m)))
  203. -- Matrix [[]]
  204. -- (reverse [0..n])
  205.  
  206. flipMatrix :: Matrix -> Matrix
  207. flipMatrix m = Matrix $ reverse (map reverse (mUnpack m))
  208.  
  209. simpleGauss :: Matrix -> Matrix
  210. simpleGauss m@(Matrix [_]) = m
  211. simpleGauss m =
  212. let m' = mRowMap
  213. (\r -> (mColTail r) -
  214. (scale ((mCell (0,0) r) `cDiv` (mCell (0,0) m))
  215. (mColTail $ mRowHead m)))
  216. (mRowTail m) in
  217. (mRowAppend
  218. (mRowHead m)
  219. (mColAppend
  220. (Matrix $ replicate (dimCol m) [0])
  221. (simpleGauss m')))
  222.  
  223.  
  224. splitCol :: Matrix -> (Matrix,Matrix)
  225. splitCol m@(Matrix rows) =
  226. let dim' = ((dimCol m) `div` 2) in
  227. join (***) Matrix
  228. (map (take dim') rows,
  229. map (drop dim') rows)
  230.  
  231. scaleToOne :: Matrix -> Matrix
  232. scaleToOne m = mRowMap (\row -> scale (1 `cDiv` (firstNonZero row)) row) m
  233. where firstNonZero = head . (filter (/=0)) . head . mUnpack
  234.  
  235.  
  236. invertMatrix :: Matrix -> Matrix
  237. invertMatrix m =
  238. let m' = mColAppend m (identityMatrix $ dimRow m)
  239. aux :: Matrix -> Matrix
  240. aux = snd . splitCol . scaleToOne . flipAppend . splitCol . simpleGauss . flipAppend . splitCol . simpleGauss
  241. flipAppend :: (Matrix, Matrix) -> Matrix
  242. flipAppend m'' = uncurry mColAppend (join (***) flipMatrix m'') in
  243. aux m'
  244.  
  245. tests :: Test
  246. tests = test [
  247. "/" ~: "1/4"
  248. ~=? (show (1%4)),
  249. "+" ~: "1"
  250. ~=? (show ((1%2) + (1%2))),
  251. "sig" ~: "-1/3"
  252. ~=? (show ((-1)%3)),
  253. "sig2" ~: "-1/3"
  254. ~=? (show (1%(-3))),
  255. "div" ~: "1/3"
  256. ~=? (show (5%15)),
  257. "dim" ~: (show (2::Int,3::Int))
  258. ~=? (show $ dim $ Matrix [[1, 2, 3],[1, 2, 3]]),
  259. "dim0" ~: (show (0::Int,0::Int))
  260. ~=? (show $ dim $ Matrix []),
  261. "matrix +" ~: (show $ Matrix [[5,7,9],[7,7,7]])
  262. ~=? (show $ (Matrix [[1,2,3],[3,2,1]]) +
  263. (Matrix [[4,5,6], [4,5,6]])),
  264. "matrix negate" ~: (show $ Matrix [[1,-2],[-3,4]])
  265. ~=? (show $ negate (Matrix [[-1,2],[3,-4]])),
  266. "scale" ~: (show $ Matrix [[2,4],[6,8]])
  267. ~=? (show $ scale 2 (Matrix [[1,2],[3,4]])),
  268. "cDiv" ~: (show (3%1))
  269. ~=? (show ((3%1) `cDiv` (1%1))),
  270. "mColTail" ~: (show $ Matrix [[2,3],[5,6]])
  271. ~=? (show $ mColTail $ Matrix [[1,2,3],[4,5,6]]),
  272. "*" ~: (show $ Matrix [[19,22],[43,50]])
  273. ~=? (show ((Matrix [[1,2],[3,4]]) * (Matrix [[5,6],[7,8]]))),
  274. "transpose" ~: (show $ Matrix [[1,2],[3,4]])
  275. ~=? (show $ transpose $ Matrix [[1,3],[2,4]]),
  276. --
  277. -- / 1 2 \ + / 1 1 \ = / 2 3 \
  278. -- \ 3 4 / + \ 2 2 / = \ 5 6 /
  279. "mColMap" ~: (show $ Matrix [[2,3],[5,6]])
  280. ~=? (show $ mColMap (+(Matrix [[1],[2]]))
  281. (Matrix [[1,2],[3,4]])),
  282.  
  283. "scalar" ~: "11"
  284. ~=? (show $ (Matrix [[1],[2]]) -|- (Matrix [[3],[4]])),
  285.  
  286. "identityMatrix" ~: (show $ Matrix [[1,0,0],[0,1,0],[0,0,1]])
  287. ~=? (show $ identityMatrix 3),
  288. "invertMatrix" ~: (show $ Matrix [[-1,1%3,1%3],[0,1%3,-2%3],[2%3,-1%3,1%3]])
  289. ~=? (show $ invertMatrix $ Matrix
  290. [[1,2,3],[4,5,6],[2,1,3]]),
  291.  
  292. "flipMatrix" ~: (show $ Matrix [[6,5,4],[3,2,1]])
  293. ~=? (show $ flipMatrix $ Matrix [[1,2,3],[4,5,6]]),
  294. "scaleToOne" ~: (show $ Matrix [[0,1,2%3],[1,3,8]])
  295. ~=? (show $ scaleToOne $ Matrix [[0,3,2], [1,3,8]])
  296. ]
  297.  
  298. --m = Matrix [[1,2,3],[4,5,6],[2,1,3]]
  299.  
  300.  
  301. main :: IO Counts
  302. main =
  303. runTestTT tests;
Add Comment
Please, Sign In to add comment