Rose trees #
A rose tree over α is a root carrying a value in α with an ordered list of child subtrees, the
n-ary counterpart of mathlib's BinaryTree. A leaf is node a []. The children are a List,
which keeps the type computable. The unordered rooted tree, whose children form a multiset, is the
quotient of this type by RoseTree.Perm (UnorderedTree).
The type is nested through List, so its recursor takes one motive for trees and one for lists.
RoseTree.rec' is the induction principle with the single hypothesis ∀ c ∈ cs, motive c, and
RoseTree.fold is the catamorphism from which map, the counts and the frontier are defined.
Main definitions #
RoseTree,RoseTree.value,RoseTree.children,RoseTree.leaf: the type, its projections and its leaves.RoseTree.rec',RoseTree.fold: induction and the catamorphism.RoseTree.map: relabelling.RoseTree.numNodes,RoseTree.numLeaves,RoseTree.height,RoseTree.arity: the counts.RoseTree.values,RoseTree.localTrees,RoseTree.leafList: the node values in preorder, each node's value with the values of its children, and the frontier.
Equations
- instReprRoseTree = { reprPrec := instReprRoseTree.repr }
Projections #
The ordered list of child subtrees at the root.
Equations
- (RoseTree.node a children).children = children
Instances For
A leaf is a root with no children.
Equations
- RoseTree.leaf a = RoseTree.node a []
Instances For
Decidable equality #
deriving DecidableEq does not fire through the nested List occurrence (as of Lean v4.35.0), so
the instance is built by mutual recursion on the tree and its child list.
Decidable equality on trees (mutual with the child-list case).
Equations
- One or more equations did not get rendered due to their size.
Instances For
Decidable equality on child lists (mutual with the tree case).
Equations
- One or more equations did not get rendered due to their size.
- RoseTree.decEqList [] [] = isTrue ⋯
- RoseTree.decEqList [] (head :: tail) = isFalse ⋯
- RoseTree.decEqList (head :: tail) [] = isFalse ⋯
Instances For
Equations
Size #
A child of a node is strictly smaller than the node in the generated SizeOf, the measure
behind rec' and the well-founded recursions over RoseTree.
The recursion principle #
Induction on a rose tree proves motive t for all t from motive (node a cs) given
motive c for every child c ∈ cs.
Equations
- RoseTree.rec' node (RoseTree.node a children) = node a children fun (c : RoseTree α) (_hc : c ∈ children) => RoseTree.rec' node c
Instances For
Catamorphism #
The structural operations (map, numNodes, height, …) are folds, and their equations at a
node come from fold_node.
The catamorphism replaces each node a cs by f a (folded children).
Equations
- RoseTree.fold f (RoseTree.node a children) = f a (RoseTree.foldList f children)
Instances For
foldList folds across a list of children.
Equations
- RoseTree.foldList f [] = []
- RoseTree.foldList f (c :: cs) = RoseTree.fold f c :: RoseTree.foldList f cs
Instances For
Postcomposing a fold with h gives the fold of the pushed-forward algebra, the RoseTree
sibling of List.foldr_hom.
Functoriality #
Relabel every node by f, preserving shape.
Equations
- RoseTree.map f = RoseTree.fold fun (a : α) (cs : List (RoseTree β)) => RoseTree.node (f a) cs
Instances For
Counting #
The number of nodes. A leaf counts as 1.
Equations
- RoseTree.numNodes = RoseTree.fold fun (x : α) (ns : List ℕ) => ns.sum + 1
Instances For
The node values in preorder list the root first, then each child's values left to right.
Equations
- RoseTree.values = RoseTree.fold fun (a : α) (ls : List (List α)) => a :: ls.flatten
Instances For
The local trees of a tree pair each node's value with the values of its children, one entry per node in preorder.
Equations
- (RoseTree.node a children).localTrees = (a, List.map RoseTree.value children) :: RoseTree.localTreesList children
Instances For
localTreesList concatenates the local trees of a list of trees.
Equations
- RoseTree.localTreesList [] = []
- RoseTree.localTreesList (c :: cs) = c.localTrees ++ RoseTree.localTreesList cs
Instances For
The ordered frontier lists the leaf values from left to right.
Equations
- RoseTree.leafList = RoseTree.fold fun (a : α) (ls : List (List α)) => match ls with | [] => [a] | ls => ls.flatten
Instances For
The number of leaves. A single leaf counts as 1.
Equations
- RoseTree.numLeaves = RoseTree.fold fun (x : α) (ns : List ℕ) => max 1 ns.sum
Instances For
Height #
The height is the number of nodes on a longest path from the root to a leaf, so a leaf has
height 1. This is the convention of BinaryTree.height, where nil has height 0.
Equations
- RoseTree.height = RoseTree.fold fun (x : α) (hs : List ℕ) => List.foldr max 0 hs + 1
Instances For
Arity #
Instances #
Equations
- RoseTree.instInhabited = { default := RoseTree.leaf default }