radiate_gp/collections/
factory.rs

1use super::{GraphNode, NodeStore, NodeType, NodeValue, TreeNode};
2use crate::Arity;
3use radiate::random_provider;
4
5pub trait Factory<I, O> {
6    fn new_instance(&self, input: I) -> O;
7}
8
9impl<T> Factory<(), T> for NodeValue<T>
10where
11    T: Factory<(), T>,
12{
13    fn new_instance(&self, _: ()) -> T {
14        match self {
15            NodeValue::Bounded(value, _) => value.new_instance(()),
16            NodeValue::Unbound(value) => value.new_instance(()),
17        }
18    }
19}
20
21impl<T> Factory<NodeType, T> for NodeStore<T>
22where
23    T: Factory<(), T> + Default,
24{
25    fn new_instance(&self, input: NodeType) -> T {
26        let new_node = self.map_by_type(input, |values| {
27            random_provider::choose(&values).new_instance(())
28        });
29
30        if let Some(new_value) = new_node {
31            return new_value;
32        }
33
34        T::default()
35    }
36}
37
38impl<T: Default + Clone> Factory<(usize, NodeType), GraphNode<T>> for NodeStore<T> {
39    fn new_instance(&self, input: (usize, NodeType)) -> GraphNode<T> {
40        let (index, node_type) = input;
41
42        let new_node = self.map_by_type(node_type, |values| {
43            let node_value = match node_type {
44                NodeType::Input => &values[index % values.len()],
45                _ => random_provider::choose(&values),
46            };
47
48            match node_value {
49                NodeValue::Bounded(value, arity) => {
50                    return (index, node_type, value.clone(), *arity).into();
51                }
52                NodeValue::Unbound(value) => {
53                    return (index, node_type, value.clone()).into();
54                }
55            }
56        });
57
58        if let Some(new_value) = new_node {
59            return new_value;
60        }
61
62        GraphNode::new(index, node_type, T::default())
63    }
64}
65
66impl<T, F> Factory<(usize, NodeType, F), GraphNode<T>> for NodeStore<T>
67where
68    T: Default + Clone,
69    F: Fn(Arity) -> bool,
70{
71    fn new_instance(&self, input: (usize, NodeType, F)) -> GraphNode<T> {
72        let (index, node_type, filter) = input;
73        let new_node = self.map(|values| {
74            let mapped_values = values
75                .into_iter()
76                .filter(|value| match value {
77                    NodeValue::Bounded(_, arity) => filter(*arity),
78                    _ => false,
79                })
80                .collect::<Vec<&NodeValue<T>>>();
81
82            let node_value = random_provider::choose(&mapped_values);
83
84            match node_value {
85                NodeValue::Bounded(value, arity) => {
86                    return GraphNode::with_arity(index, node_type, value.clone(), *arity);
87                }
88                NodeValue::Unbound(value) => {
89                    return GraphNode::new(index, node_type, value.clone());
90                }
91            }
92        });
93
94        if let Some(new_value) = new_node {
95            return new_value;
96        }
97
98        GraphNode::new(index, node_type, T::default())
99    }
100}
101
102impl<T: Clone + Default> Factory<NodeType, TreeNode<T>> for NodeStore<T> {
103    fn new_instance(&self, input: NodeType) -> TreeNode<T> {
104        let new_node = self.map_by_type(input, |values| {
105            let node_value = random_provider::choose(&values);
106
107            match node_value {
108                NodeValue::Bounded(value, arity) => {
109                    return TreeNode::with_arity(value.clone(), *arity);
110                }
111                NodeValue::Unbound(value) => {
112                    return TreeNode::new(value.clone());
113                }
114            }
115        });
116
117        if let Some(new_value) = new_node {
118            return new_value;
119        }
120
121        TreeNode::new(T::default())
122    }
123}