Skip to content

Commit c4455a5

Browse files
Jess3Janezsparal
authored andcommitted
Added rust implementation of gaussian elimination (#183)
* Created matrix struct * Added row swapping method * The gaussian elimination part works now but back substitution is completely broken * Fixed back propagation * Fixed vector initialization and max finding * Changed getter and setter to index trait * Fixed a few typos and unneeded complexities * Cleaned up a bit and added an argument to the matrix constructor
1 parent 6c69955 commit c4455a5

File tree

2 files changed

+108
-0
lines changed

2 files changed

+108
-0
lines changed
Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
// submitted by jess 3jane
2+
3+
use std::cmp::min;
4+
use std::ops::{Index, IndexMut};
5+
6+
pub struct Matrix {
7+
rows: usize,
8+
cols: usize,
9+
data: Vec<f64>,
10+
}
11+
12+
impl Matrix {
13+
fn new(rows: usize, cols: usize, data: &[f64]) -> Matrix {
14+
Matrix {
15+
rows,
16+
cols,
17+
data: data.to_vec(),
18+
}
19+
}
20+
21+
fn swap_rows(&mut self, a: usize, b: usize) {
22+
for col in 0..self.cols {
23+
self.data.swap(a * self.cols + col, b * self.cols + col);
24+
}
25+
}
26+
}
27+
28+
impl Index<(usize, usize)> for Matrix {
29+
type Output = f64;
30+
fn index(&self, (row, col): (usize, usize)) -> &f64 {
31+
&self.data[row * self.cols + col]
32+
}
33+
}
34+
35+
impl IndexMut<(usize, usize)> for Matrix {
36+
fn index_mut(&mut self, (row, col): (usize, usize)) -> &mut f64 {
37+
&mut self.data[row * self.cols + col]
38+
}
39+
}
40+
41+
fn gaussian_elimination(a: &mut Matrix) {
42+
for k in 0..min(a.cols, a.rows) {
43+
// Step 1: find the maximum element for this column
44+
let mut max_row = k;
45+
let mut max_value = a[(k, k)].abs();
46+
for row in (k + 1)..a.rows {
47+
if max_value < a[(row, k)].abs() {
48+
max_value = a[(row, k)].abs();
49+
max_row = row;
50+
}
51+
}
52+
53+
// Check to make sure the matrix is good
54+
if a[(max_row, k)] == 0.0 {
55+
println!("Matrix is singular, aborting");
56+
return;
57+
}
58+
59+
// Step 2: swap the row with the highest value for this kumn to the top
60+
a.swap_rows(k, max_row);
61+
62+
// Loop over all remaining rows
63+
for i in k + 1..a.rows {
64+
// Step 3: find the fraction
65+
let fraction = a[(i, k)] / a[(k, k)];
66+
67+
// Loop through all columns for that row
68+
for j in (k + 1)..a.cols {
69+
// Step 4: re-evaluate each element
70+
a[(i, j)] -= a[(k, j)] * fraction;
71+
}
72+
73+
// Step 5: set lower elements to 0
74+
a[(i, k)] = 0.0;
75+
}
76+
}
77+
}
78+
79+
fn back_substitution(a: &Matrix) -> Vec<f64> {
80+
let mut soln = vec![0.0; a.rows];
81+
82+
soln[a.rows - 1] = a[(a.rows - 1, a.cols - 1)] / a[(a.rows - 1, a.cols - 2)];
83+
84+
for i in (0..a.rows - 1).rev() {
85+
let mut sum = 0.0;
86+
for j in (i..a.rows).rev() {
87+
sum += soln[j] * a[(i, j)];
88+
}
89+
soln[i] = (a[(i, a.cols - 1)] - sum) / a[(i, i)];
90+
}
91+
92+
soln
93+
}
94+
95+
fn main() {
96+
// The example matrix from the text
97+
let mut a = Matrix::new(
98+
3,
99+
4,
100+
&vec![2.0, 3.0, 4.0, 6.0, 1.0, 2.0, 3.0, 4.0, 3.0, -4.0, 0.0, 10.0],
101+
);
102+
103+
gaussian_elimination(&mut a);
104+
let soln = back_substitution(&a);
105+
println!("Solution: {:?}", soln);
106+
}

chapters/matrix_methods/gaussian_elimination/gaussian_elimination.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -281,6 +281,8 @@ The full code can be seen here:
281281
{% method %}
282282
{% sample lang="jl" %}
283283
[import, lang:"julia"](code/julia/gaussian_elimination.jl)
284+
{% sample lang="rs" %}
285+
[import, lang:"rust"](code/rust/gaussian_elimination.rs)
284286
{% endmethod %}
285287

286288

0 commit comments

Comments
 (0)