Switched to petgraph as graph representation. Initialization doesn't work yet
This commit is contained in:
parent
b36038696e
commit
0eaa9d04b8
4 changed files with 103 additions and 89 deletions
|
|
@ -1,16 +1,16 @@
|
||||||
use std::fmt::Display;
|
use petgraph::graph::{Graph, NodeIndex};
|
||||||
|
|
||||||
use crate::genetics::gene::Gene;
|
use crate::genetics::gene::Gene;
|
||||||
|
|
||||||
#[derive(Default,Clone,PartialEq,Eq)]
|
#[derive(Default,Clone)]
|
||||||
pub struct Genome {
|
pub struct Genome {
|
||||||
pub(crate) graph: Vec<(Gene,Vec<usize>)>,
|
pub(crate) graph: Graph<Gene,()>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Genome {
|
impl Genome {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
Self {
|
Self {
|
||||||
graph: Vec::new()
|
graph: Graph::<Gene,()>::new()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn from_edges(nodes: Vec<Gene>,edges: Vec<(usize,usize)>) -> Result<Self,PlantCreationError> {
|
pub fn from_edges(nodes: Vec<Gene>,edges: Vec<(usize,usize)>) -> Result<Self,PlantCreationError> {
|
||||||
|
|
@ -22,13 +22,9 @@ impl Genome {
|
||||||
return Err(PlantCreationError::EmptyEdges);
|
return Err(PlantCreationError::EmptyEdges);
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut graph: Vec<(Gene,Vec<usize>)> = Vec::new();
|
let mut graph = Graph::<Gene,()>::new();
|
||||||
for gene in nodes {
|
let gene_indicies = nodes.into_iter().map(|gene|{graph.add_node(gene)}).collect::<Vec<NodeIndex>>();
|
||||||
graph.push((gene,Vec::new()));
|
edges.into_iter().map(|(node_a,node_b)|graph.add_edge(gene_indicies[node_a], gene_indicies[node_b], ()));
|
||||||
}
|
|
||||||
for edge in edges {
|
|
||||||
graph[edge.0].1.push(edge.1);
|
|
||||||
}
|
|
||||||
|
|
||||||
return Ok(Self {
|
return Ok(Self {
|
||||||
graph
|
graph
|
||||||
|
|
@ -36,27 +32,34 @@ impl Genome {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Vibecoded
|
||||||
|
use std::fmt::{self, Display};
|
||||||
|
|
||||||
impl Display for Genome {
|
impl Display for Genome {
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
let indents = {
|
let graph = &self.graph;
|
||||||
let mut result: Vec<(usize, Gene)> = Vec::new();
|
|
||||||
let mut stack: Vec<(usize, usize)> = vec![(0, 0)]; // (node_index, depth)
|
|
||||||
|
|
||||||
while let Some((node, depth)) = stack.pop() {
|
if graph.node_count() == 0 {
|
||||||
result.push((depth, self.graph[node].0.clone()));
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
// push in reverse so left-most child is processed first
|
let root = NodeIndex::new(0);
|
||||||
for &child in self.graph[node].1.iter().rev() {
|
let mut stack: Vec<(NodeIndex, usize)> = vec![(root, 0)];
|
||||||
stack.push((child, depth + 1));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
result
|
while let Some((node, depth)) = stack.pop() {
|
||||||
};
|
|
||||||
|
|
||||||
for (depth,gene) in indents {
|
|
||||||
let indent = "\t".repeat(depth);
|
let indent = "\t".repeat(depth);
|
||||||
writeln!(f,"{}{}",indent,gene)?;
|
writeln!(f, "{}{}", indent, graph[node])?;
|
||||||
|
|
||||||
|
// push in reverse to preserve child order
|
||||||
|
let mut children: Vec<NodeIndex> = graph
|
||||||
|
.neighbors(node)
|
||||||
|
.filter(|&n| n != node) // skip self-loops
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
children.reverse();
|
||||||
|
for child in children {
|
||||||
|
stack.push((child, depth + 1));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
@ -68,3 +71,4 @@ pub enum PlantCreationError {
|
||||||
EmptyNodes,
|
EmptyNodes,
|
||||||
EmptyEdges,
|
EmptyEdges,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,9 @@
|
||||||
use std::{collections::HashMap, mem::swap};
|
use std::{collections::HashMap, mem::swap};
|
||||||
|
|
||||||
|
use petgraph::graph::NodeIndex;
|
||||||
use rand::{RngExt, SeedableRng, rngs::StdRng};
|
use rand::{RngExt, SeedableRng, rngs::StdRng};
|
||||||
|
|
||||||
use crate::genetics::genome::*;
|
use crate::genetics::{gene::GenePlace, genome::*};
|
||||||
|
|
||||||
pub struct PairGenomeModificator {
|
pub struct PairGenomeModificator {
|
||||||
genome_a: Genome,
|
genome_a: Genome,
|
||||||
|
|
@ -31,61 +32,53 @@ impl PairGenomeModificator {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
pub fn allelic_crossingover(&mut self,chance: Option<u8>) -> (Genome, Genome) {
|
pub fn allelic_crossingover(&mut self,chance: Option<u8>) -> (Genome, Genome) {
|
||||||
let amount: usize = *[self.genome_a.graph.len(),self.genome_b.graph.len()].iter().min().unwrap_or(&0);
|
let amount: usize = *[self.genome_a.graph.node_count(),self.genome_b.graph.node_count()].iter().min().unwrap_or(&0);
|
||||||
|
|
||||||
for i in 0..amount {
|
for i in 0..amount {
|
||||||
let computed = self.generator.random_range(0..chance.unwrap_or(2).max(2));
|
let computed = self.generator.random_range(0..chance.unwrap_or(2).max(2));
|
||||||
if computed != 0 {continue;}
|
if computed != 0 {continue;}
|
||||||
swap(&mut self.genome_a.graph[i].0, &mut self.genome_b.graph[i].0);
|
let idx: NodeIndex = (i as u32).into();
|
||||||
|
swap(&mut self.genome_a.graph[idx], &mut self.genome_b.graph[idx]);
|
||||||
}
|
}
|
||||||
|
|
||||||
(self.genome_a.clone(),self.genome_b.clone())
|
(self.genome_a.clone(),self.genome_b.clone())
|
||||||
}
|
}
|
||||||
pub fn categoric_crossingover(&mut self, chance: Option<u8>,broad: Option<bool>) -> (Genome,Genome) {
|
pub fn categoric_crossingover(&mut self, chance: Option<u8>,broad: Option<bool>) -> (Genome,Genome) {
|
||||||
let threshold = chance.unwrap_or(2).max(2);
|
let threshold = chance.unwrap_or(2).max(2);
|
||||||
|
let mut categories = HashMap::<String,(Vec<NodeIndex>,Vec<NodeIndex>)>::new();
|
||||||
|
|
||||||
let mut categories_a: HashMap<String, Vec<usize>> = HashMap::new();
|
if broad.unwrap_or(false) {
|
||||||
let mut categories_b: HashMap<String, Vec<usize>> = HashMap::new();
|
for i in self.genome_a.graph.node_indices() {
|
||||||
|
categories.entry(self.genome_a.graph[i].place.broad().to_string()).or_default().0.push(i);
|
||||||
for (i, (gene, _)) in self.genome_a.graph.iter().enumerate() {
|
|
||||||
if broad.unwrap_or(false){
|
|
||||||
categories_a.entry(gene.place.broad().to_string()).or_default().push(i);
|
|
||||||
} else {
|
|
||||||
categories_a.entry(gene.place.to_string()).or_default().push(i);
|
|
||||||
}
|
}
|
||||||
}
|
for i in self.genome_b.graph.node_indices() {
|
||||||
for (i, (gene, _)) in self.genome_b.graph.iter().enumerate() {
|
categories.entry(self.genome_b.graph[i].place.broad().to_string()).or_default().1.push(i);
|
||||||
if broad.unwrap_or(false){
|
}
|
||||||
categories_b.entry(gene.place.broad().to_string()).or_default().push(i);
|
} else {
|
||||||
} else {
|
for i in self.genome_a.graph.node_indices() {
|
||||||
categories_b.entry(gene.place.to_string()).or_default().push(i);
|
categories.entry(self.genome_a.graph[i].place.to_string()).or_default().0.push(i);
|
||||||
|
}
|
||||||
|
for i in self.genome_b.graph.node_indices() {
|
||||||
|
categories.entry(self.genome_b.graph[i].place.to_string()).or_default().1.push(i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (category, indices_a) in &categories_a {
|
for (_,(genes_a,genes_b)) in categories {
|
||||||
let Some(indices_b) = categories_b.get(category) else { continue; };
|
if self.generator.random_range(0..threshold) != 0 {continue;}
|
||||||
|
swap(&mut self.genome_a.graph[genes_a[self.generator.random_range(0..genes_a.len())]],&mut self.genome_b.graph[genes_b[self.generator.random_range(0..genes_b.len())]]);
|
||||||
let computed = self.generator.random_range(0..threshold);
|
|
||||||
if computed != 0 { continue; }
|
|
||||||
|
|
||||||
let fi = indices_a[self.generator.random_range(0..indices_a.len())];
|
|
||||||
let si = indices_b[self.generator.random_range(0..indices_b.len())];
|
|
||||||
|
|
||||||
let gene_a = self.genome_a.graph[fi].0.clone();
|
|
||||||
let gene_b = self.genome_b.graph[si].0.clone();
|
|
||||||
self.genome_a.graph[fi].0 = gene_b;
|
|
||||||
self.genome_b.graph[si].0 = gene_a;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
(self.genome_a.clone(),self.genome_b.clone())
|
(self.genome_a.clone(),self.genome_b.clone())
|
||||||
}
|
}
|
||||||
pub fn combine(&mut self) -> (Genome,Genome){
|
pub fn combine(&mut self) -> (Genome,Genome){
|
||||||
let donor_gene: usize = self.generator.random_range(0..self.genome_a.graph.len());
|
/* let donor_gene: usize = self.generator.random_range(0..self.genome_a.graph.len());
|
||||||
let mut extracted = vec![self.genome_a.graph.remove(donor_gene)];
|
let mut extracted = vec![self.genome_a.graph.remove(donor_gene)];
|
||||||
let mut idx = 0;
|
let mut idx = 0;
|
||||||
while idx < extracted.len() {
|
while idx < extracted.len() {
|
||||||
for child_idx
|
for child_idx
|
||||||
idx += 1;
|
idx += 1;
|
||||||
}
|
}*/
|
||||||
(self.genome_a.clone(),self.genome_b.clone())
|
(self.genome_a.clone(),self.genome_b.clone())
|
||||||
}
|
}
|
||||||
pub fn cancel(&self) -> (Genome,Genome) {
|
pub fn cancel(&self) -> (Genome,Genome) {
|
||||||
|
|
|
||||||
|
|
@ -39,6 +39,10 @@ impl INode for GodotGenome {
|
||||||
PlantType::Sunflower => Some(sunflower_template()),
|
PlantType::Sunflower => Some(sunflower_template()),
|
||||||
PlantType::CherryBomb => Some(peashooter_template()),
|
PlantType::CherryBomb => Some(peashooter_template()),
|
||||||
_ => None,
|
_ => None,
|
||||||
|
};
|
||||||
|
|
||||||
|
if let Some(genome) = self.genome.as_ref() {
|
||||||
|
godot_print!("{}",genome);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,8 @@
|
||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
use godot::prelude::*;
|
use godot::prelude::*;
|
||||||
use godot::classes::{INode2D, Node2D, Sprite2D, Texture2D};
|
use godot::classes::{INode2D, Node2D, Sprite2D, Texture2D};
|
||||||
|
use petgraph::graph::NodeIndex;
|
||||||
|
|
||||||
use crate::godot_wrapper::godot_genome::GodotGenome;
|
use crate::godot_wrapper::godot_genome::GodotGenome;
|
||||||
|
|
||||||
|
|
@ -19,33 +22,37 @@ impl INode2D for Plant {
|
||||||
godot_genome.signals().genome_updated().connect_other(&*self, Self::restructure);
|
godot_genome.signals().genome_updated().connect_other(&*self, Self::restructure);
|
||||||
|
|
||||||
let Some(genome)= godot_genome.bind().get_genome() else { return; };
|
let Some(genome)= godot_genome.bind().get_genome() else { return; };
|
||||||
|
let mut root_index = NodeIndex::new(0);
|
||||||
|
|
||||||
let mut children = {
|
let mut nodes = {
|
||||||
let mut result = Vec::new();
|
let mut result = HashMap::new();
|
||||||
for i in 0..genome.graph.len() {
|
for i in genome.graph.node_indices() {
|
||||||
result.push((Sprite2D::new_alloc(),&genome.graph[i]));
|
if result.len() == 0 {
|
||||||
|
root_index = i;
|
||||||
|
}
|
||||||
|
result.insert(i, Sprite2D::new_alloc());
|
||||||
}
|
}
|
||||||
result
|
result
|
||||||
};
|
};
|
||||||
|
for idx in nodes.keys().map(|k|*k).collect::<Vec<NodeIndex>>() {
|
||||||
for i in 0..genome.graph.len() {
|
nodes.get_mut(&idx).unwrap().set_name(&genome.graph[idx].place.to_string());
|
||||||
children[i].0.set_name(&genome.graph[i].0.place.to_string());
|
|
||||||
// Setting up genes
|
// Setting up genes
|
||||||
if let Some(sprite) = genome.graph[i].0.sprite.clone() {
|
if let Some(sprite) = genome.graph[idx].sprite.clone() {
|
||||||
children[i].0.set_texture(&load::<Texture2D>(&("res://assets/sprites/".to_string() + &sprite)));
|
nodes.get_mut(&idx).unwrap().set_texture(&load::<Texture2D>(&("res://assets/sprites/".to_string() + &sprite)));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Setting up children
|
// Setting up children
|
||||||
for edge in &genome.graph[i].1 {
|
for child_idx in genome.graph.neighbors(idx) {
|
||||||
let mut gene_sprite = children[*edge].0.clone();
|
let mut gene_sprite = nodes.get(&child_idx).unwrap().clone();
|
||||||
|
|
||||||
gene_sprite.set_position((children[i].1.0.get_child_position)(children[*edge].1.0.place.clone()));
|
|
||||||
|
|
||||||
children[i].0.add_child(&gene_sprite);
|
gene_sprite.set_position((genome.graph[idx].get_child_position)(genome.graph[child_idx].place.clone()));
|
||||||
|
|
||||||
|
nodes.get_mut(&idx).unwrap().add_child(&gene_sprite);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
self.base_mut().add_child(&children[0].0);
|
self.base_mut().add_child(&nodes[&root_index]);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -60,33 +67,39 @@ impl Plant {
|
||||||
|
|
||||||
let Some(godot_genome) = self.genome.clone() else { return; };
|
let Some(godot_genome) = self.genome.clone() else { return; };
|
||||||
|
|
||||||
let Some(genome)= godot_genome.bind().get_genome() else { return; };
|
godot_genome.signals().genome_updated().connect_other(&*self, Self::restructure);
|
||||||
|
|
||||||
let mut children = {
|
let Some(genome)= godot_genome.bind().get_genome() else { return; };
|
||||||
let mut result = Vec::new();
|
let mut root_index = NodeIndex::new(0);
|
||||||
for i in 0..genome.graph.len() {
|
|
||||||
result.push((Sprite2D::new_alloc(),&genome.graph[i]));
|
let mut nodes = {
|
||||||
|
let mut result = HashMap::new();
|
||||||
|
for i in genome.graph.node_indices() {
|
||||||
|
if result.len() == 0 {
|
||||||
|
root_index = i;
|
||||||
|
}
|
||||||
|
result.insert(i, Sprite2D::new_alloc());
|
||||||
}
|
}
|
||||||
result
|
result
|
||||||
};
|
};
|
||||||
|
for idx in nodes.keys().map(|k|*k).collect::<Vec<NodeIndex>>() {
|
||||||
for i in 0..genome.graph.len() {
|
nodes.get_mut(&idx).unwrap().set_name(&genome.graph[idx].place.to_string());
|
||||||
children[i].0.set_name(&genome.graph[i].0.place.to_string());
|
|
||||||
// Setting up genes
|
// Setting up genes
|
||||||
if let Some(sprite) = genome.graph[i].0.sprite.clone() {
|
if let Some(sprite) = genome.graph[idx].sprite.clone() {
|
||||||
children[i].0.set_texture(&load::<Texture2D>(&("res://assets/sprites/".to_string() + &sprite)));
|
nodes.get_mut(&idx).unwrap().set_texture(&load::<Texture2D>(&("res://assets/sprites/".to_string() + &sprite)));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Setting up children
|
// Setting up children
|
||||||
for edge in &genome.graph[i].1 {
|
for child_idx in genome.graph.neighbors(idx) {
|
||||||
let mut gene_sprite = children[*edge].0.clone();
|
let mut gene_sprite = nodes.get(&child_idx).unwrap().clone();
|
||||||
|
|
||||||
gene_sprite.set_position((children[i].1.0.get_child_position)(children[*edge].1.0.place.clone()));
|
|
||||||
|
|
||||||
children[i].0.add_child(&gene_sprite);
|
gene_sprite.set_position((genome.graph[idx].get_child_position)(genome.graph[child_idx].place.clone()));
|
||||||
|
|
||||||
|
nodes.get_mut(&idx).unwrap().add_child(&gene_sprite);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
self.base_mut().add_child(&children[0].0);
|
self.base_mut().add_child(&nodes[&root_index]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue