use crate::{Factory, GraphNode, NodeStore, node::Node};
use radiate_core::{Chromosome, Gene, Valid};
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
use std::{fmt::Debug, hash::Hash};
#[derive(Clone)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct GraphChromosome<T> {
nodes: Vec<GraphNode<T>>,
store: Option<NodeStore<T>>,
max_nodes: Option<usize>,
}
impl<T> GraphChromosome<T> {
pub fn new(nodes: Vec<GraphNode<T>>, factory: NodeStore<T>) -> Self {
GraphChromosome {
nodes,
store: Some(factory),
max_nodes: None,
}
}
pub fn with_max_nodes(mut self, max_nodes: usize) -> Self {
self.max_nodes = Some(max_nodes + self.nodes.len());
self
}
pub fn take_nodes(&mut self) -> Vec<GraphNode<T>> {
std::mem::take(&mut self.nodes)
}
pub fn set_nodes(&mut self, nodes: Vec<GraphNode<T>>) {
self.nodes = nodes;
}
pub fn store(&self) -> Option<&NodeStore<T>> {
self.store.as_ref()
}
pub fn max_nodes(&self) -> Option<usize> {
self.max_nodes
}
}
impl<T> Factory<Option<NodeStore<T>>, GraphChromosome<T>> for GraphChromosome<T>
where
T: Clone + PartialEq + Default,
{
fn new_instance(&self, input: Option<NodeStore<T>>) -> GraphChromosome<T> {
input
.or_else(|| self.store.clone())
.map(|store| GraphChromosome {
nodes: self
.iter()
.enumerate()
.filter_map(|(index, node)| {
store
.new_instance((index, node.node_type()))
.map(|new_node| {
let mut new_node = if new_node.arity() == node.arity() {
node.with_allele(new_node.allele())
} else {
node.clone()
};
new_node.set_innovation(node.innovation());
new_node
})
})
.collect(),
store: Some(store),
max_nodes: self.max_nodes,
})
.map(|chromosome| {
if chromosome.len() != self.len() {
self.clone()
} else {
chromosome
}
})
.unwrap_or_else(|| self.clone())
}
}
impl<T> Chromosome for GraphChromosome<T>
where
T: Clone + PartialEq,
{
type Gene = GraphNode<T>;
fn as_slice(&self) -> &[GraphNode<T>] {
&self.nodes
}
fn as_mut_slice(&mut self) -> &mut [GraphNode<T>] {
&mut self.nodes
}
}
impl<T> Valid for GraphChromosome<T> {
#[inline]
fn is_valid(&self) -> bool {
self.nodes.iter().all(|gene| gene.is_valid())
}
}
impl<T> AsRef<[GraphNode<T>]> for GraphChromosome<T> {
fn as_ref(&self) -> &[GraphNode<T>] {
&self.nodes
}
}
impl<T> AsMut<[GraphNode<T>]> for GraphChromosome<T> {
fn as_mut(&mut self) -> &mut [GraphNode<T>] {
&mut self.nodes
}
}
impl<T: PartialEq> PartialEq for GraphChromosome<T> {
fn eq(&self, other: &Self) -> bool {
self.nodes == other.nodes
}
}
impl<T: Hash> Hash for GraphChromosome<T> {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
for node in self.as_ref() {
node.hash(state);
}
}
}
impl<T> From<Vec<GraphNode<T>>> for GraphChromosome<T> {
fn from(nodes: Vec<GraphNode<T>>) -> Self {
GraphChromosome {
nodes,
store: None,
max_nodes: None,
}
}
}
impl<T, I> From<(I, NodeStore<T>)> for GraphChromosome<T>
where
I: IntoIterator<Item = GraphNode<T>>,
{
fn from((iter, store): (I, NodeStore<T>)) -> Self {
GraphChromosome {
nodes: iter.into_iter().collect(),
store: Some(store),
max_nodes: None,
}
}
}
impl<T> FromIterator<GraphNode<T>> for GraphChromosome<T> {
fn from_iter<I: IntoIterator<Item = GraphNode<T>>>(iter: I) -> Self {
GraphChromosome {
nodes: iter.into_iter().collect(),
store: None,
max_nodes: None,
}
}
}
impl<T> IntoIterator for GraphChromosome<T> {
type Item = GraphNode<T>;
type IntoIter = std::vec::IntoIter<GraphNode<T>>;
fn into_iter(self) -> Self::IntoIter {
self.nodes.into_iter()
}
}
impl<T: Debug> Debug for GraphChromosome<T> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
writeln!(f, "Graph {{")?;
for node in self.as_ref() {
writeln!(f, " {:?},", node)?;
}
write!(f, "}}")
}
}