Random nodes

This commit is contained in:
Rendo 2025-11-09 13:19:07 +05:00
commit 76e1a17f6d
2 changed files with 104 additions and 9 deletions

View file

@ -15,14 +15,14 @@ pub enum NodeHandler {
impl NodeHandler { 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(), Self::Number { number } => number.clone(),
NodeHandler::Function { Self::Function {
function, function,
name, name,
max_args, max_args,
} => function(inputs), } => function(inputs),
NodeHandler::Variable => passed_x, Self::Variable => passed_x,
NodeHandler::Empty => inputs[0], Self::Empty => inputs[0],
} }
} }
} }

View file

@ -9,6 +9,9 @@ const TYPE_CHANGE_PROBABILITY: u8 = 10;
pub enum NodeManipulationError { pub enum NodeManipulationError {
TooMuchChildren(Node), TooMuchChildren(Node),
NotEnoughChildren,
ProtectedEmpty,
IndexOutOfRange(usize),
} }
impl fmt::Display for NodeManipulationError { impl fmt::Display for NodeManipulationError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
@ -17,6 +20,9 @@ impl fmt::Display for NodeManipulationError {
"{}", "{}",
match self { match self {
NodeManipulationError::TooMuchChildren(node) => "Too much children", NodeManipulationError::TooMuchChildren(node) => "Too much children",
NodeManipulationError::ProtectedEmpty => "Empty node is protected",
NodeManipulationError::NotEnoughChildren => "Not enough children",
NodeManipulationError::IndexOutOfRange(index) => "Index out of range",
} }
) )
} }
@ -31,11 +37,43 @@ pub struct NodeModifier<'a> {
impl<'a> NodeModifier<'a> { impl<'a> NodeModifier<'a> {
fn get_standard_pool() -> (Vec<NodeHandler>, Vec<fn(f64) -> f64>) { fn get_standard_pool() -> (Vec<NodeHandler>, Vec<fn(f64) -> f64>) {
let standard_function_mutation: Vec<NodeHandler> = vec![NodeHandler::Function { let standard_function_mutation: Vec<NodeHandler> = vec![
name: "Sine".to_string(), NodeHandler::Function {
name: "sin".to_string(),
function: |inputs| inputs[0].sin(), function: |inputs| inputs[0].sin(),
max_args: Some(1), max_args: Some(1),
}]; },
NodeHandler::Function {
name: "cos".to_string(),
function: |inputs| inputs[0].cos(),
max_args: Some(1),
},
NodeHandler::Function {
name: "sum".to_string(),
function: |inputs| inputs.iter().sum(),
max_args: None,
},
NodeHandler::Function {
name: "-".to_string(),
function: |inputs| -inputs[0],
max_args: Some(1),
},
NodeHandler::Function {
name: "product".to_string(),
function: |inputs| inputs.iter().product(),
max_args: None,
},
NodeHandler::Function {
name: "exp".to_string(),
function: |inputs| inputs[0].powf(inputs[1]),
max_args: Some(2),
},
NodeHandler::Function {
name: "1/".to_string(),
function: |inputs| 1f64 / inputs[0],
max_args: 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,
@ -91,6 +129,27 @@ impl<'a> NodeModifier<'a> {
self.picked_node.children.push(node); self.picked_node.children.push(node);
Ok(()) Ok(())
} }
pub fn remove_node(
&mut self,
specified_index: Option<usize>,
) -> Result<(), NodeManipulationError> {
if self.picked_node.children.len() == 0 {
return Err(NodeManipulationError::NotEnoughChildren);
}
match specified_index {
Some(index) => {
if self.picked_node.children.len() <= index {
return Err(NodeManipulationError::IndexOutOfRange(index));
}
self.picked_node.children.remove(index);
Ok(())
}
None => {
self.picked_node.children.remove(0);
Ok(())
}
}
}
pub fn insert_node( pub fn insert_node(
&mut self, &mut self,
@ -113,6 +172,7 @@ 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 {
self.change_node_type(None);
} else { } else {
match &self.picked_node.handler { match &self.picked_node.handler {
NodeHandler::Number { number } => { NodeHandler::Number { number } => {
@ -144,4 +204,39 @@ impl<'a> NodeModifier<'a> {
} }
} }
} }
pub fn change_node_type(&mut self, to: Option<NodeHandler>) {
self.picked_node.handler = to.unwrap_or(self.get_random_handler());
}
pub fn get_random_handler(&self) -> NodeHandler {
let picked = random_range(0..4);
if picked == 0 {
NodeHandler::Number {
number: random_range(0.0..=1e8f64),
}
} else if picked == 1 {
self.function_mutation_pool[random_range(0..self.function_mutation_pool.len())].clone()
} else if picked == 2 {
NodeHandler::Variable
} else {
NodeHandler::Empty
}
}
pub fn get_random_node(&self) -> Node {
let handler = self.get_random_handler();
Node {
children: vec![],
handler: handler.clone(),
max_children_count: match handler {
NodeHandler::Number { number } => Some(0),
NodeHandler::Function {
name,
function,
max_args,
} => max_args,
NodeHandler::Variable => Some(0),
NodeHandler::Empty => Some(1),
},
}
}
} }