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