This commit is contained in:
parent
eb69b6cfa5
commit
d51035270d
@ -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
|
||||
|
@ -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
18
src/gp/utils.rs
Normal 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()
|
||||
}
|
@ -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
|
||||
);
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user