Skip to content

Commit 05639f3

Browse files
committed
Added code in chapter
1 parent 285c92f commit 05639f3

File tree

3 files changed

+87
-4
lines changed

3 files changed

+87
-4
lines changed

chapters/matrix_methods/gaussian_elimination/code/haskell/gaussianElimination.hs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,9 @@ swapRows r1 r2 m
1818
subRows :: Fractional a =>
1919
(Int, Int) -> (Int, Int) -> (Int, Int) -> Matrix a -> Matrix a
2020
subRows (r, c) (r1, rn) (c1, cn) m =
21-
accum (-) m [ ((i, j), m!(i, c) * m!(r,j)/m!(r, c))
22-
| i <- [r1..rn], j <- [c1..cn]
21+
accum (-) m [ ((i, j), m!(i, c) * m!(r,j) / m!(r, c))
22+
| i <- [r1..rn]
23+
, j <- [c1..cn]
2324
]
2425

2526
toEchelon :: (Fractional a, Ord a) => Matrix a -> Matrix a
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
import Data.Array
2+
import Data.List (intercalate, maximumBy)
3+
import Data.Function (on)
4+
import Data.Ratio
5+
6+
type Matrix a = Array (Int, Int) a
7+
8+
type Vector a = Array Int a
9+
10+
swapRows :: Int -> Int -> Matrix a -> Matrix a
11+
swapRows r1 r2 m
12+
| r1 == r2 = m
13+
| otherwise = m // concat [ [((r2, c), m!(r1, c)), ((r1, c), m!(r2, c))]
14+
| c <- [c1..cn]
15+
]
16+
where ((_, c1), (_, cn)) = bounds m
17+
18+
subRows :: Fractional a =>
19+
(Int, Int) -> (Int, Int) -> (Int, Int) -> Matrix a -> Matrix a
20+
subRows (r, c) (r1, rn) (c1, cn) m =
21+
accum (-) m [ ((i, j), m!(i, c) * m!(r,j) / m!(r, c))
22+
| i <- [r1..rn]
23+
, j <- [c1..cn]
24+
]
25+
26+
gaussianElimination :: (Fractional a, Ord a) => Matrix a -> Matrix a
27+
gaussianElimination mat = go (r1, c1) mat
28+
where
29+
((r1, c1), (rn, cn)) = bounds mat
30+
go (r, c) m
31+
| c == cn = m
32+
| pivot == 0 = go (r, c + 1) m
33+
| otherwise = go (r + 1, c + 1) $ subRows (r, c) (r+1, rn) (c, cn) m'
34+
where (target, pivot)
35+
= maximumBy (compare `on` abs . snd) [ (k, m!(k, c)) | k <- [r..rn]]
36+
m' = swapRows r target m
37+
38+
gaussJordan :: (Fractional a, Eq a) => Matrix a -> Matrix a
39+
gaussJordan mat = go (r1, c1) mat
40+
where
41+
((r1, c1), (rn, cn)) = bounds mat
42+
go (r, c) m
43+
| c == cn = m
44+
| m!(r, c) == 0 = go (r, c + 1) m
45+
| otherwise = go (r + 1, c + 1) $ subRows (r, c) (r1, r-1) (c, cn) m'
46+
where m' = accum (/) m [((r, j), m!(r, c)) | j <- [c..cn] ]
47+
48+
backSubstitution :: (Fractional a) => Matrix a -> Vector a
49+
backSubstitution m = sol
50+
where
51+
((r1, c1), (rn, cn)) = bounds m
52+
sol = listArray (r1,rn) [ (m!(r, cn) - sum' r) / m!(r, r) | r <- [r1..rn]]
53+
sum' r = sum [ m!(r, k) * sol!k | k <- [r+1..rn]]
54+
55+
printM :: (Show a) => Matrix a -> String
56+
printM m =
57+
let ((r1, c1), (rn, cn)) = bounds m
58+
in unlines [ intercalate "\t" [ show $ m!(r, c) | c <- [c1..cn] ]
59+
| r <- [r1..rn]
60+
]
61+
62+
printV :: (Show a) => Vector a -> String
63+
printV = unlines . map show . elems
64+
65+
main :: IO ()
66+
main = do
67+
let m = listArray ((1,1),(3,4)) [2,3,4,6,1,2,3,4,3,-4,0,10] :: Matrix (Ratio Int)
68+
putStrLn "Original Matrix:"
69+
putStrLn $ printM m
70+
putStrLn "Echelon form"
71+
putStrLn $ printM $ gaussianElimination m
72+
putStrLn "Reduced echelon form"
73+
putStrLn $ printM $ gaussJordan $ gaussianElimination m
74+
putStrLn "Solution from back substitution"
75+
putStrLn $ printV $ backSubstitution $ gaussianElimination m

contents/gaussian_elimination/gaussian_elimination.md

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,7 @@ $$
149149
\begin{array}{ccc|c}
150150
1 & 0 & 0 & \frac{18}{11} \\
151151
0 & 1 & 0 & \frac{-14}{11} \\
152-
0 & 0 & 1 & \frac{18}{11}
152+
0 & 0 & 1 & \frac{18}{11}
153153
\end{array}
154154
\right]
155155
$$
@@ -358,6 +358,8 @@ In code, this looks like:
358358
[import:13-44, lang:"c_cpp"](code/c/gaussian_elimination.c)
359359
{% sample lang="rs" %}
360360
[import:41-78, lang:"rust"](code/rust/gaussian_elimination.rs)
361+
{% sample lang="hs" %}
362+
[import:10-36, lang:"haskell"](code/haskell/gaussianElimination.hs)
361363
{% endmethod %}
362364

363365
Now, to be clear: this algorithm creates an upper-triangular matrix.
@@ -390,6 +392,8 @@ This code does not exist yet in C, so here's Julia code (sorry for the inconveni
390392
{% sample lang="rs" %}
391393
This code does not exist yet in rust, so here's Julia code (sorry for the inconvenience)
392394
[import:70-96, lang:"julia"](code/julia/gaussian_elimination.jl)
395+
{% sample lang="hs" %}
396+
[import:38-46, lang:"haskell"](code/haskell/gaussianElimination.hs)
393397
{% endmethod %}
394398

395399
## Back-substitution
@@ -418,6 +422,8 @@ In code, this involves keeping a rolling sum of all the values we substitute in
418422
[import:46-58, lang:"c_cpp"](code/c/gaussian_elimination.c)
419423
{% sample lang="rs" %}
420424
[import:79-94, lang:"rust"](code/rust/gaussian_elimination.rs)
425+
{% sample lang="hs" %}
426+
[import:48-53, lang:"haskell"](code/haskell/gaussianElimination.hs)
421427
{% endmethod %}
422428

423429
## Conclusions
@@ -438,6 +444,8 @@ As for what's next... Well, we are in for a treat! The above algorithm clearly h
438444
[import, lang:"c_cpp"](code/c/gaussian_elimination.c)
439445
{% sample lang="rs" %}
440446
[import, lang:"rust"](code/rust/gaussian_elimination.rs)
447+
{% sample lang="hs" %}
448+
[import, lang:"haskell"](code/haskell/gaussianElimination.hs)
441449
{% endmethod %}
442450

443451

@@ -463,4 +471,3 @@ $$
463471
\newcommand{\bfomega}{\boldsymbol{\omega}}
464472
\newcommand{\bftau}{\boldsymbol{\tau}}
465473
$$
466-

0 commit comments

Comments
 (0)