radiate_gp/collections/trees/
builder.rs1use crate::collections::{Tree, TreeNode};
2use crate::node::Node;
3use crate::{Arity, Factory, NodeStore, NodeType};
4use radiate_core::Valid;
5
6const NUM_CHILDREN_ANY: usize = 2;
7
8impl<T: Clone + Default> Tree<T> {
9 pub fn with_depth(depth: usize, nodes: impl Into<NodeStore<T>>) -> Self {
26 let store = nodes.into();
27
28 let root = if store.contains_type(NodeType::Root) {
29 store.new_instance(NodeType::Root)
30 } else {
31 store.new_instance(NodeType::Vertex)
32 };
33
34 if let Some(mut root_node) = root {
35 if root_node.arity() == Arity::Any {
36 for _ in 0..NUM_CHILDREN_ANY {
37 if let Some(child) = Self::grow(depth - 1, &store) {
38 root_node.add_child(child);
39 }
40 }
41 } else {
42 for _ in 0..*root_node.arity() {
43 if let Some(child) = Self::grow(depth - 1, &store) {
44 root_node.add_child(child);
45 }
46 }
47 }
48
49 Tree::new(root_node)
50 } else {
51 Tree::default()
52 }
53 }
54
55 pub(crate) fn grow(current_depth: usize, store: &NodeStore<T>) -> Option<TreeNode<T>> {
68 if current_depth == 0 {
69 return store.new_instance(NodeType::Leaf);
70 }
71
72 let mut parent = store.new_instance(NodeType::Vertex)?;
73 let num_children = match parent.arity() {
74 Arity::Zero => 0,
75 Arity::Exact(n) => n,
76 Arity::Any => NUM_CHILDREN_ANY,
77 };
78
79 for _ in 0..num_children {
80 let child = Self::grow(current_depth - 1, store)?;
81 parent.add_child(child);
82 }
83
84 Some(parent)
85 }
86
87 #[allow(dead_code)]
88 pub(crate) fn repair_node(node: &mut TreeNode<T>, store: &NodeStore<T>) {
89 if node.children().is_none() && node.is_valid() {
90 return;
91 }
92
93 let num_children = match node.arity() {
94 Arity::Zero => 0,
95 Arity::Exact(n) => n,
96 Arity::Any => NUM_CHILDREN_ANY,
97 };
98
99 let current_num_children = node.children().map_or(0, |c| c.len());
100
101 if current_num_children < num_children {
102 for _ in 0..(num_children - current_num_children) {
103 if let Some(leaf) = store.new_instance(NodeType::Leaf) {
104 node.add_child(leaf);
105 }
106 }
107 } else if current_num_children > num_children {
108 for _ in 0..(current_num_children - num_children) {
109 node.detach(current_num_children - 1);
110 }
111 }
112
113 if let Some(children) = node.children_mut() {
114 for child in children.iter_mut() {
115 Self::repair_node(child, store);
116 }
117 }
118 }
119}
120
121#[cfg(test)]
122mod tests {
123 use super::*;
124 use crate::{Op, TreeIterator};
125
126 #[test]
127 fn test_tree_builder_depth_two() {
128 let store = vec![
129 (NodeType::Vertex, vec![Op::add(), Op::sub(), Op::mul()]),
130 (NodeType::Leaf, vec![Op::constant(1.0), Op::constant(2.0)]),
131 ];
132 let tree = Tree::with_depth(2, store);
133
134 assert!(tree.root().is_some());
135 assert_eq!(tree.root().unwrap().children().unwrap().len(), 2);
136 assert_eq!(tree.height(), 2);
137 assert_eq!(tree.size(), 7);
138
139 for node in tree.iter_breadth_first() {
140 if node.arity() == Arity::Any {
141 assert_eq!(node.children().map(|c| c.len()), Some(2));
142 } else if let Arity::Exact(n) = node.arity() {
143 assert_eq!(node.children().map(|c| c.len()), Some(n));
144 } else {
145 assert_eq!(node.children(), None);
146 }
147 }
148 }
149
150 #[test]
151 fn test_tree_builder_depth_three() {
152 let store = vec![
155 (NodeType::Vertex, vec![Op::add(), Op::sub(), Op::mul()]),
156 (NodeType::Leaf, vec![Op::constant(1.0), Op::constant(2.0)]),
157 ];
158 let tree = Tree::with_depth(3, store);
159
160 assert!(tree.root().is_some());
161 assert_eq!(tree.root().unwrap().children().unwrap().len(), 2);
162 assert_eq!(tree.height(), 3);
163 assert_eq!(tree.size(), 15);
164
165 for node in tree.iter_breadth_first() {
166 if node.arity() == Arity::Any {
167 assert_eq!(node.children().map(|c| c.len()), Some(2));
168 } else if let Arity::Exact(n) = node.arity() {
169 assert_eq!(node.children().map(|c| c.len()), Some(n));
170 } else {
171 assert_eq!(node.children(), None);
172 }
173 }
174 }
175
176 #[test]
177 fn test_vertex_with_any_arity_builds_correct_depth() {
178 let tree = Tree::with_depth(
179 2,
180 vec![
181 (
182 NodeType::Vertex,
183 vec![Op::sigmoid(), Op::relu(), Op::tanh()],
184 ),
185 (NodeType::Leaf, vec![Op::constant(1.0), Op::constant(2.0)]),
186 ],
187 );
188
189 assert!(tree.root().is_some());
190 assert_eq!(tree.root().unwrap().children().unwrap().len(), 2);
191 assert_eq!(tree.height(), 2);
192 assert_eq!(tree.size(), 7);
193
194 for node in tree.iter_breadth_first() {
195 if node.arity() == Arity::Any {
196 assert_eq!(node.children().map(|c| c.len()), Some(2));
197 } else if let Arity::Exact(n) = node.arity() {
198 assert_eq!(node.children().map(|c| c.len()), Some(n));
199 } else {
200 assert_eq!(node.children(), None);
201 }
202 }
203 }
204}