1use serde::{Deserialize, Serialize};
2use std::fmt;
3
4#[derive(Clone, Copy, Debug, PartialEq, Eq)]
6pub enum TreeError {
7 Empty,
9 Malformed { node: usize, reason: &'static str },
11 FeatureOutOfRange {
13 node: usize,
14 feature: usize,
15 n_features: usize,
16 },
17 RaggedInput { len: usize, n_features: usize },
19}
20
21impl fmt::Display for TreeError {
22 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
23 match self {
24 TreeError::Empty => write!(f, "the tree is empty"),
25 TreeError::Malformed { node, reason } => write!(f, "node {node}: {reason}"),
26 TreeError::FeatureOutOfRange {
27 node,
28 feature,
29 n_features,
30 } => write!(
31 f,
32 "node {node} tests feature {feature}, but the instance has {n_features}"
33 ),
34 TreeError::RaggedInput { len, n_features } => write!(
35 f,
36 "{len} values is not a whole number of rows of {n_features} features"
37 ),
38 }
39 }
40}
41
42impl std::error::Error for TreeError {}
43
44#[derive(Clone, Copy, Debug, Serialize, Deserialize)]
46pub struct NodeInfos {
47 pub feature: Option<usize>,
49 pub error: usize,
51 pub split: Option<f64>,
54 pub label: Option<usize>,
56}
57
58impl Default for NodeInfos {
59 fn default() -> Self {
60 NodeInfos::new()
61 }
62}
63
64impl NodeInfos {
65 pub fn new() -> NodeInfos {
66 NodeInfos {
67 feature: None,
68 error: usize::MAX,
69 split: None,
70 label: None,
71 }
72 }
73}
74
75#[derive(Copy, Clone, Serialize, Deserialize, Debug, Default)]
77pub struct TreeNode {
78 pub value: NodeInfos,
80 pub index: usize,
82 pub left: usize,
84 pub right: usize,
86}
87
88impl TreeNode {
89 pub fn new(value: NodeInfos) -> TreeNode {
90 TreeNode {
91 value,
92 index: 0,
93 left: 0,
94 right: 0,
95 }
96 }
97}
98
99#[derive(Clone, Serialize, Deserialize, Debug)]
101pub struct Tree {
102 tree: Vec<TreeNode>,
103}
104
105impl Default for Tree {
106 fn default() -> Self {
107 Self::new()
108 }
109}
110
111impl Tree {
112 pub fn new() -> Self {
113 Tree { tree: Vec::new() }
114 }
115
116 pub fn with_capacity(capacity: usize) -> Self {
117 Tree {
118 tree: Vec::with_capacity(capacity),
119 }
120 }
121
122 pub fn is_empty(&self) -> bool {
123 self.tree.is_empty()
124 }
125
126 pub fn len(&self) -> usize {
127 self.tree.len()
128 }
129
130 pub fn add_node(&mut self, parent: usize, is_left: bool, mut node: TreeNode) -> usize {
133 node.index = self.tree.len();
134 self.tree.push(node);
135 let position = self.tree.len() - 1;
136 if position == 0 {
137 return position;
138 }
139 if let Some(parent_node) = self.tree.get_mut(parent) {
140 if is_left {
141 parent_node.left = position
142 } else {
143 parent_node.right = position
144 }
145 };
146 position
147 }
148
149 pub fn add_root(&mut self, root: TreeNode) -> usize {
150 self.add_node(0, false, root)
151 }
152
153 pub fn add_left_node(&mut self, parent: usize, node: TreeNode) -> usize {
154 self.add_node(parent, true, node)
155 }
156 pub fn add_right_node(&mut self, parent: usize, node: TreeNode) -> usize {
157 self.add_node(parent, false, node)
158 }
159
160 pub fn create_child(&mut self, parent: usize, left: bool) -> usize {
161 self.add_node(parent, left, TreeNode::default())
162 }
163
164 pub fn get_root_index(&self) -> usize {
165 0
166 }
167
168 pub fn get_node(&self, index: usize) -> Option<&TreeNode> {
169 self.tree.get(index)
170 }
171
172 pub fn get_node_mut(&mut self, index: usize) -> Option<&mut TreeNode> {
173 self.tree.get_mut(index)
174 }
175
176 pub fn get_left_child(&self, node: &TreeNode) -> Option<&TreeNode> {
177 if node.left == 0 {
178 None
179 } else {
180 self.tree.get(node.left)
181 }
182 }
183 pub fn get_left_child_mut(&mut self, node: &TreeNode) -> Option<&mut TreeNode> {
184 if node.left == 0 {
185 None
186 } else {
187 self.tree.get_mut(node.left)
188 }
189 }
190
191 pub fn get_right_child(&self, node: &TreeNode) -> Option<&TreeNode> {
192 if node.right == 0 {
193 None
194 } else {
195 self.tree.get(node.right)
196 }
197 }
198 pub fn get_right_child_mut(&mut self, node: &TreeNode) -> Option<&mut TreeNode> {
199 if node.right == 0 {
200 None
201 } else {
202 self.tree.get_mut(node.right)
203 }
204 }
205
206 pub fn empty_tree(depth: usize) -> Tree {
208 let mut tree = Tree::new();
209 let value = NodeInfos::new();
210 let node = TreeNode::new(value);
211 let root = tree.add_root(node);
212 Self::build_tree_recurse(&mut tree, root, depth);
213 tree
214 }
215
216 fn build_tree_recurse(tree: &mut Tree, parent: usize, depth: usize) {
217 if depth == 0 {
218 if let Some(parent_node) = tree.get_node_mut(parent) {
219 parent_node.left = 0;
220 parent_node.right = 0;
221 }
222 } else {
223 let value = NodeInfos::new();
224 let node = TreeNode::new(value);
225 let left = tree.add_node(parent, true, node);
226 Self::build_tree_recurse(tree, left, depth - 1);
227 let node = TreeNode::new(value);
228 let right = tree.add_node(parent, false, node);
229 Self::build_tree_recurse(tree, right, depth - 1);
230 }
231 }
232
233 pub fn root_details(&self) -> NodeInfos {
234 self.get_node(self.get_root_index())
235 .map(|node| node.value)
236 .unwrap_or_default()
237 }
238
239 pub fn node_details(&self, index: usize) -> NodeInfos {
240 self.get_node(index)
241 .map(|node| node.value)
242 .unwrap_or_default()
243 }
244
245 pub fn root_error(&self) -> usize {
246 self.get_node(self.get_root_index())
247 .map(|node| node.value.error)
248 .unwrap_or(usize::MAX)
249 }
250
251 pub fn node_error(&self, index: usize) -> usize {
252 self.get_node(index)
253 .map(|node| node.value.error)
254 .unwrap_or(usize::MAX)
255 }
256
257 pub fn node_split(&self, index: usize) -> Option<f64> {
258 self.get_node(index)
259 .map(|node| node.value.split)
260 .unwrap_or(None)
261 }
262
263 pub fn root_label(&self) -> Option<usize> {
264 self.get_node(self.get_root_index())
265 .and_then(|node| node.value.label)
266 }
267
268 pub fn node_label(&self, index: usize) -> Option<usize> {
269 self.get_node(index).and_then(|node| node.value.label)
270 }
271
272 pub fn root_feature(&self) -> Option<usize> {
273 self.get_node(self.get_root_index())
274 .and_then(|node| node.value.feature)
275 }
276
277 pub fn root_split(&self) -> Option<f64> {
278 self.get_node(self.get_root_index())
279 .and_then(|node| node.value.split)
280 }
281
282 pub fn node_feature(&self, index: usize) -> Option<usize> {
283 self.get_node(index).and_then(|node| node.value.feature)
284 }
285
286 pub fn update_node(&mut self, index: usize) -> Option<NodeUpdater<'_>> {
288 self.get_node_mut(index).map(NodeUpdater::new)
289 }
290
291 pub fn update_root(&mut self) -> Option<NodeUpdater<'_>> {
292 self.get_node_mut(0).map(NodeUpdater::new)
293 }
294
295 pub fn node_children(&self, index: usize) -> (usize, usize) {
297 self.get_node(index)
298 .map_or((0, 0), |node| (node.left, node.right))
299 }
300
301 pub fn update_leaf_node(&mut self, index: usize, error: (usize, usize)) -> &mut Self {
303 if let Some(updater) = self.update_node(index) {
304 updater.error(error.0).label(error.1);
305 }
306 self
307 }
308
309 pub fn update_subtree(&mut self, index: usize, origin: &Tree, origin_index: usize) {
312 let (left_index, right_index) = self.update_node(index).map_or((0, 0), |updater| {
313 updater
314 .value(origin.node_details(origin_index))
315 .get_children()
316 });
317
318 let (origin_left_index, origin_right_index) = origin.node_children(origin_index);
319
320 for (branch_value, (&source, mut dest)) in [origin_left_index, origin_right_index]
321 .iter()
322 .zip([left_index, right_index])
323 .enumerate()
324 {
325 if source > 0 {
326 if dest == 0 {
327 dest = self.create_child(index, branch_value == 0);
328 }
329 self.update_subtree(dest, origin, source);
330 } else if dest != 0 {
331 self.detach_child(index, branch_value == 0);
334 }
335 }
336 }
337
338 fn detach_child(&mut self, index: usize, left: bool) {
339 if let Some(node) = self.get_node_mut(index) {
340 if left {
341 node.left = 0;
342 } else {
343 node.right = 0;
344 }
345 }
346 }
347
348 pub fn clean_orphaned_nodes(&mut self) {
352 if self.is_empty() {
353 return;
354 }
355 self.cleanup_leaves(self.get_root_index())
356 }
357
358 fn cleanup_leaves(&mut self, index: usize) {
359 let (left, right) = self.node_children(index);
360 if left != 0 {
361 self.cleanup_leaves(left);
362 }
363 if right != 0 {
364 self.cleanup_leaves(right)
365 }
366
367 let has_children = left != 0 || right != 0;
368 if has_children && self.can_be_leaf(index) {
369 self.update_node(index).map(|updater| updater.leaf());
370 return;
371 }
372
373 if has_children && self.is_leaf(left) && self.is_leaf(right) {
377 match (self.node_label(left), self.node_label(right)) {
378 (Some(left_label), Some(right_label)) if left_label == right_label => {
379 self.update_node(index)
380 .map(|updater| updater.label(left_label).leaf());
381 }
382 _ => {}
383 }
384 }
385 }
386
387 fn is_leaf(&self, index: usize) -> bool {
388 let (left, right) = self.node_children(index);
389 (left == 0) && (right == 0)
390 }
391
392 fn can_be_leaf(&self, index: usize) -> bool {
393 self.node_feature(index).is_none() && self.node_label(index).is_some()
394 }
395
396 pub fn nodes(&self) -> &[TreeNode] {
401 &self.tree
402 }
403
404 pub fn normalize_leaves(&mut self) {
412 if self.is_empty() {
413 return;
414 }
415 self.normalize_from(self.get_root_index());
416 }
417
418 fn normalize_from(&mut self, index: usize) {
419 let (feature, left, right) = match self.get_node(index) {
420 Some(node) => (node.value.feature, node.left, node.right),
421 None => return,
422 };
423
424 let is_leaf = match feature {
425 None => true,
426 Some(usize::MAX) => true,
427 Some(_) => left == 0 && right == 0,
428 };
429
430 if is_leaf {
431 if let Some(node) = self.get_node_mut(index) {
432 node.value.feature = None;
433 node.value.split = None;
434 node.left = 0;
435 node.right = 0;
436 }
437 return;
438 }
439
440 if left != 0 {
441 self.normalize_from(left);
442 }
443 if right != 0 {
444 self.normalize_from(right);
445 }
446 }
447
448 pub fn validate(&self) -> Result<(), TreeError> {
454 if self.is_empty() {
455 return Err(TreeError::Empty);
456 }
457 self.validate_from(self.get_root_index(), 0)
458 }
459
460 fn validate_from(&self, index: usize, depth: usize) -> Result<(), TreeError> {
461 if depth > self.tree.len() {
462 return Err(TreeError::Malformed {
463 node: index,
464 reason: "the tree contains a cycle",
465 });
466 }
467 let node = self.get_node(index).ok_or(TreeError::Malformed {
468 node: index,
469 reason: "child index points outside the arena",
470 })?;
471 let (left, right) = (node.left, node.right);
472
473 match node.value.feature {
474 None => {
475 if left != 0 || right != 0 {
476 return Err(TreeError::Malformed {
477 node: index,
478 reason: "a leaf must not have children",
479 });
480 }
481 if node.value.split.is_some() {
482 return Err(TreeError::Malformed {
483 node: index,
484 reason: "a leaf must not carry a split threshold",
485 });
486 }
487 if node.value.label.is_none() {
488 return Err(TreeError::Malformed {
489 node: index,
490 reason: "a leaf must carry a label",
491 });
492 }
493 Ok(())
494 }
495 Some(_) => {
496 if left == 0 || right == 0 {
497 return Err(TreeError::Malformed {
498 node: index,
499 reason: "an internal node must have two children",
500 });
501 }
502 match node.value.split {
503 Some(split) if split.is_finite() => {}
504 _ => {
505 return Err(TreeError::Malformed {
506 node: index,
507 reason: "an internal node must carry a finite split threshold",
508 })
509 }
510 }
511 self.validate_from(left, depth + 1)?;
512 self.validate_from(right, depth + 1)
513 }
514 }
515 }
516
517 pub fn predict_one(&self, x: &[f64]) -> Result<usize, TreeError> {
523 Ok(self.tree[self.leaf_for(x)?]
524 .value
525 .label
526 .expect("leaf_for returns a leaf, and every leaf has a label"))
527 }
528
529 pub fn decision_path(&self, x: &[f64]) -> Result<Vec<usize>, TreeError> {
531 let mut path = Vec::new();
532 let mut index = self.first_node()?;
533 loop {
534 path.push(index);
535 match self.step(index, x)? {
536 Some(next) => index = next,
537 None => return Ok(path),
538 }
539 }
540 }
541
542 pub fn predict(&self, rows: &[f64], n_features: usize) -> Result<Vec<usize>, TreeError> {
544 if n_features == 0 || rows.len() % n_features != 0 {
545 return Err(TreeError::RaggedInput {
546 len: rows.len(),
547 n_features,
548 });
549 }
550 rows.chunks_exact(n_features)
551 .map(|x| self.predict_one(x))
552 .collect()
553 }
554
555 fn first_node(&self) -> Result<usize, TreeError> {
556 if self.is_empty() {
557 return Err(TreeError::Empty);
558 }
559 Ok(self.get_root_index())
560 }
561
562 fn leaf_for(&self, x: &[f64]) -> Result<usize, TreeError> {
563 let mut index = self.first_node()?;
564 for _ in 0..=self.tree.len() {
567 match self.step(index, x)? {
568 Some(next) => index = next,
569 None => return Ok(index),
570 }
571 }
572 Err(TreeError::Malformed {
573 node: index,
574 reason: "the tree contains a cycle",
575 })
576 }
577
578 fn step(&self, index: usize, x: &[f64]) -> Result<Option<usize>, TreeError> {
580 let node = self.get_node(index).ok_or(TreeError::Malformed {
581 node: index,
582 reason: "child index points outside the arena",
583 })?;
584
585 let Some(feature) = node.value.feature else {
586 if node.value.label.is_none() {
587 return Err(TreeError::Malformed {
588 node: index,
589 reason: "a leaf must carry a label",
590 });
591 }
592 return Ok(None);
593 };
594
595 if feature >= x.len() {
596 return Err(TreeError::FeatureOutOfRange {
597 node: index,
598 feature,
599 n_features: x.len(),
600 });
601 }
602 let Some(split) = node.value.split else {
603 return Err(TreeError::Malformed {
604 node: index,
605 reason: "an internal node must carry a split threshold",
606 });
607 };
608
609 let next = if x[feature] <= split {
610 node.left
611 } else {
612 node.right
613 };
614 if next == 0 {
615 return Err(TreeError::Malformed {
616 node: index,
617 reason: "an internal node must have two children",
618 });
619 }
620 Ok(Some(next))
621 }
622}
623
624impl fmt::Display for Tree {
626 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
627 let mut stack: Vec<(usize, Option<&TreeNode>)> = Vec::new();
628 stack.push((0, self.get_node(self.get_root_index())));
629 while let Some((depth, node)) = stack.pop() {
630 if let Some(node) = node {
631 writeln!(f, "{}----{:?}", " ".repeat(depth), node.value)?;
632 stack.push((depth + 1, self.get_right_child(node)));
633 stack.push((depth + 1, self.get_left_child(node)));
634 }
635 }
636 Ok(())
637 }
638}
639
640pub struct NodeUpdater<'a> {
642 node: &'a mut TreeNode,
643}
644
645impl<'a> NodeUpdater<'a> {
646 pub fn new(node: &'a mut TreeNode) -> Self {
647 Self { node }
648 }
649
650 pub fn value(self, value: NodeInfos) -> Self {
651 self.node.value = value;
652 self
653 }
654
655 pub fn error(self, error: usize) -> Self {
656 self.node.value.error = error;
657 self
658 }
659
660 pub fn split(self, metric: f64) -> Self {
661 self.node.value.split = Some(metric);
662 self
663 }
664
665 pub fn label(self, output: usize) -> Self {
666 self.node.value.label = Some(output);
667 self
668 }
669
670 pub fn feature(self, test: usize) -> Self {
671 self.node.value.feature = Some(test);
672 self
673 }
674
675 pub fn leaf(self) -> Self {
677 self.node.value.feature = None;
678 self.node.value.split = None;
679 self.node.left = 0;
680 self.node.right = 0;
681 self
682 }
683
684 pub fn get_children(&self) -> (usize, usize) {
685 (self.node.left, self.node.right)
686 }
687}