gaussian noise utility/alternation done
Some checks failed
/ Test-Suite (push) Failing after 1m12s

This commit is contained in:
Rowan Torbitzky-Lane 2025-04-29 01:10:53 -05:00
parent eb69b6cfa5
commit d51035270d
4 changed files with 266 additions and 4 deletions

View File

@ -12,8 +12,8 @@ pub enum ClosingType {
#[allow(dead_code)]
struct PushArgs {
alignment_deviation: usize, // For alternation, std dev of deviation of index when alternating
alternation_rate: Decimal, // For alternation, prob of switching parents at each location
alignment_deviation: Decimal, // For alternation, std dev of deviation of index when alternating
alternation_rate: usize, // For alternation, prob of switching parents at each location. A number 0-100
closes: ClosingType, // How push should automatically place Gene::Close into a plushy
dont_end: bool, // If true, keep running until limit regardless of success
// downsample: bool, // Whether or not to downsample. TODO later with all the related args

View File

@ -1,5 +1,6 @@
pub mod args;
pub mod genome;
pub mod utils;
pub mod variation;
// pub fn gp_loop

18
src/gp/utils.rs Normal file
View File

@ -0,0 +1,18 @@
use rand::Rng;
use rust_decimal::prelude::*;
pub fn gaussian_noise_factor(rng: &mut impl Rng) -> Decimal {
let u0f64: f64 = rng.random();
let u1f64: f64 = rng.random();
let u0: Decimal = FromPrimitive::from_f64(u0f64).unwrap();
let u1: Decimal = FromPrimitive::from_f64(u1f64).unwrap();
let u0 = if u0 == dec!(0.0) {
FromPrimitive::from_f64(f64::EPSILON).unwrap()
} else {
u0
};
(dec!(-2.0) * u0.ln()).sqrt().unwrap() * (dec!(2.0) * rust_decimal::Decimal::PI * u1).cos()
}

View File

@ -1,3 +1,10 @@
use crate::gp::utils::gaussian_noise_factor;
use crate::push::state::Gene;
use rand::Rng;
use rust_decimal::Decimal;
use rust_decimal::prelude::ToPrimitive;
use std::iter::zip;
pub enum Variation {
Crossover,
Alternation,
@ -6,3 +13,239 @@ pub enum Variation {
UniformReplacement,
UniformDeletion,
}
fn is_crossover_padding(gene: &Gene) -> bool {
match gene {
Gene::CrossoverPadding => true,
_ => false,
}
}
fn crossover(plushy0: Vec<Gene>, plushy1: Vec<Gene>, mut rng: impl Rng) -> Vec<Gene> {
let mut shorter: Vec<Gene>;
let longer: Vec<Gene>;
let mut new_plushy: Vec<Gene> = vec![];
if plushy0.len() >= plushy1.len() {
shorter = plushy1;
longer = plushy0;
} else {
shorter = plushy0;
longer = plushy1;
}
for _ in 0..(longer.len() - shorter.len()) {
shorter.push(Gene::CrossoverPadding)
}
// Add genes here
for (sgene, lgene) in zip(shorter, longer) {
if rng.random_range(0..=99) < 50 {
new_plushy.push(sgene)
} else {
new_plushy.push(lgene)
}
}
new_plushy
.into_iter()
.filter(|gene| !is_crossover_padding(gene))
.collect()
}
fn tail_aligned_crossover(plushy0: Vec<Gene>, plushy1: Vec<Gene>, mut rng: impl Rng) -> Vec<Gene> {
let mut shorter: Vec<Gene>;
let longer: Vec<Gene>;
let mut new_plushy: Vec<Gene> = vec![];
if plushy0.len() >= plushy1.len() {
shorter = plushy1;
longer = plushy0;
} else {
shorter = plushy0;
longer = plushy1;
}
for _ in 0..(longer.len() - shorter.len()) {
shorter.insert(0, Gene::CrossoverPadding)
}
// Add genes here
for (sgene, lgene) in zip(shorter, longer) {
if rng.random_range(0..=99) < 50 {
new_plushy.push(sgene)
} else {
new_plushy.push(lgene)
}
}
new_plushy
.into_iter()
.filter(|gene| !is_crossover_padding(gene))
.collect()
}
fn alternation(
plushy0: Vec<Gene>,
plushy1: Vec<Gene>,
alternation_rate: usize,
alignment_deviation: Decimal,
mut rng: impl Rng,
) -> Vec<Gene> {
let mut use_plushy0: bool = true;
let mut result_plushy: Vec<Gene> = vec![];
let mut iteration_budget = plushy0.len() + plushy1.len();
let mut n: i128 = 0;
loop {
if use_plushy0 {
if n >= plushy0.len() as i128 {
return result_plushy;
}
} else {
if n >= plushy1.len() as i128 {
return result_plushy;
}
}
if iteration_budget <= 0 {
return result_plushy;
}
if rng.random_range(0..=99) < alternation_rate {
let pre_usize = alignment_deviation * gaussian_noise_factor(&mut rng);
n = 0i128.max(n + ToPrimitive::to_i128(&(pre_usize).round()).unwrap());
use_plushy0 = !use_plushy0;
} else {
result_plushy.push(if use_plushy0 {
plushy0[n as usize].clone()
} else {
plushy1[n as usize].clone()
});
n += 1;
}
iteration_budget -= 1;
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::instructions::common::*;
use crate::instructions::numeric::*;
use crate::push::state::Gene;
use rand::SeedableRng;
use rand::rngs::StdRng;
use rust_decimal::dec;
#[test]
fn crossover_test() {
let rng = StdRng::seed_from_u64(42);
let plushy0 = vec![
Gene::StateFunc(exec_swap),
Gene::StateFunc(float_tan),
Gene::StateFunc(int_pop),
Gene::Close,
Gene::StateFunc(exec_flush),
Gene::Close,
Gene::StateFunc(boolean_pop),
Gene::StateFunc(vector_int_swap),
Gene::StateFunc(vector_char_pop),
];
let plushy1 = vec![
Gene::StateFunc(string_swap),
Gene::StateFunc(float_arctan),
Gene::StateFunc(char_pop),
Gene::GeneChar('a'),
Gene::StateFunc(code_flush),
Gene::GeneInt(1),
Gene::StateFunc(float_pop),
];
let res_plushy = crossover(plushy0, plushy1, rng);
assert_eq!(
vec![
Gene::StateFunc(string_swap),
Gene::StateFunc(float_tan),
Gene::StateFunc(char_pop),
Gene::Close,
Gene::StateFunc(exec_flush),
Gene::Close,
Gene::StateFunc(boolean_pop),
Gene::StateFunc(vector_char_pop),
],
res_plushy
)
}
#[test]
fn tail_aligned_crossover_test() {
let rng = StdRng::seed_from_u64(42);
let plushy0 = vec![
Gene::StateFunc(exec_swap),
Gene::StateFunc(float_tan),
Gene::StateFunc(int_pop),
Gene::Close,
Gene::StateFunc(exec_flush),
Gene::Close,
Gene::StateFunc(boolean_pop),
Gene::StateFunc(vector_int_swap),
Gene::StateFunc(vector_char_pop),
];
let plushy1 = vec![
Gene::StateFunc(string_swap),
Gene::StateFunc(float_arctan),
Gene::StateFunc(char_pop),
Gene::GeneChar('a'),
Gene::StateFunc(code_flush),
Gene::GeneInt(1),
Gene::StateFunc(float_pop),
];
let res_plushy = tail_aligned_crossover(plushy0, plushy1, rng);
assert_eq!(
vec![
Gene::StateFunc(float_tan),
Gene::StateFunc(string_swap),
Gene::Close,
Gene::StateFunc(exec_flush),
Gene::Close,
Gene::StateFunc(boolean_pop),
Gene::GeneInt(1),
Gene::StateFunc(vector_char_pop),
],
res_plushy
)
}
#[test]
fn alternation_test() {
let rng = StdRng::seed_from_u64(42);
let plushy0 = vec![
Gene::StateFunc(exec_swap),
Gene::StateFunc(float_tan),
Gene::StateFunc(int_pop),
Gene::Close,
Gene::StateFunc(exec_flush),
Gene::Close,
Gene::StateFunc(boolean_pop),
Gene::StateFunc(vector_int_swap),
Gene::StateFunc(vector_char_pop),
];
let plushy1 = vec![
Gene::StateFunc(string_swap),
Gene::StateFunc(float_arctan),
Gene::StateFunc(char_pop),
Gene::GeneChar('a'),
Gene::StateFunc(code_flush),
Gene::GeneInt(1),
Gene::StateFunc(float_pop),
];
let res_plushy = alternation(plushy0, plushy1, 50, dec!(2.0), rng);
assert_eq!(
vec![
Gene::StateFunc(char_pop),
Gene::GeneChar('a'),
Gene::StateFunc(boolean_pop),
Gene::StateFunc(vector_int_swap),
Gene::StateFunc(vector_char_pop),
],
res_plushy
);
}
}