Random nodes
This commit is contained in:
parent
80c9d47399
commit
76e1a17f6d
2 changed files with 104 additions and 9 deletions
|
|
@ -15,14 +15,14 @@ pub enum NodeHandler {
|
|||
impl NodeHandler {
|
||||
pub fn run(&self, inputs: Vec<f64>, passed_x: f64) -> f64 {
|
||||
match self {
|
||||
NodeHandler::Number { number } => number.clone(),
|
||||
NodeHandler::Function {
|
||||
Self::Number { number } => number.clone(),
|
||||
Self::Function {
|
||||
function,
|
||||
name,
|
||||
max_args,
|
||||
} => function(inputs),
|
||||
NodeHandler::Variable => passed_x,
|
||||
NodeHandler::Empty => inputs[0],
|
||||
Self::Variable => passed_x,
|
||||
Self::Empty => inputs[0],
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,6 +9,9 @@ const TYPE_CHANGE_PROBABILITY: u8 = 10;
|
|||
|
||||
pub enum NodeManipulationError {
|
||||
TooMuchChildren(Node),
|
||||
NotEnoughChildren,
|
||||
ProtectedEmpty,
|
||||
IndexOutOfRange(usize),
|
||||
}
|
||||
impl fmt::Display for NodeManipulationError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
|
|
@ -17,6 +20,9 @@ impl fmt::Display for NodeManipulationError {
|
|||
"{}",
|
||||
match self {
|
||||
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> {
|
||||
fn get_standard_pool() -> (Vec<NodeHandler>, Vec<fn(f64) -> f64>) {
|
||||
let standard_function_mutation: Vec<NodeHandler> = vec![NodeHandler::Function {
|
||||
name: "Sine".to_string(),
|
||||
let standard_function_mutation: Vec<NodeHandler> = vec![
|
||||
NodeHandler::Function {
|
||||
name: "sin".to_string(),
|
||||
function: |inputs| inputs[0].sin(),
|
||||
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![
|
||||
|x| x * 4f64,
|
||||
|x| x / 4.0f64,
|
||||
|
|
@ -91,6 +129,27 @@ impl<'a> NodeModifier<'a> {
|
|||
self.picked_node.children.push(node);
|
||||
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(
|
||||
&mut self,
|
||||
|
|
@ -113,6 +172,7 @@ impl<'a> NodeModifier<'a> {
|
|||
|
||||
pub fn mutate_node(&mut self) {
|
||||
if random_range(0..TYPE_CHANGE_PROBABILITY) == TYPE_CHANGE_PROBABILITY - 1 {
|
||||
self.change_node_type(None);
|
||||
} else {
|
||||
match &self.picked_node.handler {
|
||||
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),
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue