use super::afftree::*;
use crate::tree::iter::{Bfs, TraversalMut};
impl AffTree<2> {
pub fn reduce(&mut self) {
let mut elements = Vec::from_iter(Bfs::iter(&self.tree, self.tree.get_root_idx()));
elements.reverse();
for value in elements.into_iter() {
if let Ok(node) = self.tree.tree_node(value.index) {
if node.children_iter().count() == 0 {
continue;
}
if value.index == self.tree.get_root_idx() {
continue;
}
if let (Some(left_idx), Some(right_idx)) = (node.children[0], node.children[1]) {
let left = self.tree.tree_node(left_idx).unwrap();
let right = self.tree.tree_node(right_idx).unwrap();
if left.children_iter().count() != 0 || right.children_iter().count() != 0 {
continue;
}
if left.value.aff == right.value.aff {
self.tree.remove_child(value.index, 1);
self.tree.merge_child_with_parent(value.index, 0).unwrap();
}
}
}
}
}
}
#[cfg(test)]
mod tests {
use assertables::*;
use itertools::Itertools;
use ndarray::{arr1, arr2};
use super::*;
use crate::aff;
use crate::linalg::affine::AffFunc;
#[test]
fn test_reduce() {
let mut dd = AffTree::<2>::from_aff(AffFunc::from_mats(arr2(&[[2., 1.]]), arr1(&[-1.])));
dd.add_child_node(0, 1, aff!([[1., 2.]] + [-1.5])).unwrap(); dd.add_child_node(1, 1, aff!([[0.5, 5.]] + [1.0])).unwrap(); dd.add_child_node(2, 1, aff!([[3., -1.]] + [0.])).unwrap(); dd.add_child_node(3, 1, aff!([[-1., -1.]] + [6.])).unwrap(); dd.add_child_node(4, 0, aff!([[-1., 7.]] + [4.])).unwrap(); dd.add_child_node(5, 1, aff!([[-2., -0.2]] + [3.])).unwrap(); dd.add_child_node(6, 0, aff!([[0., 0.]] + [1.])).unwrap(); dd.add_child_node(6, 1, aff!([[0., 0.]] + [0.])).unwrap();
dd.reduce();
assert_eq!(dd.len(), 9);
}
#[test]
fn test_reduce2() {
let mut dd = AffTree::<2>::from_aff(AffFunc::from_mats(arr2(&[[2., 1.]]), arr1(&[-1.])));
dd.add_child_node(0, 1, aff!([[1., 2.]] + [-1.5])).unwrap(); dd.add_child_node(1, 1, aff!([[0.5, 5.]] + [1.0])).unwrap(); dd.add_child_node(2, 1, aff!([[3., -1.]] + [0.])).unwrap(); dd.add_child_node(3, 1, aff!([[-1., -1.]] + [6.])).unwrap(); dd.add_child_node(4, 0, aff!([[-1., 7.]] + [4.])).unwrap(); dd.add_child_node(5, 1, aff!([[-2., -0.2]] + [3.])).unwrap(); dd.add_child_node(6, 0, aff!([[0., 0.]] + [0.])).unwrap(); dd.add_child_node(6, 1, aff!([[0., 0.]] + [0.])).unwrap();
dd.add_child_node(5, 0, aff!([[0., 0.]] + [0.])).unwrap(); dd.add_child_node(4, 1, aff!([[0., 0.]] + [0.])).unwrap();
dd.reduce();
assert_eq!(dd.len(), 5);
let nodes = dd.tree.node_indices().collect_vec();
assert_contains!(nodes, &9);
assert_not_contains!(nodes, &7);
assert_not_contains!(nodes, &8);
assert_not_contains!(nodes, &10);
}
#[test]
fn test_reduce3() {
let mut dd = AffTree::<2>::from_aff(AffFunc::from_mats(arr2(&[[2., 1.]]), arr1(&[-1.])));
dd.add_child_node(0, 1, aff!([[1., 2.]] + [-1.5])).unwrap(); dd.add_child_node(1, 1, aff!([[0.5, 5.]] + [1.0])).unwrap(); dd.add_child_node(2, 1, aff!([[3., -1.]] + [0.])).unwrap(); dd.add_child_node(3, 1, aff!([[-1., -1.]] + [6.])).unwrap(); dd.add_child_node(4, 0, aff!([[-1., 7.]] + [4.])).unwrap(); dd.add_child_node(5, 1, aff!([[-2., -0.2]] + [3.])).unwrap(); dd.add_child_node(6, 0, aff!([[0., 0.]] + [0.])).unwrap(); dd.add_child_node(6, 1, aff!([[0., 0.]] + [0.])).unwrap();
dd.add_child_node(5, 0, aff!([[0., 0.]] + [1.])).unwrap();
dd.add_child_node(4, 1, aff!([[0., 0.]] + [0.])).unwrap();
dd.reduce();
assert_eq!(dd.len(), 9);
let nodes = dd.tree.node_indices().collect_vec();
assert_contains!(nodes, &7);
assert_not_contains!(nodes, &8);
assert_not_contains!(nodes, &6);
}
}