From 0c097a72fba23e595f742e8975ba8cdce6b6848b Mon Sep 17 00:00:00 2001 From: Rendo Date: Sun, 9 Nov 2025 01:43:11 +0500 Subject: [PATCH] Functions now have names --- src/node/functions.rs | 10 --------- src/node/handler.rs | 18 +++++++++++---- src/node/mod.rs | 21 +++++++++++++----- src/node/node_modifier.rs | 46 ++++++++++++++++++++------------------- src/tests.rs | 14 ++++++++++-- 5 files changed, 66 insertions(+), 43 deletions(-) delete mode 100644 src/node/functions.rs diff --git a/src/node/functions.rs b/src/node/functions.rs deleted file mode 100644 index dc55816..0000000 --- a/src/node/functions.rs +++ /dev/null @@ -1,10 +0,0 @@ -pub fn sine(inputs: Vec) -> f64 { - inputs[0].sin() -} -pub fn sum(inputs: Vec) -> f64 { - let mut sum = 0f64; - for i in inputs { - sum += i; - } - sum -} diff --git a/src/node/handler.rs b/src/node/handler.rs index bebf744..50254e3 100644 --- a/src/node/handler.rs +++ b/src/node/handler.rs @@ -1,7 +1,13 @@ -#[derive(Clone, Copy)] +#[derive(Clone)] pub enum NodeHandler { - Number { number: f64 }, - Function { function: fn(Vec) -> f64 }, + Number { + number: f64, + }, + Function { + name: String, + function: fn(Vec) -> f64, + max_args: Option, + }, Variable, Empty, } @@ -10,7 +16,11 @@ impl NodeHandler { pub fn run(&self, inputs: Vec, passed_x: f64) -> f64 { match self { NodeHandler::Number { number } => number.clone(), - NodeHandler::Function { function } => function(inputs), + NodeHandler::Function { + function, + name, + max_args, + } => function(inputs), NodeHandler::Variable => passed_x, NodeHandler::Empty => inputs[0], } diff --git a/src/node/mod.rs b/src/node/mod.rs index 06b3746..ce00cc6 100644 --- a/src/node/mod.rs +++ b/src/node/mod.rs @@ -3,7 +3,6 @@ use std::fmt; use crate::node::node_modifier::NodeModifier; use handler::*; -mod functions; mod handler; pub mod node_modifier; @@ -40,10 +39,18 @@ impl Node { max_children_count: Some(0), } } - pub fn function(func: fn(Vec) -> f64, max_children_count: Option) -> Self { + pub fn function( + func_name: String, + func: fn(Vec) -> f64, + max_children_count: Option, + ) -> Self { Self { children: vec![], - handler: NodeHandler::Function { function: func }, + handler: NodeHandler::Function { + name: func_name, + function: func, + max_args: max_children_count, + }, max_children_count, } } @@ -78,9 +85,13 @@ impl fmt::Display for Node { write!( f, "{}", - match self.handler { + match &self.handler { NodeHandler::Number { number } => number.to_string(), - NodeHandler::Function { function } => "Function".to_string(), + NodeHandler::Function { + function, + name, + max_args, + } => name.clone(), 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 b41047c..1a40ac4 100644 --- a/src/node/node_modifier.rs +++ b/src/node/node_modifier.rs @@ -2,7 +2,6 @@ use std::fmt; use crate::node::Node; use crate::node::NodeHandler; -use crate::node::functions; use rand::random_range; const PICK_STOP_PROBABILITY: u8 = 2; @@ -26,17 +25,17 @@ impl fmt::Display for NodeManipulationError { pub struct NodeModifier<'a> { picked_node: &'a mut Node, // This looks very monstrous, but it means "vector of functions for node paired with their maximum children count, if it exists" - function_mutation_pool: Vec<(fn(Vec) -> f64, Option)>, + function_mutation_pool: Vec, number_mutation_pool: Vec f64>, } impl<'a> NodeModifier<'a> { - fn get_standard_pool() -> ( - Vec<(fn(Vec) -> f64, Option)>, - Vec f64>, - ) { - let standard_function_mutation: Vec<(fn(Vec) -> f64, Option)> = - vec![(functions::sine, Some(1))]; + fn get_standard_pool() -> (Vec, Vec f64>) { + let standard_function_mutation: Vec = vec![NodeHandler::Function { + name: "Sine".to_string(), + function: |inputs| inputs[0].sin(), + max_args: Some(1), + }]; let standard_number_mutation: Vec f64> = vec![ |x| x * 4f64, |x| x / 4.0f64, @@ -50,10 +49,7 @@ impl<'a> NodeModifier<'a> { //Builders pub fn from_random( root: &'a mut Node, - custom_pools: Option<( - Vec<(fn(Vec) -> f64, Option)>, - Vec f64>, - )>, + custom_pools: Option<(Vec, Vec f64>)>, ) -> Self { let mut selected = root; while random_range(0..PICK_STOP_PROBABILITY) == PICK_STOP_PROBABILITY - 1 { @@ -72,10 +68,7 @@ impl<'a> NodeModifier<'a> { } pub fn from_node( node: &'a mut Node, - custom_pools: Option<( - Vec<(fn(Vec) -> f64, Option)>, - Vec f64>, - )>, + custom_pools: Option<(Vec, Vec f64>)>, ) -> Self { let pools = custom_pools.unwrap_or(NodeModifier::get_standard_pool()); Self { @@ -121,21 +114,30 @@ impl<'a> NodeModifier<'a> { pub fn mutate_node(&mut self) { if random_range(0..TYPE_CHANGE_PROBABILITY) == TYPE_CHANGE_PROBABILITY - 1 { } else { - match self.picked_node.handler { + match &self.picked_node.handler { NodeHandler::Number { number } => { self.picked_node.handler = NodeHandler::Number { number: (self.number_mutation_pool [random_range(0..self.number_mutation_pool.len())])( - number + number.clone() ), }; } - NodeHandler::Function { function } => { + NodeHandler::Function { + function, + name, + max_args, + } => { let selected_mutation = &self.function_mutation_pool [random_range(0..self.function_mutation_pool.len())]; - self.picked_node.max_children_count = selected_mutation.1; - self.picked_node.handler = NodeHandler::Function { - function: selected_mutation.0, + if let NodeHandler::Function { + name, + function, + max_args, + } = &selected_mutation + { + self.picked_node.max_children_count = max_args.clone(); + self.picked_node.handler = selected_mutation.clone(); } } _ => {} diff --git a/src/tests.rs b/src/tests.rs index 4a889af..234e12b 100644 --- a/src/tests.rs +++ b/src/tests.rs @@ -13,7 +13,14 @@ fn test_plus_one() { assert!( formula .modify_tree() - .insert_node(Node::function(|inputs| inputs[0] + 1f64, Some(1)), None) + .insert_node( + Node::function( + "+1".to_string(), + |inputs: Vec| inputs[0] + 1f64, + Some(1) + ), + None + ) .is_err() == false ); @@ -27,7 +34,10 @@ fn test_branch_sum() { assert!( formula .modify_tree() - .insert_node(Node::function(|inputs| inputs.iter().sum(), Some(2)), None) + .insert_node( + Node::function("Sum".to_string(), |inputs| inputs.iter().sum(), Some(2)), + None + ) .is_err() == false );