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.
|
/// Returns a nested element inside a block based on an int.
|
||||||
pub fn _extract(vals: Vec<Gene>, auxs: Vec<i128>) -> Option<Gene> {
|
pub fn _extract(vals: Vec<Gene>, auxs: Vec<i128>) -> Option<Gene> {
|
||||||
match vals[0].clone() {
|
Some(match vals[0].clone() {
|
||||||
block @ Gene::Block(_) => {
|
Gene::Block(val) => {
|
||||||
let block_len = block.rec_len();
|
if *val.len() == 0 {
|
||||||
if block_len == 0 {
|
|
||||||
return None;
|
return None;
|
||||||
} else {
|
} else {
|
||||||
let ndx = (auxs[0] % block_len as i128).abs() as usize;
|
let ndx = (auxs[0] % *val.len()).abs();
|
||||||
Some(vals[0].clone().code_at_point(ndx)?)
|
// @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,
|
val => val,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
make_instruction_clone!(code, code, _reverse, Gene, 1);
|
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
@ -1086,160 +1027,4 @@ mod tests {
|
|||||||
code_size(&mut test_state);
|
code_size(&mut test_state);
|
||||||
assert_eq!(vec![2], test_state.int);
|
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 logical;
|
||||||
pub mod numeric;
|
pub mod numeric;
|
||||||
pub mod utils;
|
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>>),
|
Block(Box<Vec<Gene>>),
|
||||||
CrossoverPadding,
|
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