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 {
Number { number: f64 },
Function { function: fn(Vec<f64>) -> f64 },
Number {
number: f64,
},
Function {
name: String,
function: fn(Vec<f64>) -> f64,
max_args: Option<usize>,
},
Variable,
Empty,
}
@ -10,7 +16,11 @@ impl NodeHandler {
pub fn run(&self, inputs: Vec<f64>, 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],
}

View file

@ -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>) -> 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 {
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(),
}

View file

@ -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>) -> f64, Option<usize>)>,
function_mutation_pool: Vec<NodeHandler>,
number_mutation_pool: Vec<fn(f64) -> f64>,
}
impl<'a> NodeModifier<'a> {
fn get_standard_pool() -> (
Vec<(fn(Vec<f64>) -> f64, Option<usize>)>,
Vec<fn(f64) -> f64>,
) {
let standard_function_mutation: Vec<(fn(Vec<f64>) -> f64, Option<usize>)> =
vec![(functions::sine, Some(1))];
fn get_standard_pool() -> (Vec<NodeHandler>, Vec<fn(f64) -> f64>) {
let standard_function_mutation: Vec<NodeHandler> = vec![NodeHandler::Function {
name: "Sine".to_string(),
function: |inputs| inputs[0].sin(),
max_args: Some(1),
}];
let standard_number_mutation: Vec<fn(f64) -> 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>) -> f64, Option<usize>)>,
Vec<fn(f64) -> f64>,
)>,
custom_pools: Option<(Vec<NodeHandler>, Vec<fn(f64) -> 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>) -> f64, Option<usize>)>,
Vec<fn(f64) -> f64>,
)>,
custom_pools: Option<(Vec<NodeHandler>, Vec<fn(f64) -> 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();
}
}
_ => {}

View file

@ -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<f64>| 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
);