From 57ca40e15408c5e9e745903850e9cefe51bd076d Mon Sep 17 00:00:00 2001 From: Jess 3Jane Date: Thu, 28 Jun 2018 05:25:21 -0400 Subject: [PATCH 1/8] Created matrix struct --- .../code/rust/gaussian_elimination.rs | 48 +++++++++++++++++++ 1 file changed, 48 insertions(+) create mode 100644 chapters/matrix_methods/gaussian_elimination/code/rust/gaussian_elimination.rs diff --git a/chapters/matrix_methods/gaussian_elimination/code/rust/gaussian_elimination.rs b/chapters/matrix_methods/gaussian_elimination/code/rust/gaussian_elimination.rs new file mode 100644 index 000000000..550869d53 --- /dev/null +++ b/chapters/matrix_methods/gaussian_elimination/code/rust/gaussian_elimination.rs @@ -0,0 +1,48 @@ +use std::fmt; + +pub struct Matrix { + rows: usize, + cols: usize, + data: Vec, +} + +impl Matrix { + fn new(rows: usize, cols: usize) -> Matrix { + let mut data = Vec::with_capacity(rows*cols); + for _ in 0..rows*cols { data.push(0.0); } + Matrix { rows, cols, data } + } + + fn get(&self, row: usize, col: usize) -> f64 { + self.data[row * self.cols + col] + } + + fn set(&mut self, row: usize, col: usize, value: f64) { + self.data[row * self.cols + col] = value; + } +} + +impl fmt::Display for Matrix { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + for row in 0..self.rows { + if row != 0 { writeln!(f, "")?; } + for col in 0..self.cols { + if col != 0 { write!(f, " ")?; } + write!(f, "{}", self.get(row, col))?; + } + } + Ok(()) + } +} + +fn main() { + let mut mat = Matrix::new(3,3); + + for i in 0..3 { + for j in 0..3 { + mat.set(i, j, (i*j) as f64); + } + } + + println!("{}", mat); +} From e4b5b53d1e41ab887901075fd0a6b11414e6488a Mon Sep 17 00:00:00 2001 From: Jess 3Jane Date: Thu, 28 Jun 2018 05:30:01 -0400 Subject: [PATCH 2/8] Added row swapping method --- .../code/rust/gaussian_elimination.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/chapters/matrix_methods/gaussian_elimination/code/rust/gaussian_elimination.rs b/chapters/matrix_methods/gaussian_elimination/code/rust/gaussian_elimination.rs index 550869d53..26a3a84da 100644 --- a/chapters/matrix_methods/gaussian_elimination/code/rust/gaussian_elimination.rs +++ b/chapters/matrix_methods/gaussian_elimination/code/rust/gaussian_elimination.rs @@ -20,6 +20,12 @@ impl Matrix { fn set(&mut self, row: usize, col: usize, value: f64) { self.data[row * self.cols + col] = value; } + + fn swap_rows(&mut self, a: usize, b: usize) { + for col in 0..self.cols { + self.data.swap(a * self.cols + col, b * self.cols + col); + } + } } impl fmt::Display for Matrix { @@ -44,5 +50,7 @@ fn main() { } } + mat.swap_rows(0, 1); + println!("{}", mat); } From bf264c20b2f539da794637ddf45c11221b078e38 Mon Sep 17 00:00:00 2001 From: Jess 3Jane Date: Thu, 28 Jun 2018 10:51:08 -0400 Subject: [PATCH 3/8] The gaussian elimination part works now but back substitution is completely broken --- .../code/rust/gaussian_elimination.rs | 79 +++++++++++++++++-- 1 file changed, 71 insertions(+), 8 deletions(-) diff --git a/chapters/matrix_methods/gaussian_elimination/code/rust/gaussian_elimination.rs b/chapters/matrix_methods/gaussian_elimination/code/rust/gaussian_elimination.rs index 26a3a84da..55becbcd0 100644 --- a/chapters/matrix_methods/gaussian_elimination/code/rust/gaussian_elimination.rs +++ b/chapters/matrix_methods/gaussian_elimination/code/rust/gaussian_elimination.rs @@ -1,4 +1,5 @@ use std::fmt; +use std::cmp::min; pub struct Matrix { rows: usize, @@ -34,23 +35,85 @@ impl fmt::Display for Matrix { if row != 0 { writeln!(f, "")?; } for col in 0..self.cols { if col != 0 { write!(f, " ")?; } - write!(f, "{}", self.get(row, col))?; + write!(f, "{:3}", self.get(row, col))?; } } Ok(()) } } -fn main() { - let mut mat = Matrix::new(3,3); +fn gaussian_elimination(a: &mut Matrix) { + for k in 0..min(a.cols, a.rows) { + // Step 1: find the maximum element for this kumn + let mut max_row = 0; + let mut max_value = 0.0; + for row in k..a.rows { + if max_value < a.get(row, k).abs() { + max_value = a.get(row, k).abs(); + max_row = row; + } + } + + // Check to make sure the matrix is good + if a.get(max_row, k) == 0.0 { + println!("Matrix is singular, aborting"); + return; + } + + // Step 2: swap the row with the highest value for this kumn to the top + a.swap_rows(k, max_row); + println!("{}:\n{}", k, a); + + // Loop over all remaining rows + for i in k+1..a.rows { + // Step 3: find the fraction + let fraction = a.get(i, k)/a.get(k, k); + + // Loop through all columns for that row + for j in (k+1)..a.cols { + // Step 4: re-evaluate each element + let val = a.get(i, j) - a.get(k, j)*fraction; + a.set(i, j, val); + } - for i in 0..3 { - for j in 0..3 { - mat.set(i, j, (i*j) as f64); + // Step 5: set lower elements to 0 + a.set(i, k, 0.0); } } +} + +fn back_substitution(a: &Matrix) -> Vec { + let mut soln = Vec::with_capacity(a.rows); + for _ in 0..a.rows { soln.push(0.0); } + + soln[a.rows - 1] = a.get(a.rows - 1, a.cols - 1) / a.get(a.rows - 1, a.cols - 2); + + for i in (0..a.rows - 2).rev() { + let mut sum = 0.0; + for j in (i..a.rows - 1).rev() { + sum += soln[j] * a.get(i, j); + println!("{}, {}", i, j); + } + soln[i] = (a.get(i, a.cols - 1) - sum) / a.get(i,i); + } + + soln +} + +fn main() { + // The example matrix from the text + let mut a = Matrix::new(3,4); + a.data = 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,]; + + println!("Original:"); + println!("{}", a); - mat.swap_rows(0, 1); + gaussian_elimination(&mut a); + println!("Reduced:"); + println!("{}", a); - println!("{}", mat); + let soln = back_substitution(&a); + println!("Solution: {:?}", soln); } From dc4fe0a8d755c633694233a6b61335add5937fed Mon Sep 17 00:00:00 2001 From: Jess 3Jane Date: Sat, 30 Jun 2018 01:21:16 -0400 Subject: [PATCH 4/8] Fixed back propagation --- .../code/rust/gaussian_elimination.rs | 28 +++---------------- .../gaussian_elimination.md | 2 ++ 2 files changed, 6 insertions(+), 24 deletions(-) diff --git a/chapters/matrix_methods/gaussian_elimination/code/rust/gaussian_elimination.rs b/chapters/matrix_methods/gaussian_elimination/code/rust/gaussian_elimination.rs index 55becbcd0..28d85fda6 100644 --- a/chapters/matrix_methods/gaussian_elimination/code/rust/gaussian_elimination.rs +++ b/chapters/matrix_methods/gaussian_elimination/code/rust/gaussian_elimination.rs @@ -1,4 +1,5 @@ -use std::fmt; +// submitted by jess 3jane + use std::cmp::min; pub struct Matrix { @@ -29,19 +30,6 @@ impl Matrix { } } -impl fmt::Display for Matrix { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - for row in 0..self.rows { - if row != 0 { writeln!(f, "")?; } - for col in 0..self.cols { - if col != 0 { write!(f, " ")?; } - write!(f, "{:3}", self.get(row, col))?; - } - } - Ok(()) - } -} - fn gaussian_elimination(a: &mut Matrix) { for k in 0..min(a.cols, a.rows) { // Step 1: find the maximum element for this kumn @@ -62,7 +50,6 @@ fn gaussian_elimination(a: &mut Matrix) { // Step 2: swap the row with the highest value for this kumn to the top a.swap_rows(k, max_row); - println!("{}:\n{}", k, a); // Loop over all remaining rows for i in k+1..a.rows { @@ -88,11 +75,10 @@ fn back_substitution(a: &Matrix) -> Vec { soln[a.rows - 1] = a.get(a.rows - 1, a.cols - 1) / a.get(a.rows - 1, a.cols - 2); - for i in (0..a.rows - 2).rev() { + for i in (0..a.rows - 1).rev() { let mut sum = 0.0; - for j in (i..a.rows - 1).rev() { + for j in (i..a.rows).rev() { sum += soln[j] * a.get(i, j); - println!("{}, {}", i, j); } soln[i] = (a.get(i, a.cols - 1) - sum) / a.get(i,i); } @@ -107,13 +93,7 @@ fn main() { 1.0, 2.0, 3.0, 4.0, 3.0, -4.0, 0.0, 10.0,]; - println!("Original:"); - println!("{}", a); - gaussian_elimination(&mut a); - println!("Reduced:"); - println!("{}", a); - let soln = back_substitution(&a); println!("Solution: {:?}", soln); } diff --git a/chapters/matrix_methods/gaussian_elimination/gaussian_elimination.md b/chapters/matrix_methods/gaussian_elimination/gaussian_elimination.md index 877bd0538..d0d4c010e 100644 --- a/chapters/matrix_methods/gaussian_elimination/gaussian_elimination.md +++ b/chapters/matrix_methods/gaussian_elimination/gaussian_elimination.md @@ -281,6 +281,8 @@ The full code can be seen here: {% method %} {% sample lang="jl" %} [import, lang:"julia"](code/julia/gaussian_elimination.jl) +{% sample lang="rs" %} +[import, lang:"rust"](code/rust/gaussian_elimination.rs) {% endmethod %} From 165cbe5df509a1e7961b83817203c9a27ce170e6 Mon Sep 17 00:00:00 2001 From: Jess 3Jane Date: Sat, 30 Jun 2018 17:26:43 -0400 Subject: [PATCH 5/8] Fixed vector initialization and max finding --- .../code/rust/gaussian_elimination.rs | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/chapters/matrix_methods/gaussian_elimination/code/rust/gaussian_elimination.rs b/chapters/matrix_methods/gaussian_elimination/code/rust/gaussian_elimination.rs index 28d85fda6..2fe7694cc 100644 --- a/chapters/matrix_methods/gaussian_elimination/code/rust/gaussian_elimination.rs +++ b/chapters/matrix_methods/gaussian_elimination/code/rust/gaussian_elimination.rs @@ -10,9 +10,7 @@ pub struct Matrix { impl Matrix { fn new(rows: usize, cols: usize) -> Matrix { - let mut data = Vec::with_capacity(rows*cols); - for _ in 0..rows*cols { data.push(0.0); } - Matrix { rows, cols, data } + Matrix { rows, cols, data: vec![0.0; rows * cols] } } fn get(&self, row: usize, col: usize) -> f64 { @@ -33,9 +31,9 @@ impl Matrix { fn gaussian_elimination(a: &mut Matrix) { for k in 0..min(a.cols, a.rows) { // Step 1: find the maximum element for this kumn - let mut max_row = 0; - let mut max_value = 0.0; - for row in k..a.rows { + let mut max_row = k; + let mut max_value = a.get(k, k).abs(); + for row in (k+1)..a.rows { if max_value < a.get(row, k).abs() { max_value = a.get(row, k).abs(); max_row = row; @@ -70,8 +68,7 @@ fn gaussian_elimination(a: &mut Matrix) { } fn back_substitution(a: &Matrix) -> Vec { - let mut soln = Vec::with_capacity(a.rows); - for _ in 0..a.rows { soln.push(0.0); } + let mut soln = vec![0.0; a.rows]; soln[a.rows - 1] = a.get(a.rows - 1, a.cols - 1) / a.get(a.rows - 1, a.cols - 2); From 931e18b4841741ed0935529bd5381d32ad081e15 Mon Sep 17 00:00:00 2001 From: Jess 3Jane Date: Sat, 30 Jun 2018 17:38:28 -0400 Subject: [PATCH 6/8] Changed getter and setter to index trait --- .../code/rust/gaussian_elimination.rs | 45 +++++++++++-------- 1 file changed, 26 insertions(+), 19 deletions(-) diff --git a/chapters/matrix_methods/gaussian_elimination/code/rust/gaussian_elimination.rs b/chapters/matrix_methods/gaussian_elimination/code/rust/gaussian_elimination.rs index 2fe7694cc..20d2bfce2 100644 --- a/chapters/matrix_methods/gaussian_elimination/code/rust/gaussian_elimination.rs +++ b/chapters/matrix_methods/gaussian_elimination/code/rust/gaussian_elimination.rs @@ -1,6 +1,7 @@ // submitted by jess 3jane use std::cmp::min; +use std::ops::{IndexMut, Index}; pub struct Matrix { rows: usize, @@ -13,14 +14,6 @@ impl Matrix { Matrix { rows, cols, data: vec![0.0; rows * cols] } } - fn get(&self, row: usize, col: usize) -> f64 { - self.data[row * self.cols + col] - } - - fn set(&mut self, row: usize, col: usize, value: f64) { - self.data[row * self.cols + col] = value; - } - fn swap_rows(&mut self, a: usize, b: usize) { for col in 0..self.cols { self.data.swap(a * self.cols + col, b * self.cols + col); @@ -28,20 +21,35 @@ impl Matrix { } } +impl Index<(usize, usize)> for Matrix { + type Output = f64; + fn index<'a>(&'a self, index: (usize, usize)) -> &'a f64 { + let (row, col) = index; + &self.data[row * self.cols + col] + } +} + +impl IndexMut<(usize, usize)> for Matrix { + fn index_mut<'a>(&'a mut self, index: (usize, usize)) -> &'a mut f64 { + let (row, col) = index; + &mut self.data[row * self.cols + col] + } +} + fn gaussian_elimination(a: &mut Matrix) { for k in 0..min(a.cols, a.rows) { // Step 1: find the maximum element for this kumn let mut max_row = k; - let mut max_value = a.get(k, k).abs(); + let mut max_value = a[(k, k)].abs(); for row in (k+1)..a.rows { - if max_value < a.get(row, k).abs() { - max_value = a.get(row, k).abs(); + if max_value < a[(row, k)].abs() { + max_value = a[(row, k)].abs(); max_row = row; } } // Check to make sure the matrix is good - if a.get(max_row, k) == 0.0 { + if a[(max_row, k)] == 0.0 { println!("Matrix is singular, aborting"); return; } @@ -52,17 +60,16 @@ fn gaussian_elimination(a: &mut Matrix) { // Loop over all remaining rows for i in k+1..a.rows { // Step 3: find the fraction - let fraction = a.get(i, k)/a.get(k, k); + let fraction = a[(i, k)]/a[(k, k)]; // Loop through all columns for that row for j in (k+1)..a.cols { // Step 4: re-evaluate each element - let val = a.get(i, j) - a.get(k, j)*fraction; - a.set(i, j, val); + a[(i, j)] -= a[(k, j)]*fraction; } // Step 5: set lower elements to 0 - a.set(i, k, 0.0); + a[(i, k)] = 0.0; } } } @@ -70,14 +77,14 @@ fn gaussian_elimination(a: &mut Matrix) { fn back_substitution(a: &Matrix) -> Vec { let mut soln = vec![0.0; a.rows]; - soln[a.rows - 1] = a.get(a.rows - 1, a.cols - 1) / a.get(a.rows - 1, a.cols - 2); + soln[a.rows - 1] = a[(a.rows - 1, a.cols - 1)] / a[(a.rows - 1, a.cols - 2)]; for i in (0..a.rows - 1).rev() { let mut sum = 0.0; for j in (i..a.rows).rev() { - sum += soln[j] * a.get(i, j); + sum += soln[j] * a[(i, j)]; } - soln[i] = (a.get(i, a.cols - 1) - sum) / a.get(i,i); + soln[i] = (a[(i, a.cols - 1)] - sum) / a[(i, i)]; } soln From f23060aad03516c99e8dc5dc8a9a4da77e6d2b82 Mon Sep 17 00:00:00 2001 From: Jess 3Jane Date: Sun, 1 Jul 2018 07:39:50 -0400 Subject: [PATCH 7/8] Fixed a few typos and unneeded complexities --- .../code/rust/gaussian_elimination.rs | 37 ++++++++++--------- 1 file changed, 19 insertions(+), 18 deletions(-) diff --git a/chapters/matrix_methods/gaussian_elimination/code/rust/gaussian_elimination.rs b/chapters/matrix_methods/gaussian_elimination/code/rust/gaussian_elimination.rs index 20d2bfce2..575ad0a06 100644 --- a/chapters/matrix_methods/gaussian_elimination/code/rust/gaussian_elimination.rs +++ b/chapters/matrix_methods/gaussian_elimination/code/rust/gaussian_elimination.rs @@ -1,7 +1,7 @@ // submitted by jess 3jane use std::cmp::min; -use std::ops::{IndexMut, Index}; +use std::ops::{Index, IndexMut}; pub struct Matrix { rows: usize, @@ -11,7 +11,11 @@ pub struct Matrix { impl Matrix { fn new(rows: usize, cols: usize) -> Matrix { - Matrix { rows, cols, data: vec![0.0; rows * cols] } + Matrix { + rows, + cols, + data: vec![0.0; rows * cols], + } } fn swap_rows(&mut self, a: usize, b: usize) { @@ -23,25 +27,24 @@ impl Matrix { impl Index<(usize, usize)> for Matrix { type Output = f64; - fn index<'a>(&'a self, index: (usize, usize)) -> &'a f64 { + fn index(&self, index: (usize, usize)) -> &f64 { let (row, col) = index; &self.data[row * self.cols + col] } } impl IndexMut<(usize, usize)> for Matrix { - fn index_mut<'a>(&'a mut self, index: (usize, usize)) -> &'a mut f64 { - let (row, col) = index; + fn index_mut<'a>(&'a mut self, (row, col): (usize, usize)) -> &'a mut f64 { &mut self.data[row * self.cols + col] } } fn gaussian_elimination(a: &mut Matrix) { for k in 0..min(a.cols, a.rows) { - // Step 1: find the maximum element for this kumn + // Step 1: find the maximum element for this column let mut max_row = k; let mut max_value = a[(k, k)].abs(); - for row in (k+1)..a.rows { + for row in (k + 1)..a.rows { if max_value < a[(row, k)].abs() { max_value = a[(row, k)].abs(); max_row = row; @@ -58,17 +61,17 @@ fn gaussian_elimination(a: &mut Matrix) { a.swap_rows(k, max_row); // Loop over all remaining rows - for i in k+1..a.rows { + for i in k + 1..a.rows { // Step 3: find the fraction - let fraction = a[(i, k)]/a[(k, k)]; + let fraction = a[(i, k)] / a[(k, k)]; // Loop through all columns for that row - for j in (k+1)..a.cols { + for j in (k + 1)..a.cols { // Step 4: re-evaluate each element - a[(i, j)] -= a[(k, j)]*fraction; + a[(i, j)] -= a[(k, j)] * fraction; } - // Step 5: set lower elements to 0 + // Step 5: set lower elements to 0 a[(i, k)] = 0.0; } } @@ -76,7 +79,7 @@ fn gaussian_elimination(a: &mut Matrix) { fn back_substitution(a: &Matrix) -> Vec { let mut soln = vec![0.0; a.rows]; - + soln[a.rows - 1] = a[(a.rows - 1, a.cols - 1)] / a[(a.rows - 1, a.cols - 2)]; for i in (0..a.rows - 1).rev() { @@ -92,11 +95,9 @@ fn back_substitution(a: &Matrix) -> Vec { fn main() { // The example matrix from the text - let mut a = Matrix::new(3,4); - a.data = 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,]; - + let mut a = Matrix::new(3, 4); + a.data = 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]; + gaussian_elimination(&mut a); let soln = back_substitution(&a); println!("Solution: {:?}", soln); From 7ea86ebce56fe50fdadf268fc9d1067f4a7da333 Mon Sep 17 00:00:00 2001 From: jess Date: Mon, 2 Jul 2018 03:12:19 +0200 Subject: [PATCH 8/8] Cleaned up a bit and added an argument to the matrix constructor --- .../code/rust/gaussian_elimination.rs | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/chapters/matrix_methods/gaussian_elimination/code/rust/gaussian_elimination.rs b/chapters/matrix_methods/gaussian_elimination/code/rust/gaussian_elimination.rs index 575ad0a06..ee1658ea2 100644 --- a/chapters/matrix_methods/gaussian_elimination/code/rust/gaussian_elimination.rs +++ b/chapters/matrix_methods/gaussian_elimination/code/rust/gaussian_elimination.rs @@ -10,11 +10,11 @@ pub struct Matrix { } impl Matrix { - fn new(rows: usize, cols: usize) -> Matrix { + fn new(rows: usize, cols: usize, data: &[f64]) -> Matrix { Matrix { rows, cols, - data: vec![0.0; rows * cols], + data: data.to_vec(), } } @@ -27,14 +27,13 @@ impl Matrix { impl Index<(usize, usize)> for Matrix { type Output = f64; - fn index(&self, index: (usize, usize)) -> &f64 { - let (row, col) = index; + fn index(&self, (row, col): (usize, usize)) -> &f64 { &self.data[row * self.cols + col] } } impl IndexMut<(usize, usize)> for Matrix { - fn index_mut<'a>(&'a mut self, (row, col): (usize, usize)) -> &'a mut f64 { + fn index_mut(&mut self, (row, col): (usize, usize)) -> &mut f64 { &mut self.data[row * self.cols + col] } } @@ -95,8 +94,11 @@ fn back_substitution(a: &Matrix) -> Vec { fn main() { // The example matrix from the text - let mut a = Matrix::new(3, 4); - a.data = 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]; + let mut a = Matrix::new( + 3, + 4, + &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], + ); gaussian_elimination(&mut a); let soln = back_substitution(&a);