diff --git a/src/formula.rs b/src/formula.rs index f2700da..179fe40 100644 --- a/src/formula.rs +++ b/src/formula.rs @@ -1,4 +1,5 @@ use crate::node::Node; +use crate::node::node_modifier::NodeModifier; #[derive(Clone)] pub struct Formula { @@ -10,7 +11,7 @@ impl Formula { let mut formula = Self { tree: Node::empty(), }; - formula.tree.modify_tree().add_node(Node::variable()); + formula.tree.modify_node().add_node(Node::variable()); formula } @@ -22,4 +23,29 @@ impl Formula { outputs } pub fn mutate(&mut self) {} + + pub fn modify_tree(&mut self) -> NodeModifier { + self.tree.modify_tree() + } + pub fn display_tree(&self) { + self.display_recursion(0, vec![&self.tree]); + } + fn display_recursion(&self, indent_level: u8, nodes: Vec<&Node>) { + for node in nodes { + if indent_level != 0 { + for _ in 0..(indent_level) { + print!("|\t"); + } + } + println!("{node}"); + if node.children.len() == 0 { + continue; + } + let mut next_nodes: Vec<&Node> = Vec::new(); + for node in &node.children { + next_nodes.push(node); + } + self.display_recursion(indent_level + 1, next_nodes); + } + } } diff --git a/src/lib.rs b/src/lib.rs index 52cf965..ac0c947 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,2 +1,4 @@ -mod formula; -mod node; +pub mod formula; +pub mod node; +#[cfg(test)] +mod tests; diff --git a/src/main.rs b/src/main.rs index 9e18c4f..e1b67d2 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,9 +1,22 @@ -use crate::formula::Formula; +use crate::{formula::Formula, node::Node}; mod formula; mod node; +#[cfg(test)] +mod tests; fn main() { - let formula = Formula::new(); - dbg!(formula.run(vec![1f64])); + let mut formula = Formula::new(); + formula + .modify_tree() + .insert_node(Node::function(|inputs| inputs.iter().sum(), Some(2)), None); + if let Err(x) = formula + .modify_tree() + .go_down(0) + .add_node(Node::number(1f64)) + { + println!("{x}"); + } + formula.display_tree(); + let results = formula.run(vec![0f64, 1f64, 2f64, 3f64, 4f64, 5f64]); } diff --git a/src/node/mod.rs b/src/node/mod.rs index 34dcad1..06b3746 100644 --- a/src/node/mod.rs +++ b/src/node/mod.rs @@ -1,15 +1,17 @@ +use std::fmt; + use crate::node::node_modifier::NodeModifier; use handler::*; mod functions; mod handler; -mod node_modifier; +pub mod node_modifier; #[derive(Clone)] pub struct Node { - children: Vec, - handler: NodeHandler, - max_children_count: Option, + pub(crate) children: Vec, + pub(crate) handler: NodeHandler, + pub(crate) max_children_count: Option, } impl Node { @@ -63,7 +65,25 @@ impl Node { return self.handler.run(inputs, passed_x); } - pub fn modify_tree(&mut self) -> NodeModifier { + pub fn modify_node(&mut self) -> NodeModifier { NodeModifier::from_random(self, None) } + pub fn modify_tree(&mut self) -> NodeModifier { + NodeModifier::from_node(self, None) + } +} + +impl fmt::Display for Node { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!( + f, + "{}", + match self.handler { + NodeHandler::Number { number } => number.to_string(), + NodeHandler::Function { function } => "Function".to_string(), + NodeHandler::Variable => "X".to_string(), + NodeHandler::Empty => "Empty".to_string(), + } + ) + } } diff --git a/src/node/node_modifier.rs b/src/node/node_modifier.rs index b2cd066..655a104 100644 --- a/src/node/node_modifier.rs +++ b/src/node/node_modifier.rs @@ -1,3 +1,5 @@ +use std::fmt; + use crate::node::Node; use crate::node::NodeHandler; use crate::node::functions; @@ -9,6 +11,17 @@ const TYPE_CHANGE_PROBABILITY: u8 = 10; pub enum NodeManipulationError { TooMuchChildren(Node), } +impl fmt::Display for NodeManipulationError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!( + f, + "{}", + match self { + NodeManipulationError::TooMuchChildren(node) => "Too much children", + } + ) + } +} pub struct NodeModifier<'a> { picked_node: &'a mut Node, @@ -71,6 +84,10 @@ impl<'a> NodeModifier<'a> { number_mutation_pool: pools.1, } } + pub fn go_down(mut self, to_child: usize) -> Self { + self.picked_node = &mut self.picked_node.children[to_child]; + self + } pub fn add_node(&mut self, node: Node) -> Result<(), NodeManipulationError> { if let Some(x) = self.picked_node.max_children_count { diff --git a/src/tests.rs b/src/tests.rs new file mode 100644 index 0000000..8a16cb1 --- /dev/null +++ b/src/tests.rs @@ -0,0 +1,38 @@ +use crate::{formula::Formula, node::Node}; + +#[test] +fn test_node_variable() { + let formula = Formula::new(); + let results = formula.run(vec![0f64, 1f64, 2f64, 3f64, 4f64, 5f64]); + assert_eq!(results, vec![0f64, 1f64, 2f64, 3f64, 4f64, 5f64]) +} + +#[test] +fn test_plus_one() { + let mut formula = Formula::new(); + assert!( + formula + .modify_tree() + .insert_node(Node::function(|inputs| inputs[0] + 1f64, Some(1)), None) + .is_err() + == false + ); + let results = formula.run(vec![0f64, 1f64, 2f64, 3f64, 4f64, 5f64]); + assert_eq!(results, vec![1f64, 2f64, 3f64, 4f64, 5f64, 6f64]) +} + +#[test] +fn test_branch_sum() { + let mut formula = Formula::new(); + assert!( + formula + .modify_tree() + .insert_node(Node::function(|inputs| inputs.iter().sum(), Some(2)), None) + .is_err() + == false + ); + assert!(formula.modify_tree().add_node(Node::number(1f64)).is_err() == false); + formula.display_tree(); + let results = formula.run(vec![0f64, 1f64, 2f64, 3f64, 4f64, 5f64]); + assert_eq!(results, vec![1f64, 2f64, 3f64, 4f64, 5f64, 6f64]) +}