Files
obitools4/pkg/obitax/lca.go

64 lines
1.3 KiB
Go
Raw Normal View History

package obitax
import (
2024-11-16 05:59:41 +01:00
"fmt"
)
2024-11-16 05:59:41 +01:00
// LCA computes the Lowest Common Ancestor (LCA) of two Taxon instances.
// It traverses the paths from both taxa to the root and finds the deepest
// common node in the taxonomy hierarchy.
//
// Parameters:
// - t2: A pointer to another Taxon instance to find the LCA with.
//
// Returns:
// - A pointer to the Taxon representing the LCA of the two taxa, or an error
// if either of the taxa is nil, if they are not in the same taxonomy, or
// if the taxonomy is unrooted.
2024-11-14 19:10:23 +01:00
func (t1 *Taxon) LCA(t2 *Taxon) (*Taxon, error) {
if t1 == nil && t2 != nil {
return t2, nil
}
if t2 == nil && t1 != nil {
return t1, nil
}
if t1 == nil && t2 == nil {
return nil, fmt.Errorf("try to get LCA of nil taxa")
}
if t1.Node == nil {
return nil, fmt.Errorf("try to get LCA of nil taxa")
}
if t2.Node == nil {
2024-11-16 05:59:41 +01:00
return nil, fmt.Errorf("try to get LCA of nil taxon")
}
if t1.Taxonomy != t2.Taxonomy {
return nil, fmt.Errorf("taxa are not in the same taxonomy")
}
if !t1.Taxonomy.HasRoot() {
return nil, fmt.Errorf("taxa belong to an unrooted taxonomy")
}
2024-11-14 19:10:23 +01:00
p1 := t1.Path()
p2 := t2.Path()
2024-11-14 19:10:23 +01:00
i1 := p1.Len() - 1
i2 := p2.Len() - 1
2024-11-14 19:10:23 +01:00
for i1 >= 0 && i2 >= 0 && p1.slice[i1].id == p2.slice[i2].id {
i1--
i2--
}
2024-11-14 19:10:23 +01:00
return &Taxon{
Taxonomy: t1.Taxonomy,
Node: p1.slice[i1+1],
}, nil
}