Pain - made to order

This commit is contained in:
Rendo 2025-11-09 00:07:40 +05:00
commit 5e61ee8e70
5 changed files with 95 additions and 61 deletions

View file

@ -3,16 +3,21 @@ use crate::node::Node;
#[derive(Clone)] #[derive(Clone)]
pub struct Formula { pub struct Formula {
tree: Node, tree: Node,
x: f64,
rating: f64,
} }
impl Formula { impl Formula {
pub fn run(&mut self, inputs: Vec<f64>) -> Vec<f64> { pub fn new() -> Self {
let mut formula = Self {
tree: Node::empty(),
};
formula.tree.modify_tree().add_node(Node::variable());
formula
}
pub fn run(&self, inputs: Vec<f64>) -> Vec<f64> {
let mut outputs: Vec<f64> = vec![]; let mut outputs: Vec<f64> = vec![];
for input in inputs { for input in inputs {
self.x = input; outputs.push(self.tree.get_value(input));
outputs.push(self.tree.get_value());
} }
outputs outputs
} }

View file

@ -1,3 +1,9 @@
use crate::formula::Formula;
mod formula;
mod node;
fn main() { fn main() {
println!("Hello, world!"); let formula = Formula::new();
dbg!(formula.run(vec![1f64]));
} }

View file

@ -2,17 +2,17 @@
pub enum NodeHandler { pub enum NodeHandler {
Number { number: f64 }, Number { number: f64 },
Function { function: fn(Vec<f64>) -> f64 }, Function { function: fn(Vec<f64>) -> f64 },
Variable { getter: fn() -> f64 }, Variable,
Empty, Empty,
} }
impl NodeHandler { impl NodeHandler {
pub fn run(&self, inputs: Vec<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 } => function(inputs),
NodeHandler::Variable { getter } => getter(), NodeHandler::Variable => passed_x,
NodeHandler::Empty => 0f64, NodeHandler::Empty => inputs[0],
} }
} }
} }

View file

@ -24,39 +24,46 @@ impl Node {
max_children_count, max_children_count,
} }
} }
pub fn get_value(&self) -> f64 { pub fn empty() -> Self {
if self.children.len() == 0 { Self {
return self.handler.run(vec![0f64]);
}
let mut inputs: Vec<f64> = vec![];
for node in &self.children {
inputs.push(node.get_value());
}
return self.handler.run(inputs);
}
pub fn modify_tree<'a>(&'a mut self) -> NodeModifier<'a> {
NodeModifier::from_random(self, None)
}
pub fn number(n: f64) -> Node {
Node {
children: vec![], children: vec![],
handler: NodeHandler::Number { number: n }, handler: NodeHandler::Empty,
max_children_count: None, max_children_count: None,
} }
} }
pub fn function(func: fn(Vec<f64>) -> f64) -> Node { pub fn number(n: f64) -> Self {
Node { Self {
children: vec![], children: vec![],
handler: NodeHandler::Function { function: func }, handler: NodeHandler::Number { number: n },
max_children_count: Some(1),
}
}
pub fn variable(getter: fn() -> f64) -> Node {
Node {
children: vec![],
handler: NodeHandler::Variable { getter },
max_children_count: Some(0), max_children_count: Some(0),
} }
} }
pub fn function(func: fn(Vec<f64>) -> f64, max_children_count: Option<usize>) -> Self {
Self {
children: vec![],
handler: NodeHandler::Function { function: func },
max_children_count,
}
}
pub fn variable() -> Self {
Self {
children: vec![],
handler: NodeHandler::Variable,
max_children_count: Some(0),
}
}
pub fn get_value(&self, passed_x: f64) -> f64 {
if self.children.len() == 0 {
return self.handler.run(vec![0f64], passed_x);
}
let mut inputs: Vec<f64> = vec![];
for node in &self.children {
inputs.push(node.get_value(passed_x));
}
return self.handler.run(inputs, passed_x);
}
pub fn modify_tree(&mut self) -> NodeModifier {
NodeModifier::from_random(self, None)
}
} }

View file

@ -4,6 +4,7 @@ use crate::node::functions;
use rand::random_range; use rand::random_range;
const PICK_STOP_PROBABILITY: u8 = 2; const PICK_STOP_PROBABILITY: u8 = 2;
const TYPE_CHANGE_PROBABILITY: u8 = 10;
pub enum NodeManipulationError { pub enum NodeManipulationError {
TooMuchChildren(Node), TooMuchChildren(Node),
@ -11,14 +12,18 @@ pub enum NodeManipulationError {
pub struct NodeModifier<'a> { pub struct NodeModifier<'a> {
picked_node: &'a mut Node, picked_node: &'a mut Node,
function_mutation_pool: Vec<fn(Vec<f64>) -> f64>, // 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>)>,
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() -> (Vec<fn(Vec<f64>) -> f64>, Vec<fn(f64) -> f64>) { fn get_standard_pool() -> (
let standard_function_mutation: Vec<fn(Vec<f64>) -> f64> = vec![functions::sine]; Vec<(fn(Vec<f64>) -> f64, Option<usize>)>,
// *4, /4, *2, Vec<fn(f64) -> f64>,
) {
let standard_function_mutation: Vec<(fn(Vec<f64>) -> f64, Option<usize>)> =
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,
@ -32,8 +37,11 @@ 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<(Vec<fn(Vec<f64>) -> f64>, Vec<fn(f64) -> f64>)>, custom_pools: Option<(
) -> NodeModifier<'a> { Vec<(fn(Vec<f64>) -> f64, Option<usize>)>,
Vec<fn(f64) -> f64>,
)>,
) -> 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 {
let len = selected.children.len(); let len = selected.children.len();
@ -43,7 +51,7 @@ impl<'a> NodeModifier<'a> {
selected = &mut selected.children[random_range(0..len)]; selected = &mut selected.children[random_range(0..len)];
} }
let pools = custom_pools.unwrap_or(NodeModifier::get_standard_pool()); let pools = custom_pools.unwrap_or(NodeModifier::get_standard_pool());
NodeModifier { Self {
picked_node: selected, picked_node: selected,
function_mutation_pool: pools.0, function_mutation_pool: pools.0,
number_mutation_pool: pools.1, number_mutation_pool: pools.1,
@ -51,10 +59,13 @@ impl<'a> NodeModifier<'a> {
} }
pub fn from_node( pub fn from_node(
node: &'a mut Node, node: &'a mut Node,
custom_pools: Option<(Vec<fn(Vec<f64>) -> f64>, Vec<fn(f64) -> f64>)>, custom_pools: Option<(
) -> NodeModifier<'a> { Vec<(fn(Vec<f64>) -> f64, Option<usize>)>,
Vec<fn(f64) -> f64>,
)>,
) -> Self {
let pools = custom_pools.unwrap_or(NodeModifier::get_standard_pool()); let pools = custom_pools.unwrap_or(NodeModifier::get_standard_pool());
NodeModifier { Self {
picked_node: node, picked_node: node,
function_mutation_pool: pools.0, function_mutation_pool: pools.0,
number_mutation_pool: pools.1, number_mutation_pool: pools.1,
@ -91,6 +102,8 @@ 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 {
} 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 {
@ -101,12 +114,15 @@ impl<'a> NodeModifier<'a> {
}; };
} }
NodeHandler::Function { function } => { NodeHandler::Function { function } => {
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 { self.picked_node.handler = NodeHandler::Function {
function: self.function_mutation_pool function: selected_mutation.0,
[random_range(0..self.function_mutation_pool.len())],
} }
} }
_ => {} _ => {}
} }
} }
}
} }