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;
|
||||
|
||||
#[derive(Default,Clone,PartialEq,Eq)]
|
||||
#[derive(Default,Clone)]
|
||||
pub struct Genome {
|
||||
pub(crate) graph: Vec<(Gene,Vec<usize>)>,
|
||||
pub(crate) graph: Graph<Gene,()>,
|
||||
}
|
||||
|
||||
impl Genome {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
graph: Vec::new()
|
||||
graph: Graph::<Gene,()>::new()
|
||||
}
|
||||
}
|
||||
pub fn from_edges(nodes: Vec<Gene>,edges: Vec<(usize,usize)>) -> Result<Self,PlantCreationError> {
|
||||
|
|
@ -22,13 +22,9 @@ impl Genome {
|
|||
return Err(PlantCreationError::EmptyEdges);
|
||||
}
|
||||
|
||||
let mut graph: Vec<(Gene,Vec<usize>)> = Vec::new();
|
||||
for gene in nodes {
|
||||
graph.push((gene,Vec::new()));
|
||||
}
|
||||
for edge in edges {
|
||||
graph[edge.0].1.push(edge.1);
|
||||
}
|
||||
let mut graph = Graph::<Gene,()>::new();
|
||||
let gene_indicies = nodes.into_iter().map(|gene|{graph.add_node(gene)}).collect::<Vec<NodeIndex>>();
|
||||
edges.into_iter().map(|(node_a,node_b)|graph.add_edge(gene_indicies[node_a], gene_indicies[node_b], ()));
|
||||
|
||||
return Ok(Self {
|
||||
graph
|
||||
|
|
@ -36,29 +32,36 @@ impl Genome {
|
|||
}
|
||||
}
|
||||
|
||||
// Vibecoded
|
||||
use std::fmt::{self, Display};
|
||||
|
||||
impl Display for Genome {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
let indents = {
|
||||
let mut result: Vec<(usize, Gene)> = Vec::new();
|
||||
let mut stack: Vec<(usize, usize)> = vec![(0, 0)]; // (node_index, depth)
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
let graph = &self.graph;
|
||||
|
||||
if graph.node_count() == 0 {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let root = NodeIndex::new(0);
|
||||
let mut stack: Vec<(NodeIndex, usize)> = vec![(root, 0)];
|
||||
|
||||
while let Some((node, depth)) = stack.pop() {
|
||||
result.push((depth, self.graph[node].0.clone()));
|
||||
let indent = "\t".repeat(depth);
|
||||
writeln!(f, "{}{}", indent, graph[node])?;
|
||||
|
||||
// push in reverse so left-most child is processed first
|
||||
for &child in self.graph[node].1.iter().rev() {
|
||||
// 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));
|
||||
}
|
||||
}
|
||||
|
||||
result
|
||||
};
|
||||
|
||||
for (depth,gene) in indents {
|
||||
let indent = "\t".repeat(depth);
|
||||
writeln!(f,"{}{}",indent,gene)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
|
@ -68,3 +71,4 @@ pub enum PlantCreationError {
|
|||
EmptyNodes,
|
||||
EmptyEdges,
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,8 +1,9 @@
|
|||
use std::{collections::HashMap, mem::swap};
|
||||
|
||||
use petgraph::graph::NodeIndex;
|
||||
use rand::{RngExt, SeedableRng, rngs::StdRng};
|
||||
|
||||
use crate::genetics::genome::*;
|
||||
use crate::genetics::{gene::GenePlace, genome::*};
|
||||
|
||||
pub struct PairGenomeModificator {
|
||||
genome_a: Genome,
|
||||
|
|
@ -31,61 +32,53 @@ impl PairGenomeModificator {
|
|||
};
|
||||
}
|
||||
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 {
|
||||
let computed = self.generator.random_range(0..chance.unwrap_or(2).max(2));
|
||||
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())
|
||||
}
|
||||
pub fn categoric_crossingover(&mut self, chance: Option<u8>,broad: Option<bool>) -> (Genome,Genome) {
|
||||
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();
|
||||
let mut categories_b: HashMap<String, Vec<usize>> = HashMap::new();
|
||||
|
||||
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);
|
||||
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 in self.genome_b.graph.node_indices() {
|
||||
categories.entry(self.genome_b.graph[i].place.broad().to_string()).or_default().1.push(i);
|
||||
}
|
||||
} else {
|
||||
categories_a.entry(gene.place.to_string()).or_default().push(i);
|
||||
for i in self.genome_a.graph.node_indices() {
|
||||
categories.entry(self.genome_a.graph[i].place.to_string()).or_default().0.push(i);
|
||||
}
|
||||
}
|
||||
for (i, (gene, _)) in self.genome_b.graph.iter().enumerate() {
|
||||
if broad.unwrap_or(false){
|
||||
categories_b.entry(gene.place.broad().to_string()).or_default().push(i);
|
||||
} else {
|
||||
categories_b.entry(gene.place.to_string()).or_default().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 {
|
||||
let Some(indices_b) = categories_b.get(category) else { continue; };
|
||||
|
||||
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;
|
||||
for (_,(genes_a,genes_b)) in categories {
|
||||
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())]]);
|
||||
}
|
||||
|
||||
|
||||
(self.genome_a.clone(),self.genome_b.clone())
|
||||
}
|
||||
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 idx = 0;
|
||||
while idx < extracted.len() {
|
||||
for child_idx
|
||||
idx += 1;
|
||||
}
|
||||
}*/
|
||||
(self.genome_a.clone(),self.genome_b.clone())
|
||||
}
|
||||
pub fn cancel(&self) -> (Genome,Genome) {
|
||||
|
|
|
|||
|
|
@ -39,6 +39,10 @@ impl INode for GodotGenome {
|
|||
PlantType::Sunflower => Some(sunflower_template()),
|
||||
PlantType::CherryBomb => Some(peashooter_template()),
|
||||
_ => 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::classes::{INode2D, Node2D, Sprite2D, Texture2D};
|
||||
use petgraph::graph::NodeIndex;
|
||||
|
||||
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);
|
||||
|
||||
let Some(genome)= godot_genome.bind().get_genome() else { return; };
|
||||
let mut root_index = NodeIndex::new(0);
|
||||
|
||||
let mut children = {
|
||||
let mut result = Vec::new();
|
||||
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
|
||||
};
|
||||
|
||||
for i in 0..genome.graph.len() {
|
||||
children[i].0.set_name(&genome.graph[i].0.place.to_string());
|
||||
for idx in nodes.keys().map(|k|*k).collect::<Vec<NodeIndex>>() {
|
||||
nodes.get_mut(&idx).unwrap().set_name(&genome.graph[idx].place.to_string());
|
||||
// Setting up genes
|
||||
if let Some(sprite) = genome.graph[i].0.sprite.clone() {
|
||||
children[i].0.set_texture(&load::<Texture2D>(&("res://assets/sprites/".to_string() + &sprite)));
|
||||
if let Some(sprite) = genome.graph[idx].sprite.clone() {
|
||||
nodes.get_mut(&idx).unwrap().set_texture(&load::<Texture2D>(&("res://assets/sprites/".to_string() + &sprite)));
|
||||
}
|
||||
|
||||
// Setting up children
|
||||
for edge in &genome.graph[i].1 {
|
||||
let mut gene_sprite = children[*edge].0.clone();
|
||||
for child_idx in genome.graph.neighbors(idx) {
|
||||
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(genome)= godot_genome.bind().get_genome() else { return; };
|
||||
godot_genome.signals().genome_updated().connect_other(&*self, Self::restructure);
|
||||
|
||||
let mut children = {
|
||||
let mut result = Vec::new();
|
||||
for i in 0..genome.graph.len() {
|
||||
result.push((Sprite2D::new_alloc(),&genome.graph[i]));
|
||||
let Some(genome)= godot_genome.bind().get_genome() else { return; };
|
||||
let mut root_index = NodeIndex::new(0);
|
||||
|
||||
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
|
||||
};
|
||||
|
||||
for i in 0..genome.graph.len() {
|
||||
children[i].0.set_name(&genome.graph[i].0.place.to_string());
|
||||
for idx in nodes.keys().map(|k|*k).collect::<Vec<NodeIndex>>() {
|
||||
nodes.get_mut(&idx).unwrap().set_name(&genome.graph[idx].place.to_string());
|
||||
// Setting up genes
|
||||
if let Some(sprite) = genome.graph[i].0.sprite.clone() {
|
||||
children[i].0.set_texture(&load::<Texture2D>(&("res://assets/sprites/".to_string() + &sprite)));
|
||||
if let Some(sprite) = genome.graph[idx].sprite.clone() {
|
||||
nodes.get_mut(&idx).unwrap().set_texture(&load::<Texture2D>(&("res://assets/sprites/".to_string() + &sprite)));
|
||||
}
|
||||
|
||||
// Setting up children
|
||||
for edge in &genome.graph[i].1 {
|
||||
let mut gene_sprite = children[*edge].0.clone();
|
||||
for child_idx in genome.graph.neighbors(idx) {
|
||||
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