diff --git a/gemla/src/bracket/mod.rs b/gemla/src/bracket/mod.rs index 49f7ffb..2ce9040 100644 --- a/gemla/src/bracket/mod.rs +++ b/gemla/src/bracket/mod.rs @@ -7,11 +7,15 @@ use uuid::Uuid; use std::str::FromStr; impl tree::Tree { - pub fn run_simulation(&self) { - println!("================================"); - println!("Running simulation for node: {}", self.val); - println!("With children {} and {}", tree::fmt_node(&self.left), tree::fmt_node(&self.right)); - } + pub fn run_simulation(&self) { + println!("================================"); + println!("Running simulation for node: {}", self.val); + println!( + "With children {} and {}", + tree::fmt_node(&self.left), + tree::fmt_node(&self.right) + ); + } } // pub struct Bracket { @@ -21,46 +25,55 @@ impl tree::Tree { /// Constructs a tree with a given height while simultaneously running a simulation on each node. fn build_tree(h: u32) -> Option>> { - let mut result: Option>> = None; + let mut result: Option>> = None; - // Recursively building a tree and running the simulation after wards to ensure a bottom-up - // execution order. - if h != 0 { - result = Some(Box::new(tree::Tree::new(Uuid::new_v4(), build_tree(h - 1), build_tree(h - 1)))); - match &result { - Some(r) => (*r).run_simulation(), - _ => () - } - } + // Recursively building a tree and running the simulation after wards to ensure a bottom-up + // execution order. + if h != 0 { + result = Some(Box::new(tree::Tree::new( + Uuid::new_v4(), + build_tree(h - 1), + build_tree(h - 1), + ))); + match &result { + Some(r) => (*r).run_simulation(), + _ => (), + } + } - result + result } /// Generates a bracket tree and runs simulation against each node. -/// +/// /// TODO: Explain reasoning for bracket system against genetic algorithm. pub fn run_bracket() { - let mut height = 1; - let mut tree = FileLinked::new(*build_tree(height).expect("Error getting result from build_tree"), "temp") - .expect("Unable to create file linked object from tree"); + let mut height = 1; + let mut tree = FileLinked::new( + *build_tree(height).expect("Error getting result from build_tree"), + "temp", + ).expect("Unable to create file linked object from tree"); - // Building tree one node at a time, appending to the top. - loop { - println!("========================================="); - println!("Running bracket..."); - height += 1; - tree.replace(tree::Tree::new(Uuid::new_v4(), Some(Box::new(tree.readonly().clone())), build_tree(height))) - .expect("Error building up tree node"); - tree.readonly().run_simulation(); + // Building tree one node at a time, appending to the top. + loop { + println!("========================================="); + println!("Running bracket..."); + height += 1; + tree.replace(tree::Tree::new( + Uuid::new_v4(), + Some(Box::new(tree.readonly().clone())), + build_tree(height), + )).expect("Error building up tree node"); + tree.readonly().run_simulation(); - if height == 3 { - println!("{}\n\n", tree); - let s = format!("{}", tree); - println!("{}\n\n", s); - let tree2: tree::Tree = tree::Tree::from_str(&s).unwrap(); - println!("{}\n\n", tree2); - break; - } - } -} \ No newline at end of file + if height == 3 { + println!("{}\n\n", tree); + let s = format!("{}", tree); + println!("{}\n\n", s); + let tree2: tree::Tree = tree::Tree::from_str(&s).unwrap(); + println!("{}\n\n", tree2); + break; + } + } +} diff --git a/gemla/src/bracket/state.rs b/gemla/src/bracket/state.rs index 4c0a24a..61e3d63 100644 --- a/gemla/src/bracket/state.rs +++ b/gemla/src/bracket/state.rs @@ -15,4 +15,4 @@ // State { // id: id.clone() // } -// } \ No newline at end of file +// } diff --git a/gemla/src/constants/args.rs b/gemla/src/constants/args.rs index 6a59c9a..2eb1281 100644 --- a/gemla/src/constants/args.rs +++ b/gemla/src/constants/args.rs @@ -1,2 +1,2 @@ /// Corresponds to the DIRECTORY command line argument used in accordance with the clap crate. -pub const DIRECTORY: &str = "DIRECTORY"; \ No newline at end of file +pub const DIRECTORY: &str = "DIRECTORY"; diff --git a/gemla/src/constants/mod.rs b/gemla/src/constants/mod.rs index 8c43337..6e10f4a 100644 --- a/gemla/src/constants/mod.rs +++ b/gemla/src/constants/mod.rs @@ -1 +1 @@ -pub mod args; \ No newline at end of file +pub mod args; diff --git a/gemla/src/file_linked/mod.rs b/gemla/src/file_linked/mod.rs index 3d6ed39..3de6e6f 100644 --- a/gemla/src/file_linked/mod.rs +++ b/gemla/src/file_linked/mod.rs @@ -6,91 +6,100 @@ use std::io::Read; use std::io::Write; pub struct FileLinked { - val: T, - path: String + val: T, + path: String, } -impl FileLinked where T: FromStr + fmt::Display + Default { - pub fn from_file(path: &str) -> Result, String> { - let meta = fs::metadata(path); +impl FileLinked +where + T: FromStr + fmt::Display + Default, +{ + pub fn from_file(path: &str) -> Result, String> { + let meta = fs::metadata(path); - match &meta { - Ok(m) if m.is_file() => { - let mut file = fs::OpenOptions::new().read(true).open(path) - .or(Err(format!("Unable to open file {}", path)))?; - let mut s = String::new(); - file.read_to_string(&mut s) - .or(Err(String::from("Unable to read from file.")))?; + match &meta { + Ok(m) if m.is_file() => { + let mut file = fs::OpenOptions::new().read(true).open(path).or( + Err(format!( + "Unable to open file {}", + path + )), + )?; + let mut s = String::new(); + file.read_to_string(&mut s).or(Err(String::from( + "Unable to read from file.", + )))?; - let val = T::from_str(&s).or(Err(String::from("Unable to parse value from file.")))?; + let val = T::from_str(&s).or(Err(String::from( + "Unable to parse value from file.", + )))?; - Ok(FileLinked { - val, - path: String::from(path) - }) - }, - Ok(_) => { - Err(format!("{} is not a file.", path)) - }, - _ => { - let result = FileLinked { - val: T::default(), - path: String::from(path) - }; + Ok(FileLinked { + val, + path: String::from(path), + }) + } + Ok(_) => Err(format!("{} is not a file.", path)), + _ => { + let result = FileLinked { + val: T::default(), + path: String::from(path), + }; - result.write_data()?; + result.write_data()?; - Ok(result) - } - } - } + Ok(result) + } + } + } - pub fn new(val: T, path: &str) -> Result, String> { - let result = FileLinked { - val, - path: String::from(path) - }; + pub fn new(val: T, path: &str) -> Result, String> { + let result = FileLinked { + val, + path: String::from(path), + }; - result.write_data()?; + result.write_data()?; - Ok(result) - } + Ok(result) + } - pub fn write_data(&self) -> Result<(), String> { - let mut file = fs::OpenOptions::new() - .write(true) - .create(true) - .truncate(true) - .open(&self.path) - .or(Err(format!("Unable to open path {}", self.path)))?; + pub fn write_data(&self) -> Result<(), String> { + let mut file = fs::OpenOptions::new() + .write(true) + .create(true) + .truncate(true) + .open(&self.path) + .or(Err(format!("Unable to open path {}", self.path)))?; - write!(file, "{}", self.val) - .or(Err(String::from("Unable to write to file.")))?; + write!(file, "{}", self.val).or(Err(String::from( + "Unable to write to file.", + )))?; - Ok(()) - } + Ok(()) + } - pub fn readonly(&self) -> &T { - &self.val - } + pub fn readonly(&self) -> &T { + &self.val + } - pub fn mutate U>(&mut self, op: F) -> Result { - let result = op(&mut self.val); + pub fn mutate U>(&mut self, op: F) -> Result { + let result = op(&mut self.val); - self.write_data()?; + self.write_data()?; - Ok(result) - } + Ok(result) + } - pub fn replace(&mut self, val: T) -> Result<(), String>{ - self.val = val; + pub fn replace(&mut self, val: T) -> Result<(), String> { + self.val = val; - self.write_data() - } + self.write_data() + } } impl fmt::Display for FileLinked { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{}", self.val) - } -} \ No newline at end of file + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{}", self.val) + } +} diff --git a/gemla/src/main.rs b/gemla/src/main.rs index af13f13..1b933d8 100644 --- a/gemla/src/main.rs +++ b/gemla/src/main.rs @@ -11,30 +11,32 @@ use clap::App; use std::fs::metadata; /// Runs a simluation of a genetic algorithm against a dataset. -/// +/// /// Use the -h, --h, or --help flag to see usage syntax. /// TODO fn main() { - // Command line arguments are parsed with the clap crate. And this program uses - // the yaml method with clap. - let yaml = load_yaml!("../cli.yml"); - let matches = App::from_yaml(yaml).get_matches(); + // Command line arguments are parsed with the clap crate. And this program uses + // the yaml method with clap. + let yaml = load_yaml!("../cli.yml"); + let matches = App::from_yaml(yaml).get_matches(); - // Checking that the first argument is a valid directory - let directory = matches.value_of(constants::args::DIRECTORY).unwrap(); - let metadata = metadata(directory); - match &metadata { - Ok(m) if m.is_dir() == true => { - println!("{} is a valid directory!", directory); - println!("Building tree for {}.", directory); - bracket::run_bracket(); + // Checking that the first argument is a valid directory + let directory = matches.value_of(constants::args::DIRECTORY).unwrap(); + let metadata = metadata(directory); + match &metadata { + Ok(m) if m.is_dir() == true => { + println!("{} is a valid directory!", directory); + println!("Building tree for {}.", directory); + bracket::run_bracket(); - println!("\n\nReading tree from temp file."); - let tree: file_linked::FileLinked> = file_linked::FileLinked::from_file("temp") - .expect("Unable to read tree from existing file"); - println!("Value read from file:\n{}", tree); - }, - Ok(_) => println!("{} is not a valid directory!", directory), - _ => println!("{} does not exist!", directory) - } -} \ No newline at end of file + println!("\n\nReading tree from temp file."); + let tree: file_linked::FileLinked> = + file_linked::FileLinked::from_file("temp").expect( + "Unable to read tree from existing file", + ); + println!("Value read from file:\n{}", tree); + } + Ok(_) => println!("{} is not a valid directory!", directory), + _ => println!("{} does not exist!", directory), + } +} diff --git a/gemla/src/tree/mod.rs b/gemla/src/tree/mod.rs index 464ce4a..573423e 100644 --- a/gemla/src/tree/mod.rs +++ b/gemla/src/tree/mod.rs @@ -4,159 +4,188 @@ use regex::Regex; #[derive(Default, Clone)] pub struct Tree { - pub val: T, - pub left: Option>>, - pub right: Option>> + pub val: T, + pub left: Option>>, + pub right: Option>>, } impl Tree { - pub fn new(val: T, left: Option>>, right: Option>>) -> Tree { - Tree { - val, - left, - right - } - } + pub fn new(val: T, left: Option>>, right: Option>>) -> Tree { + Tree { val, left, right } + } } impl fmt::Display for Tree { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - let node_str = |t: &Option>>| -> String { - match t { - Some(n) => format!("{}", *n), - _ => String::from("_") - } - }; + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + let node_str = |t: &Option>>| -> String { + match t { + Some(n) => format!("{}", *n), + _ => String::from("_"), + } + }; - write!(f, "({} :{}|{})", self.val, node_str(&self.left), node_str(&self.right)) - } + write!( + f, + "({} :{}|{})", + self.val, + node_str(&self.left), + node_str(&self.right) + ) + } } pub fn fmt_node(t: &Option>>) -> String { - match t { - Some(n) => format!("{}", (*n).val), - _ => String::from("_") - } + match t { + Some(n) => format!("{}", (*n).val), + _ => String::from("_"), + } } fn seperate_nodes(s: &str) -> Result<(&str, &str), ParseTreeError> { - let mut result = Err(ParseTreeError::new(format!("Unable to seperate string: {}", s))); - let mut stack: Vec = Vec::new(); + let mut result = Err(ParseTreeError::new( + format!("Unable to seperate string: {}", s), + )); + let mut stack: Vec = Vec::new(); - for (i, c) in s.char_indices() { - if c == '(' { - stack.push(c); - } else if c == ')' { - if stack.is_empty() { - result = Err(ParseTreeError::new(format!("Unbalanced parenthesis found in string: {}", s))); - break; - } + for (i, c) in s.char_indices() { + if c == '(' { + stack.push(c); + } else if c == ')' { + if stack.is_empty() { + result = Err(ParseTreeError::new( + format!("Unbalanced parenthesis found in string: {}", s), + )); + break; + } - stack.pop(); - } else if c == '|' && stack.is_empty() { - result = Ok((&s[..i], &s[i+1..])); - break; - } - } + stack.pop(); + } else if c == '|' && stack.is_empty() { + result = Ok((&s[..i], &s[i + 1..])); + break; + } + } - result + result } fn from_str_helper(s: &str) -> Result>>, ParseTreeError> { - let mut result = Err(ParseTreeError::new(String::from("Unable to parse tree, string format unrecognized."))); - let emptyre = Regex::new(r"\s*_\s*").unwrap(); - let re = Regex::new(r"\(([0-9a-fA-F-]+)\s*:\s*(.*)\)$").unwrap(); - let caps = re.captures(s); + let mut result = Err(ParseTreeError::new(String::from( + "Unable to parse tree, string format unrecognized.", + ))); + let emptyre = Regex::new(r"\s*_\s*").unwrap(); + let re = Regex::new(r"\(([0-9a-fA-F-]+)\s*:\s*(.*)\)$").unwrap(); + let caps = re.captures(s); - if let Some(c) = caps { - let val = T::from_str(c.get(1).unwrap().as_str()) - .or(Err(ParseTreeError::new(format!("Unable to parse node value: {}", c.get(1).unwrap().as_str()))))?; - let (left, right) = seperate_nodes(c.get(2).unwrap().as_str())?; - let left = from_str_helper(left)?; - let right = from_str_helper(right)?; + if let Some(c) = caps { + let val = T::from_str(c.get(1).unwrap().as_str()).or(Err( + ParseTreeError::new( + format!( + "Unable to parse node value: {}", + c.get(1) + .unwrap() + .as_str() + ), + ), + ))?; + let (left, right) = seperate_nodes(c.get(2).unwrap().as_str())?; + let left = from_str_helper(left)?; + let right = from_str_helper(right)?; - result = Ok(Some(Box::new(Tree::new(val, left, right)))); - } else if emptyre.is_match(s) { - result = Ok(None); - } + result = Ok(Some(Box::new(Tree::new(val, left, right)))); + } else if emptyre.is_match(s) { + result = Ok(None); + } - result + result } -impl FromStr for Tree where T: FromStr { - type Err = ParseTreeError; +impl FromStr for Tree +where + T: FromStr, +{ + type Err = ParseTreeError; - fn from_str(s: &str) -> Result { - let mut result = Err(ParseTreeError::new(String::from("Unable to parse tree, string format unreognized."))); - let re = Regex::new(r"\(([0-9a-fA-F-]+)\s*:\s*(.*)\)$").unwrap(); - let caps = re.captures(s); + fn from_str(s: &str) -> Result { + let mut result = Err(ParseTreeError::new(String::from( + "Unable to parse tree, string format unreognized.", + ))); + let re = Regex::new(r"\(([0-9a-fA-F-]+)\s*:\s*(.*)\)$").unwrap(); + let caps = re.captures(s); - if let Some(c) = caps { - let val = T::from_str(c.get(1).unwrap().as_str()) - .or(Err(ParseTreeError::new(format!("Unable to parse node value: {}", c.get(1).unwrap().as_str()))))?; - let (left, right) = seperate_nodes(c.get(2).unwrap().as_str())?; - let left = from_str_helper(left)?; - let right = from_str_helper(right)?; - - result = Ok(Tree::new(val, left, right)); - } + if let Some(c) = caps { + let val = T::from_str(c.get(1).unwrap().as_str()).or(Err( + ParseTreeError::new( + format!( + "Unable to parse node value: {}", + c.get(1) + .unwrap() + .as_str() + ), + ), + ))?; + let (left, right) = seperate_nodes(c.get(2).unwrap().as_str())?; + let left = from_str_helper(left)?; + let right = from_str_helper(right)?; - // if let Some(c) = caps { - // result = T::from_str(c.get(1).unwrap().as_str()) - // .or(Err(ParseTreeError::new(format!("Unable to parse node value: {}", c.get(1).unwrap().as_str())))) - // .and_then(|v| { - // seperate_nodes(c.get(2).unwrap().as_str()) - // .and_then(|(left, right)| { - // from_str_helper(left) - // .and_then(|l| { - // from_str_helper(right) - // .and_then(|r| { - // Ok(Tree::new(v, l, r)) - // }) - // }) - // }) - // }) - // } + result = Ok(Tree::new(val, left, right)); + } - // if let Some(c) = caps { - // let val = T::from_str(c.get(1).unwrap().as_str()); - // if let Ok(v) = val { - // match seperate_nodes(c.get(2).unwrap().as_str()) { - // Ok((l, r)) => { - // match (from_str_helper(l), from_str_helper(r)) { - // (Ok(left), Ok(right)) => { - // result = Ok(Tree::new(v, left, right)); - // }, - // (Err(e), _) => { - // result = Err(e); - // }, - // (_, Err(e)) => { - // result = Err(e); - // } - // } - // }, - // Err(e) => { - // result = Err(e); - // } - // } - // } else { - // result = Err(ParseTreeError::new(format!("Unable to parse node value: {}", c.get(1).unwrap().as_str()))); - // } - // } + // if let Some(c) = caps { + // result = T::from_str(c.get(1).unwrap().as_str()) + // .or(Err(ParseTreeError::new( + // format!("Unable to parse node value: {}", c.get(1).unwrap().as_str())))) + // .and_then(|v| { + // seperate_nodes(c.get(2).unwrap().as_str()) + // .and_then(|(left, right)| { + // from_str_helper(left) + // .and_then(|l| { + // from_str_helper(right) + // .and_then(|r| { + // Ok(Tree::new(v, l, r)) + // }) + // }) + // }) + // }) + // } - result - } + // if let Some(c) = caps { + // let val = T::from_str(c.get(1).unwrap().as_str()); + // if let Ok(v) = val { + // match seperate_nodes(c.get(2).unwrap().as_str()) { + // Ok((l, r)) => { + // match (from_str_helper(l), from_str_helper(r)) { + // (Ok(left), Ok(right)) => { + // result = Ok(Tree::new(v, left, right)); + // }, + // (Err(e), _) => { + // result = Err(e); + // }, + // (_, Err(e)) => { + // result = Err(e); + // } + // } + // }, + // Err(e) => { + // result = Err(e); + // } + // } + // } else { + // result = Err(ParseTreeError::new( + // format!("Unable to parse node value: {}", c.get(1).unwrap().as_str()))); + // } + // } + + result + } } #[derive(Debug)] pub struct ParseTreeError { - pub msg: String + pub msg: String, } impl ParseTreeError { - fn new(msg: String) -> ParseTreeError { - ParseTreeError { - msg - } - } -} \ No newline at end of file + fn new(msg: String) -> ParseTreeError { + ParseTreeError { msg } + } +}