use std::f32::consts::PI;
use std::fmt::{self, Debug};
use bevy::prelude::*;
use rand::prelude::*;
use serde::{Serialize, Deserialize};
use crate::blob::block::NeuronId;
use crate::brain::neuron::GenericNN;
use crate::consts::*;
use super::blob_builder::BlobBuilder;
use super::block::PhysiBlockBundle;
pub struct GenoBlobBuilder<'a> {
builder: BlobBuilder<'a>,
}
impl<'a> GenoBlobBuilder<'a> {
pub fn from_commands(commands: Commands<'a, 'a>, nnvec: &'a mut Vec<GenericNN>) -> Self {
Self {
builder: BlobBuilder::from_commands(commands, nnvec),
}
}
pub fn build(&mut self, geno: &mut BlobGeno, center: [f32; 2]) {
let builder = &mut self.builder;
if let Some(nn_id) = geno.get_first().unwrap().nn_id {
let root_nn = NeuronId::new(nn_id,None);
builder.create_first(
geno.get_first()
.unwrap()
.to_bundle(center),
root_nn);
build_node_with_nn(builder, &mut geno.vec_tree, 0, nn_id)
} else {
geno.assign_nn_id_to_root(
builder.create_first(
geno.get_first()
.unwrap()
.to_bundle(center)
.with_color(Color::BLUE),
(),).unwrap()
);
build_node(&mut self.builder, &mut geno.vec_tree, 0);
}
self.builder.update_geno(geno.clone());
self.builder.clean();
}
}
fn lambda(node: &mut Option<GenericGenoNode>) -> Option<&mut GenoNode> {
node.as_mut().and_then(|node| match node {
GenericGenoNode::Parent => None,
GenericGenoNode::Child(child) => Some(child),
})
}
fn build_node(
builder: &mut BlobBuilder,
tree: &mut QuadTree<GenericGenoNode>,
index: usize,
) {
if let Some(Some(_)) = tree.nodes.get_mut(index) {
let children = tree.children(index);
if let Some(mut node) = tree.nodes.get_mut(children[0]).and_then(lambda) {
let nn_id = builder.add_to_top(
node.size[0],
node.size[1],
None,
Some(node.joint_limits),
(),
);
if node.nn_id.is_none() {
node.nn_id = nn_id
}
build_node(builder, tree, children[0]);
builder.bottom();
}
if let Some(mut node) = tree.nodes.get_mut(children[1]).and_then(lambda) {
let nn_id = builder.add_to_bottom(
node.size[0],
node.size[1],
None,
Some(node.joint_limits),
(),
);
if node.nn_id.is_none() {
node.nn_id = nn_id
}
build_node(builder, tree, children[1]);
builder.top();
}
if let Some(node) = tree.nodes.get_mut(children[2]).and_then(lambda) {
let nn_id = builder.add_to_left(
node.size[0],
node.size[1],
None,
Some(node.joint_limits),
(),
);
if node.nn_id.is_none() {
node.nn_id = nn_id
}
build_node(builder, tree, children[2]);
builder.right();
}
if let Some(node) = tree.nodes.get_mut(children[3]).and_then(lambda) {
let nn_id = builder.add_to_right(
node.size[0],
node.size[1],
None,
Some(node.joint_limits),
(),
);
if node.nn_id.is_none() {
node.nn_id = nn_id
}
build_node(builder, tree, children[3]);
builder.left();
}
}
}
fn build_node_with_nn(
builder: &mut BlobBuilder,
tree: &mut QuadTree<GenericGenoNode>,
index: usize,
parent_nn_id: usize
) {
if let Some(Some(_)) = tree.nodes.get_mut(index) {
let children = tree.children(index);
if let Some(node) = tree.nodes.get_mut(children[0]).and_then(lambda) {
let nn_id = node.nn_id.unwrap();
let neuron_id = NeuronId::new(nn_id,Some(parent_nn_id));
builder.add_to_top(
node.size[0],
node.size[1],
None,
Some(node.joint_limits),
neuron_id,
);
build_node_with_nn(builder, tree, children[0],nn_id);
builder.bottom();
}
if let Some(node) = tree.nodes.get_mut(children[1]).and_then(lambda) {
let nn_id = node.nn_id.unwrap();
let neuron_id = NeuronId::new(nn_id,Some(parent_nn_id));
builder.add_to_bottom(
node.size[0],
node.size[1],
None,
Some(node.joint_limits),
neuron_id,
);
build_node_with_nn(builder, tree, children[1],nn_id);
builder.top();
}
if let Some(node) = tree.nodes.get_mut(children[2]).and_then(lambda) {
let nn_id = node.nn_id.unwrap();
let neuron_id = NeuronId::new(nn_id,Some(parent_nn_id));
builder.add_to_left(
node.size[0],
node.size[1],
None,
Some(node.joint_limits),
neuron_id,
);
build_node_with_nn(builder, tree, children[2], nn_id);
builder.right();
}
if let Some(node) = tree.nodes.get_mut(children[3]).and_then(lambda) {
let nn_id = node.nn_id.unwrap();
let neuron_id = NeuronId::new(nn_id,Some(parent_nn_id));
builder.add_to_right(
node.size[0],
node.size[1],
None,
Some(node.joint_limits),
neuron_id,
);
build_node_with_nn(builder, tree, children[3], nn_id);
builder.left();
}
}
}
#[derive(Debug, Component, Clone, Serialize, Deserialize)]
pub struct BlobGeno {
pub vec_tree: QuadTree<GenericGenoNode>,
}
impl Default for BlobGeno {
fn default() -> Self {
Self {
vec_tree: QuadTree::<GenericGenoNode>::new(GENO_MAX_DEPTH),
}
}
}
impl BlobGeno {
pub fn new_rand() -> BlobGeno {
let mut occupied_region = Vec::<[f32; 4]>::new();
fn is_overlapped(
center: [f32; 2],
size: [f32; 2],
occupied_region: &mut Vec<[f32; 4]>,
) -> bool {
let x_min = center[0] - size[0];
let x_max = center[0] + size[0];
let y_min = center[1] - size[1];
let y_max = center[1] + size[1];
for region in occupied_region.iter() {
let x_overlap = x_min <= region[1] && x_max >= region[0];
let y_overlap = y_min <= region[3] && y_max >= region[2];
if x_overlap && y_overlap {
occupied_region.push([x_min, x_max, y_min, y_max]);
return true;
}
}
occupied_region.push([x_min, x_max, y_min, y_max]);
return false;
}
fn rand_nodes(
parent: &GenoNode,
direction: usize,
occupied_region: &mut Vec<[f32; 4]>,
) -> Option<GenericGenoNode> {
let mut rng = thread_rng();
let parent_size = parent.size;
let parent_center = parent.center;
let dx_dy_limits_top_bottom =
[parent_size[0], DEFAULT_BLOCK_SIZE[0] * RAND_SIZE_SCALER[1]];
let dx_dy_limits_left_right =
[DEFAULT_BLOCK_SIZE[0] * RAND_SIZE_SCALER[1], parent_size[1]];
if rng.gen_bool(RAND_NODE_NOT_NONE) {
let joint_limits = [rng.gen_range(-PI * 0.9..0.0), rng.gen_range(0.0..PI * 0.9)];
let mut size = [
rng.gen_range(
RAND_SIZE_SCALER[0] * DEFAULT_BLOCK_SIZE[0]..dx_dy_limits_top_bottom[0],
),
rng.gen_range(
RAND_SIZE_SCALER[0] * DEFAULT_BLOCK_SIZE[1]..dx_dy_limits_top_bottom[1],
),
];
if direction == 2 || direction == 3 {
size = [
rng.gen_range(
RAND_SIZE_SCALER[0] * DEFAULT_BLOCK_SIZE[0]..dx_dy_limits_left_right[0],
),
rng.gen_range(
RAND_SIZE_SCALER[0] * DEFAULT_BLOCK_SIZE[1]..dx_dy_limits_left_right[1],
),
];
}
let mut center = [
parent_center[0],
parent_center[1] + parent_size[1] + size[1],
];
if direction == 1 {
center = [
parent_center[0],
parent_center[1] - parent_size[1] - size[1],
];
} else if direction == 2 {
center = [
parent_center[0] - parent_size[0] - size[0],
parent_center[1],
];
} else if direction == 3 {
center = [
parent_center[0] + parent_size[0] + size[0],
parent_center[1],
]
}
if is_overlapped(center, size, occupied_region) {
return None;
} else {
return Some(GenericGenoNode::Child(GenoNode {
joint_limits,
size,
center,
nn_id: None
}));
}
};
return None;
}
fn build(
tree: &mut QuadTree<GenericGenoNode>,
index: usize,
occupied_region: &mut Vec<[f32; 4]>,
) {
let mut rng = thread_rng();
let children = tree.children(index);
if tree.nodes.get(children[3]).is_none() {
return;
}
if let Some(GenericGenoNode::Child(node)) = tree.nodes[index].clone() {
for (i, &child) in children.iter().enumerate() {
tree.nodes[child] = rand_nodes(&node, i, occupied_region)
}
let parent_idx = *children.choose(&mut rng).unwrap();
tree.nodes[parent_idx] = Some(GenericGenoNode::Parent);
for &i in children.iter() {
if i != parent_idx {
build(tree, i, occupied_region);
}
}
}
}
let mut bg = BlobGeno::default();
bg.vec_tree.nodes[0] = Some(GenericGenoNode::Child(GenoNode::default()));
build(&mut bg.vec_tree, 0, &mut occupied_region);
bg
}
pub fn get_first(&self) -> Option<&GenoNode> {
self.vec_tree.nodes[0].as_ref().and_then(|node| match node {
GenericGenoNode::Parent => None,
GenericGenoNode::Child(child) => Some(child),
})
}
pub fn is_valid(&self) -> bool {
fn is_overlapped(
center: [f32; 2],
size: [f32; 2],
occupied_region: &mut Vec<[f32; 4]>,
) -> bool {
let x_min = center[0] - size[0];
let x_max = center[0] + size[0];
let y_min = center[1] - size[1];
let y_max = center[1] + size[1];
for region in occupied_region.iter() {
let x_overlap = x_min < region[1] - POSITION_EPSILON && x_max - POSITION_EPSILON > region[0];
let y_overlap = y_min < region[3] - POSITION_EPSILON && y_max - POSITION_EPSILON > region[2];
if x_overlap && y_overlap {
occupied_region.push([x_min, x_max, y_min, y_max]);
return true;
}
}
occupied_region.push([x_min, x_max, y_min, y_max]);
return false;
}
fn check (
tree: &QuadTree<GenericGenoNode>,
mut occupied_region: &mut Vec<[f32; 4]>,
idx: usize
) -> bool {
if let Some(Some(GenericGenoNode::Child(cur))) = tree.nodes.get(idx) {
if !is_overlapped(cur.center, cur.size, &mut occupied_region) {
tree.children(idx).iter().all(|&i| check(tree, occupied_region, i))
} else {
false
}
} else {
true
}
}
let mut occupied_region: Vec<[f32; 4]> = Vec::new();
check(&self.vec_tree, &mut occupied_region, 0)
}
pub fn leaf_nodes(&self) -> Vec<usize> {
let mut result = Vec::new();
for i in 1..self.vec_tree.nodes.len() {
if let Some(GenericGenoNode::Parent) = self.vec_tree.nodes[i] {
continue; }
if self.vec_tree.nodes[i].is_some() && self.vec_tree.children(i).iter().all(
|&child_idx|
child_idx >= self.vec_tree.nodes.len() ||
self.vec_tree.nodes[child_idx].is_none() ||
matches!(
self.vec_tree.nodes[child_idx],
Some(GenericGenoNode::Parent)
)
) {
result.push(i);
}
}
result
}
pub fn assign_nn_id_to_root(&mut self, id: usize) {
if let Some(Some(GenericGenoNode::Child(node))) = self.vec_tree.nodes.get_mut(0) {
if node.nn_id.is_none() {
node.nn_id = Some(id);
}
} else {
panic!()
}
}
pub fn all_usize_nn_ids(&self) -> Vec<usize> {
self.vec_tree.nodes.iter()
.filter_map(|node_option|{
match node_option {
Some(GenericGenoNode::Child(node)) => Some(node.nn_id.unwrap()),
_ => None
}
})
.collect()
}
pub fn all_nn_ids_mut(&mut self) -> Vec<&mut Option<usize>> {
self.vec_tree.nodes.iter_mut()
.filter_map(|node_option| {
match node_option {
Some(GenericGenoNode::Child(child_node)) => Some(&mut child_node.nn_id),
_ => None,
}
})
.collect()
}
pub fn all_nn_ids_indices(&self) -> Vec<usize> {
self.vec_tree.nodes.iter().enumerate()
.filter_map(|(idx, node_option)| {
match node_option {
Some(GenericGenoNode::Child(_)) => Some(idx),
_ => None,
}
})
.collect()
}
pub fn move_subtree_nodes_root(&mut self, old_size: [f32;2], new_size: [f32;2]) {
let root_index: usize = 0;
let xmove = new_size[0]-old_size[0];
let ymove = new_size[1]-old_size[1];
let children = self.vec_tree.children(root_index);
for (direction, subtree_root_index) in children.iter().enumerate() {
let subtree_indices: Vec<usize> = self.vec_tree.subtree_indices(*subtree_root_index);
match direction {
0 => {
for &i in &subtree_indices {
if let Some(Some(genericnode)) = self.vec_tree.nodes.get_mut(i) {
if let GenericGenoNode::Child(node) = genericnode{
node.center[1] += ymove;
}
} else {
panic!()
}
}
},
1 => {
for &i in &subtree_indices {
if let Some(Some(genericnode)) = self.vec_tree.nodes.get_mut(i) {
if let GenericGenoNode::Child(node) = genericnode{
node.center[1] -= ymove;
}
} else {
panic!()
}
}
},
2 => {
for &i in &subtree_indices {
if let Some(Some(genericnode)) = self.vec_tree.nodes.get_mut(i) {
if let GenericGenoNode::Child(node) = genericnode{
node.center[1] -= xmove;
}
} else {
panic!()
}
}
},
3 => {
for &i in &subtree_indices {
if let Some(Some(genericnode)) = self.vec_tree.nodes.get_mut(i) {
if let GenericGenoNode::Child(node) = genericnode{
node.center[1] += xmove;
}
} else {
panic!()
}
}
}
_ => {panic!()}
}
}
}
pub fn move_subtree_nodes(&mut self, root_index: usize, move_vec: ([f32;2],[f32;2],[f32;2])) {
if root_index == 0 {
panic!()
}
let forward = move_vec.0;
let left_movec = move_vec.1;
let right_movec = move_vec.2;
let subtree_indices: Vec<usize> = self.vec_tree.subtree_indices(root_index);
for &i in &subtree_indices {
if let Some(Some(genericnode)) = self.vec_tree.nodes.get_mut(i) {
if let GenericGenoNode::Child(node) = genericnode{
node.center[0] += forward[0];
node.center[1] += forward[1];
}
} else {
panic!()
}
}
let direction = self.vec_tree.child_direction(root_index).unwrap();
let children = self.vec_tree.children(root_index);
let forward_root = children[direction];
let subtree_indices: Vec<usize> = self.vec_tree.subtree_indices(forward_root);
for &i in &subtree_indices {
if let Some(Some(genericnode)) = self.vec_tree.nodes.get_mut(i) {
if let GenericGenoNode::Child(node) = genericnode{
node.center[0] += forward[0];
node.center[1] += forward[1];
}
} else {
panic!()
}
}
let left_root_index = children[get_left_right_direction(direction).0];
let subtree_indices = self.vec_tree.subtree_indices(left_root_index);
for &i in &subtree_indices {
if let Some(Some(genericnode)) = self.vec_tree.nodes.get_mut(i) {
if let GenericGenoNode::Child(node) = genericnode{
node.center[0] += left_movec[0];
node.center[1] += left_movec[1];
}
} else {
panic!()
}
}
let right_root_index = children[get_left_right_direction(direction).1];
let subtree_indices = self.vec_tree.subtree_indices(right_root_index);
for &i in &subtree_indices {
if let Some(Some(genericnode)) = self.vec_tree.nodes.get_mut(i) {
if let GenericGenoNode::Child(node) = genericnode{
node.center[0] += right_movec[0];
node.center[1] += right_movec[1];
}
} else {
panic!()
}
}
}
pub fn change_node_size(&mut self, index: usize, new_size: [f32;2]) {
if let Some(Some(GenericGenoNode::Child(node))) = self.vec_tree.nodes.get_mut(index) {
node.size = new_size;
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum GenericGenoNode {
Parent,
Child(GenoNode),
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct GenoNode {
pub joint_limits: [f32; 2],
pub size: [f32; 2],
pub center: [f32; 2],
pub nn_id: Option<usize>,
}
impl Default for GenoNode {
fn default() -> Self {
Self {
joint_limits: [-PI, PI],
size: DEFAULT_BLOCK_SIZE,
center: [0.0, 0.0],
nn_id: None
}
}
}
impl GenoNode {
pub fn from_nn_id(nn_id: usize) -> Self {
Self {
joint_limits: [-PI, PI],
size: DEFAULT_BLOCK_SIZE,
center: [0.0, 0.0],
nn_id: Some(nn_id)
}
}
fn to_bundle(&self, center: [f32; 2]) -> PhysiBlockBundle {
PhysiBlockBundle::from_xy_dx_dy(center[0], center[1], self.size[0], self.size[1])
}
}
#[derive(Clone, Serialize, Deserialize)]
pub struct QuadTree<T> {
pub nodes: Vec<Option<T>>,
pub max_depth: u32,
}
impl<T> QuadTree<T> {
pub fn new(max_depth: u32) -> Self {
let capacity = usize::pow(4, max_depth)+1;
let nodes = (0..capacity).map(|_| None).collect();
Self { max_depth, nodes }
}
pub fn parent(&self, index: usize) -> Option<usize> {
if index == 0 {
None
} else {
Some((index - 1) / 4)
}
}
pub fn children(&self, index: usize) -> [usize; 4] {
let base = 4 * index;
[base + 1, base + 2, base + 3, base + 4]
}
pub fn depth(&self, index: usize) -> u32 {
(index as f64).log(4.0).floor() as u32
}
pub fn is_leaf(&self, index: usize) -> bool {
let children_indices = self.children(index);
children_indices.iter().all(|&child_index| {
child_index >= self.nodes.len() || self.nodes[child_index].is_none()
})
}
pub fn clean_subtree(&mut self, index: usize) {
self.nodes[index] = None;
let child_indices = self.children(index);
for &child_index in &child_indices {
if child_index < self.nodes.len() && self.nodes[child_index].is_some() {
self.clean_subtree(child_index);
}
}
}
pub fn clean_subtree_without_self(&mut self, index: usize) {
let child_indices = self.children(index);
for &child_index in &child_indices {
if child_index < self.nodes.len() && self.nodes[child_index].is_some() {
self.clean_subtree(child_index);
}
}
}
pub fn branch_nodes(&self) -> Vec<usize> {
let mut result = Vec::new();
for i in 0..self.nodes.len() {
if self.nodes[i].is_some()
&& self.depth(i) < self.max_depth - 1 && self.children(i).iter().any(
|&child_idx|
child_idx >= self.nodes.len() || self.nodes[child_idx].is_none()
) {
result.push(i);
}
}
result
}
pub fn subtree_indices(&self, index: usize) -> Vec<usize> {
let mut result = Vec::new();
fn collect_indices<T>(quad_tree: &QuadTree<T>, index: usize, result: &mut Vec<usize>) {
if quad_tree.nodes.get(index).is_some() && quad_tree.nodes[index].is_some() {
result.push(index);
for &child_index in &quad_tree.children(index) {
if child_index < quad_tree.nodes.len() {
collect_indices(quad_tree, child_index, result);
}
}
}
}
collect_indices(self, index, &mut result);
result
}
pub fn child_direction(&self, index: usize) -> Option<usize>{
if index == 0 || index > self.nodes.len() || self.nodes[index].is_none(){
None
} else {
Some((index - 1) % 4)
}
}
pub fn is_empty(&self, index: usize) -> bool {
index < self.nodes.len() && self.nodes[index].is_none()
}
pub fn tree_edit_distance(&self, other: &QuadTree<T>) -> usize {
let mut dp = vec![vec![None; other.nodes.len()]; self.nodes.len()];
self._tree_edit_distance(0, 0, other, &mut dp)
}
fn _tree_edit_distance(
&self,
i: usize,
j: usize,
other: &QuadTree<T>,
dp: &mut Vec<Vec<Option<usize>>>
) -> usize {
if i >= self.nodes.len() && j >= other.nodes.len() {
return 0;
}
if i >= self.nodes.len() {
return 1 + other.children(j).iter().map(|&child_j| self._tree_edit_distance(i, child_j, other, dp)).sum::<usize>();
}
if j >= other.nodes.len() {
return 1 + self.children(i).iter().map(|&child_i| self._tree_edit_distance(child_i, j, other, dp)).sum::<usize>();
}
if let Some(val) = dp[i][j] {
return val;
}
let cost = if self.nodes[i].is_some() && other.nodes[j].is_some() {
let children_i = self.children(i);
let children_j = other.children(j);
(0..4).map(|k| self._tree_edit_distance(children_i[k], children_j[k], other, dp)).sum::<usize>()
} else if self.nodes[i].is_some() {
1 + self.children(i).iter().map(|&child_i| self._tree_edit_distance(child_i, j, other, dp)).sum::<usize>()
} else if other.nodes[j].is_some() {
1 + other.children(j).iter().map(|&child_j| self._tree_edit_distance(i, child_j, other, dp)).sum::<usize>()
} else {
0
};
dp[i][j] = Some(cost);
cost
}
}
impl<T: Debug> Debug for QuadTree<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fn print_node<T: Debug>(
tree: &QuadTree<T>,
index: usize,
indent: &str,
f: &mut fmt::Formatter<'_>,
) -> fmt::Result {
match tree.nodes.get(index) {
None | Some(None) => Ok(()), Some(Some(node)) => {
writeln!(f, "{}- Node {}: {:?}", indent, index, node)?;
let children = tree.children(index);
for &child_index in &children {
print_node(tree, child_index, &format!("{} ", indent), f)?;
}
Ok(())
}
}
}
writeln!(f, "QuadTree {{")?;
print_node(self, 0, " ", f)?;
writeln!(f, "}}")
}
}
fn get_left_right_direction(direction:usize) -> (usize,usize) {
match direction {
0 => (2,3),
1 => (3,2),
2 => (1,0),
3 => (0,1),
_ => {panic!()}
}
}
#[cfg(test)]
mod builder_validation_test {
use super::*;
#[test]
fn test_geno_builder_validation() {
for _ in 0..100 {
let geno = BlobGeno::new_rand();
assert!(geno.is_valid());
}
}
}