From 002c27aefc5529eca6e339a02dbaf06fd982db43 Mon Sep 17 00:00:00 2001 From: Zastian Pretorius Date: Wed, 20 Jul 2022 13:52:18 +0100 Subject: [PATCH] did some restructureing by placing simplec in its own mod --- src/main.rs | 257 +--------------------------------------- src/simplex/mod.rs | 1 + src/simplex/simplex.rs | 258 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 262 insertions(+), 254 deletions(-) create mode 100644 src/simplex/mod.rs create mode 100644 src/simplex/simplex.rs diff --git a/src/main.rs b/src/main.rs index cc7435d..3dfb915 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,256 +1,5 @@ -use std::io::{self, Write}; -use std::vec::Vec; -use prettytable::{Table, Row, Cell}; -struct Coll { - restriction: Vec, - sign: String, - rhs: f64, -} +mod simplex; +use simplex::simplex::simplex; fn main() { - let amount_restrictions = int_input("Enter amount of restrictions: "); - let amount_variables = int_input("Enter amount of variables: "); - let mut max_z: Vec = vec![]; - for z in 0..amount_variables { - let input = float_input(&format!("{}x{}:","Enter max value of variable ",z)); - max_z.push(input); - } - let all_colls = fill_coll(amount_restrictions, amount_variables); - let mut table: Vec> = vec![]; - //fill in max_z with 0 for the rest of the table till size amount_restrictions - for _i in 0..amount_restrictions { - max_z.push(0.0); - } - table.push(max_z); - - let mut count = 0; - for mut coll in all_colls{ - for i in 0..amount_restrictions { - //push 1 if i = count - if i == count { - coll.restriction.push(1.0); - } else { - coll.restriction.push(0.0); - } - } - coll.restriction.push(coll.rhs); - count += 1; - table.push(coll.restriction); - } - - println!("t*"); - print_first_table(&table); - println!(""); - println!("ti"); - let mut table = flip_z(&mut table); - //print_table(&table); - //pivot table until table is optimal - // table is optimal when z has no negative values - println!(""); - let mut optimal = false; - while !optimal { - let pivot_col = find_pivot_col(&table); - let ratio = ratio_test(&table, pivot_col); - let pivot_row = find_pivot_row(&ratio); - print_table(&table,&pivot_col,&pivot_row); - table = pivot_table(&mut table, pivot_row, pivot_col); - println!(""); - if check_optimal(&table){ - print_table(&table, &pivot_col, &pivot_row); - optimal = true; - } - } -} - -fn check_optimal(table: &Vec>) -> bool { -// tebale is optimal when z has no negative values - let mut z_index = 0; - for i in 0..table[0].len() { - if table[0][i] < 0.0 { - z_index = i; - } - } - if z_index == 0 { - return true; - } else { - return false; - } -} - -fn print_first_table(table: &Vec>){ - let mut print_table = Table::new(); - let mut titles: Vec = vec![]; - for title in 0..table[0].len(){ - if title == table[1].len() - 1 { - titles.push(Cell::new("rhs")); - } else if title < table[0].len() / 2 { - titles.push(Cell::new(&format!("x{}",title+1))); - } else { - titles.push(Cell::new(&format!("s{}",title - table[0].len() / 2 + 1))); - } - } - print_table.add_row(Row::new(titles)); - for i in 0..table.len() { - let mut cells: Vec = vec![]; - for j in 0..table[i].len(){ - cells.push(Cell::new(&table[i][j].to_string())); - }; - print_table.add_row(Row::new(cells)); - }; - print_table.printstd(); - -} - - -fn print_table(table: &Vec>,pivot_col: &usize, pivot_row: &usize) { - let mut print_table = Table::new(); - let mut titles: Vec = vec![]; - for title in 0..table[0].len(){ - if title == table[0].len() - 1 { - titles.push(Cell::new("rhs")); - } else if title < table[0].len() / 2 { - titles.push(Cell::new(&format!("x{}",title+1))); - } else { - titles.push(Cell::new(&format!("s{}",title - table[0].len() / 2 + 1))); - } - } - print_table.add_row(Row::new(titles)); - for i in 0..table.len() { - let mut cells: Vec = vec![]; - for j in 0..table[i].len(){ - cells.push(Cell::new(&table[i][j].to_string()).style_spec(if j == *pivot_col || i == *pivot_row+1{ "Fgb"} else {""})); - }; - print_table.add_row(Row::new(cells)); - }; - print_table.printstd(); -} - -fn pivot_table(table: &mut Vec>, pivot_row: usize, pivot_col: usize) -> Vec> { - // firnd the pivot point - let mut new_table = table.clone(); - let pivot_point = table[pivot_row+1][pivot_col]; - // divide pivot row by pivot point - for i in 0..table[pivot_row+1].len() { - new_table[pivot_row+1][i] = table[pivot_row+1][i] / pivot_point; - }; - // current possition-(pivot_row*new_table pivot_point) - for i in 0..table.len() { - if i != pivot_row+1 { - let current_possition = table[i][pivot_col]; - for j in 0..table[i].len() { - new_table[i][j] = table[i][j] - (current_possition * new_table[pivot_row+1][j]); - } - } - } - return new_table; -} - - -fn flip_z(table: &mut Vec>) -> Vec>{ - for i in 0..table[0].len(){ - if table[0][i] > 0.0 { - table[0][i] = -table[0][i]; - } - } - table[0].push(0.0); - return table.to_vec(); -} - -fn find_pivot_col(table: &Vec>) -> usize { - let mut largest = 0.0; - let mut largest_index = 0; - for i in 0..table[0].len() { - if table[0][i] < largest{ - largest = table[0][i]; - largest_index = i; - } - } - return largest_index; -} - -fn ratio_test(table: &Vec>, test_col: usize) -> Vec { - let mut ratios: Vec = vec![]; - for i in 1..table.len() { - if table[i][test_col] != 0.0 { - ratios.push(table[i][table[i].len() - 1] / table[i][test_col]); - } else { - ratios.push(std::f64::MAX); - } - } - return ratios; -} - -fn find_pivot_row(ratios: &Vec) -> usize { - //find the index of the smallest ratio - let mut smallest = std::f64::MAX; - let mut smallest_index = 0; - for i in 0..ratios.len() { - if ratios[i] < smallest && ratios[i] > 0.0 { - smallest = ratios[i]; - smallest_index = i; - } - } - return smallest_index; -} - - -fn fill_coll(amount_restrictions: usize, amount_vars: usize) -> Vec { - let mut colls : Vec = vec![]; - for _restriction in 0..amount_restrictions { - let mut restrictions:Vec = vec![]; - let mut count = 1; - for _var in 0..amount_vars { - let input = float_input(&format!("{}x{}:","Enter restriction ",count)); - restrictions.push(input.clone()); - count += 1; - } - let sign_local = string_input("Enter sign: "); - let rhs_local = float_input("Enter rhs: "); - let coll_local = Coll { - restriction: restrictions, - sign: sign_local, - rhs: rhs_local, - }; - colls.push(coll_local); - } - colls -} - - - -pub fn string_input(prompt: &str) -> String { - print!("{}", prompt); - let mut input = String::new(); - let _ = io::stdout().flush(); - io::stdin() - .read_line(&mut input) - .expect("Error reading from STDIN"); - input.trim().to_string() -} - -pub fn int_input(prompt: &str) -> usize { - print!("{}", prompt); - let mut input = String::new(); - let _ = io::stdout().flush(); - io::stdin() - .read_line(&mut input) - .expect("Error reading from STDIN"); - //try to parse the input as usize else return max usize - match input.trim().parse::() { - Ok(i) => i, - Err(_) => { - usize::max_value() - } - } -} - -pub fn float_input(prompt: &str) -> f64 { - print!("{}", prompt); - let mut input = String::new(); - let _ = io::stdout().flush(); - io::stdin() - .read_line(&mut input) - .expect("Error reading from STDIN"); - //try to parse the input as f64 else return max f64 - let output = input.trim().parse::().unwrap(); - output + simplex(); } diff --git a/src/simplex/mod.rs b/src/simplex/mod.rs new file mode 100644 index 0000000..0040312 --- /dev/null +++ b/src/simplex/mod.rs @@ -0,0 +1 @@ +pub mod simplex; diff --git a/src/simplex/simplex.rs b/src/simplex/simplex.rs new file mode 100644 index 0000000..74ca838 --- /dev/null +++ b/src/simplex/simplex.rs @@ -0,0 +1,258 @@ +use std::io::{self, Write}; +use std::vec::Vec; +use prettytable::{Table, Row, Cell}; +struct Coll { + restriction: Vec, + sign: String, + rhs: f64, +} +pub fn simplex() { + let mut stuff: Vec = ["Red".to_string(),"Green".to_string(),"Blue".to_string()].to_vec(); + stuff.push("Yellow".to_string()); + let amount_restrictions = int_input("Enter amount of restrictions: "); + let amount_variables = int_input("Enter amount of variables: "); + let mut max_z: Vec = vec![]; + for z in 0..amount_variables { + let input = float_input(&format!("{}x{}:","Enter max value of variable ",z)); + max_z.push(input); + } + let all_colls = fill_coll(amount_restrictions, amount_variables); + let mut table: Vec> = vec![]; + //fill in max_z with 0 for the rest of the table till size amount_restrictions + for _i in 0..amount_restrictions { + max_z.push(0.0); + } + table.push(max_z); + + let mut count = 0; + for mut coll in all_colls{ + for i in 0..amount_restrictions { + //push 1 if i = count + if i == count { + coll.restriction.push(1.0); + } else { + coll.restriction.push(0.0); + } + } + coll.restriction.push(coll.rhs); + count += 1; + table.push(coll.restriction); + } + + println!("t*"); + print_first_table(&table); + println!(""); + println!("ti"); + let mut table = flip_z(&mut table); + //print_table(&table); + //pivot table until table is optimal + // table is optimal when z has no negative values + println!(""); + let mut optimal = false; + while !optimal { + let pivot_col = find_pivot_col(&table); + let ratio = ratio_test(&table, pivot_col); + let pivot_row = find_pivot_row(&ratio); + print_table(&table,&pivot_col,&pivot_row); + table = pivot_table(&mut table, pivot_row, pivot_col); + println!(""); + if check_optimal(&table){ + print_table(&table, &pivot_col, &pivot_row); + optimal = true; + } + } +} + +fn check_optimal(table: &Vec>) -> bool { +// tebale is optimal when z has no negative values + let mut z_index = 0; + for i in 0..table[0].len() { + if table[0][i] < 0.0 { + z_index = i; + } + } + if z_index == 0 { + return true; + } else { + return false; + } +} + +fn print_first_table(table: &Vec>){ + let mut print_table = Table::new(); + let mut titles: Vec = vec![]; + for title in 0..table[0].len(){ + if title == table[1].len() - 1 { + titles.push(Cell::new("rhs")); + } else if title < table[0].len() / 2 { + titles.push(Cell::new(&format!("x{}",title+1))); + } else { + titles.push(Cell::new(&format!("s{}",title - table[0].len() / 2 + 1))); + } + } + print_table.add_row(Row::new(titles)); + for i in 0..table.len() { + let mut cells: Vec = vec![]; + for j in 0..table[i].len(){ + cells.push(Cell::new(&table[i][j].to_string())); + }; + print_table.add_row(Row::new(cells)); + }; + print_table.printstd(); + +} + + +fn print_table(table: &Vec>,pivot_col: &usize, pivot_row: &usize) { + let mut print_table = Table::new(); + let mut titles: Vec = vec![]; + for title in 0..table[0].len(){ + if title == table[0].len() - 1 { + titles.push(Cell::new("rhs")); + } else if title < table[0].len() / 2 { + titles.push(Cell::new(&format!("x{}",title+1))); + } else { + titles.push(Cell::new(&format!("s{}",title - table[0].len() / 2 + 1))); + } + } + print_table.add_row(Row::new(titles)); + for i in 0..table.len() { + let mut cells: Vec = vec![]; + for j in 0..table[i].len(){ + cells.push(Cell::new(&table[i][j].to_string()).style_spec(if j == *pivot_col || i == *pivot_row+1{ "Fgb"} else {""})); + }; + print_table.add_row(Row::new(cells)); + }; + print_table.printstd(); +} + +fn pivot_table(table: &mut Vec>, pivot_row: usize, pivot_col: usize) -> Vec> { + // firnd the pivot point + let mut new_table = table.clone(); + let pivot_point = table[pivot_row+1][pivot_col]; + // divide pivot row by pivot point + for i in 0..table[pivot_row+1].len() { + new_table[pivot_row+1][i] = table[pivot_row+1][i] / pivot_point; + }; + // current possition-(pivot_row*new_table pivot_point) + for i in 0..table.len() { + if i != pivot_row+1 { + let current_possition = table[i][pivot_col]; + for j in 0..table[i].len() { + new_table[i][j] = table[i][j] - (current_possition * new_table[pivot_row+1][j]); + } + } + } + return new_table; +} + + +fn flip_z(table: &mut Vec>) -> Vec>{ + for i in 0..table[0].len(){ + if table[0][i] > 0.0 { + table[0][i] = -table[0][i]; + } + } + table[0].push(0.0); + return table.to_vec(); +} + +fn find_pivot_col(table: &Vec>) -> usize { + let mut largest = 0.0; + let mut largest_index = 0; + for i in 0..table[0].len() { + if table[0][i] < largest{ + largest = table[0][i]; + largest_index = i; + } + } + return largest_index; +} + +fn ratio_test(table: &Vec>, test_col: usize) -> Vec { + let mut ratios: Vec = vec![]; + for i in 1..table.len() { + if table[i][test_col] != 0.0 { + ratios.push(table[i][table[i].len() - 1] / table[i][test_col]); + } else { + ratios.push(std::f64::MAX); + } + } + return ratios; +} + +fn find_pivot_row(ratios: &Vec) -> usize { + //find the index of the smallest ratio + let mut smallest = std::f64::MAX; + let mut smallest_index = 0; + for i in 0..ratios.len() { + if ratios[i] < smallest && ratios[i] > 0.0 { + smallest = ratios[i]; + smallest_index = i; + } + } + return smallest_index; +} + + +fn fill_coll(amount_restrictions: usize, amount_vars: usize) -> Vec { + let mut colls : Vec = vec![]; + for _restriction in 0..amount_restrictions { + let mut restrictions:Vec = vec![]; + let mut count = 1; + for _var in 0..amount_vars { + let input = float_input(&format!("{}x{}:","Enter restriction ",count)); + restrictions.push(input.clone()); + count += 1; + } + let sign_local = string_input("Enter sign: "); + let rhs_local = float_input("Enter rhs: "); + let coll_local = Coll { + restriction: restrictions, + sign: sign_local, + rhs: rhs_local, + }; + colls.push(coll_local); + } + colls +} + + + +pub fn string_input(prompt: &str) -> String { + print!("{}", prompt); + let mut input = String::new(); + let _ = io::stdout().flush(); + io::stdin() + .read_line(&mut input) + .expect("Error reading from STDIN"); + input.trim().to_string() +} + +pub fn int_input(prompt: &str) -> usize { + print!("{}", prompt); + let mut input = String::new(); + let _ = io::stdout().flush(); + io::stdin() + .read_line(&mut input) + .expect("Error reading from STDIN"); + //try to parse the input as usize else return max usize + match input.trim().parse::() { + Ok(i) => i, + Err(_) => { + usize::max_value() + } + } +} + +pub fn float_input(prompt: &str) -> f64 { + print!("{}", prompt); + let mut input = String::new(); + let _ = io::stdout().flush(); + io::stdin() + .read_line(&mut input) + .expect("Error reading from STDIN"); + //try to parse the input as f64 else return max f64 + let output = input.trim().parse::().unwrap(); + output +}