August 20th 2021, 2:23 am
This commit is contained in:
parent
61786ab303
commit
f6de0191cd
6 changed files with 276 additions and 86 deletions
|
@ -68,51 +68,53 @@ pub trait GeneticNode {
|
||||||
/// }
|
/// }
|
||||||
///
|
///
|
||||||
/// struct Node {
|
/// struct Node {
|
||||||
/// pub model: Vec<Model>,
|
/// pub models: Vec<Model>,
|
||||||
/// //...
|
/// //...
|
||||||
/// }
|
/// }
|
||||||
///
|
///
|
||||||
/// impl Model {
|
/// impl Model {
|
||||||
/// fn fit(&mut self, epochs: u64) -> Result<(), String> {
|
/// fn fit(&mut self, epochs: u64) -> Result<(), String> {
|
||||||
/// //...
|
/// //...
|
||||||
/// # self.fit_score += epochs as f64;
|
/// # self.fit_score += epochs as f64;
|
||||||
/// # Ok(())
|
/// # Ok(())
|
||||||
/// }
|
/// }
|
||||||
/// }
|
/// }
|
||||||
///
|
///
|
||||||
/// impl GeneticNode for Node {
|
/// impl GeneticNode for Node {
|
||||||
/// # fn initialize() -> Result<Box<Self>, String> {
|
/// # fn initialize() -> Result<Box<Self>, String> {
|
||||||
/// # Ok(Box::new(Node {fit_score: 0.0, model: Model {fit_score: 0.0}}))
|
/// # Ok(Box::new(Node {models: vec![Model {fit_score: 0.0}]}))
|
||||||
/// # }
|
/// # }
|
||||||
/// #
|
/// #
|
||||||
/// //...
|
/// //...
|
||||||
///
|
///
|
||||||
/// fn simulate(&mut self, iterations: u64) -> Result<(), String> {
|
/// fn simulate(&mut self, iterations: u64) -> Result<(), String> {
|
||||||
/// self.model.fit(iterations)?;
|
/// for m in self.models.iter_mut()
|
||||||
/// self.fit_score = self.model.fit_score;
|
/// {
|
||||||
/// Ok(())
|
/// m.fit(iterations)?;
|
||||||
/// }
|
/// }
|
||||||
|
/// Ok(())
|
||||||
|
/// }
|
||||||
///
|
///
|
||||||
/// //...
|
/// //...
|
||||||
|
///
|
||||||
|
/// # fn get_fit_score(&self) -> f64 {
|
||||||
|
/// # self.models.iter().max_by(|m1, m2| m1.fit_score.partial_cmp(&m2.fit_score).unwrap()).unwrap().fit_score
|
||||||
|
/// # }
|
||||||
/// #
|
/// #
|
||||||
/// # fn get_fit_score(&self) -> f64 {
|
/// # fn calculate_scores_and_trim(&mut self) -> Result<(), String> {
|
||||||
/// # self.fit_score
|
/// # Ok(())
|
||||||
/// # }
|
/// # }
|
||||||
/// #
|
/// #
|
||||||
/// # fn calculate_scores_and_trim(&mut self) -> Result<(), String> {
|
/// # fn mutate(&mut self) -> Result<(), String> {
|
||||||
/// # Ok(())
|
/// # Ok(())
|
||||||
/// # }
|
/// # }
|
||||||
/// #
|
|
||||||
/// # fn mutate(&mut self) -> Result<(), String> {
|
|
||||||
/// # Ok(())
|
|
||||||
/// # }
|
|
||||||
/// }
|
/// }
|
||||||
///
|
///
|
||||||
/// # fn main() -> Result<(), String> {
|
/// # fn main() -> Result<(), String> {
|
||||||
/// let mut node = Node::initialize()?;
|
/// let mut node = Node::initialize()?;
|
||||||
/// (*node).simulate(5)?;
|
/// node.simulate(5)?;
|
||||||
/// # assert_eq!(node.get_fit_score(), 5.0);
|
/// assert_eq!(node.get_fit_score(), 5.0);
|
||||||
/// # Ok(())
|
/// # Ok(())
|
||||||
/// # }
|
/// # }
|
||||||
/// ```
|
/// ```
|
||||||
fn simulate(&mut self, iterations: u64) -> Result<(), String>;
|
fn simulate(&mut self, iterations: u64) -> Result<(), String>;
|
||||||
|
@ -121,7 +123,6 @@ pub trait GeneticNode {
|
||||||
/// This will be used by a bracket in order to determine the most successful child.
|
/// This will be used by a bracket in order to determine the most successful child.
|
||||||
///
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
|
||||||
/// ```
|
/// ```
|
||||||
/// # use gemla::bracket::genetic_node::GeneticNode;
|
/// # use gemla::bracket::genetic_node::GeneticNode;
|
||||||
/// #
|
/// #
|
||||||
|
@ -130,47 +131,242 @@ pub trait GeneticNode {
|
||||||
/// //...
|
/// //...
|
||||||
/// }
|
/// }
|
||||||
///
|
///
|
||||||
/// impl GeneticNode for Model {
|
/// struct Node {
|
||||||
|
/// pub models: Vec<Model>,
|
||||||
|
/// //...
|
||||||
|
/// }
|
||||||
|
///
|
||||||
|
/// # impl Model {
|
||||||
|
/// # fn fit(&mut self, epochs: u64) -> Result<(), String> {
|
||||||
|
/// # //...
|
||||||
|
/// # self.fit_score += epochs as f64;
|
||||||
|
/// # Ok(())
|
||||||
|
/// # }
|
||||||
|
/// # }
|
||||||
|
///
|
||||||
|
/// impl GeneticNode for Node {
|
||||||
/// # fn initialize() -> Result<Box<Self>, String> {
|
/// # fn initialize() -> Result<Box<Self>, String> {
|
||||||
/// # Ok(Box::new(Model {fit_score: 0.0, model: Model {fit_score: 0.0}}))
|
/// # Ok(Box::new(Node {models: vec![Model {fit_score: 0.0}]}))
|
||||||
/// # }
|
/// # }
|
||||||
///
|
/// #
|
||||||
|
/// # //...
|
||||||
|
/// #
|
||||||
|
/// # fn simulate(&mut self, iterations: u64) -> Result<(), String> {
|
||||||
|
/// # for m in self.models.iter_mut()
|
||||||
|
/// # {
|
||||||
|
/// # m.fit(iterations)?;
|
||||||
|
/// # }
|
||||||
|
/// # Ok(())
|
||||||
|
/// # }
|
||||||
|
/// #
|
||||||
/// //...
|
/// //...
|
||||||
///
|
///
|
||||||
/// # fn simulate(&mut self, iterations: u64) -> Result<(), String> {
|
/// fn get_fit_score(&self) -> f64 {
|
||||||
/// # self.model.fit(iterations)?;
|
/// self.models.iter().max_by(|m1, m2| m1.fit_score.partial_cmp(&m2.fit_score).unwrap()).unwrap().fit_score
|
||||||
/// # self.fit_score = self.model.fit_score;
|
/// }
|
||||||
/// # Ok(())
|
|
||||||
/// # }
|
|
||||||
/// #
|
|
||||||
/// #
|
|
||||||
/// fn get_fit_score(&self) -> f64 {
|
|
||||||
/// self.fit_score
|
|
||||||
/// }
|
|
||||||
///
|
///
|
||||||
/// //...
|
/// //...
|
||||||
|
/// # fn calculate_scores_and_trim(&mut self) -> Result<(), String> {
|
||||||
|
/// # Ok(())
|
||||||
|
/// # }
|
||||||
/// #
|
/// #
|
||||||
/// # fn calculate_scores_and_trim(&mut self) -> Result<(), String> {
|
/// # fn mutate(&mut self) -> Result<(), String> {
|
||||||
/// # Ok(())
|
/// # Ok(())
|
||||||
/// # }
|
/// # }
|
||||||
/// #
|
|
||||||
/// # fn mutate(&mut self) -> Result<(), String> {
|
|
||||||
/// # Ok(())
|
|
||||||
/// # }
|
|
||||||
/// }
|
/// }
|
||||||
///
|
///
|
||||||
/// # fn main() -> Result<(), String> {
|
/// # fn main() -> Result<(), String> {
|
||||||
/// let mut model = Model::initialize()?;
|
/// let mut node = Node::initialize()?;
|
||||||
/// assert_eq!(node.get_fit_score(), 0.0);
|
/// node.simulate(5)?;
|
||||||
/// # Ok(())
|
/// assert_eq!(node.get_fit_score(), 5.0);
|
||||||
|
/// # Ok(())
|
||||||
/// # }
|
/// # }
|
||||||
/// ```
|
/// ```
|
||||||
fn get_fit_score(&self) -> f64;
|
fn get_fit_score(&self) -> f64;
|
||||||
|
|
||||||
/// Used when scoring the nodes after simulating and should remove underperforming children.
|
/// Used when scoring the nodes after simulating and should remove underperforming children.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
/// ```
|
||||||
|
/// # use gemla::bracket::genetic_node::GeneticNode;
|
||||||
|
/// #
|
||||||
|
/// struct Model {
|
||||||
|
/// pub fit_score: f64,
|
||||||
|
/// //...
|
||||||
|
/// }
|
||||||
|
///
|
||||||
|
/// struct Node {
|
||||||
|
/// pub models: Vec<Model>,
|
||||||
|
/// population_size: i64,
|
||||||
|
/// //...
|
||||||
|
/// }
|
||||||
|
///
|
||||||
|
/// # impl Model {
|
||||||
|
/// # fn fit(&mut self, epochs: u64) -> Result<(), String> {
|
||||||
|
/// # //...
|
||||||
|
/// # self.fit_score += epochs as f64;
|
||||||
|
/// # Ok(())
|
||||||
|
/// # }
|
||||||
|
/// # }
|
||||||
|
///
|
||||||
|
/// impl GeneticNode for Node {
|
||||||
|
/// # fn initialize() -> Result<Box<Self>, String> {
|
||||||
|
/// # Ok(Box::new(Node {
|
||||||
|
/// # models: vec![
|
||||||
|
/// # Model { fit_score: 0.0 },
|
||||||
|
/// # Model { fit_score: 1.0 },
|
||||||
|
/// # Model { fit_score: 2.0 },
|
||||||
|
/// # Model { fit_score: 3.0 },
|
||||||
|
/// # Model { fit_score: 4.0 },
|
||||||
|
/// # ],
|
||||||
|
/// # population_size: 5,
|
||||||
|
/// # }))
|
||||||
|
/// # }
|
||||||
|
/// #
|
||||||
|
/// # //...
|
||||||
|
/// #
|
||||||
|
/// # fn simulate(&mut self, iterations: u64) -> Result<(), String> {
|
||||||
|
/// # for m in self.models.iter_mut() {
|
||||||
|
/// # m.fit(iterations)?;
|
||||||
|
/// # }
|
||||||
|
/// # Ok(())
|
||||||
|
/// # }
|
||||||
|
/// #
|
||||||
|
/// //...
|
||||||
|
///
|
||||||
|
/// # fn get_fit_score(&self) -> f64 {
|
||||||
|
/// # self.models
|
||||||
|
/// # .iter()
|
||||||
|
/// # .max_by(|m1, m2| m1.fit_score.partial_cmp(&m2.fit_score).unwrap())
|
||||||
|
/// # .unwrap()
|
||||||
|
/// # .fit_score
|
||||||
|
/// # }
|
||||||
|
/// #
|
||||||
|
/// fn calculate_scores_and_trim(&mut self) -> Result<(), String> {
|
||||||
|
/// self.models.sort_by(|a, b| a.fit_score.partial_cmp(&b.fit_score).unwrap().reverse());
|
||||||
|
/// self.models.truncate(3);
|
||||||
|
/// Ok(())
|
||||||
|
/// }
|
||||||
|
///
|
||||||
|
/// //...
|
||||||
|
/// #
|
||||||
|
/// # fn mutate(&mut self) -> Result<(), String> {
|
||||||
|
/// # Ok(())
|
||||||
|
/// # }
|
||||||
|
/// }
|
||||||
|
///
|
||||||
|
/// # fn main() -> Result<(), String> {
|
||||||
|
/// let mut node = Node::initialize()?;
|
||||||
|
/// assert_eq!(node.models.len(), 5);
|
||||||
|
///
|
||||||
|
/// node.simulate(5)?;
|
||||||
|
/// node.calculate_scores_and_trim()?;
|
||||||
|
/// assert_eq!(node.models.len(), 3);
|
||||||
|
///
|
||||||
|
/// # assert_eq!(node.get_fit_score(), 9.0);
|
||||||
|
/// # Ok(())
|
||||||
|
/// # }
|
||||||
|
/// ```
|
||||||
fn calculate_scores_and_trim(&mut self) -> Result<(), String>;
|
fn calculate_scores_and_trim(&mut self) -> Result<(), String>;
|
||||||
|
|
||||||
/// Mutates members in a population and/or crossbreeds them to produce new offspring.
|
/// Mutates members in a population and/or crossbreeds them to produce new offspring.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
/// ```
|
||||||
|
/// # use gemla::bracket::genetic_node::GeneticNode;
|
||||||
|
/// # use std::convert::TryInto;
|
||||||
|
/// #
|
||||||
|
/// struct Model {
|
||||||
|
/// pub fit_score: f64,
|
||||||
|
/// //...
|
||||||
|
/// }
|
||||||
|
///
|
||||||
|
/// struct Node {
|
||||||
|
/// pub models: Vec<Model>,
|
||||||
|
/// population_size: i64,
|
||||||
|
/// //...
|
||||||
|
/// }
|
||||||
|
///
|
||||||
|
/// # impl Model {
|
||||||
|
/// # fn fit(&mut self, epochs: u64) -> Result<(), String> {
|
||||||
|
/// # //...
|
||||||
|
/// # self.fit_score += epochs as f64;
|
||||||
|
/// # Ok(())
|
||||||
|
/// # }
|
||||||
|
/// # }
|
||||||
|
///
|
||||||
|
/// fn mutate_random_individuals(_models: &Vec<Model>) -> Model
|
||||||
|
/// {
|
||||||
|
/// //...
|
||||||
|
/// # Model {
|
||||||
|
/// # fit_score: 0.0
|
||||||
|
/// # }
|
||||||
|
/// }
|
||||||
|
///
|
||||||
|
/// impl GeneticNode for Node {
|
||||||
|
/// # fn initialize() -> Result<Box<Self>, String> {
|
||||||
|
/// # Ok(Box::new(Node {
|
||||||
|
/// # models: vec![
|
||||||
|
/// # Model { fit_score: 0.0 },
|
||||||
|
/// # Model { fit_score: 1.0 },
|
||||||
|
/// # Model { fit_score: 2.0 },
|
||||||
|
/// # Model { fit_score: 3.0 },
|
||||||
|
/// # Model { fit_score: 4.0 },
|
||||||
|
/// # ],
|
||||||
|
/// # population_size: 5,
|
||||||
|
/// # }))
|
||||||
|
/// # }
|
||||||
|
/// #
|
||||||
|
/// # fn simulate(&mut self, iterations: u64) -> Result<(), String> {
|
||||||
|
/// # for m in self.models.iter_mut() {
|
||||||
|
/// # m.fit(iterations)?;
|
||||||
|
/// # }
|
||||||
|
/// # Ok(())
|
||||||
|
/// # }
|
||||||
|
/// #
|
||||||
|
/// # fn get_fit_score(&self) -> f64 {
|
||||||
|
/// # self.models
|
||||||
|
/// # .iter()
|
||||||
|
/// # .max_by(|m1, m2| m1.fit_score.partial_cmp(&m2.fit_score).unwrap())
|
||||||
|
/// # .unwrap()
|
||||||
|
/// # .fit_score
|
||||||
|
/// # }
|
||||||
|
/// #
|
||||||
|
/// # fn calculate_scores_and_trim(&mut self) -> Result<(), String> {
|
||||||
|
/// # self.models.sort_by(|a, b| a.fit_score.partial_cmp(&b.fit_score).unwrap().reverse());
|
||||||
|
/// # self.models.truncate(3);
|
||||||
|
/// # Ok(())
|
||||||
|
/// # }
|
||||||
|
/// //...
|
||||||
|
///
|
||||||
|
/// fn mutate(&mut self) -> Result<(), String> {
|
||||||
|
/// loop {
|
||||||
|
/// if self.models.len() < self.population_size.try_into().unwrap()
|
||||||
|
/// {
|
||||||
|
/// self.models.push(mutate_random_individuals(&self.models))
|
||||||
|
/// }
|
||||||
|
/// else{
|
||||||
|
/// return Ok(());
|
||||||
|
/// }
|
||||||
|
/// }
|
||||||
|
/// }
|
||||||
|
/// }
|
||||||
|
///
|
||||||
|
/// # fn main() -> Result<(), String> {
|
||||||
|
/// let mut node = Node::initialize()?;
|
||||||
|
/// assert_eq!(node.models.len(), 5);
|
||||||
|
///
|
||||||
|
/// node.simulate(5)?;
|
||||||
|
/// node.calculate_scores_and_trim()?;
|
||||||
|
/// assert_eq!(node.models.len(), 3);
|
||||||
|
///
|
||||||
|
/// node.mutate()?;
|
||||||
|
/// assert_eq!(node.models.len(), 5);
|
||||||
|
///
|
||||||
|
/// # assert_eq!(node.get_fit_score(), 9.0);
|
||||||
|
/// # Ok(())
|
||||||
|
/// # }
|
||||||
|
/// ```
|
||||||
fn mutate(&mut self) -> Result<(), String>;
|
fn mutate(&mut self) -> Result<(), String>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -124,8 +124,7 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests
|
mod tests {
|
||||||
{
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
@ -237,5 +236,4 @@ mod tests
|
||||||
|
|
||||||
std::fs::remove_file("./temp2").expect("Unable to remove file");
|
std::fs::remove_file("./temp2").expect("Unable to remove file");
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -141,5 +141,4 @@ mod tests {
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,7 +23,6 @@
|
||||||
//! //# }
|
//! //# }
|
||||||
//! ```
|
//! ```
|
||||||
|
|
||||||
|
|
||||||
use serde::de::DeserializeOwned;
|
use serde::de::DeserializeOwned;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
@ -136,10 +135,8 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests
|
mod tests {
|
||||||
{
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
Loading…
Add table
Reference in a new issue