diff --git a/.gitignore b/.gitignore index 9386f3b..d97d817 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,4 @@ /target /Cargo.lock **/*.rs.bk +metrics.ansi diff --git a/src/flow/binary/balancing.rs b/src/flow/binary/balancing.rs index 2d8165a..721dc5b 100644 --- a/src/flow/binary/balancing.rs +++ b/src/flow/binary/balancing.rs @@ -1,4 +1,6 @@ -use super::*; +use std::fmt::Display; + +use super::{avl::*, bounds::bound::BinaryTreesBindable, *}; pub trait BinaryTreesUnbalanced<'a>: BinaryTreesHeight<'a> { fn tree_of_with_height(&self, node: Self::Node, height: u64) -> BTWrap<'a, Self, Self::Tree>; @@ -25,6 +27,12 @@ pub trait BinaryTreesUnbalanced<'a>: BinaryTreesHeight<'a> { #[derive(Clone)] pub struct BalancedTrees(BT); +impl BalancedTrees { + pub fn new(bt: BT) -> Self { + Self(bt) + } +} + impl<'a, BT: FunctorContext<'a>> FunctorContext<'a> for BalancedTrees { type T = BT::T; } @@ -37,6 +45,25 @@ pub enum BalancingError { HeightMismatch { children: (u64, u64), parent: u64 }, } +impl Display for BalancingError { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + Self::NodeHeight => write!(f, "invalid AVL non-leaf height: 0."), + Self::LeafHeight(height) => { + write!(f, "invalid AVL leaf height: {height}!=0.") + } + Self::Balance(hl, hr) => write!(f, "unbalanced AVL node: {hl} {hr}."), + Self::HeightOverflow => write!(f, "AVL tree height overflow"), + Self::HeightMismatch { children, parent } => { + write!( + f, + "AVL child-parent height mismatch: {children:?}, {parent}" + ) + } + } + } +} + fn balanced(hl: u64, hr: u64) -> Result<(), BalancingError> { if hl.abs_diff(hr) > 1 { Err(BalancingError::Balance(hl, hr)) @@ -151,3 +178,24 @@ impl<'a, BT: BinaryTreesUnbalanced<'a> + BinaryTreesTryJoin<'a>> BinaryTreesTryJ .balancing_bind(balanced(hl, hr), |_| self.0.try_join(tl, key, tr)) } } + +impl<'a, BT: BinaryTreesUnbalanced<'a> + BinaryTreesBindable<'a>> BinaryTreesBindable<'a> + for BalancedTrees +{ + fn bounds_error(&self, error: bounds::BoundsError) -> BTWrap<'a, Self, T> { + self.0.bounds_error(error) + } +} + +impl<'a, BT: BinaryTreesUnbalanced<'a> + BinaryTreesEmpty<'a> + BinaryTreesTryJoin<'a>> + BinaryTreesMutable<'a> for BalancedTrees +{ + fn join_key( + self, + tl: Self::Tree, + key: Self::Key, + tr: Self::Tree, + ) -> BTWrap<'a, Self, Self::Node> { + self.join_key_balanced(tl, key, tr) + } +} diff --git a/src/mrds/trees.rs b/src/mrds/trees.rs index 3380f2e..d1866cf 100644 --- a/src/mrds/trees.rs +++ b/src/mrds/trees.rs @@ -1,2 +1,3 @@ pub mod avl; +pub mod heighted; pub mod unbalanced; diff --git a/src/mrds/trees/avl.rs b/src/mrds/trees/avl.rs index 90fc8f3..bd187c5 100644 --- a/src/mrds/trees/avl.rs +++ b/src/mrds/trees/avl.rs @@ -1,7 +1,7 @@ use std::{fmt::Display, marker::PhantomData, rc::Rc}; use crate::flow::{ - binary::{avl::*, bounds::bound::BinaryTreesBindable, *}, + binary::{avl::*, bounds::bound::*, *}, comparator::*, }; use crate::func::{context::*, *}; @@ -199,14 +199,12 @@ impl<'a, A: 'a + PartialOrd + Clone> BinaryTreesTryJoin<'a> for AvlTs { impl<'a, A: 'a + PartialOrd + Clone> BinaryTreesBindable<'a> for AvlTs { fn bounds_error(&self, _error: bounds::BoundsError) -> BTWrap<'a, Self, T> { - panic!("bounds violated"); + panic!("bounds violated."); } } #[cfg(test)] mod tests { - use crate::flow::binary::bounds::bound::*; - use super::*; #[test] diff --git a/src/mrds/trees/heighted.rs b/src/mrds/trees/heighted.rs new file mode 100644 index 0000000..1201006 --- /dev/null +++ b/src/mrds/trees/heighted.rs @@ -0,0 +1,245 @@ +use std::{fmt::Display, marker::PhantomData, rc::Rc}; + +use crate::flow::{ + binary::{balancing::*, bounds::bound::*, *}, + comparator::*, +}; +use crate::func::{context::*, *}; + +#[derive(Clone)] +struct Node { + l: Tree, + r: Tree, + key: A, +} + +impl Display for Node { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "({} {} {})", self.l, self.key, self.r) + } +} + +struct Reference { + node: Rc>, +} + +impl Clone for Reference { + fn clone(&self) -> Self { + Self { + node: self.node.clone(), + } + } +} + +impl Display for Reference { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{}", self.node) + } +} + +struct Tree { + reference: Option>, + height: u64, +} + +impl Clone for Tree { + fn clone(&self) -> Self { + Self { + reference: self.reference.clone(), + height: self.height, + } + } +} + +impl Display for Tree { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match &self.reference { + Some(reference) => write!(f, "{}", reference), + None => write!(f, "-"), + } + } +} + +struct Trees { + _a: PhantomData, +} + +impl Trees { + fn new() -> Self { + Self { _a: PhantomData } + } +} + +impl Clone for Trees { + fn clone(&self) -> Self { + Self::new() + } +} + +impl<'a, A: 'a> FunctorContext<'a> for Trees { + type T = instances::solo::SoloInstance; +} + +impl<'a, A: 'a + PartialOrd + Clone> BinaryTrees<'a> for Trees { + type Node = Node; + + type Reference = Reference; + + type Tree = Tree; + + type Key = A; + + type Comparator = DefaultComparator; + + type _Tm = Self::T; + + fn comparator(&self) -> &Self::Comparator { + &DefaultComparator + } + + fn split(&self, node: &Self::Node) -> Split<'a, Self> { + (node.l.clone(), node.r.clone(), node.key.clone()) + } + + fn resolve(&self, reference: &Self::Reference) -> BTWrap<'a, Self, Self::Node> { + reference.node.as_ref().clone() + } + + fn equal(&self, _rhs: &Self::Reference, _lhs: &Self::Reference) -> bool { + false + } + + fn refer(&self, tree: &Self::Tree) -> Option { + tree.reference.clone() + } +} + +impl<'a, A: 'a + PartialOrd + Clone> BinaryTreesHeight<'a> for Trees { + fn height(&self, tree: &Self::Tree) -> u64 { + tree.height + } + + fn leaf_height_error(&self, height: u64) -> BTWrap<'a, Self, T> { + panic!("leaf height error: {height}.") + } +} + +impl<'a, A: 'a + PartialOrd + Clone> BinaryTreesEmpty<'a> for Trees { + fn empty(&self) -> Self::Tree { + Tree { + reference: None, + height: 0, + } + } + + fn split_key_empty( + &self, + _tree: Self::Tree, + _key: Self::Key, + ) -> BTWrap<'a, Self, KeySplit<'a, Self>> { + (self.empty(), self.empty()) + } +} + +impl<'a, A: 'a + PartialOrd + Clone> BinaryTreesTryJoin<'a> for Trees { + fn try_join( + &self, + tl: Self::Tree, + key: Self::Key, + tr: Self::Tree, + ) -> BTWrap<'a, Self, Self::Node> { + Node { l: tl, r: tr, key } + } +} + +impl<'a, A: 'a + PartialOrd + Clone> BinaryTreesUnbalanced<'a> for Trees { + fn tree_of_with_height(&self, node: Self::Node, height: u64) -> BTWrap<'a, Self, Self::Tree> { + Tree { + reference: Some(Reference { + node: Rc::new(node), + }), + height, + } + } + + fn balancing_error(&self, _error: BalancingError) -> BTWrap<'a, Self, T> { + panic!("balancing error.") + } +} + +impl<'a, A: 'a + PartialOrd + Clone> BinaryTreesBindable<'a> for Trees { + fn bounds_error(&self, _error: bounds::BoundsError) -> BTWrap<'a, Self, T> { + panic!("bounds violated."); + } +} + +#[cfg(test)] +mod tests { + use super::*; + + impl Node { + fn balanced(&self) -> bool { + let (hl, hr) = (self.l.height, self.r.height); + std::cmp::max(hl, hr) - std::cmp::min(hl, hr) < 2 + && self.l.balanced() + && self.r.balanced() + } + } + + impl Reference { + fn balanced(&self) -> bool { + self.node.balanced() + } + } + + impl Tree { + fn balanced(&self) -> bool { + match &self.reference { + Some(reference) => reference.balanced(), + None => true, + } + } + } + + #[test] + fn test() { + let trees = BalancedTrees::new(Trees::new()); + let mut tree = trees.empty(); + for i in [ + 8, 3, 10, 17, 0, 13, 6, 1, 11, 5, 4, 7, 18, 14, 15, 9, 2, 19, 16, 12, + ] { + tree = trees.clone().add_tree(tree, i); + assert!(tree.balanced()); + // println!("{} {}", tree.height, tree); + } + for i in [ + 2, 9, 4, 7, 8, 10, 17, 1, 13, 15, 18, 12, 5, 0, 3, 6, 16, 19, 14, 11, + ] { + tree = trees.clone().remove(tree, i); + assert!(tree.balanced()); + // println!("{} {}", tree.height, tree); + } + // assert!(false); + } + + #[test] + fn test_with_bounds() { + let trees = BoundTrees::new(BalancedTrees::new(Trees::new())); + let mut tree = trees.empty(); + for i in [ + 8, 3, 10, 17, 0, 13, 6, 1, 11, 5, 4, 7, 18, 14, 15, 9, 2, 19, 16, 12, + ] { + tree = trees.clone().add_tree(tree, i); + assert!(tree.balanced()); + // println!("{} {}", tree.height, tree); + } + for i in [ + 2, 9, 4, 7, 8, 10, 17, 1, 13, 15, 18, 12, 5, 0, 3, 6, 16, 19, 14, 11, + ] { + tree = trees.clone().remove(tree, i); + assert!(tree.balanced()); + // println!("{} {}", tree.height, tree); + } + // assert!(false); + } +}