1use crate::node::Node;
2use crate::{Arity, NodeType};
3use radiate_core::{Gene, Valid};
4use radiate_utils::SortedBuffer;
5#[cfg(feature = "serde")]
6use serde::{Deserialize, Serialize};
7use std::fmt::Debug;
8use std::hash::Hash;
9use std::sync::atomic::{AtomicU64, Ordering};
10
11#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
32#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
33#[repr(transparent)]
34pub struct GraphNodeId(u64);
35
36impl GraphNodeId {
37 pub fn new() -> Self {
38 static GRAPH_NODE_ID: AtomicU64 = AtomicU64::new(0);
39 GraphNodeId(GRAPH_NODE_ID.fetch_add(1, Ordering::Relaxed))
40 }
41}
42
43#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
79#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
80pub enum Direction {
81 Forward,
82 Backward,
83}
84
85#[derive(Clone, PartialEq)]
150#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
151pub struct GraphNode<T> {
152 value: T,
153 id: GraphNodeId,
154 index: usize,
155 direction: Direction,
156 node_type: Option<NodeType>,
157 arity: Option<Arity>,
158 incoming: SortedBuffer<usize>,
159 outgoing: SortedBuffer<usize>,
160}
161
162impl<T> GraphNode<T> {
163 pub fn new(index: usize, node_type: NodeType, value: T) -> Self {
168 GraphNode {
169 id: GraphNodeId::new(),
170 index,
171 value,
172 direction: Direction::Forward,
173 node_type: Some(node_type),
174 arity: None,
175 incoming: SortedBuffer::new(),
176 outgoing: SortedBuffer::new(),
177 }
178 }
179
180 pub fn with_arity(index: usize, node_type: NodeType, value: T, arity: Arity) -> Self {
186 GraphNode {
187 id: GraphNodeId::new(),
188 index,
189 value,
190 direction: Direction::Forward,
191 node_type: Some(node_type),
192 arity: Some(arity),
193 incoming: SortedBuffer::new(),
194 outgoing: SortedBuffer::new(),
195 }
196 }
197
198 pub fn with_incoming<I: IntoIterator<Item = usize>>(mut self, incoming: I) -> Self {
199 SortedBuffer::set_sorted_unique(&mut self.incoming, incoming);
200 self
201 }
202
203 pub fn with_outgoing<O: IntoIterator<Item = usize>>(mut self, outgoing: O) -> Self {
204 SortedBuffer::set_sorted_unique(&mut self.outgoing, outgoing);
205 self
206 }
207
208 pub fn direction(&self) -> Direction {
209 self.direction
210 }
211
212 pub fn set_direction(&mut self, direction: Direction) {
213 self.direction = direction;
214 }
215
216 pub fn index(&self) -> usize {
217 self.index
218 }
219
220 pub fn id(&self) -> &GraphNodeId {
221 &self.id
222 }
223
224 pub fn is_recurrent(&self) -> bool {
225 self.direction == Direction::Backward
226 || self.incoming.contains(&self.index)
227 || self.outgoing.contains(&self.index)
228 }
229
230 pub fn incoming(&self) -> &[usize] {
231 self.incoming.as_slice()
232 }
233
234 pub fn outgoing(&self) -> &[usize] {
235 self.outgoing.as_slice()
236 }
237
238 pub fn incoming_mut(&mut self) -> &mut [usize] {
239 self.incoming.as_mut_slice()
240 }
241
242 pub fn outgoing_mut(&mut self) -> &mut [usize] {
243 self.outgoing.as_mut_slice()
244 }
245
246 pub fn is_locked(&self) -> bool {
247 match self.arity() {
248 Arity::Any => false,
249 _ => self.incoming.len() == *self.arity(),
250 }
251 }
252
253 pub fn insert_incoming(&mut self, value: usize) {
254 SortedBuffer::insert_sorted_unique(&mut self.incoming, value);
255 }
256
257 pub fn remove_incoming(&mut self, value: &usize) {
258 SortedBuffer::remove_sorted(&mut self.incoming, value);
259 }
260
261 pub fn insert_outgoing(&mut self, value: usize) {
262 SortedBuffer::insert_sorted_unique(&mut self.outgoing, value);
263 }
264
265 pub fn remove_outgoing(&mut self, value: &usize) {
266 SortedBuffer::remove_sorted(&mut self.outgoing, value);
267 }
268}
269
270impl<T> Node for GraphNode<T> {
273 type Value = T;
274
275 fn value(&self) -> &Self::Value {
276 &self.value
277 }
278
279 fn value_mut(&mut self) -> &mut Self::Value {
280 &mut self.value
281 }
282
283 fn node_type(&self) -> NodeType {
284 if let Some(node_type) = self.node_type {
285 return node_type;
286 }
287
288 let arity = self.arity();
289
290 if let Arity::Any = arity {
291 if self.outgoing.is_empty() && self.incoming.is_empty() {
292 NodeType::Vertex
293 } else if self.outgoing.is_empty() {
294 NodeType::Output
295 } else {
296 NodeType::Vertex
297 }
298 } else if let Arity::Exact(1) = arity {
299 if self.incoming.len() == 1 && self.outgoing.len() == 1 {
300 NodeType::Edge
301 } else {
302 NodeType::Vertex
303 }
304 } else if let Arity::Zero = arity {
305 NodeType::Input
306 } else {
307 NodeType::Vertex
308 }
309 }
310
311 fn arity(&self) -> Arity {
312 if let Some(node_type) = self.node_type {
313 return self.arity.unwrap_or(match node_type {
314 NodeType::Input => Arity::Zero,
315 NodeType::Output => Arity::Any,
316 NodeType::Vertex => Arity::Any,
317 NodeType::Edge => Arity::Exact(1),
318 NodeType::Leaf => Arity::Zero,
319 NodeType::Root => Arity::Any,
320 });
321 }
322
323 self.arity.unwrap_or(Arity::Any)
324 }
325}
326
327impl<T> Gene for GraphNode<T>
328where
329 T: Clone + PartialEq,
330{
331 type Allele = T;
332
333 fn allele(&self) -> &Self::Allele {
334 self.value()
335 }
336
337 fn allele_mut(&mut self) -> &mut Self::Allele {
338 &mut self.value
339 }
340
341 fn new_instance(&self) -> GraphNode<T> {
342 GraphNode {
343 id: GraphNodeId::new(),
344 index: self.index,
345 value: self.value.clone(),
346 direction: self.direction,
347 node_type: self.node_type,
348 arity: self.arity,
349 incoming: self.incoming.clone(),
350 outgoing: self.outgoing.clone(),
351 }
352 }
353
354 fn with_allele(&self, allele: &Self::Allele) -> GraphNode<T> {
355 GraphNode {
356 id: GraphNodeId::new(),
357 index: self.index,
358 value: allele.clone(),
359 direction: self.direction,
360 node_type: self.node_type,
361 arity: self.arity,
362 incoming: self.incoming.clone(),
363 outgoing: self.outgoing.clone(),
364 }
365 }
366}
367
368impl<T> Valid for GraphNode<T> {
379 #[inline]
380 fn is_valid(&self) -> bool {
381 match self.node_type() {
382 NodeType::Input => self.incoming.is_empty() && !self.outgoing.is_empty(),
383 NodeType::Output => {
384 (!self.incoming.is_empty())
385 && (self.incoming.len() == *self.arity() || self.arity() == Arity::Any)
386 }
387 NodeType::Vertex => {
388 if !self.incoming.is_empty() && !self.outgoing.is_empty() {
389 if let Arity::Exact(n) = self.arity() {
390 return self.incoming.len() == n;
391 } else if self.arity() == Arity::Any {
392 return true;
393 }
394 }
395 false
396 }
397 NodeType::Edge => {
398 if self.arity() == Arity::Exact(1) {
399 return self.incoming.len() == 1 && self.outgoing.len() == 1;
400 }
401
402 false
403 }
404 _ => false,
405 }
406 }
407}
408
409impl<T> From<(usize, NodeType, T)> for GraphNode<T> {
410 fn from((index, node_type, value): (usize, NodeType, T)) -> Self {
411 GraphNode::new(index, node_type, value)
412 }
413}
414
415impl<T: Default> From<(usize, T)> for GraphNode<T> {
416 fn from((index, value): (usize, T)) -> Self {
417 GraphNode {
418 index,
419 id: GraphNodeId::new(),
420 value,
421 direction: Direction::Forward,
422 node_type: None,
423 arity: None,
424 incoming: SortedBuffer::new(),
425 outgoing: SortedBuffer::new(),
426 }
427 }
428}
429
430impl<T> From<(usize, NodeType, T, Arity)> for GraphNode<T> {
431 fn from((index, node_type, value, arity): (usize, NodeType, T, Arity)) -> Self {
432 GraphNode::with_arity(index, node_type, value, arity)
433 }
434}
435
436impl<T: Default> From<(usize, T, Arity)> for GraphNode<T> {
437 fn from((index, value, arity): (usize, T, Arity)) -> Self {
438 GraphNode {
439 index,
440 id: GraphNodeId::new(),
441 value,
442 direction: Direction::Forward,
443 node_type: None,
444 arity: Some(arity),
445 incoming: SortedBuffer::new(),
446 outgoing: SortedBuffer::new(),
447 }
448 }
449}
450
451impl<T, I> From<(usize, NodeType, T, I, I)> for GraphNode<T>
452where
453 I: Into<SortedBuffer<usize>>,
454{
455 fn from((index, node_type, value, incoming, outgoing): (usize, NodeType, T, I, I)) -> Self {
456 let incoming = incoming.into();
457 let outgoing = outgoing.into();
458
459 GraphNode {
460 index,
461 id: GraphNodeId::new(),
462 value,
463 direction: Direction::Forward,
464 node_type: Some(node_type),
465 arity: None,
466 incoming,
467 outgoing,
468 }
469 }
470}
471
472impl<T: Default> Default for GraphNode<T> {
473 fn default() -> Self {
474 GraphNode {
475 id: GraphNodeId::new(),
476 index: 0,
477 value: Default::default(),
478 direction: Direction::Forward,
479 node_type: None,
480 arity: None,
481 incoming: SortedBuffer::new(),
482 outgoing: SortedBuffer::new(),
483 }
484 }
485}
486
487impl<T: Hash> Hash for GraphNode<T> {
488 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
489 self.id.hash(state);
490 self.index.hash(state);
491 self.direction.hash(state);
492 self.node_type.hash(state);
493 self.arity.hash(state);
494 self.incoming.hash(state);
495 self.outgoing.hash(state);
496 self.value.hash(state);
497 }
498
499 fn hash_slice<H: std::hash::Hasher>(data: &[Self], state: &mut H)
500 where
501 Self: Sized,
502 {
503 for item in data {
504 item.hash(state);
505 }
506 }
507}
508
509impl<T: Debug> Debug for GraphNode<T> {
510 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
511 let incoming = self
512 .incoming
513 .iter()
514 .map(|idx| idx.to_string())
515 .collect::<Vec<String>>()
516 .join(", ");
517
518 write!(
519 f,
520 "[{:<3}] [{:<7?}] {:>10?} :: {:<10} {:<12} V:{:<5} R:{:<5} {:<2} {:<2} < [{}]",
521 self.index,
522 self.id.0,
523 format!("{:?}", self.node_type())[..3].to_owned(),
524 self.arity(),
525 format!("{:?}", self.value).to_owned(),
526 self.is_valid(),
527 self.is_recurrent(),
528 self.incoming.len(),
529 self.outgoing.len(),
530 incoming,
531 )
532 }
533}
534
535#[cfg(test)]
536mod tests {
537 use super::*;
538 use crate::NodeType;
539
540 #[test]
541 fn test_graph_node_default() {
542 let node = GraphNode::<usize>::default();
543
544 assert_eq!(node.index(), 0);
545 assert_eq!(node.node_type(), NodeType::Vertex);
546 assert_eq!(node.arity(), Arity::Any);
547 assert!(!node.is_valid());
548 assert!(!node.is_recurrent());
549 assert_eq!(node.incoming(), &[] as &[usize]);
550 assert_eq!(node.outgoing(), &[] as &[usize]);
551 }
552
553 #[test]
554 fn test_graph_node() {
555 let node = GraphNode::new(0, NodeType::Input, 0.0);
556
557 assert_eq!(node.index(), 0);
558 assert_eq!(node.node_type(), NodeType::Input);
559 assert_eq!(node.arity(), Arity::Zero);
560 assert!(!node.is_valid());
561 assert!(!node.is_recurrent());
562 assert_eq!(node.incoming(), &[] as &[usize]);
563 assert_eq!(node.outgoing(), &[] as &[usize]);
564 }
565
566 #[test]
567 fn test_graph_node_with_arity() {
568 let node = GraphNode::with_arity(0, NodeType::Input, 0.0, Arity::Zero);
569
570 assert_eq!(node.index(), 0);
571 assert_eq!(node.node_type(), NodeType::Input);
572 assert_eq!(node.arity(), Arity::Zero);
573 assert!(!node.is_valid());
574 assert!(!node.is_recurrent());
575 assert_eq!(node.incoming(), &[] as &[usize]);
576 assert_eq!(node.outgoing(), &[] as &[usize]);
577 }
578
579 #[test]
580 fn test_graph_node_with_allele() {
581 let node = GraphNode::new(0, NodeType::Input, 0.0);
582
583 let new_node = node.with_allele(&1.0);
584 assert_eq!(new_node.index(), 0);
585 assert_eq!(new_node.node_type(), NodeType::Input);
586 assert_eq!(new_node.arity(), Arity::Zero);
587 assert!(!new_node.is_valid());
588 assert!(!new_node.is_recurrent());
589 assert_eq!(new_node.incoming(), &[] as &[usize]);
590 assert_eq!(new_node.outgoing(), &[] as &[usize]);
591 }
592
593 #[test]
594 fn test_graph_node_with_direction() {
595 let mut node_one = GraphNode::new(0, NodeType::Input, 0.0);
596
597 assert!(!node_one.is_recurrent());
598 node_one.set_direction(Direction::Backward);
599 assert!(node_one.is_recurrent());
600
601 let mut node_two = GraphNode::new(0, NodeType::Input, 0.0);
602
603 assert!(!node_two.is_recurrent());
604 node_two.insert_incoming(0);
605 assert!(node_two.is_recurrent());
606 }
607
608 #[test]
609 fn graph_node_from_fns_produce_valid_arities() {
610 let node = GraphNode::from((0, NodeType::Input, 0.0));
611 assert_eq!(node.arity(), Arity::Zero);
612
613 let node = GraphNode::from((0, NodeType::Output, 0.0));
614 assert_eq!(node.arity(), Arity::Any);
615
616 let node = GraphNode::from((0, NodeType::Vertex, 0.0));
617 assert_eq!(node.arity(), Arity::Any);
618
619 let node = GraphNode::from((0, NodeType::Edge, 0.0));
620 assert_eq!(node.arity(), Arity::Exact(1));
621
622 let node = GraphNode::from((0, NodeType::Input, 0.0, Arity::Zero));
623 assert_eq!(node.arity(), Arity::Zero);
624
625 let node = GraphNode::from((0, NodeType::Output, 0.0, Arity::Any));
626 assert_eq!(node.arity(), Arity::Any);
627
628 let node = GraphNode::from((0, NodeType::Vertex, 0.0, Arity::Any));
629 assert_eq!(node.arity(), Arity::Any);
630
631 let node = GraphNode::from((0, NodeType::Edge, 0.0, Arity::Exact(1)));
632 assert_eq!(node.arity(), Arity::Exact(1));
633 }
634
635 #[test]
636 fn test_graph_node_validity() {
637 let mut input_node = GraphNode::new(0, NodeType::Input, 0.0);
638 assert!(!input_node.is_valid());
639
640 input_node.insert_outgoing(1);
641 assert!(input_node.is_valid());
642
643 let mut output_node = GraphNode::new(1, NodeType::Output, 0.0);
644 assert!(!output_node.is_valid());
645
646 output_node.insert_incoming(0);
647 assert!(output_node.is_valid());
648 }
649
650 #[test]
651 fn test_graph_node_connections_sorted() {
652 let mut node = GraphNode::new(0, NodeType::Vertex, 0.0);
653
654 node.insert_incoming(3);
655 node.insert_incoming(1);
656 node.insert_incoming(2);
657 node.insert_incoming(2); assert_eq!(node.incoming(), &[1, 2, 3]);
660
661 node.insert_outgoing(5);
662 node.insert_outgoing(4);
663 node.insert_outgoing(6);
664 node.insert_outgoing(5); assert_eq!(node.outgoing(), &[4, 5, 6]);
667
668 node.remove_incoming(&2);
669 assert_eq!(node.incoming(), &[1, 3]);
670
671 node.remove_outgoing(&5);
672 assert_eq!(node.outgoing(), &[4, 6]);
673 }
674
675 #[test]
676 #[cfg(feature = "serde")]
677 fn test_graph_node_serde() {
678 let node = GraphNode::new(0, NodeType::Input, 42.0);
679 let serialized = serde_json::to_string(&node).unwrap();
680 let deserialized = serde_json::from_str::<GraphNode<f32>>(&serialized).unwrap();
681
682 assert_eq!(node, deserialized);
683 assert_eq!(node.value(), &42.0);
684 assert_eq!(deserialized.value(), &42.0);
685 }
686}