Compare commits
No commits in common. "1e14538caf397f6e6cc3e2393381ddb4565b5704" and "85e3b7ca33bc4dc499d86cebce1088d73b153ff7" have entirely different histories.
1e14538caf
...
85e3b7ca33
@ -426,77 +426,18 @@ make_instruction_clone!(exec, int, _size, Gene, 1);
|
||||
|
||||
/// Returns a nested element inside a block based on an int.
|
||||
pub fn _extract(vals: Vec<Gene>, auxs: Vec<i128>) -> Option<Gene> {
|
||||
match vals[0].clone() {
|
||||
block @ Gene::Block(_) => {
|
||||
let block_len = block.rec_len();
|
||||
if block_len == 0 {
|
||||
Some(match vals[0].clone() {
|
||||
Gene::Block(val) => {
|
||||
if *val.len() == 0 {
|
||||
return None;
|
||||
} else {
|
||||
let ndx = (auxs[0] % block_len as i128).abs() as usize;
|
||||
Some(vals[0].clone().code_at_point(ndx)?)
|
||||
let ndx = (auxs[0] % *val.len()).abs();
|
||||
// @TODO: Finish this later!
|
||||
}
|
||||
}
|
||||
val => Some(val),
|
||||
}
|
||||
}
|
||||
make_instruction_aux!(code, code, _extract, Gene, 1, int, 1, i128);
|
||||
|
||||
/// Inserts a gene at a given position in into the top block based off an
|
||||
/// int from the top of the int stack. The top code item is coerced into a block
|
||||
/// if needed.
|
||||
pub fn _insert(vals: Vec<Gene>, auxs: Vec<i128>) -> Option<Gene> {
|
||||
let mut block = match vals[0].clone() {
|
||||
iblock @ Gene::Block(_) => iblock,
|
||||
val => Gene::Block(Box::new(vec![val])),
|
||||
};
|
||||
if block.rec_len() == 0 {
|
||||
return _combine(vec![block, vals[1].clone()]);
|
||||
}
|
||||
let ndx = auxs[0].abs() as usize % block.rec_len();
|
||||
block.with_code_inserted_at_point(vals[1].clone(), ndx);
|
||||
Some(block)
|
||||
}
|
||||
make_instruction_aux!(code, code, _insert, Gene, 2, int, 1, i128);
|
||||
|
||||
/// Pushes the first position of the 2nd code item within the top code item.
|
||||
/// If not found, pushes -1. If top code item isn't a block, returns 0 if top
|
||||
/// two code items equal, -1 otherwise.
|
||||
pub fn _first_position(vals: Vec<Gene>) -> Option<i128> {
|
||||
let bad_cond: bool = match &vals[0] {
|
||||
Gene::Block(val) => val.len() == 0,
|
||||
_ => true,
|
||||
};
|
||||
if bad_cond {
|
||||
if vals[0] == vals[1] {
|
||||
return Some(0);
|
||||
}
|
||||
} else {
|
||||
match &vals[0] {
|
||||
Gene::Block(val) => {
|
||||
for (idx, el) in val.iter().enumerate() {
|
||||
if el == &vals[1] {
|
||||
return Some(idx as i128);
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => panic!("Error: Invariant of only a block failed in _first_position!"),
|
||||
}
|
||||
}
|
||||
Some(-1)
|
||||
}
|
||||
make_instruction_clone!(code, int, _first_position, Gene, 2);
|
||||
|
||||
/// Reverses the top block. Does nothing if not a block.
|
||||
pub fn _reverse(vals: Vec<Gene>) -> Option<Gene> {
|
||||
Some(match vals[0].clone() {
|
||||
Gene::Block(mut val) => {
|
||||
val.reverse();
|
||||
Gene::Block(val)
|
||||
}
|
||||
val => val,
|
||||
})
|
||||
}
|
||||
make_instruction_clone!(code, code, _reverse, Gene, 1);
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
@ -1086,160 +1027,4 @@ mod tests {
|
||||
code_size(&mut test_state);
|
||||
assert_eq!(vec![2], test_state.int);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn extract_test() {
|
||||
let mut test_state = EMPTY_STATE;
|
||||
|
||||
let test_code = vec![Gene::Block(Box::new(vec![
|
||||
Gene::GeneBoolean(true),
|
||||
Gene::GeneInt(1),
|
||||
Gene::Block(Box::new(vec![
|
||||
Gene::GeneInt(4),
|
||||
Gene::GeneFloat(dec!(6.0)),
|
||||
Gene::Block(Box::new(vec![Gene::GeneString(vec!['t'])])),
|
||||
])),
|
||||
Gene::GeneInt(10),
|
||||
Gene::Block(Box::new(vec![Gene::GeneBoolean(false)])),
|
||||
]))];
|
||||
|
||||
test_state.code = test_code.clone();
|
||||
test_state.int = vec![0];
|
||||
code_member(&mut test_state);
|
||||
assert_eq!(test_code.clone(), test_state.code);
|
||||
|
||||
test_state.code = test_code.clone();
|
||||
test_state.int = vec![2];
|
||||
code_extract(&mut test_state);
|
||||
assert_eq!(vec![Gene::GeneInt(1)], test_state.code);
|
||||
|
||||
test_state.code = test_code.clone();
|
||||
test_state.int = vec![4];
|
||||
code_extract(&mut test_state);
|
||||
assert_eq!(vec![Gene::GeneInt(4)], test_state.code);
|
||||
|
||||
test_state.code = test_code.clone();
|
||||
test_state.int = vec![9];
|
||||
code_extract(&mut test_state);
|
||||
assert_eq!(
|
||||
vec![Gene::Block(Box::new(vec![Gene::GeneBoolean(false)]))],
|
||||
test_state.code
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn insert_test() {
|
||||
let mut test_state = EMPTY_STATE;
|
||||
|
||||
test_state.code = vec![
|
||||
Gene::GeneInt(20),
|
||||
Gene::Block(Box::new(vec![
|
||||
Gene::GeneInt(1),
|
||||
Gene::Block(Box::new(vec![Gene::GeneInt(1), Gene::GeneInt(1)])),
|
||||
])),
|
||||
];
|
||||
test_state.int = vec![1];
|
||||
let inserted_block = vec![Gene::Block(Box::new(vec![
|
||||
Gene::GeneInt(1),
|
||||
Gene::GeneInt(20),
|
||||
Gene::Block(Box::new(vec![Gene::GeneInt(1), Gene::GeneInt(1)])),
|
||||
]))];
|
||||
code_insert(&mut test_state);
|
||||
assert_eq!(inserted_block, test_state.code);
|
||||
|
||||
test_state.code = vec![
|
||||
Gene::GeneInt(20),
|
||||
Gene::Block(Box::new(vec![
|
||||
Gene::GeneBoolean(true),
|
||||
Gene::GeneInt(1),
|
||||
Gene::Block(Box::new(vec![
|
||||
Gene::GeneInt(4),
|
||||
Gene::GeneFloat(dec!(6.0)),
|
||||
Gene::Block(Box::new(vec![Gene::GeneString(vec!['t'])])),
|
||||
])),
|
||||
Gene::GeneInt(10),
|
||||
Gene::Block(Box::new(vec![Gene::GeneBoolean(false)])),
|
||||
])),
|
||||
];
|
||||
test_state.int = vec![4];
|
||||
let inserted_block = vec![Gene::Block(Box::new(vec![
|
||||
Gene::GeneBoolean(true),
|
||||
Gene::GeneInt(1),
|
||||
Gene::Block(Box::new(vec![
|
||||
Gene::GeneInt(4),
|
||||
Gene::GeneInt(20),
|
||||
Gene::GeneFloat(dec!(6.0)),
|
||||
Gene::Block(Box::new(vec![Gene::GeneString(vec!['t'])])),
|
||||
])),
|
||||
Gene::GeneInt(10),
|
||||
Gene::Block(Box::new(vec![Gene::GeneBoolean(false)])),
|
||||
]))];
|
||||
code_insert(&mut test_state);
|
||||
assert_eq!(inserted_block, test_state.code);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn first_position_test() {
|
||||
let mut test_state = EMPTY_STATE;
|
||||
|
||||
test_state.code = vec![
|
||||
Gene::GeneInt(20),
|
||||
Gene::Block(Box::new(vec![
|
||||
Gene::GeneBoolean(true),
|
||||
Gene::GeneInt(1),
|
||||
Gene::GeneInt(20),
|
||||
Gene::GeneFloat(dec!(6.0)),
|
||||
])),
|
||||
];
|
||||
code_first_position(&mut test_state);
|
||||
assert_eq!(vec![2], test_state.int);
|
||||
test_state.int.clear();
|
||||
|
||||
test_state.code = vec![Gene::GeneBoolean(false), Gene::GeneBoolean(false)];
|
||||
code_first_position(&mut test_state);
|
||||
assert_eq!(vec![0], test_state.int);
|
||||
test_state.int.clear();
|
||||
|
||||
test_state.code = vec![Gene::GeneBoolean(false), Gene::GeneBoolean(true)];
|
||||
code_first_position(&mut test_state);
|
||||
assert_eq!(vec![-1], test_state.int);
|
||||
test_state.int.clear();
|
||||
|
||||
test_state.code = vec![
|
||||
Gene::GeneInt(-6),
|
||||
Gene::Block(Box::new(vec![
|
||||
Gene::GeneBoolean(true),
|
||||
Gene::GeneInt(1),
|
||||
Gene::GeneInt(20),
|
||||
Gene::GeneFloat(dec!(6.0)),
|
||||
])),
|
||||
];
|
||||
code_first_position(&mut test_state);
|
||||
assert_eq!(vec![-1], test_state.int);
|
||||
test_state.int.clear();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn code_reverse_test() {
|
||||
let mut test_state = EMPTY_STATE;
|
||||
|
||||
test_state.code = vec![Gene::GeneInt(1)];
|
||||
code_reverse(&mut test_state);
|
||||
assert_eq!(vec![Gene::GeneInt(1)], test_state.code);
|
||||
|
||||
test_state.code = vec![Gene::Block(Box::new(vec![
|
||||
Gene::GeneBoolean(false),
|
||||
Gene::GeneInt(1),
|
||||
Gene::GeneInt(20),
|
||||
]))];
|
||||
code_reverse(&mut test_state);
|
||||
assert_eq!(
|
||||
vec![Gene::Block(Box::new(vec![
|
||||
Gene::GeneInt(20),
|
||||
Gene::GeneInt(1),
|
||||
Gene::GeneBoolean(false),
|
||||
]))],
|
||||
test_state.code
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -200,4 +200,3 @@ pub mod common;
|
||||
pub mod logical;
|
||||
pub mod numeric;
|
||||
pub mod utils;
|
||||
pub mod vector;
|
||||
|
@ -1,36 +0,0 @@
|
||||
use crate::push::state::PushState;
|
||||
use rust_decimal::Decimal;
|
||||
|
||||
pub fn _concat<T>(vals: Vec<Vec<T>>) -> Option<Vec<T>>
|
||||
where
|
||||
T: Clone,
|
||||
{
|
||||
let mut concat_vec = vals[0].clone();
|
||||
concat_vec.extend(vals[1].clone().into_iter());
|
||||
Some(concat_vec)
|
||||
}
|
||||
make_instruction_clone!(vector_int, vector_int, _concat, Vec<i128>, 2);
|
||||
make_instruction_clone!(vector_float, vector_float, _concat, Vec<Decimal>, 2);
|
||||
make_instruction_clone!(vector_string, vector_string, _concat, Vec<Vec<char>>, 2);
|
||||
make_instruction_clone!(vector_boolean, vector_boolean, _concat, Vec<bool>, 2);
|
||||
make_instruction_clone!(vector_char, vector_char, _concat, Vec<char>, 2);
|
||||
make_instruction_clone!(string, string, _concat, Vec<char>, 2);
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::push::state::EMPTY_STATE;
|
||||
|
||||
#[test]
|
||||
fn test_vector_concat() {
|
||||
let mut test_state = EMPTY_STATE;
|
||||
|
||||
test_state.vector_int = vec![vec![4, 5, 6], vec![1, 2, 3]];
|
||||
vector_int_concat(&mut test_state);
|
||||
assert_eq!(vec![vec![1, 2, 3, 4, 5, 6]], test_state.vector_int);
|
||||
|
||||
test_state.string = vec![vec!['s', 't'], vec!['t', 'e']];
|
||||
string_concat(&mut test_state);
|
||||
assert_eq!(vec![vec!['t', 'e', 's', 't']], test_state.string);
|
||||
}
|
||||
}
|
@ -54,170 +54,3 @@ pub enum Gene {
|
||||
Block(Box<Vec<Gene>>),
|
||||
CrossoverPadding,
|
||||
}
|
||||
|
||||
impl Gene {
|
||||
/// Returns the len of a gene. If the gene is a block, returns
|
||||
/// the size of the block counting the size of nested blocks.
|
||||
pub fn rec_len(&self) -> usize {
|
||||
let mut size: usize = 0;
|
||||
match self {
|
||||
Gene::Block(val) => {
|
||||
for el in val.iter() {
|
||||
match el {
|
||||
iblock @ Gene::Block(_) => size += iblock.rec_len() + 1,
|
||||
_ => size += 1,
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => size += 1,
|
||||
};
|
||||
size
|
||||
}
|
||||
|
||||
/// Extracts code at a point in the genome. Recurses into a block
|
||||
/// if necessary. Point is based on an int. Pulled straight from HushGP.
|
||||
pub fn code_at_point(self, index: usize) -> Option<Gene> {
|
||||
if index == 0 {
|
||||
return Some(self);
|
||||
}
|
||||
let mut idx = index;
|
||||
match self {
|
||||
Gene::Block(val) => {
|
||||
for el in val.iter() {
|
||||
idx -= 1;
|
||||
if idx == 0 {
|
||||
return Some(el.clone());
|
||||
}
|
||||
match el {
|
||||
iblock @ Gene::Block(_) => {
|
||||
if let Some(next_depth) = iblock.clone().code_at_point(idx) {
|
||||
return Some(next_depth);
|
||||
}
|
||||
idx -= iblock.rec_len();
|
||||
}
|
||||
_ => continue,
|
||||
}
|
||||
}
|
||||
return None;
|
||||
}
|
||||
val => Some(val),
|
||||
}
|
||||
}
|
||||
|
||||
/// Insert an element into a block recursively counting along the way.
|
||||
/// Depth first. Modifies in-place.
|
||||
pub fn with_code_inserted_at_point(&mut self, gene: Gene, idx: usize) {
|
||||
if idx > self.rec_len() {
|
||||
match self {
|
||||
Gene::Block(val) => val.push(gene.clone()),
|
||||
_ => {
|
||||
panic!("Error: self must be a block for with_code_inserted_at_point to work!")
|
||||
}
|
||||
}
|
||||
}
|
||||
let _ = self.attempt_code_insert(gene, idx);
|
||||
}
|
||||
|
||||
/// Attempts to insert an item into a block.
|
||||
fn attempt_code_insert(&mut self, gene: Gene, index: usize) -> bool {
|
||||
let mut idx = index;
|
||||
match self {
|
||||
Gene::Block(val) => {
|
||||
for (n, el) in val.iter_mut().enumerate() {
|
||||
if idx == 0 {
|
||||
val.insert(n, gene.clone());
|
||||
return true;
|
||||
}
|
||||
match el {
|
||||
iblock @ Gene::Block(_) => {
|
||||
// This line has side effects on iblock if inserts properly.
|
||||
let success = iblock.attempt_code_insert(gene.clone(), idx - 1);
|
||||
if success {
|
||||
return true;
|
||||
}
|
||||
idx -= iblock.rec_len() + 1
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
idx -= 1;
|
||||
}
|
||||
if idx == 0 {
|
||||
return true;
|
||||
}
|
||||
false
|
||||
}
|
||||
_ => panic!("Error: self must be a block for attempt_code_insert to work!"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn rec_len_test() {
|
||||
let block = Gene::Block(Box::new(vec![
|
||||
Gene::GeneInt(1),
|
||||
Gene::Block(Box::new(vec![Gene::GeneInt(1), Gene::GeneInt(1)])),
|
||||
]));
|
||||
assert_eq!(4, block.rec_len());
|
||||
|
||||
let block = Gene::Block(Box::new(vec![
|
||||
Gene::GeneBoolean(true),
|
||||
Gene::GeneInt(1),
|
||||
Gene::Block(Box::new(vec![
|
||||
Gene::GeneInt(4),
|
||||
Gene::GeneFloat(dec!(6.0)),
|
||||
Gene::Block(Box::new(vec![Gene::GeneString(vec!['t'])])),
|
||||
])),
|
||||
Gene::GeneInt(10),
|
||||
Gene::Block(Box::new(vec![Gene::GeneBoolean(false)])),
|
||||
]));
|
||||
assert_eq!(10, block.rec_len());
|
||||
|
||||
let block = Gene::Block(Box::new(vec![]));
|
||||
assert_eq!(0, block.rec_len());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn insert_test() {
|
||||
let mut block = Gene::Block(Box::new(vec![
|
||||
Gene::GeneInt(1),
|
||||
Gene::Block(Box::new(vec![Gene::GeneInt(1), Gene::GeneInt(1)])),
|
||||
]));
|
||||
let inserted_block = Gene::Block(Box::new(vec![
|
||||
Gene::GeneInt(1),
|
||||
Gene::GeneInt(20),
|
||||
Gene::Block(Box::new(vec![Gene::GeneInt(1), Gene::GeneInt(1)])),
|
||||
]));
|
||||
block.with_code_inserted_at_point(Gene::GeneInt(20), 1);
|
||||
assert_eq!(inserted_block, block);
|
||||
|
||||
let mut block = Gene::Block(Box::new(vec![
|
||||
Gene::GeneBoolean(true),
|
||||
Gene::GeneInt(1),
|
||||
Gene::Block(Box::new(vec![
|
||||
Gene::GeneInt(4),
|
||||
Gene::GeneFloat(dec!(6.0)),
|
||||
Gene::Block(Box::new(vec![Gene::GeneString(vec!['t'])])),
|
||||
])),
|
||||
Gene::GeneInt(10),
|
||||
Gene::Block(Box::new(vec![Gene::GeneBoolean(false)])),
|
||||
]));
|
||||
let inserted_block = Gene::Block(Box::new(vec![
|
||||
Gene::GeneBoolean(true),
|
||||
Gene::GeneInt(1),
|
||||
Gene::Block(Box::new(vec![
|
||||
Gene::GeneInt(4),
|
||||
Gene::GeneInt(20),
|
||||
Gene::GeneFloat(dec!(6.0)),
|
||||
Gene::Block(Box::new(vec![Gene::GeneString(vec!['t'])])),
|
||||
])),
|
||||
Gene::GeneInt(10),
|
||||
Gene::Block(Box::new(vec![Gene::GeneBoolean(false)])),
|
||||
]));
|
||||
block.with_code_inserted_at_point(Gene::GeneInt(20), 4);
|
||||
assert_eq!(inserted_block, block);
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user