radiate_gp/collections/graphs/
chromosome.rs1use crate::{Factory, GraphNode, NodeStore, node::Node};
2use radiate_core::{Chromosome, Gene, Valid};
3#[cfg(feature = "serde")]
4use serde::{Deserialize, Serialize};
5use std::{fmt::Debug, hash::Hash};
6
7#[derive(Clone)]
65#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
66pub struct GraphChromosome<T> {
67 nodes: Vec<GraphNode<T>>,
68 store: Option<NodeStore<T>>,
69 max_nodes: Option<usize>,
70}
71
72impl<T> GraphChromosome<T> {
73 pub fn new(nodes: Vec<GraphNode<T>>, factory: NodeStore<T>) -> Self {
74 GraphChromosome {
75 nodes,
76 store: Some(factory),
77 max_nodes: None,
78 }
79 }
80
81 pub fn with_max_nodes(mut self, max_nodes: usize) -> Self {
82 self.max_nodes = Some(max_nodes + self.nodes.len());
83 self
84 }
85
86 pub fn take_nodes(&mut self) -> Vec<GraphNode<T>> {
87 std::mem::take(&mut self.nodes)
88 }
89
90 pub fn set_nodes(&mut self, nodes: Vec<GraphNode<T>>) {
91 self.nodes = nodes;
92 }
93
94 pub fn store(&self) -> Option<&NodeStore<T>> {
95 self.store.as_ref()
96 }
97
98 pub fn max_nodes(&self) -> Option<usize> {
99 self.max_nodes
100 }
101}
102
103impl<T> Factory<Option<NodeStore<T>>, GraphChromosome<T>> for GraphChromosome<T>
104where
105 T: Clone + PartialEq + Default,
106{
107 fn new_instance(&self, input: Option<NodeStore<T>>) -> GraphChromosome<T> {
108 input
109 .or_else(|| self.store.clone())
110 .map(|store| GraphChromosome {
111 nodes: self
112 .iter()
113 .enumerate()
114 .filter_map(|(index, node)| {
115 store
116 .new_instance((index, node.node_type()))
117 .map(|new_node| {
118 let mut new_node = if new_node.arity() == node.arity() {
119 node.with_allele(new_node.allele())
120 } else {
121 node.clone()
122 };
123
124 new_node.set_innovation(node.innovation());
125 new_node
126 })
127 })
128 .collect(),
129 store: Some(store),
130 max_nodes: self.max_nodes,
131 })
132 .map(|chromosome| {
133 if chromosome.len() != self.len() {
134 self.clone()
135 } else {
136 chromosome
137 }
138 })
139 .unwrap_or_else(|| self.clone())
140 }
141}
142
143impl<T> Chromosome for GraphChromosome<T>
144where
145 T: Clone + PartialEq,
146{
147 type Gene = GraphNode<T>;
148
149 fn get(&self, index: usize) -> Option<&Self::Gene> {
150 self.nodes.get(index)
151 }
152
153 fn get_mut(&mut self, index: usize) -> Option<&mut Self::Gene> {
154 self.nodes.get_mut(index)
155 }
156
157 fn set(&mut self, index: usize, gene: Self::Gene) {
158 if let Some(slot) = self.nodes.get_mut(index) {
159 *slot = gene;
160 }
161 }
162
163 fn iter(&self) -> impl Iterator<Item = &Self::Gene> {
164 self.nodes.iter()
165 }
166
167 fn iter_mut(&mut self) -> impl Iterator<Item = &mut Self::Gene> {
168 self.nodes.iter_mut()
169 }
170
171 fn len(&self) -> usize {
172 self.nodes.len()
173 }
174}
175
176impl<T> Valid for GraphChromosome<T> {
177 #[inline]
178 fn is_valid(&self) -> bool {
179 self.nodes.iter().all(|gene| gene.is_valid())
180 }
181}
182
183impl<T> AsRef<[GraphNode<T>]> for GraphChromosome<T> {
184 fn as_ref(&self) -> &[GraphNode<T>] {
185 &self.nodes
186 }
187}
188
189impl<T> AsMut<[GraphNode<T>]> for GraphChromosome<T> {
190 fn as_mut(&mut self) -> &mut [GraphNode<T>] {
191 &mut self.nodes
192 }
193}
194
195impl<T: PartialEq> PartialEq for GraphChromosome<T> {
196 fn eq(&self, other: &Self) -> bool {
197 self.nodes == other.nodes
198 }
199}
200
201impl<T: Hash> Hash for GraphChromosome<T> {
202 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
203 for node in self.as_ref() {
204 node.hash(state);
205 }
206 }
207}
208
209impl<T> From<Vec<GraphNode<T>>> for GraphChromosome<T> {
210 fn from(nodes: Vec<GraphNode<T>>) -> Self {
211 GraphChromosome {
212 nodes,
213 store: None,
214 max_nodes: None,
215 }
216 }
217}
218
219impl<T, I> From<(I, NodeStore<T>)> for GraphChromosome<T>
220where
221 I: IntoIterator<Item = GraphNode<T>>,
222{
223 fn from((iter, store): (I, NodeStore<T>)) -> Self {
224 GraphChromosome {
225 nodes: iter.into_iter().collect(),
226 store: Some(store),
227 max_nodes: None,
228 }
229 }
230}
231
232impl<T> FromIterator<GraphNode<T>> for GraphChromosome<T> {
233 fn from_iter<I: IntoIterator<Item = GraphNode<T>>>(iter: I) -> Self {
234 GraphChromosome {
235 nodes: iter.into_iter().collect(),
236 store: None,
237 max_nodes: None,
238 }
239 }
240}
241
242impl<T> IntoIterator for GraphChromosome<T> {
243 type Item = GraphNode<T>;
244 type IntoIter = std::vec::IntoIter<GraphNode<T>>;
245
246 fn into_iter(self) -> Self::IntoIter {
247 self.nodes.into_iter()
248 }
249}
250
251impl<T: Debug> Debug for GraphChromosome<T> {
252 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
253 writeln!(f, "Graph {{")?;
254 for node in self.as_ref() {
255 writeln!(f, " {:?},", node)?;
256 }
257 write!(f, "}}")
258 }
259}