diff --git a/.gitignore b/.gitignore index ff86a46..e3c49a2 100644 --- a/.gitignore +++ b/.gitignore @@ -10,3 +10,5 @@ Cargo.lock **/*.rs.bk settings.json + +.DS_Store \ No newline at end of file diff --git a/file_linked/src/lib.rs b/file_linked/src/lib.rs index a2bd716..d7741fb 100644 --- a/file_linked/src/lib.rs +++ b/file_linked/src/lib.rs @@ -29,10 +29,8 @@ where T: Serialize, { fn drop(&mut self) { - if self.file_thread.is_some() { - let file_thread = self.file_thread.take(); + if let Some(file_thread) = self.file_thread.take() { file_thread - .unwrap() .join() .expect("Error cleaning up file thread for file_linked object"); } @@ -145,9 +143,9 @@ where let thread_temp_path = self.temp_file_path.clone(); let thread_val = bincode::serialize(&self.val) .with_context(|| "Unable to serialize object into bincode".to_string())?; - if self.file_thread.is_some() { - let file_thread = self.file_thread.take(); - file_thread.unwrap().join().expect("Unable to join thread"); + + if let Some(file_thread) = self.file_thread.take() { + file_thread.join().expect("Error cleaning up file thread for file_linked object"); } match File::open(&self.path) { diff --git a/gemla/src/bin/bin.rs b/gemla/src/bin/bin.rs index add122d..e1c948b 100644 --- a/gemla/src/bin/bin.rs +++ b/gemla/src/bin/bin.rs @@ -6,6 +6,7 @@ extern crate log; mod test_state; +use anyhow::anyhow; use clap::App; use gemla::core::{Gemla, GemlaConfig}; use gemla::error::log_error; @@ -46,19 +47,24 @@ fn main() -> anyhow::Result<()> { let yaml = load_yaml!("../../cli.yml"); let matches = App::from_yaml(yaml).get_matches(); - // Checking that the first argument is a valid directory - let file_path = matches.value_of(gemla::constants::args::FILE).unwrap(); - let mut gemla = log_error(Gemla::::new( - &PathBuf::from(file_path), - GemlaConfig { - generations_per_node: 1, - overwrite: true, - }, - ))?; + // Checking that the first argument is a valid file + if let Some(file_path) = matches.value_of(gemla::constants::args::FILE) { + let mut gemla = log_error(Gemla::::new( + &PathBuf::from(file_path), + GemlaConfig { + generations_per_node: 3, + overwrite: true, + }, + ))?; - log_error(gemla.simulate(3).await)?; + log_error(gemla.simulate(3).await)?; - Ok(()) + Ok(()) + } else { + Err(gemla::error::Error::Other(anyhow!( + "Invalid argument for FILE" + ))) + } }) }); diff --git a/gemla/src/bin/test_state/mod.rs b/gemla/src/bin/test_state/mod.rs index d91c21d..72a09e3 100644 --- a/gemla/src/bin/test_state/mod.rs +++ b/gemla/src/bin/test_state/mod.rs @@ -3,7 +3,6 @@ use gemla::error; use rand::prelude::*; use rand::thread_rng; use serde::{Deserialize, Serialize}; -use std::convert::TryInto; const POPULATION_SIZE: u64 = 5; const POPULATION_REDUCTION_SIZE: u64 = 3; @@ -47,7 +46,7 @@ impl GeneticNode for TestState { self.population = v[0..(POPULATION_REDUCTION_SIZE as usize)].to_vec(); loop { - if self.population.len() >= POPULATION_SIZE.try_into().unwrap() { + if self.population.len() as u64 >= POPULATION_SIZE { break; } diff --git a/gemla/src/core/genetic_node.rs b/gemla/src/core/genetic_node.rs index 2b016f7..b59bf0c 100644 --- a/gemla/src/core/genetic_node.rs +++ b/gemla/src/core/genetic_node.rs @@ -105,16 +105,13 @@ where } pub fn process_node(&mut self) -> Result { - match (&self.state, &self.node) { + match (self.state, &mut self.node) { (GeneticState::Initialize, _) => { self.node = Some(*T::initialize()?); self.state = GeneticState::Simulate; } - (GeneticState::Simulate, Some(_)) => { - self.node - .as_mut() - .unwrap() - .simulate() + (GeneticState::Simulate, Some(n)) => { + n.simulate() .with_context(|| format!("Error simulating node: {:?}", self))?; self.state = if self.generation >= self.max_generations { @@ -123,11 +120,8 @@ where GeneticState::Mutate }; } - (GeneticState::Mutate, Some(_)) => { - self.node - .as_mut() - .unwrap() - .mutate() + (GeneticState::Mutate, Some(n)) => { + n.mutate() .with_context(|| format!("Error mutating node: {:?}", self))?; self.generation += 1; diff --git a/gemla/src/core/mod.rs b/gemla/src/core/mod.rs index e5cbd01..b3803f1 100644 --- a/gemla/src/core/mod.rs +++ b/gemla/src/core/mod.rs @@ -76,21 +76,36 @@ where info!( "Height of simulation tree increased to {}", - self.data.readonly().0.as_ref().unwrap().height() + self.data + .readonly() + .0 + .as_ref() + .map(|t| format!("{}", t.height())) + .unwrap_or_else(|| "Tree is not defined".to_string()) ); loop { - if Gemla::is_completed(self.data.readonly().0.as_ref().unwrap()) { + if self + .data + .readonly() + .0 + .as_ref() + .map(|t| Gemla::is_completed(t)) + .unwrap_or(false) + { self.join_threads().await?; info!("Processed tree"); break; } - let node_to_process = - self.get_unprocessed_node(self.data.readonly().0.as_ref().unwrap()); - - if let Some(node) = node_to_process { + if let Some(node) = self + .data + .readonly() + .0 + .as_ref() + .and_then(|t| self.get_unprocessed_node(t)) + { trace!("Adding node to process list {}", node.id()); self.threads @@ -116,21 +131,22 @@ where self.threads.clear(); reduced_results.and_then(|r| { - let failed_nodes = self - .data - .mutate(|(d, _)| Gemla::replace_nodes(d.as_mut().unwrap(), r))?; + self.data.mutate(|(d, _)| { + if let Some(t) = d { + let failed_nodes = Gemla::replace_nodes(t, r); + if !failed_nodes.is_empty() { + warn!( + "Unable to find {:?} to replace in tree", + failed_nodes.iter().map(|n| n.id()) + ) + } - if !failed_nodes.is_empty() { - warn!( - "Unable to find {:?} to replace in tree", - failed_nodes.iter().map(|n| n.id()) - ) - } - - self.data - .mutate(|(d, _)| Gemla::merge_completed_nodes(d.as_mut().unwrap()))??; - - Ok(()) + Gemla::merge_completed_nodes(t) + } else { + warn!("Unable to replce nodes {:?} in empty tree", r); + Ok(()) + } + })? })?; } @@ -145,15 +161,14 @@ where && r.val.state() == GeneticState::Finish => { info!("Merging nodes {} and {}", l.val.id(), r.val.id()); - - let left_node = l.val.as_ref().unwrap(); - let right_node = r.val.as_ref().unwrap(); - let merged_node = GeneticNode::merge(left_node, right_node)?; - tree.val = GeneticNodeWrapper::from( - *merged_node, - tree.val.max_generations(), - tree.val.id(), - ); + if let (Some(left_node), Some(right_node)) = (l.val.as_ref(), r.val.as_ref()) { + let merged_node = GeneticNode::merge(left_node, right_node)?; + tree.val = GeneticNodeWrapper::from( + *merged_node, + tree.val.max_generations(), + tree.val.id(), + ); + } } (Some(l), Some(r)) => { Gemla::merge_completed_nodes(l)?; @@ -162,21 +177,25 @@ where (Some(l), None) if l.val.state() == GeneticState::Finish => { trace!("Copying node {}", l.val.id()); - tree.val = GeneticNodeWrapper::from( - l.val.as_ref().unwrap().clone(), - tree.val.max_generations(), - tree.val.id(), - ); + if let Some(left_node) = l.val.as_ref() { + GeneticNodeWrapper::from( + left_node.clone(), + tree.val.max_generations(), + tree.val.id(), + ); + } } (Some(l), None) => Gemla::merge_completed_nodes(l)?, (None, Some(r)) if r.val.state() == GeneticState::Finish => { trace!("Copying node {}", r.val.id()); - tree.val = GeneticNodeWrapper::from( - r.val.as_ref().unwrap().clone(), - tree.val.max_generations(), - tree.val.id(), - ); + if let Some(right_node) = r.val.as_ref() { + tree.val = GeneticNodeWrapper::from( + right_node.clone(), + tree.val.max_generations(), + tree.val.id(), + ); + } } (None, Some(r)) => Gemla::merge_completed_nodes(r)?, (_, _) => (), @@ -289,7 +308,7 @@ mod tests { use serde::{Deserialize, Serialize}; use std::str::FromStr; - #[derive(Default, Deserialize, Serialize, Clone, Debug, PartialEq)] + #[derive(Deserialize, Serialize, Clone, Debug, PartialEq)] struct TestState { pub score: f64, }