Skip to content

Commit c4a0511

Browse files
authored
improve performance of canonical representation (#51)
* improve performance of canonical representation * improve performance of tree comparisons slightly
1 parent afd3dcc commit c4a0511

File tree

1 file changed

+18
-10
lines changed

1 file changed

+18
-10
lines changed

src/RootedTrees.jl

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -140,11 +140,10 @@ function Base.isless(t1::RootedTree, t2::RootedTree)
140140
return false
141141
end
142142

143-
root1 = first(t1.level_sequence)
144-
root2 = first(t2.level_sequence)
143+
root1_minus_root2 = first(t1.level_sequence) - first(t2.level_sequence)
145144
for (e1, e2) in zip(t1.level_sequence, t2.level_sequence)
146-
v1 = e1 - root1
147-
v2 = e2 - root2
145+
v1 = e1
146+
v2 = e2 + root1_minus_root2
148147
v1 == v2 || return isless(v1, v2)
149148
end
150149
return isless(length(t1.level_sequence), length(t2.level_sequence))
@@ -180,10 +179,9 @@ function Base.:(==)(t1::RootedTree, t2::RootedTree)
180179
return true
181180
end
182181

183-
root1 = first(t1.level_sequence)
184-
root2 = first(t2.level_sequence)
182+
root1_minus_root2 = first(t1.level_sequence) - first(t2.level_sequence)
185183
for (e1, e2) in zip(t1.level_sequence, t2.level_sequence)
186-
e1 - root1 == e2 - root2 || return false
184+
e1 == e2 + root1_minus_root2 || return false
187185
end
188186

189187
return true
@@ -304,17 +302,24 @@ function canonical_representation!(t::RootedTree, buffer=similar(t.level_sequenc
304302
# order of the level sequences).
305303
if number_of_subtrees > 1
306304
# Simple bubble sort that can act in-place, avoiding allocations
305+
# We keep track of the last index of the last subtree that we need to sort
306+
# since we know that the last `n` subtrees are already sorted after `n`
307+
# iterations.
308+
subtree_last_index_to_sort = order(t)
307309
swapped = true
308310
while swapped
309311
swapped = false
310312

311313
# Search the first complete subtree
312314
subtree1_root_index = 2
313-
while subtree1_root_index <= order(t)
315+
subtree1_last_index = 0
316+
subtree2_last_index = 0
317+
while subtree1_root_index <= subtree_last_index_to_sort
314318
subtree1_last_index = _subtree_last_index(subtree1_root_index, t.level_sequence)
319+
subtree2_last_index = subtree1_last_index
315320

316321
# Search the next complete subtree
317-
subtree1_last_index == order(t) && break
322+
subtree1_last_index == subtree_last_index_to_sort && break
318323

319324
subtree2_root_index = subtree1_last_index + 1
320325
subtree2_last_index = _subtree_last_index(subtree2_root_index, t.level_sequence)
@@ -333,9 +338,12 @@ function canonical_representation!(t::RootedTree, buffer=similar(t.level_sequenc
333338
end
334339

335340
# Move on to the next pair of subtrees
336-
subtree2_last_index == order(t) && break
341+
subtree2_last_index == subtree_last_index_to_sort && break
337342
subtree1_root_index = subtree1_last_index + 1
338343
end
344+
345+
# Update the last subtree we need to look at
346+
subtree_last_index_to_sort = min(subtree1_last_index, subtree2_last_index)
339347
end
340348
end
341349

0 commit comments

Comments
 (0)