This commit is contained in:
parent
35ad71ffc3
commit
f424a7bd3a
@ -1,3 +1,4 @@
|
|||||||
|
use crate::gp::selection::Selection;
|
||||||
use crate::gp::variation::Variation;
|
use crate::gp::variation::Variation;
|
||||||
use crate::push::state::Gene;
|
use crate::push::state::Gene;
|
||||||
use polars::prelude::*;
|
use polars::prelude::*;
|
||||||
@ -19,23 +20,58 @@ pub struct PushArgs {
|
|||||||
pub dont_end: bool, // If true, keep running until limit regardless of success
|
pub dont_end: bool, // If true, keep running until limit regardless of success
|
||||||
// pub downsample: bool, // Whether or not to downsample. TODO later with all the related args
|
// pub downsample: bool, // Whether or not to downsample. TODO later with all the related args
|
||||||
pub elitism: bool, // Whether to always add the best individual to next generation
|
pub elitism: bool, // Whether to always add the best individual to next generation
|
||||||
pub error_function: fn(&PushArgs, &DataFrame, Vec<Gene>) -> Vec<Decimal>, // The error function
|
pub error_function: Option<fn(&PushArgs, &DataFrame, Vec<Gene>) -> Vec<Decimal>>, // The error function
|
||||||
pub instructions: Vec<Gene>, // Instructions to use in a run
|
pub instructions: Option<Vec<Gene>>, // Instructions to use in a run
|
||||||
pub max_init_plushy_size: usize, // max initial plushy size
|
pub max_init_plushy_size: usize, // max initial plushy size
|
||||||
pub max_generations: usize, // Max amount of generations
|
pub max_generations: usize, // Max amount of generations
|
||||||
pub parent_selection: usize, // Selection to use, TODO change this later.
|
pub parent_selection: Selection, // Selection to use, TODO change this later.
|
||||||
pub pop_size: usize, // Population size
|
pub pop_size: usize, // Population size
|
||||||
pub replacement_rate: f64, // For uniform replacement, rate items replaced
|
pub replacement_rate: f64, // For uniform replacement, rate items replaced
|
||||||
pub use_simplification: bool, // Whether to use simplification at end of run
|
pub use_simplification: bool, // Whether to use simplification at end of run
|
||||||
pub simplification_k: usize, // Max amt of genes to attempt removal during one round of simplification process
|
pub simplification_k: usize, // Max amt of genes to attempt removal during one round of simplification process
|
||||||
pub simplification_steps: usize, // How many attempts to find simplified genomes
|
pub simplification_steps: usize, // How many attempts to find simplified genomes
|
||||||
pub simplification_verbose: bool, // Whether to send extra messages about simplification or not
|
pub simplification_verbose: bool, // Whether to send extra messages about simplification or not
|
||||||
pub solution_error_threshold: Decimal, // Max total error for solutions
|
pub solution_error_threshold: Decimal, // Max total error for solutions
|
||||||
pub use_single_thread: bool, // if true, only single threaded
|
pub use_single_thread: bool, // if true, only single threaded
|
||||||
pub step_limit: usize, // Amount of steps a push interpreter can run for
|
pub step_limit: usize, // Amount of steps a push interpreter can run for
|
||||||
pub testing_data: DataFrame, // The testing data, must be formatted the same as training data
|
pub testing_data: Option<DataFrame>, // The testing data, must be formatted the same as training data
|
||||||
pub tournament_size: usize, // Tournament size for tournament selection
|
pub tournament_size: usize, // Tournament size for tournament selection
|
||||||
pub training_data: DataFrame, // The training data, must be formatted the same as testing data
|
pub training_data: Option<DataFrame>, // The training data, must be formatted the same as testing data
|
||||||
pub umad_rate: f64, // addition rate (deletion rate derived) for UMAD
|
pub umad_rate: f64, // addition rate (deletion rate derived) for UMAD
|
||||||
pub variation: HashMap<Variation, f64>, // genetic operators and probability for use. should sum to 1,
|
pub variation: HashMap<Variation, f64>, // genetic operators and probability for use. should sum to 1,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl PushArgs {
|
||||||
|
/// Holds the default arguments
|
||||||
|
pub fn new() -> Self {
|
||||||
|
let mut map = HashMap::new();
|
||||||
|
map.insert(Variation::UMAD, 1.0);
|
||||||
|
|
||||||
|
Self {
|
||||||
|
alignment_deviation: dec!(2.0),
|
||||||
|
alternation_rate: 10,
|
||||||
|
closes: ClosingType::Specified,
|
||||||
|
dont_end: false,
|
||||||
|
elitism: false,
|
||||||
|
error_function: None,
|
||||||
|
instructions: None,
|
||||||
|
max_init_plushy_size: 100,
|
||||||
|
max_generations: 1000,
|
||||||
|
parent_selection: Selection::Lexicase,
|
||||||
|
pop_size: 1000,
|
||||||
|
replacement_rate: 0.1,
|
||||||
|
use_simplification: true,
|
||||||
|
simplification_k: 4,
|
||||||
|
simplification_steps: 1000,
|
||||||
|
simplification_verbose: true,
|
||||||
|
use_single_thread: false,
|
||||||
|
solution_error_threshold: dec!(0.0),
|
||||||
|
step_limit: 1000,
|
||||||
|
testing_data: None,
|
||||||
|
tournament_size: 5,
|
||||||
|
training_data: None,
|
||||||
|
umad_rate: 0.1,
|
||||||
|
variation: map,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -2,6 +2,11 @@ use crate::gp::args::PushArgs;
|
|||||||
use crate::gp::individual::Individual;
|
use crate::gp::individual::Individual;
|
||||||
use rand::Rng;
|
use rand::Rng;
|
||||||
|
|
||||||
|
pub enum Selection {
|
||||||
|
Lexicase,
|
||||||
|
Tournament,
|
||||||
|
}
|
||||||
|
|
||||||
pub fn select_parent(
|
pub fn select_parent(
|
||||||
_pop: Vec<Individual>,
|
_pop: Vec<Individual>,
|
||||||
_push_args: &PushArgs,
|
_push_args: &PushArgs,
|
||||||
|
@ -53,7 +53,12 @@ where
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
let initial_errors = error_func(&push_args, &push_args.training_data, plushy.clone());
|
let training_data = (&push_args)
|
||||||
|
.training_data
|
||||||
|
.clone()
|
||||||
|
.expect("Must provide training_data");
|
||||||
|
|
||||||
|
let mut curr_errors = error_func(&push_args, &training_data, plushy.clone());
|
||||||
let mut step = 0;
|
let mut step = 0;
|
||||||
let mut curr_plushy = plushy;
|
let mut curr_plushy = plushy;
|
||||||
|
|
||||||
@ -62,15 +67,23 @@ where
|
|||||||
let random_k = rng.random_range(1..=push_args.simplification_k);
|
let random_k = rng.random_range(1..=push_args.simplification_k);
|
||||||
|
|
||||||
let new_plushy = delete_k_random(random_k, &curr_plushy, &mut rng);
|
let new_plushy = delete_k_random(random_k, &curr_plushy, &mut rng);
|
||||||
let new_plushy_errors =
|
let new_plushy_errors = error_func(&push_args, &training_data, new_plushy.clone());
|
||||||
error_func(&push_args, &push_args.training_data, new_plushy.clone());
|
|
||||||
|
|
||||||
if new_plushy_errors.iter().sum::<Decimal>() <= initial_errors.iter().sum() {
|
if new_plushy_errors.iter().sum::<Decimal>() <= curr_errors.iter().sum() {
|
||||||
curr_plushy = new_plushy;
|
curr_plushy = new_plushy;
|
||||||
|
curr_errors = new_plushy_errors;
|
||||||
}
|
}
|
||||||
|
|
||||||
step += 1;
|
step += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if push_args.simplification_verbose {
|
||||||
|
println!(
|
||||||
|
"{{ end_plushy_length: {}, k: {} }}",
|
||||||
|
curr_plushy.len(),
|
||||||
|
push_args.simplification_k
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
curr_plushy
|
curr_plushy
|
||||||
}
|
}
|
||||||
|
@ -12,7 +12,7 @@ use std::iter::zip;
|
|||||||
use super::args::ClosingType;
|
use super::args::ClosingType;
|
||||||
use super::utils::random_instruction;
|
use super::utils::random_instruction;
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone, PartialEq, Eq, Hash)]
|
||||||
pub enum Variation {
|
pub enum Variation {
|
||||||
Crossover,
|
Crossover,
|
||||||
Alternation,
|
Alternation,
|
||||||
@ -21,6 +21,7 @@ pub enum Variation {
|
|||||||
UniformReplacement,
|
UniformReplacement,
|
||||||
UniformDeletion,
|
UniformDeletion,
|
||||||
Reproduction,
|
Reproduction,
|
||||||
|
UMAD,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn crossover(plushy0: Vec<Gene>, plushy1: Vec<Gene>, mut rng: impl Rng) -> Vec<Gene> {
|
fn crossover(plushy0: Vec<Gene>, plushy1: Vec<Gene>, mut rng: impl Rng) -> Vec<Gene> {
|
||||||
@ -132,13 +133,13 @@ fn uniform_addition(
|
|||||||
instructions: Vec<Gene>,
|
instructions: Vec<Gene>,
|
||||||
umad_rate: f64,
|
umad_rate: f64,
|
||||||
closing_type: ClosingType,
|
closing_type: ClosingType,
|
||||||
mut rng: impl Rng,
|
rng: &mut impl Rng,
|
||||||
) -> Vec<Gene> {
|
) -> Vec<Gene> {
|
||||||
let mut new_plushy: Vec<Gene> = vec![];
|
let mut new_plushy: Vec<Gene> = vec![];
|
||||||
|
|
||||||
for gene in plushy {
|
for gene in plushy {
|
||||||
if rng.random::<f64>() < umad_rate {
|
if rng.random::<f64>() < umad_rate {
|
||||||
let new_instruction = random_instruction(instructions.clone(), closing_type, &mut rng);
|
let new_instruction = random_instruction(instructions.clone(), closing_type, rng);
|
||||||
|
|
||||||
// Randomly decide order (original first or new first)
|
// Randomly decide order (original first or new first)
|
||||||
if rng.random::<bool>() {
|
if rng.random::<bool>() {
|
||||||
@ -231,7 +232,10 @@ pub fn new_individual(pop: Vec<Individual>, argmap: &PushArgs, rng: &mut impl Rn
|
|||||||
let parent = select_parent(pop, argmap, rng);
|
let parent = select_parent(pop, argmap, rng);
|
||||||
uniform_addition(
|
uniform_addition(
|
||||||
parent.plushy.clone(),
|
parent.plushy.clone(),
|
||||||
argmap.instructions.clone(),
|
argmap
|
||||||
|
.instructions
|
||||||
|
.clone()
|
||||||
|
.expect("Must provide instructions"),
|
||||||
argmap.umad_rate,
|
argmap.umad_rate,
|
||||||
argmap.closes,
|
argmap.closes,
|
||||||
rng,
|
rng,
|
||||||
@ -242,7 +246,10 @@ pub fn new_individual(pop: Vec<Individual>, argmap: &PushArgs, rng: &mut impl Rn
|
|||||||
let parent = select_parent(pop, argmap, rng);
|
let parent = select_parent(pop, argmap, rng);
|
||||||
uniform_replacement(
|
uniform_replacement(
|
||||||
parent.plushy.clone(),
|
parent.plushy.clone(),
|
||||||
argmap.instructions.clone(),
|
argmap
|
||||||
|
.instructions
|
||||||
|
.clone()
|
||||||
|
.expect("Must provide instructions!"),
|
||||||
argmap.replacement_rate,
|
argmap.replacement_rate,
|
||||||
argmap.closes,
|
argmap.closes,
|
||||||
rng,
|
rng,
|
||||||
@ -266,6 +273,25 @@ pub fn new_individual(pop: Vec<Individual>, argmap: &PushArgs, rng: &mut impl Rn
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Variation::UMAD => {
|
||||||
|
let parent = select_parent(pop, argmap, rng);
|
||||||
|
let parent_plushy = parent.plushy.clone();
|
||||||
|
|
||||||
|
// Apply uniform addition followed by uniform deletion
|
||||||
|
let after_addition = uniform_addition(
|
||||||
|
parent_plushy,
|
||||||
|
argmap
|
||||||
|
.instructions
|
||||||
|
.clone()
|
||||||
|
.expect("Must provide instructions"),
|
||||||
|
argmap.umad_rate,
|
||||||
|
argmap.closes,
|
||||||
|
rng,
|
||||||
|
);
|
||||||
|
|
||||||
|
uniform_deletion(after_addition, argmap.umad_rate, rng)
|
||||||
|
}
|
||||||
|
|
||||||
Variation::Reproduction => {
|
Variation::Reproduction => {
|
||||||
let parent = select_parent(pop, argmap, rng);
|
let parent = select_parent(pop, argmap, rng);
|
||||||
parent.plushy.clone()
|
parent.plushy.clone()
|
||||||
@ -407,14 +433,15 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn uniform_addition_test() {
|
fn uniform_addition_test() {
|
||||||
let rng = StdRng::seed_from_u64(42);
|
let mut rng = StdRng::seed_from_u64(42);
|
||||||
let plushy0 = vec![
|
let plushy0 = vec![
|
||||||
Gene::StateFunc(exec_swap),
|
Gene::StateFunc(exec_swap),
|
||||||
Gene::StateFunc(float_tan),
|
Gene::StateFunc(float_tan),
|
||||||
Gene::StateFunc(int_pop),
|
Gene::StateFunc(int_pop),
|
||||||
Gene::Close,
|
Gene::Close,
|
||||||
];
|
];
|
||||||
let res_plushy = uniform_addition(plushy0, most_genes(), 0.75, ClosingType::Balanced, rng);
|
let res_plushy =
|
||||||
|
uniform_addition(plushy0, most_genes(), 0.75, ClosingType::Balanced, &mut rng);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
vec![
|
vec![
|
||||||
Gene::StateFunc(exec_swap),
|
Gene::StateFunc(exec_swap),
|
||||||
|
@ -19,7 +19,9 @@ pub fn gene_to_stack(state: &mut PushState, gene: Gene) {
|
|||||||
Gene::Block(x) => state.exec.extend(x.into_iter().rev()),
|
Gene::Block(x) => state.exec.extend(x.into_iter().rev()),
|
||||||
Gene::Close => panic!("Close found in the exec stack, this should not happen!"),
|
Gene::Close => panic!("Close found in the exec stack, this should not happen!"),
|
||||||
Gene::Open(_) => panic!("Open found in the exec stack, this should not happen!"),
|
Gene::Open(_) => panic!("Open found in the exec stack, this should not happen!"),
|
||||||
Gene::Skip => panic!("Skip found in the exec stack, this should not happen!"),
|
Gene::Skip => {
|
||||||
|
state.exec.pop(); // Skip the next item by removing it.
|
||||||
|
}
|
||||||
Gene::CrossoverPadding => {
|
Gene::CrossoverPadding => {
|
||||||
panic!("CrossoverPadding found in the exec stack, this should not happen!")
|
panic!("CrossoverPadding found in the exec stack, this should not happen!")
|
||||||
}
|
}
|
||||||
|
@ -18,6 +18,7 @@ pub struct PushState {
|
|||||||
pub vector_char: Vec<Vec<char>>,
|
pub vector_char: Vec<Vec<char>>,
|
||||||
pub exec: Vec<Gene>,
|
pub exec: Vec<Gene>,
|
||||||
pub code: Vec<Gene>,
|
pub code: Vec<Gene>,
|
||||||
|
pub input: Vec<Gene>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const EMPTY_STATE: PushState = PushState {
|
pub const EMPTY_STATE: PushState = PushState {
|
||||||
@ -33,6 +34,7 @@ pub const EMPTY_STATE: PushState = PushState {
|
|||||||
vector_char: vec![],
|
vector_char: vec![],
|
||||||
exec: vec![],
|
exec: vec![],
|
||||||
code: vec![],
|
code: vec![],
|
||||||
|
input: vec![],
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(PartialEq, Eq, Debug, Clone, Hash)]
|
#[derive(PartialEq, Eq, Debug, Clone, Hash)]
|
||||||
|
68
tests/simplification_test.rs
Normal file
68
tests/simplification_test.rs
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
use polars::prelude::*;
|
||||||
|
use rush::gp::args::PushArgs;
|
||||||
|
use rush::gp::simplification::auto_simplify_plushy;
|
||||||
|
use rush::instructions::numeric::*;
|
||||||
|
use rush::push::state::Gene;
|
||||||
|
use rush::push::utils::most_genes;
|
||||||
|
use rust_decimal::{Decimal, dec};
|
||||||
|
|
||||||
|
fn test_error_function(
|
||||||
|
_push_args: &PushArgs,
|
||||||
|
data: &DataFrame,
|
||||||
|
_push_program: Vec<Gene>,
|
||||||
|
) -> Vec<Decimal> {
|
||||||
|
let err_vec: Vec<Decimal> = vec![];
|
||||||
|
|
||||||
|
let y = data.column("y").unwrap();
|
||||||
|
let x = data.drop("y").unwrap();
|
||||||
|
|
||||||
|
// println!("x: {x:#?}");
|
||||||
|
// println!("y: {y:#?}");
|
||||||
|
|
||||||
|
for n in 0..x.height() {
|
||||||
|
let mut inputs: Vec<Gene> = Vec::with_capacity(x.width());
|
||||||
|
let row = x.get_row(n).unwrap();
|
||||||
|
for datum in row.0.iter() {
|
||||||
|
// println!("{:?}", val);
|
||||||
|
inputs.push(match datum {
|
||||||
|
&AnyValue::Int32(val) => Gene::GeneInt(val as i128),
|
||||||
|
_ => Gene::Close,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
println!("{:?}", inputs);
|
||||||
|
inputs.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
vec![dec!(0.0)]
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn simplification_function_test() {
|
||||||
|
let train_df: DataFrame = df!(
|
||||||
|
"x0" => [1, 2, 3],
|
||||||
|
"x1" => [7, 8, 9],
|
||||||
|
"y" => [8, 10, 12],
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
println!("{}", train_df);
|
||||||
|
// println!("{:#?}", train_df["x0"]);
|
||||||
|
|
||||||
|
// push program declaration
|
||||||
|
let push_program: Vec<Gene> = vec![
|
||||||
|
Gene::StateFunc(float_tan),
|
||||||
|
Gene::StateFunc(float_sub),
|
||||||
|
Gene::StateFunc(int_add),
|
||||||
|
Gene::StateFunc(float_tan),
|
||||||
|
Gene::StateFunc(float_sub),
|
||||||
|
Gene::StateFunc(float_rem),
|
||||||
|
Gene::StateFunc(float_inc),
|
||||||
|
];
|
||||||
|
|
||||||
|
let mut args = PushArgs::new();
|
||||||
|
args.training_data = Some(train_df.clone());
|
||||||
|
args.instructions = Some(most_genes());
|
||||||
|
args.simplification_steps = 100;
|
||||||
|
args.error_function = Some(test_error_function);
|
||||||
|
|
||||||
|
test_error_function(&args, &train_df, push_program);
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user