From 619c57b3957a44a0ad5f730f85a8058be6d8ac54 Mon Sep 17 00:00:00 2001 From: Hendrik Ranocha Date: Wed, 13 Oct 2021 15:09:56 +0200 Subject: [PATCH] WIP: draft a representation of rooted trees using vertex lists First performance measurements of suggest that this might be a bit more efficient than the current version based on level sequences. However, everything would need to be re-implemented again. --- src/RootedTrees.jl | 1 + src/rooted_tree_vertex_list.jl | 139 +++++++++++++++++++++++++++++++++ 2 files changed, 140 insertions(+) create mode 100644 src/rooted_tree_vertex_list.jl diff --git a/src/RootedTrees.jl b/src/RootedTrees.jl index 2e540412..ade9c7bb 100644 --- a/src/RootedTrees.jl +++ b/src/RootedTrees.jl @@ -1350,6 +1350,7 @@ end include("latexify.jl") include("plots.jl") +include("rooted_tree_vertex_list.jl") end # module diff --git a/src/rooted_tree_vertex_list.jl b/src/rooted_tree_vertex_list.jl new file mode 100644 index 00000000..e1b70b8c --- /dev/null +++ b/src/rooted_tree_vertex_list.jl @@ -0,0 +1,139 @@ + +struct RootedTreeVertexList + children::Vector{RootedTreeVertexList} + isempty::Bool + iscanonical::Bool +end + +const RootedTreeVL = RootedTreeVertexList + +function RootedTreeVL(t::RootedTree) + children = Vector{RootedTreeVL}() + for subtree in SubtreeIterator(t) + push!(children, RootedTreeVL(subtree)) + end + RootedTreeVL(children, isempty(t), iscanonical(t)) +end + +function RootedTree(t::RootedTreeVL, root=1) + isempty(t) && return RootedTree(Vector{typeof(root)}(), iscanonical(t)) + + level_sequence = [root] + for subtree in t.children + append!(level_sequence, RootedTree(subtree, root + 1).level_sequence) + end + RootedTree(level_sequence, iscanonical(t)) +end + + +iscanonical(t::RootedTreeVL) = t.iscanonical + +Base.copy(t::RootedTreeVL) = RootedTreeVL(copy(t.children), t.isempty, t.iscanonical) +Base.isempty(t::RootedTreeVL) = t.isempty +Base.empty(t::RootedTreeVL) = RootedTreeVL(empty(t.children), true, iscanonical(t)) + + +function Base.show(io::IO, t::RootedTreeVL) + print(io, "RootedTreeVL: ") + show(io, RootedTree(t).level_sequence) +end + + +function Base.cmp(t1::RootedTreeVL, t2::RootedTreeVL) + for (subtree1, subtree2) in zip(t1.children, t2.children) + result = cmp(subtree1, subtree2) + result != 0 && return result + end + return cmp(length(t1.children), length(t2.children)) +end + +Base.isless(t1::RootedTreeVL, t2::RootedTreeVL) = cmp(t1, t2) < 0 +Base.:(==)(t1::RootedTreeVL, t2::RootedTreeVL) = cmp(t1, t2) == 0 + +# function Base.isless(t1::RootedTreeVL, t2::RootedTreeVL) +# if isempty(t1) +# if isempty(t2) +# # empty trees are equal +# return false +# else +# # the empty tree `isless` than any other tree +# return true +# end +# elseif isempty(t2) +# # the empty tree `isless` than any other tree +# return false +# end + +# for (subtree1, subtree2) in zip(t1.children, t2.children) +# subtree1 == subtree2 || return isless(subtree1, subtree2) +# end +# return isless(order(t1), order(t2)) +# end + +# function Base.:(==)(t1::RootedTreeVL, t2::RootedTreeVL) +# order(t1) == order(t2) || return false + +# if isempty(t1) +# # empty trees are equal +# return true +# end + +# for (subtree1, subtree2) in zip(t1.children, t2.children) +# subtree1 == subtree2 || return false +# end + +# return true +# end + + +# TODO: Base.hash + + +function canonical_representation(t::RootedTreeVL) + canonical_representation!(copy(t)) +end + +function canonical_representation!(t::RootedTreeVL) + for subtree in t.children + canonical_representation!(subtree) + end + + # simple bubble sort + n = length(t.children) + swapped = true + while swapped + swapped = false + for i in 2:n + subtree1 = t.children[i-1] + subtree2 = t.children[i] + if subtree1 > subtree2 + t.children[i-1], t.children[i] = subtree2, subtree1 + swapped = true + end + end + n = n - 1 + end + + RootedTreeVL(t.children, isempty(t), true) +end + + +# functions on trees + +function order(t::RootedTreeVL) + result = isempty(t) ? 0 : 1 + for subtree in t.children + result += order(subtree) + end + result +end + + + +function partition_skeleton(t::RootedTreeVL, edge_set) + partition_skeleton!(copy(t), copy(edge_set)) +end + +function partition_skeleton!(t::RootedTreeVL, edge_set) + +end