finish random instruction for now

This commit is contained in:
Rowan Torbitzky-Lane 2025-04-29 13:51:40 -05:00
parent f68e9577d6
commit e8f3910112
2 changed files with 83 additions and 3 deletions

View File

@ -29,7 +29,7 @@ pub fn make_random_plushy(
} }
/// A map of genes to their number of blocks they open. /// A map of genes to their number of blocks they open.
static OPEN_MAP: LazyLock<HashMap<Gene, u8>> = LazyLock::new(|| { pub static OPEN_MAP: LazyLock<HashMap<Gene, u8>> = LazyLock::new(|| {
let mut temp_map = HashMap::default(); let mut temp_map = HashMap::default();
temp_map.insert(StateFunc(exec_dup), 1u8); temp_map.insert(StateFunc(exec_dup), 1u8);
temp_map.insert(StateFunc(exec_dup_times), 1u8); temp_map.insert(StateFunc(exec_dup_times), 1u8);

View File

@ -1,4 +1,5 @@
use crate::gp::args::ClosingType; use crate::gp::args::ClosingType;
use crate::gp::genome::OPEN_MAP;
use crate::push::state::Gene; use crate::push::state::Gene;
use rand::Rng; use rand::Rng;
use rand::seq::IndexedRandom; use rand::seq::IndexedRandom;
@ -12,9 +13,57 @@ pub fn random_instruction(
match closing_type { match closing_type {
ClosingType::Specified => return instructions.choose(rng).unwrap().clone(), ClosingType::Specified => return instructions.choose(rng).unwrap().clone(),
ClosingType::Balanced => { ClosingType::Balanced => {
let let source: Vec<Gene> = instructions
.iter()
.filter(|instr| !matches!(instr, Gene::Close))
.cloned()
.collect();
let total_opens: usize = source
.iter()
.filter_map(|instr| {
if let Gene::StateFunc(_) = instr {
OPEN_MAP.get(instr).copied().map(|val| val as usize)
} else {
None
}
})
.sum();
let p = if source.is_empty() {
0.0
} else {
total_opens as f64 / source.len() as f64
};
// Return Close or a random instruction based on probability
if rng.random::<f64>() < p {
Gene::Close
} else {
source.choose(rng).unwrap().clone()
}
}
ClosingType::None => {
// Find multi-block instructions (those with opens > 1)
let multi_block_instructions: Vec<Gene> = instructions
.iter()
.filter(|instr| {
if let Gene::StateFunc(_) = instr {
OPEN_MAP.get(instr).map_or(false, |&opens| opens > 1)
} else {
false
}
})
.cloned()
.collect();
// Remove Close and multi-block instructions
let source: Vec<Gene> = instructions
.into_iter() // Take ownership of instructions
.filter(|instr| {
!matches!(instr, Gene::Close) && !multi_block_instructions.contains(instr)
})
.collect();
source.choose(rng).unwrap().clone()
} }
_ => todo!(),
} }
} }
@ -33,3 +82,34 @@ pub fn gaussian_noise_factor(rng: &mut impl Rng) -> Decimal {
(dec!(-2.0) * u0.ln()).sqrt().unwrap() * (dec!(2.0) * rust_decimal::Decimal::PI * u1).cos() (dec!(-2.0) * u0.ln()).sqrt().unwrap() * (dec!(2.0) * rust_decimal::Decimal::PI * u1).cos()
} }
#[cfg(test)]
mod tests {
use super::*;
use crate::instructions::code::*;
use crate::instructions::common::boolean_rotate;
use crate::instructions::vector::*;
use crate::push::utils::most_genes;
use rand::SeedableRng;
use rand::rngs::StdRng;
#[test]
fn random_instruction_test() {
let mut rng = StdRng::seed_from_u64(42);
let genes = most_genes();
let rand_instruction = random_instruction(genes.clone(), ClosingType::Specified, &mut rng);
assert_eq!(
Gene::StateFunc(vector_float_from_last_prim),
rand_instruction
);
let mut rng = StdRng::seed_from_u64(32038);
let rand_instruction = random_instruction(genes.clone(), ClosingType::Balanced, &mut rng);
assert_eq!(Gene::StateFunc(boolean_rotate), rand_instruction);
let mut rng = StdRng::seed_from_u64(3203890821);
let rand_instruction = random_instruction(genes, ClosingType::None, &mut rng);
assert_eq!(Gene::StateFunc(code_insert), rand_instruction);
}
}