This commit is contained in:
parent
eb69b6cfa5
commit
d51035270d
@ -12,10 +12,10 @@ pub enum ClosingType {
|
|||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
struct PushArgs {
|
struct PushArgs {
|
||||||
alignment_deviation: usize, // For alternation, std dev of deviation of index when alternating
|
alignment_deviation: Decimal, // For alternation, std dev of deviation of index when alternating
|
||||||
alternation_rate: Decimal, // For alternation, prob of switching parents at each location
|
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
|
closes: ClosingType, // How push should automatically place Gene::Close into a plushy
|
||||||
dont_end: bool, // If true, keep running until limit regardless of success
|
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
|
// downsample: bool, // Whether or not to downsample. TODO later with all the related args
|
||||||
elitism: bool, // Whether to always add the best individual to next generation
|
elitism: bool, // Whether to always add the best individual to next generation
|
||||||
error_function: fn(&PushArgs, DataFrame, Vec<Gene>) -> Series, // The error function
|
error_function: fn(&PushArgs, DataFrame, Vec<Gene>) -> Series, // The error function
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
pub mod args;
|
pub mod args;
|
||||||
pub mod genome;
|
pub mod genome;
|
||||||
|
pub mod utils;
|
||||||
pub mod variation;
|
pub mod variation;
|
||||||
|
|
||||||
// pub fn gp_loop
|
// 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 {
|
pub enum Variation {
|
||||||
Crossover,
|
Crossover,
|
||||||
Alternation,
|
Alternation,
|
||||||
@ -6,3 +13,239 @@ pub enum Variation {
|
|||||||
UniformReplacement,
|
UniformReplacement,
|
||||||
UniformDeletion,
|
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