Functions now have names

This commit is contained in:
Rendo 2025-11-09 01:43:11 +05:00
commit 0c097a72fb
5 changed files with 66 additions and 43 deletions

View file

@ -1,10 +0,0 @@
pub fn sine(inputs: Vec<f64>) -> f64 {
inputs[0].sin()
}
pub fn sum(inputs: Vec<f64>) -> f64 {
let mut sum = 0f64;
for i in inputs {
sum += i;
}
sum
}

View file

@ -1,7 +1,13 @@
#[derive(Clone, Copy)] #[derive(Clone)]
pub enum NodeHandler { pub enum NodeHandler {
Number { number: f64 }, Number {
Function { function: fn(Vec<f64>) -> f64 }, number: f64,
},
Function {
name: String,
function: fn(Vec<f64>) -> f64,
max_args: Option<usize>,
},
Variable, Variable,
Empty, Empty,
} }
@ -10,7 +16,11 @@ impl NodeHandler {
pub fn run(&self, inputs: Vec<f64>, passed_x: f64) -> f64 { pub fn run(&self, inputs: Vec<f64>, passed_x: f64) -> f64 {
match self { match self {
NodeHandler::Number { number } => number.clone(), NodeHandler::Number { number } => number.clone(),
NodeHandler::Function { function } => function(inputs), NodeHandler::Function {
function,
name,
max_args,
} => function(inputs),
NodeHandler::Variable => passed_x, NodeHandler::Variable => passed_x,
NodeHandler::Empty => inputs[0], NodeHandler::Empty => inputs[0],
} }

View file

@ -3,7 +3,6 @@ use std::fmt;
use crate::node::node_modifier::NodeModifier; use crate::node::node_modifier::NodeModifier;
use handler::*; use handler::*;
mod functions;
mod handler; mod handler;
pub mod node_modifier; pub mod node_modifier;
@ -40,10 +39,18 @@ impl Node {
max_children_count: Some(0), max_children_count: Some(0),
} }
} }
pub fn function(func: fn(Vec<f64>) -> f64, max_children_count: Option<usize>) -> Self { pub fn function(
func_name: String,
func: fn(Vec<f64>) -> f64,
max_children_count: Option<usize>,
) -> Self {
Self { Self {
children: vec![], children: vec![],
handler: NodeHandler::Function { function: func }, handler: NodeHandler::Function {
name: func_name,
function: func,
max_args: max_children_count,
},
max_children_count, max_children_count,
} }
} }
@ -78,9 +85,13 @@ impl fmt::Display for Node {
write!( write!(
f, f,
"{}", "{}",
match self.handler { match &self.handler {
NodeHandler::Number { number } => number.to_string(), 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::Variable => "X".to_string(),
NodeHandler::Empty => "Empty".to_string(), NodeHandler::Empty => "Empty".to_string(),
} }

View file

@ -2,7 +2,6 @@ use std::fmt;
use crate::node::Node; use crate::node::Node;
use crate::node::NodeHandler; use crate::node::NodeHandler;
use crate::node::functions;
use rand::random_range; use rand::random_range;
const PICK_STOP_PROBABILITY: u8 = 2; const PICK_STOP_PROBABILITY: u8 = 2;
@ -26,17 +25,17 @@ impl fmt::Display for NodeManipulationError {
pub struct NodeModifier<'a> { pub struct NodeModifier<'a> {
picked_node: &'a mut Node, 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" // 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>) -> f64, Option<usize>)>, function_mutation_pool: Vec<NodeHandler>,
number_mutation_pool: Vec<fn(f64) -> f64>, number_mutation_pool: Vec<fn(f64) -> f64>,
} }
impl<'a> NodeModifier<'a> { impl<'a> NodeModifier<'a> {
fn get_standard_pool() -> ( fn get_standard_pool() -> (Vec<NodeHandler>, Vec<fn(f64) -> f64>) {
Vec<(fn(Vec<f64>) -> f64, Option<usize>)>, let standard_function_mutation: Vec<NodeHandler> = vec![NodeHandler::Function {
Vec<fn(f64) -> f64>, name: "Sine".to_string(),
) { function: |inputs| inputs[0].sin(),
let standard_function_mutation: Vec<(fn(Vec<f64>) -> f64, Option<usize>)> = max_args: Some(1),
vec![(functions::sine, Some(1))]; }];
let standard_number_mutation: Vec<fn(f64) -> f64> = vec![ let standard_number_mutation: Vec<fn(f64) -> f64> = vec![
|x| x * 4f64, |x| x * 4f64,
|x| x / 4.0f64, |x| x / 4.0f64,
@ -50,10 +49,7 @@ impl<'a> NodeModifier<'a> {
//Builders //Builders
pub fn from_random( pub fn from_random(
root: &'a mut Node, root: &'a mut Node,
custom_pools: Option<( custom_pools: Option<(Vec<NodeHandler>, Vec<fn(f64) -> f64>)>,
Vec<(fn(Vec<f64>) -> f64, Option<usize>)>,
Vec<fn(f64) -> f64>,
)>,
) -> Self { ) -> Self {
let mut selected = root; let mut selected = root;
while random_range(0..PICK_STOP_PROBABILITY) == PICK_STOP_PROBABILITY - 1 { while random_range(0..PICK_STOP_PROBABILITY) == PICK_STOP_PROBABILITY - 1 {
@ -72,10 +68,7 @@ impl<'a> NodeModifier<'a> {
} }
pub fn from_node( pub fn from_node(
node: &'a mut Node, node: &'a mut Node,
custom_pools: Option<( custom_pools: Option<(Vec<NodeHandler>, Vec<fn(f64) -> f64>)>,
Vec<(fn(Vec<f64>) -> f64, Option<usize>)>,
Vec<fn(f64) -> f64>,
)>,
) -> Self { ) -> Self {
let pools = custom_pools.unwrap_or(NodeModifier::get_standard_pool()); let pools = custom_pools.unwrap_or(NodeModifier::get_standard_pool());
Self { Self {
@ -121,21 +114,30 @@ impl<'a> NodeModifier<'a> {
pub fn mutate_node(&mut self) { pub fn mutate_node(&mut self) {
if random_range(0..TYPE_CHANGE_PROBABILITY) == TYPE_CHANGE_PROBABILITY - 1 { if random_range(0..TYPE_CHANGE_PROBABILITY) == TYPE_CHANGE_PROBABILITY - 1 {
} else { } else {
match self.picked_node.handler { match &self.picked_node.handler {
NodeHandler::Number { number } => { NodeHandler::Number { number } => {
self.picked_node.handler = NodeHandler::Number { self.picked_node.handler = NodeHandler::Number {
number: (self.number_mutation_pool number: (self.number_mutation_pool
[random_range(0..self.number_mutation_pool.len())])( [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 let selected_mutation = &self.function_mutation_pool
[random_range(0..self.function_mutation_pool.len())]; [random_range(0..self.function_mutation_pool.len())];
self.picked_node.max_children_count = selected_mutation.1; if let NodeHandler::Function {
self.picked_node.handler = NodeHandler::Function { name,
function: selected_mutation.0, function,
max_args,
} = &selected_mutation
{
self.picked_node.max_children_count = max_args.clone();
self.picked_node.handler = selected_mutation.clone();
} }
} }
_ => {} _ => {}

View file

@ -13,7 +13,14 @@ fn test_plus_one() {
assert!( assert!(
formula formula
.modify_tree() .modify_tree()
.insert_node(Node::function(|inputs| inputs[0] + 1f64, Some(1)), None) .insert_node(
Node::function(
"+1".to_string(),
|inputs: Vec<f64>| inputs[0] + 1f64,
Some(1)
),
None
)
.is_err() .is_err()
== false == false
); );
@ -27,7 +34,10 @@ fn test_branch_sum() {
assert!( assert!(
formula formula
.modify_tree() .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() .is_err()
== false == false
); );