PMCCPMCCPMCC

Search tips
Search criteria 

Advanced

 
Logo of amolbioBioMed CentralBiomed Central Web Sitesearchsubmit a manuscriptregisterthis articleAlgorithms for Molecular Biology : AMB
 
Algorithms Mol Biol. 2017; 12: 7.
Published online 2017 March 16. doi:  10.1186/s13015-017-0099-7
PMCID: PMC5356459

An efficient algorithm for testing the compatibility of phylogenies with nested taxa

Abstract

Background

Semi-labeled trees generalize ordinary phylogenetic trees, allowing internal nodes to be labeled by higher-order taxa. Taxonomies are examples of semi-labeled trees. Suppose we are given collection 𝒫 of semi-labeled trees over various subsets of a set of taxa. The ancestral compatibility problem asks whether there is a semi-labeled tree that respects the clusterings and the ancestor/descendant relationships implied by the trees in 𝒫. The running time and space usage of the best previous algorithm for testing ancestral compatibility depend on the degrees of the nodes in the trees in 𝒫.

Results

We give a algorithm for the ancestral compatibility problem that runs in O(M𝒫log2M𝒫) time and uses O(M𝒫) space, where M𝒫 is the total number of nodes and edges in the trees in 𝒫.

Conclusions

Taxonomies enable researchers to expand greatly the taxonomic coverage of their phylogenetic analyses. The running time of our method does not depend on the degrees of the nodes in the trees in 𝒫. This characteristic is important when taxonomies—which can have nodes of high degree—are used.

Keywords: Algorithms, Phylogenetics, Supertrees, Taxonomies

Introduction

In the tree compatibility problem, we are given a collection 𝒫 = {𝒯1, 𝒯2, …, 𝒯k} of rooted phylogenetic trees with partially overlapping taxon sets. 𝒫 is called a profile and the trees in 𝒫 are the input trees. The question is whether there exists a tree 𝒯 whose taxon set is the union of the taxon sets of the input trees, such that 𝒯 exhibits the clusterings implied by the input trees. That is, if two taxa are together in a subtree of some input tree, then they must also be together in some subtree of 𝒯. The tree compatibility problem has been studied for over three decades [14].

In the original version of the tree compatibility problem, only the leaves of the input trees are labeled. Here we study a generalization, called ancestral compatibility, in which taxa may be nested. That is, the internal nodes may also be labeled; these labels represent higher-order taxa, which are, in effect, sets of taxa. Thus, for example, an input tree may contain the taxon Glycine max (soybean) nested within a subtree whose root is labeled Fabaceae (the legumes), itself nested within an Angiosperm subtree. Note that leaves themselves may be labeled by higher-order taxa. The question now is whether there is a tree 𝒯 whose taxon set is the union of the taxon sets of the input trees, such that 𝒯 exhibits not only the clusterings among the taxa, but also the ancestor/descendant relationships among taxa in the input trees. Our main result is a O(M𝒫log2M𝒫) algorithm for the compatibility problem for trees with nested taxa, where M𝒫 is the total number of nodes and edges in the trees in 𝒫.

Background

The tree compatibility problem is a basic special case of the supertree problem. A supertree method is a way to synthesize a collection of phylogenetic trees with partially overlapping taxon sets into a single supertree that represents the information in the input trees. The supertree approach, proposed in the early 90s [5, 6], has been used successfully to build large-scale phylogenies [7].

The original supertree methods were limited to input trees where only the leaves are labeled. Page [8] was among the first to note the need to handle phylogenies where internal nodes are labeled, and taxa are nested. A major motivation is the desire to incorporate taxonomies as input trees in large-scale supertree analyses, as way to circumvent one of the obstacles to building comprehensive phylogenies: the limited taxonomic overlap among different phylogenetic studies [9]. Taxonomies group organisms according to a system of taxonomic rank (e.g., family, genus, and species); two examples are the NCBI taxonomy [10] and the Angiosperm taxonomy [11]. Taxonomies spanning a broad range of taxa provide structure and completeness that might be hard to obtain otherwise. A recent example of the utility of taxonomies is the Open Tree of Life, a draft phylogeny for over 2.3 million species [12].

Taxonomies are not, strictly speaking, phylogenies. In particular, their internal nodes and some of their leaves are labeled with higher-order taxa. Nevertheless, taxonomies have many of the same mathematical characteristics as phylogenies. Indeed, both phylogenies and taxonomies are semi-labeled trees [13, 14]. We will use this term throughout the rest of the paper to refer to trees with nested taxa.

The fastest previous algorithm for testing ancestral compatibility, based on earlier work by Daniel and Semple [15], is due to Berry and Semple [16]. Their algorithm runs in O(log2n · τ𝒫) time using O(τ𝒫) space. Here, n is the number of distinct taxa in 𝒫 and τP=i=1kvI(Ti)d(v)2, where I(𝒯i) is the set of internal nodes of 𝒯i, for each i ∈ {1, …, k}, and d(v) is the degree of node v. While the algorithm is polynomial, its dependence on node degrees is problematic: semi-labeled trees can be highly unresolved (i.e., contain nodes of high degree), especially if they are taxonomies.

Our contributions

As stated earlier, our main result is an algorithm to test ancestral compatibility that runs in O(M𝒫log2M𝒫) time, using O(M𝒫) space. These bounds are independent of the degrees of the nodes of the input trees, a valuable characteristic for large datasets that include taxonomies. To achieve our result, we extend ideas from our recent algorithm for testing the compatibility of ordinary phylogenetic trees [2]. As in that algorithm, a central notion in the current paper is the display graph of profile 𝒫, denoted H𝒫. This is the graph obtained from the disjoint union of the trees in 𝒫 by identifying nodes that have the same label (see the section titled  "Testing ancestral compatibility"). The term “display graph” was introduced by Bryant and Lagergren [17], but similar ideas have been used elsewhere. In particular, the display graph is closely related to Berry and Semple’s restricted descendancy graph [16], a mixed graph whose directed edges correspond to the (undirected) edges of H𝒫 and whose undirected edges have no correspondence in H𝒫. The second kind of edges are the major component of the τ𝒫 term in the time and space complexity of Berry and Semple’s algorithm. The absence of such edges makes H𝒫 significantly smaller than the restricted descendancy graph. Display graphs also bear some relation to tree alignment graphs [18].

Here, we exploit the display graph more extensively than in our previous work. Although the display graph of a collection of semi-labeled trees is more complex than that of a collection of ordinary phylogenies, we are able to extend several of the key ideas—notably, that of a semi-universal label—to the general setting of semi-labeled trees. As in [2], the implementation relies on a dynamic graph data structure, but it requires a more careful amortized analysis based on a weighing scheme.

Contents

This paper has five sections, in addition to this introduction. The section titled "Preliminaries" presents basic definitions regarding graphs, semi-labeled trees, and ancestral compatibility. The section titled "The display graph" introduces the display graph and discusses its properties. The section titled "Testing ancestral compatibility" presents BuildNT, our algorithm for testing ancestral compatibility. We first present the algorithm recursively, and then show how to transform it into an iterative algorithm, BuildNTN, that is easier to implement. We also give an example of the execution of BuildNTN. The "Implementation" section gives the implementation details for BuildNTN. The "Discussion" section gives some concluding remarks.

Preliminaries

For each positive integer r, [r] denotes the set {1, …, r}.

Graph notation

Let G be a graph. V(G) and E(G) denote the node and edge sets of G. The degree of a node v ∈ V(G) is the number of edges incident on v. A tree is an acyclic connected graph. In this paper, all trees are assumed to be rooted. For a tree T, r(T) denotes the root of T. Suppose uv ∈ V(T). Then, u is an ancestor of v in T, denoted uTv, if u lies on the path from v to r(T) in T. If uTv, then v is a descendant of u. Node u is a proper descendant of v if u is a descendant of v and v ≠ u. If {uv} ∈ E(T) and uTv, then u is the parent of v and v is a child of u. If neither uTv nor vTu hold, then we write uTv and say that u and v are not comparable in T.

Semi-labeled trees

A semi-labeled tree is a pair 𝒯 = (Tϕ) where T is a tree and ϕ is a mapping from a set L(𝒯) to V(T) such that, for every node v ∈ V(T) of degree at most two, v ∈ ϕ(L(𝒯)). L(𝒯) is the label set of 𝒯 and ϕ is the labeling function of 𝒯.

For every node v ∈ V(T), ϕ-1(v) denotes the (possibly empty) subset of L(𝒯) whose elements map into v; these elements as the labels of v (thus, each label is a taxon). If ϕ-1(v) ≠ ∅, then v is labeled; otherwise, v is unlabeled. Note that, by definition, every leaf in a semi-labeled tree is labeled. Further, any node, including the root, that has a single child must be labeled. Nodes with two or more children may be labeled or unlabeled. A semi-labeled tree 𝒯 = (Tϕ) is singularly labeled if every node in T has at most one label; 𝒯 is fully labeled if every node in T is labeled.

Semi-labeled trees, also known as X -trees, generalize ordinary phylogenetic trees, also known as phylogenetic X -trees [14]. An ordinary phylogenetic tree is a semi-labeled tree 𝒯 = (Tϕ) where r(T) has degree at least two and ϕ is a bijection from L(𝒯) into leaf set of T (thus, internal nodes are not labeled).

Let 𝒯 = (Tϕ) be a semi-labeled tree and let and be two labels in L(𝒯). If ϕ()≤Tϕ(), then we write 𝒯, and say that is a descendant of in 𝒯 and that is an ancestor of . We write <𝒯 if ϕ() is a proper descendant of ϕ(). If ϕ()‖Tϕ(), then we write 𝒯 and say that and are not comparable in 𝒯. If 𝒯 is fully labeled and ϕ() is the parent of ϕ() in T, then is the parent of in 𝒯 and is a child of in 𝒯; two labels with the same parent are siblings.

Two semi-labelled trees 𝒯 = (Tϕ) and 𝒯 = (Tϕ) are isomorphic if there exists a bijection ψ:V(T) → V(T) such that ϕψ ∘ ϕ and, for any two nodes uv ∈ V(T), (uv) ∈ E(T) if and only (ψ(u), ψ(v)) ∈ E(T).

Let 𝒯 = (Tϕ) be a semi-labeled tree. For each u ∈ V(T), X(u) denotes the set of all labels in the subtree of T rooted at u; that is, X(u) = ⋃v:uTvϕ-1(v). X(u) is called a cluster of T. Cl(𝒯) denotes the set of all clusters of 𝒯. It is well known [14, Theorem 3.5.2] that a semi-labeled tree 𝒯 is completely determined by Cl(𝒯). That is, if Cl(𝒯) = Cl(𝒯) for some other semi-labeled tree 𝒯, then 𝒯 is isomorphic to 𝒯.

Suppose A ⊆ L(𝒯) for a semi-labeled tree 𝒯 = (Tϕ). The restriction of 𝒯 to A, denoted 𝒯|A, is the semi-labeled tree whose cluster set is Cl(𝒯|A) = {X ∩ A:X ∈ Cl(𝒯) and X ∩ A ≠ ∅}. Intuitively, 𝒯|A is obtained from the minimal rooted subtree of T that connects the nodes in ϕ(A) by suppressing all vertices of degree two that are not in ϕ(A).

Let 𝒯 = (Tϕ) and 𝒯 = (Tϕ) be semi-labeled trees such that L(𝒯) ⊆ L(𝒯). 𝒯 ancestrally displays 𝒯 if Cl(𝒯) ⊆ Cl(𝒯|L(𝒯)). Equivalently, 𝒯 ancestrally displays 𝒯 if 𝒯 can be obtained from 𝒯|L(𝒯) by contracting edges, and, for any 12 ∈ L(𝒯),

  • (i)
    if 1<𝒯2, then 1<𝒯2, and
  • (ii)
    if 1𝒯2, then 1𝒯2.

The notion of “ancestrally displays” for semi-labeled trees generalizes the well-known notion of “displays” for ordinary phylogenetic trees [14].

For a semi-labelled tree 𝒯, let us define D(𝒯) and N(𝒯) as follows.

D(T)={(,):,L(T)and<T}N(T)={{,}:,L(T)andT}

Note that D(𝒯) consists of ordered pairs, while N(𝒯) consists of unordered pairs.

Lemma 1

(Bordewich et al. [13]) Let 𝒯 and 𝒯 be semi-labelled trees such that L(𝒯) ⊆ L(𝒯). Then 𝒯 ancestrally displays 𝒯 if and only if D(𝒯) ⊆ D(𝒯) and N(𝒯) ⊆ N(𝒯).

Profiles and ancestral compatibility

Throughout the rest of this paper 𝒫 = {𝒯1, 𝒯2, …, 𝒯k} denotes a set where, for each i ∈ [k], 𝒯i = (Tiϕi) is a semi-labeled tree. We refer to 𝒫 as a profile, and write L(𝒫) to denote i∈[k]L(𝒯i), the label set of 𝒫. Figure 1 shows a profile where L(𝒫) = {abcdefghi}. We write V(𝒫) for i∈[k]V(Ti) and E(𝒫) for i∈[k]E(Ti), The size of 𝒫 is M𝒫 = |V(𝒫)| + |E(𝒫)|.

Fig. 1
A profile 𝒫 = {𝒯1, 𝒯2, 𝒯3}—trees are ordered left-to-right. The letters are the original labels; grey numbers are labels added to make the trees fully labeled

𝒫 is ancestrally compatible if there is a rooted semi-labeled tree 𝒯 that ancestrally displays each of the trees in 𝒫. If 𝒯 exists, we say that 𝒯 ancestrally displays 𝒫 (see Fig. Fig.22).

Fig. 2
A tree 𝒯 that ancestrally displays the profile of Fig. Fig.11

Given a subset X of L(𝒫), the restriction of 𝒫 to X, denoted 𝒫|X, is the profile defined as

𝒫|X = {𝒯1|X ∩ L(𝒯1), 𝒯2|X ∩ L(𝒯2), …, 𝒯k|X ∩ L(𝒯k)}.

The proof of the following lemma is straightforward.

Lemma 2

Suppose 𝒫 is ancestrally compatible and let 𝒯 be a tree that ancestrally displays 𝒫. Then, for any X ⊆ L(𝒫), 𝒯|X ancestrally displays 𝒫|X.

For technical reasons, fully labeled trees are easier to handle than those that are not. Suppose 𝒫 contains trees that are not fully labeled. We can convert 𝒫 into an equivalent profile 𝒫 of fully-labeled trees as follows. For each i ∈ [k], let li be the number of unlabeled nodes in Ti. Create a set L of n = ∑i∈[k]li labels such that L ∩ L(𝒫) = ∅. For each i ∈ [k] and each v ∈ V(Ti) such that ϕi-1(v)=, make ϕi-1(v)={}, where is a distinct element from L. We refer to 𝒫 as the profile obtained by adding distinct new labels to 𝒫 (see Fig. Fig.11).

Lemma 3

(Daniel and Semple [15]) Let 𝒫 be the profile obtained by adding distinct new labels to 𝒫. Then, 𝒫 is ancestrally compatible if and only if 𝒫 is ancestrally compatible. Further, if 𝒯 is a semi-labeled phylogenetic tree that ancestrally displays 𝒫, then 𝒯 ancestrally displays 𝒫.

From this point forward, we make the following assumption.

Assumption 1

For each i ∈ [k], 𝒯i is fully and singularly labeled.

By Lemma 3, no generality is lost in assuming that all trees in 𝒫 are fully labeled. The assumption that the trees are singularly labeled is inessential; it is only for clarity. Note that, even with the latter assumption, a tree that ancestrally displays 𝒫 is not necessarily singularly labeled. Figure Figure22 illustrates this fact.

The display graph

The display graph of a profile 𝒫, denoted H𝒫, is the graph obtained from the disjoint union of the underlying trees T1T2, …, Tk by identifying nodes that have the same label. Multiple edges between the same pair of nodes are replaced by a single edge. See Fig. Fig.33.

Fig. 3
The display graph H𝒫 for the profile of Fig. Fig.11

H𝒫 has O(M𝒫) nodes and edges, and can be constructed in O(M𝒫) time. By Assumption 1, there is a bijection between the labels in L(𝒫) and the nodes of H𝒫. Thus, from this point forward, we refer to the nodes of H𝒫 by their labels. It is easy to see that if H𝒫 is not connected, then 𝒫 decomposes into label-disjoint sub-profiles, and that 𝒫 is compatible if and only if each sub-profile is compatible. Thus, without loss of generality, we shall assume the following.

Assumption 2

H𝒫 is connected.

Positions

Our compatibility algorithm processes the trees in 𝒫 from the top down, starting at the roots. We refer to the set of nodes in 𝒫 currently being considered as a “position”. The algorithm advances from the current position to the next by replacing certain nodes in the current position by their children. Formally, a position (for 𝒫) is a vector U = (U(1), U(2), …, U(k)), where U(i) ⊆ L(𝒯i), for each i ∈ [k]. Since labels may be shared among trees, we may have U(i) ∩ U(j) ≠ ∅, for ij ∈ [k] with i ≠ j. For each i ∈ [k], let Desci(U) = {:𝒯i,  for some  ∈ U(i)}, and let Desc𝒫(U) = ⋃i∈[k]Desci(U).

A position U is valid if, for each i ∈ [k],

  1. if |U(i)| ≥ 2, then the elements of U(i) are siblings in 𝒯i and
  2. Desci(U) = Desc𝒫(U) ∩ L(𝒯i).

Lemma 4

For any valid position U,

𝒫|Desc𝒫(U) = {𝒯1|Desc1(U), 𝒯2|Desc1(U), …, 𝒯k|Desck(U)}.

Proof

By (V2), we have that 𝒯i|Desci(U) and 𝒯i|Desc𝒫(U) ∩ L(𝒯i) are isomorphic, for each i ∈ [k]. The lemma then follows from the definition of 𝒫|Desc𝒫(U).

For any valid position U, H𝒫(U) denotes the subgraph of H𝒫 induced by Desc𝒫(U).

Observation 1

For any valid position U, H𝒫(U) is the subgraph of H𝒫 obtained by deleting all labels in V(H𝒫)\Desc𝒫(U), along with all incident edges.

A valid position of special interest to us is Uroot, the root position, defined as follows.

Uroot=(ϕi-1(r(T1)),ϕi-1(r(T2)),,ϕi-1(r(Tk))).
1

That is, for each i ∈ [k], Uroot(i) is a singleton containing only the label of r(Ti). In Fig. Fig.3,3, Uroot = ({1}, {2}, {g}). It is straightforward to verify that Uroot is indeed valid, that Desc𝒫(Uroot) = L(𝒫), and that H𝒫(Uroot) = H𝒫.

Semi-universal labels

Let U be a valid position, and let be a label in U. Then, is semi-universal in U if U(i) = {}, for every i ∈ [k] such that  ∈ L(𝒯i). In Fig. Fig.3,3, labels 1 and 2 are semi-universal in Uroot, but g is not, since g is in both L(𝒯2) and L(𝒯3), but Uroot(2) ≠ {g}.

The term “semi-universal”, borrowed from Pe’er et al. [19], derives from the following fact. Suppose that 𝒫 is ancestrally compatible, that 𝒯 is a tree that ancestrally displays 𝒫, and that is a semi-universal label for some valid position U. Then, as we shall see, must label the root u of a subtree of 𝒯 that contains all the descendants of in 𝒯i, for every i such that  ∈ L(𝒯i). The qualifier “semi” is because this subtree may also contain labels that do not descend from in any input tree, but descend instead from some other semi-universal label in U. In this case, also labels u. We exploit this property of semi-universal labels in our ancestral compatibility algorithm and its proof of correctness (see "Testing ancestral compatibility").

For each label  ∈ L(𝒫), let k denote the number of input trees that contain label . We can obtain k for every  ∈ L(𝒫) in O(M𝒫) time during the construction of H𝒫.

Lemma 5

Let U = (U(1), …, U(k)) be a valid position. Then, label is semi-universal in U if the cardinality of the set J = {i ∈ [k]:U(i) = {}} equals k.

Proof

By definition, U(i) = {}, for every i ∈ J. Since |J| = k, the lemma follows.

Successor positions

For every i ∈ [k] and every  ∈ L(𝒯i), let Chi() denote the set of children of in L(𝒯i). For a subset A of L(𝒯i), let Chi(A) = ⋃AChi(). Let U be a valid position, and S be the set of semi-universal labels in U. The successor of U with respect to S is the position U = (U(1), U(2), …, U(k)), where, for each i ∈ [k], U(i) is defined as follows.

U(i)=Chi()ifU(i)={},for someS,U(i)otherwise.

In Fig. Fig.3,3, the set of semi-universal labels in Uroot is S = {1, 2}. Since Ch1(1) = {3, f} and Ch2(2) = {efg}, the successor of Uroot is Uroot=({3,f},{e,f,g},{g}).

Observation 2

Let U be a valid position, and let U be the successor of U with respect to the set S of semi-universal labels in U. Then, H𝒫(U) can be obtained from H𝒫(U) by doing the following for each  ∈ S: (1) for each i ∈ [k] such that U(i) = {}, delete all edges between and Chi(); (2) delete .

Let U be a valid position, and W be a subset of Desc𝒫(U). Then, U|W denotes the position (U(1) ∩ WU(2) ∩ W, …, U(k) ∩ W). In Fig. Fig.3,3, the components of H𝒫(U), where U is the successor of Uroot, are W1 = {3, 4, abcdeg} and W2 = {fhi}. Thus, U|W1 = ({3}, {eg}, {g}) and U|W2 = ({f}, {f}, ∅). We have the following result.

Lemma 6

Let U be a valid position, and S be the set of all semi-universal labels in U. Let U be the successor of U with respect to S, and let W1W2, …, Wp be the label sets of the connected components of H𝒫(U). Then, U|Wj is a valid position, for each j ∈ [p].

Proof

It suffices to argue that U satisfies conditions (V1) and (V2). The lemma then follows from the fact that the connected components of H𝒫(U) are label-disjoint.

U must satisfy condition (V1), since U does. Suppose  ∈ S. Then, for each i ∈ [k] such that  ∈ L(𝒯i), Desci(U) = Desci(U)\{} and Desc𝒫(U) ∩ L(𝒯i) = (Desc𝒫(U) ∩ L(𝒯i))\{}. Thus, since (V2) holds for U, it also holds for U.

Testing ancestral compatibility

Overview of the algorithm

BuildNT (Algorithm 1) is our algorithm for testing compatibility of semi-labeled trees. Its argument, U, is a valid position in 𝒫 such that H𝒫(U) is connected. BuildNT relies on the fact—proved later, in Theorem 1—that if 𝒫|Desc𝒫(U) is compatible, then U must contain a nonempty set S of semi-universal labels. If such a set S exists, the algorithm replaces U by its successor U with respect to S. It then processes each connected component of H𝒫(U) recursively, to determine if the associated sub-profile is compatible. If all the recursive calls are successful, then their results are combined into a supertree for 𝒫|Desc𝒫(U).

In detail, BuildNT proceeds as follows. Line 1 computes the set S of semi-universal labels in U. If S is empty, then, 𝒫|Desc𝒫(U) is incompatible, and, thus, so is 𝒫. This fact is reported in Line 3. Line 4 creates a tentative root rU, labeled by S, for the tree 𝒯U for L(U). Line 5 checks if S contains exactly one label , with no proper descendants. If so, by the connectivity assumption, must be the sole member of Desc𝒫(U); that is, L(U) = . Therefore, Line 6 simply returns the tree with a single node, labeled by S = {}. Line 7 updates U, replacing it by its successor with respect to S. Let W1W2,  ⋯ , Wp be the connected components of H𝒫(U) after updating U. By Lemma 6, U|Wj is a valid position, for each j ∈ [p]. Lines 8–12 recursively invoke BuildNT on U|Wj for each j ∈ [p], to determine if there is a tree tj that ancestrally displays 𝒫|Desc𝒫(U ∩ Wj). If any subproblem is incompatible, Line 12 reports that 𝒫 is incompatible. Otherwise, Line 13 returns the tree obtained by making the tjs the subtrees of root rU.

An external file that holds a picture, illustration, etc.
Object name is 13015_2017_99_Figa_HTML.jpg

Next, we argue the correctness of BuildNT.

Correctness

Lemma 7

Let U be a valid position in 𝒫. If BuildNT(U) returns a tree 𝒯U, then 𝒯U is a phylogenetic tree such that L(𝒯U) = L(U).

Proof

We use induction on |L(U)|. The base case, where |L(U)| = 1, is handled by Lines 5–6. In this case, SL(U) = {} and BuildNT(U) correctly returns the tree consisting of a single node, labeled by {}. Otherwise, let W1, …, Wp be the connected components of H𝒫(U) in step 8. Since BuildNT(U) returns tree 𝒯U, it must be the case that, for each j ∈ [p], the result tj returned by the recursive call to BuildNT(U|Wj) in Line 10 is a tree. Since |S| ≥ 1, we have |L(Wj)| < |L(U)|, for each j ∈ [p]. Thus, we can assume inductively that tj is a phylogenetic tree for L(Wj). Since S ∪ ⋃j∈[p]L(Wj) = L(U), the tree returned in Line 13 is a phylogeny with species set L(U).

Theorem 1

Let 𝒫 = {𝒯1, 𝒯2, …, 𝒯k} be a profile and let Uroot be the root position, as defined in Eq. (1). Then, BuildNT(Uroot) returns either (i) a semi-labeled tree 𝒯 that ancestrally displays 𝒫, if 𝒫 is ancestrally compatible, or (ii) incompatible otherwise.

Proof

BuildNT(Uroot) either returns a tree or incompatible. We consider each case separately.

  • (i)
    Suppose that BuildNT(Uroot) returns a semi-labeled tree 𝒯. By Lemma 7, L(𝒯) = L(𝒫). We prove that 𝒯 ancestrally displays 𝒫. By Lemma 1, it suffices to show that D(𝒯i) ⊆ D(𝒯) and N(𝒯i) ⊆ N(𝒯), for each i ∈ [k]. Consider any () ∈ D(𝒯i). Then, has a child ′′ in 𝒯i such that ′′𝒯i —note that we may have ′′. There must be a recursive call to BuildNT(U), for some valid position U, where is the set S of semi-universal labels obtained in Line 1. By Observation 2, label ′′, and thus , both lie in one of the connected components of the graph obtained by deleting all labels in S, including , and their incident edges from H𝒫(U). It now follows from the construction of 𝒯 that () ∈ D(𝒯). Thus, D(𝒯i) ⊆ D(𝒯). Now, consider any {} ∈ N(𝒯i). Let v be the lowest common ancestor of ϕi() and ϕi() in 𝒯i and let v be the label of v. Then, v has a pair of children, 1 and 2 say, in 𝒯i such that 1𝒯i, and 2𝒯i. Because BuildNT(Uroot) returns a tree, there are recursive calls BuildNT(U1) and BuildNT(U2) for valid positions U1 and U2 such that 1 is semi-universal for U1 and 2 is semi-universal for U2. We must have U1 ≠ U2; otherwise, |U1(i)| = |U2(i)| ≥ 2, and, thus, neither 1 nor 2 is semi-universal, a contradiction. Further, it follows from the construction of 𝒯 that we must have Desc𝒫(U1) ∩ Desc𝒫(U2) = ∅. Hence, 𝒯, and, therefore, {} ∈ N(𝒯).
  • (ii)
    Asssume, by way of contradiction, that BuildNT(Uroot) returns incompatible, but that 𝒫 is ancestrally compatible. By assumption, there exists a semi-labeled tree 𝒯 that ancestrally displays 𝒫. Since BuildNT(Uroot) returns incompatible, there is a recursive call to BuildNT(U) for some valid position U such that U has no semi-universal label, and the set S of Line 1 is empty. By Lemma 2, 𝒯|Desc𝒫(U) ancestrally displays 𝒫|Desc𝒫(U). Thus, by Lemma 4, 𝒯|Desc𝒫(U) ancestrally displays 𝒯i|Desci(U), for every i ∈ [k]. Let be any label in the label set of the root of 𝒯|Desc𝒫(U). Then, for each i ∈ [k] such that  ∈ L(𝒯i), must be the label of the root of 𝒯i|Desci(U). Thus, for each such i, U(i) = {}. Hence, is semi-universal in U, a contradiction.

An iterative version

We now present BuildNTN (Algorithm 2), an iterative version of BuildNT, which lends itself naturally to an efficient implementation. BuildNTN performs a breadth-first traversal of BuildNT’s recursion tree, using a first-in first-out queue Q that stores pairs of the form (U, pred), where U is a valid position in 𝒫 and pred is a reference to the parent of the node corresponding to U in the supertree built so far. BuildNTN simulates recursive calls in BuildNT by enqueuing pairs corresponding to subproblems. We explain this in more detail next.

BuildNTN initializes its queue to contain the starting position, Uroot, with a null parent. It then proceeds to the while loop of Lines 3–14. Each iteration of the loop starts by dequeuing a valid position U, along with a reference pred to the potential parent for the subtree for L(U) in the supertree. The body of the loop closely follows the steps performed by a call to BuildNT(U). Line 5 computes the set S of semi-universal labels in U. If S is empty, the algorithm reports that 𝒫 is incompatible and terminates (Lines 6–7). The algorithm then creates a tentative root rU labeled by S for the tree 𝒯U for L(U), and links rU to its parent (Line 8). If S consists of exactly one element that has no proper descendants, we skip the rest of the current iteration of the while loop, and continue to the next iteration (Lines 9–10). Line 11 replaces U by its successor with respect to S. Lines 13–14 enqueue each of U|W1U|W2, …, U|Wp, along with rU, for processing in a subsequent iteration. If the while loop terminates without any incompatibility being detected, the algorithm returns the tree with root rUroot.

An external file that holds a picture, illustration, etc.
Object name is 13015_2017_99_Figb_HTML.jpg

Although the order in which BuildNTN processes connected components differs from that of BuildNT —breadth-first instead of depth-first—, it is straightforward to see that the effect is equivalent, and the proof of correctness of BuildNT (Theorem 1) applies to BuildNTN as well. We thus state the following without proof.

Theorem 2

Let 𝒫 = {𝒯1, 𝒯2, …, 𝒯k} be a profile. Then, BuildNTN(𝒫) returns either (i) a semi-labeled tree 𝒯 that ancestrally displays 𝒫, if 𝒫 is ancestrally compatible, or (ii) incompatible otherwise.

Let Q be BuildNTN’s first-in first-out queue. In the rest of the paper, we will say that a valid position U is in Q if (U, pred) ∈ Q,  for some pred. Let HQ be the subgraph of H𝒫 induced by  ⋃ {Desc(U):U is in Q}. By Observation 1, HQ is obtained from H𝒫 through edge and node deletions.

Lemma 8

At the start of any iteration of BuildNTNs while loop, the set of connected components of HQ is {V(H𝒫(U)):U is in Q}.

Proof

The property holds at the outset, since, by Assumption 2, H𝒫H𝒫(Uroot) is a connected graph, and the only element of Q is (Uroot, null). Assume that the property holds at the beginning of iteration l. Let (U, pred) be the element dequeued from Q in Line 4. Then, H𝒫(U) is connected. In place of (U, pred), Lines 13–14 enqueue (U|WjrU), for each j ∈ [p], where, by construction, H𝒫(U|Wj) is a connected component of H𝒫(U). Thus, the property holds at the beginning of iteration l + 1.

In other words, Lemma 8 states that each iteration of BuildNTN(𝒫) deals with a subgraph of H𝒫, whose connected components are in one-to-one correspondence with the valid positions stored in Q. This is illustrated by the next example.

An example

Figures Figures4,4, ,5,5, ,6,6, ,77 and and88 illustrate the execution of BuildNTN on the profile 𝒫 = (𝒯1, 𝒯2, 𝒯3) of Fig. Fig.1.1. The figures show how the graph HQ —initially equal to H𝒫H𝒫(Uroot) (Fig. (Fig.3)—evolves3)—evolves as its edges and nodes are deleted.

Fig. 4
After generating all supertree nodes in level 0
Fig. 5
After generating all supertree nodes in level 1
Fig. 6
After generating all supertree nodes in level 2
Fig. 7
After generating all supertree nodes in level 3
Fig. 8
After generating all supertree nodes in level 4

In each figure, HQ is shown on the left and the current supertree is shown on the right. For brevity, the figures only exhibit the state of HQ and the supertree after all the nodes at each level are generated. The various valid positions processed by BuildNTN(𝒫) are denoted by Uα, for different subscripts α; Sα denotes the semi-universal labels in Uα, and Uα denotes the successor of Uα with respect to Sα. We write Lα as an abbreviation for L(Uα) The root of the tree for Lα is rUα and is labeled by Sα.

Initially, Q = ((Uroot, null)). In what follows, the elements of Q are listed from front to rear.

Level 0. Refer to Fig. Fig.4.4. As seen earlier, the set of semi-universal labels of Uroot is Sroot = {1, 2}. Thus, HP(Uroot) has two components W1 and W2. Let U1=Uroot|W1 and U2=Uroot|W2. Then,

U1 = ({3}, {eg}, {g}) and U2 = ({f}, {f}, ∅).

After level 0 is processed, Q = ((U1rUroot), (U2rUroot)). Thus, the roots of the subtrees for L1 and L2 will be children of rUroot.

Level 1. Refer to Fig. Fig.5.5. We have S1 = {3}, so HP(U1) has two components W11 and W12. Let U11=U1|W11 and U12=U1|W12. Then,

U11 = ({ad}, {g}, {g}) and U12 = ({e}, {e}, ∅).

We have S2 = {f}, so HP(U2) has two components W21 and W22. Let U21=U2|W21 and U22=U2|W22. Then,

U21 = (∅, {h}, ∅) and U21 = (∅, {i}, ∅).

After level 1 is processed, Q = ((U11r1), (U12r1), (U21r2), (U22r2)).

Level 2. Refer to Fig. Fig.6.6. We have S11 = {g}, so HP(U11) has two components W111 and W112. Let U111=U11|W111 and U112=U11|W112. Then,

U111 = ({a}, {a}, {4}) and U112 = (∅, {d}, {d}).

The only semi-universal labels in U12, U21, and U22 are, respectively, e, h, and i. Since none of these labels have proper descendants, each of them is a leaf in the supertree.

After level 2 is processed, Q = ((U111r11), (U112r11)).

Level 3. Refer to Fig. Fig.7.7. We have S111 = {4, a}, so HP(U111) has two components W1111 and W1112. Let U1111=U111|W1111 and U1112=U111|W1112. Then,

U1111 = ({b}, ∅, {b}) and U1112 = ({c}, ∅, {c}).

The only semi-universal label in U112 is d. Since d has no proper descendants, it becomes a leaf in the supertree.

After level 3 is processed, Q = ((U1111r111), (U1112r111)).

Level 4. Refer to Fig. Fig.8.8. The only semi-universal labels in U1111 and U1112 are, respectively, b and c. Since neither of these labels have proper descendants, each of them is a leaf in the supertree.

After level 4 is processed, Q is empty, and BuildNTN(𝒫) terminates.

Implementation

Here we prove the following result.

Theorem 3

There is an algorithm that, given a profile 𝒫 of rooted trees, runs in O(M𝒫log2M𝒫) time, and either returns a tree that displays 𝒫, if 𝒫 is compatible, or reports that is 𝒫 is incompatible otherwise.

We prove this theorem by showing how to implement BuildNTN so that the algorithm runs in O(M𝒫log2M𝒫) on any profile 𝒫.

As in the section titled "An iterative version", let HQ denote the subgraph of H𝒫 associated with the valid positions in BuildNTN’s queue. By Lemma 8, each valid position U in Q corresponds to one connected component of HQ —namely Desc(U) —and vice-versa. We use this fact in the implementation of BuildNTN: alongside each valid position U in Q, we also store a reference to the respective connected component, together with additional information, described next, to quickly identify semi-universal labels.

Let U be any valid set in Q, let YV(H𝒫(U)) be the corresponding connected component of HQ, and let be any label in Y. Our implementation maintains the following data fields.

  • Let JU = {i ∈ [k]:U(i) ≠ ∅}. Then, Y.map is a map from JU to L(U), where, for each i ∈ JU, Y.map(i) = U(i).
  • For each  ∈ Y, .count equals the cardinality of the set {i ∈ [k]:Y.map(i) = {}}. (Recall that k is the number of input trees that contain .).
  • Y.exposed, a set consisting of all i ∈ [k] such that Y.map(i) = {} for some  ∈ Y such that .count = k.
  • Y.weight, which equals Yk. This field is needed for technical reasons, to be explained later.

For the purpose of analysis, we assume that the exposed fields are represented as balanced binary search trees (BSTs), which ensures O(logk) = O(logM𝒫) time per access and update. The map fields are also implemented using BSTs. We store the set JU = {i ∈ [k]:U(i) ≠ ∅} as a BST, enabling is to determine in O(logk) time if an index i is in JU, and, if this is the case, to access Y.map(i). The latter is also stored as a BST, allowing us to search and update Y.map(i) in O(log|U(i)|) = O(logM𝒫) time. Note that, in practice, hashing may be a better alternative for both exposed and map fields, as it offers expected constant time performance per operation.

The data fields listed above allow us to efficiently retrieve the set S of semi-universal labels in U, as needed in line 5 of BuildNTN(𝒫). Indeed, suppose that U is the valid position extracted from Q at the beginning of an iteration of the while loop of Lines 3–14, and that YV(H𝒫(U)). Then, by Lemma 5, we have S = {v ∈ Y.map(i):i ∈ Y.exposed}. What remains is to devise an efficient way to update these fields for each of the connected components of H𝒫(U) created by replacing U with its successor in Line 11.

Let U be the value of U after Line 11; thus, U is the successor of U. By Observation 2, H𝒫(U) is obtained from H𝒫(U) through edge and node deletions. We need to

  1. Generate the new connected components resulting from these deletions, and
  2. Produce the required map, count, and exposed data fields for the various connected components.

We accomplish (a) using the dynamic graph connectivity data structure of Holm et al. [20], which we refer to as HDT. HDT allows us to maintain the list of nodes in each component, as well as the number of these nodes so that, if we start with no edges in a graph with N nodes, the amortized cost of each update is O(log2N). Since H𝒫 has O(M𝒫) nodes, each update takes O(log2M𝒫) time. The total number of edge and node deletions performed by BuildNTN(𝒫) —including all deletions in the interations—is at most the total number of edges and nodes in H𝒫, which is O(M𝒫). HDT allows us to maintain connectivity information throughout the entire algorithm in O(M𝒫log2M𝒫) time, which is within the time bound claimed in Theorem 3.

For part (b), we need to augment HDT in order to maintain the the required data fields for the various connected components created during edge and node deletion. In the next subsections, we describe how to do this. We begin by explaining how to initialize all the required data fields for H𝒫H𝒫(Uroot).

Initializing the data fields

Graph H𝒫(Uroot) has a single connected component, YrootL(𝒫), which is the entire vertex set of the graph. We initialize the data fields as follows.

  • For each i ∈ [k], Yroot.map(i) = {r(Ti)}. This takes O(k) time.
  • Yroot.weight = ∑L(𝒫)k. This takes O(M𝒫) time.

We initialize the count fields in O(M𝒫) time as follows:

  1. Set .count to 0 for all  ∈ L(𝒫).
  2. For each i ∈ [k], do the following.
    1. Let ρi denote the label of r(Ti).
    2. Increment ρi.count by one.

Once the count fields are initialized, it is easy to initialize Yroot.exposed in O(k) time. Thus, we can initialize all the required fields in O(M𝒫) time.

Maintaining the data fields

Suppose that all data fields fields are correctly computed for every connected component that is in Q at the beginning of an iteration of the while loop in 3–14 of BuildNTN. We now show how to generate the same fields efficiently for the new connected components created by Line 11.

Computing successor positions

Let U be the valid position extracted from Q at the beginning of an iteration of BuildNTN’s while loop, and let YV(Desc(U)) be the associated connected component. Assume all the data fields for Y have been correctly computed. To obtain the successor of U in Line 11 of BuildNTN, we perform the following steps.

  1. Identify the set S of semi-universal labels in U. As we saw, this set is given by S = { ∈ Y.map(i):i ∈ Y.exposed}.
  2. Set Y.map(i) = ∅, for every i ∈ Y.exposed.
  3. Make Y.exposed = ∅.
  4. For each  ∈ S and each i such that  ∈ L(Ti), do the following.
    • If Chi() ≠ ∅, replace Y.map(i) by Chi(). If Chi() is a singleton set {α}, increment α.count by one. If α.count = k, add i to Y.exposed.
    • Otherwise, Y.map(i) is undefined.
  5. For each label in S, delete the edges incident on and then itself, updating the data fields as necessary after each deletion.

The total number of operations on map and exposed fields in Steps 1–4 is O(∑Sk). Since each label becomes semi-universal at most once, the total number of operations on map fields over the entire execution of BuildNTN(𝒫) is O(∑L(𝒫)k), which is O(M𝒫). The same bound holds for updates to count and exposed fields.

Next let us focus on how to handle the deletion of a single edge in Step 5.

Deleting an edge

To delete an edge between and a child α of , we proceed as follows.

  1. Delete (α), querying HDT to determine whether this disconnects Y.
    • If Y remains connected, skip the next steps and proceed directly to the next child of .
    • Otherwise, Y is split into two components, Y1 and Y2.
  2. Update Y1.weight and Y2.weight.
  3. Identify which of Y1 and Y2 has the smaller weight field. Without loss of generality, assume that Y1.weight ≤ Y2.weight.
  4. Initialize Y1.map and Y1.exposed to null.
  5. Initialize Y2.map and Y2.exposed to Y.map and Y.exposed, respectively.
  6. For each label β in Y1, perform the following steps for each i such that β ∈ L(𝒯i).
    1. Delete β from Y2.map(i) and add β to Y1.map(i).
    2. Adjust count and exposed fields as necessary.

The connectivity test in Step 1 is done by querying HDT. Steps 3–5 are trivial. We thus focus on Steps 2 and 6.

To perform Step 2, we use the well-known technique of scanning the smaller component [21]. We first consult HDT to determine which of Y1 or Y2 has fewer nodes. Assume, without loss of generality, that |Y1| ≤ |Y2|. We initialize Y1.weight to 0 and Y2.weight to Y.weight. We then scan the labels of Y1, incrementing Y1.weight by k for each label  ∈ Y1. When the scan of Y1 is complete, we make Y2.weight = Y2.weight - Y1.weight. We claim that any label  ∈ L(𝒫) is scanned O(logM𝒫) times over the entire execution of BuildNTN(𝒫). To verify this, let N() be the number of nodes in the connected component containing . Suppose that, initially, N() = N. Then, the rth time we scan , N() ≤ N/2r. Thus, is scanned O(logN) times. The claim follows, since NO(M𝒫). Therefore, the total number of updates over all labels is O(M𝒫logM𝒫).

Each execution of Step 6(a) updates each of Y1.map(i) and Y2.map(i) once. Step 6(b) is more complex, but can also be accomplished with O(1) data field updates. We omit the (tedious) details. In summary, each execution of step 6 for some β ∈ L(𝒫) performs O(kβ) data field updates.

Let us track the number of data field updates in Step 6 that can be attributed to some specific label β ∈ L(P) over the entire execution of BuildNTN(𝒫). Let wr(β) be the weight of the connected component containing β at the beginning of Step 6, on the rth time that β is considered in that step. Thus, w0(β) ≤ ∑L(𝒫)k. We claim that wr(β) ≤ w0(β)/2r. The reason is that we only consider β if (a) β is contained in one of the two components that result from deleting an edge in step 1 and (b) the component containing β has the smaller weight. Hence, the number of times β is considered in step 6 over the entire execution of BuildNTN(𝒫) is O(logw0(β)), which is O(logM𝒫), since w0(β) = O(M𝒫). Therefore, the total number of data field updates in Step 6, over all labels in L(𝒫) considered throughout the entire execution of BuildNTN(𝒫), is O(logM𝒫 · ∑L(𝒫)k), which is O(M𝒫logM𝒫).

Summary

Let us review the running times of each aspect of our implementation of BuildNTN.

  • Initializing the data structures. This has two parts.
    • Setting up the HDT data structure for H𝒫. This takes O(M𝒫log2M𝒫) time.
    • Initializing the data fields for the single connected component of H𝒫. This takes O(M𝒫) time.
  • Maintaining the data structures. This also has two parts.
    • Updating the HDT data structure. There are O(M𝒫) edge and node deletions, at an amortized cost of O(log2M𝒫) per deletion, yielding a total time of O(M𝒫log2M𝒫).
    • Maintaining the relevant data fields for the connected components. We have seen that the total number of updates is O(M𝒫logM𝒫). Assume, conservatively, that each update can be done in O(logM𝒫) time. Then, this part takes a total of O(M𝒫log2M𝒫) over the entire execution of BuildNTN.

We conclude that the total running time of BuildNTN(𝒫) is O(M𝒫log2M𝒫), completing the proof of Theorem 3.

Discussion

Like our earlier algorithm for compatibility of ordinary phylogenetic trees, the more general algorithm presented here, BuildNTN, is a polylogarithmic factor away from optimality (a trivial lower bound is Ω(M𝒫), the time to read the input). BuildNTN has a linear-space implementation, using the results of Thorup [22]. A question to be investigated next is the performance of the algorithm on real data. Another important issue is integrating our algorithm into a synthesis method that deals with incompatible profiles.

Authors' contributions

Algorithms and proofs were developed jointly by YD and DFB. The first draft of the paper was written by DFB, with substantial contributions from YD. YD and DFB both proofread the manuscript. Both authors read and approved the final manuscript.

Acknowledgements

The authors were supported in part by the National Science Foundation under Grant CCF-1422134.

Competing interests

The authors declare that they have no competing interests.

Footnotes

Yun Deng and David Fernández-Baca contributed equally

Contributor Information

Yun Deng, ude.etatsai@gnednuy.

David Fernández-Baca, ude.etatsai@ednanref.

References

1. Aho AV, Sagiv Y, Szymanski TG, Ullman JD. Inferring a tree from lowest common ancestors with an application to the optimization of relational expressions. SIAM J Comput. 1981;10(3):405–421. doi: 10.1137/0210030. [Cross Ref]
2. Deng Y, Fernández-Baca D. Fast compatibility testing for rooted phylogenetic trees. In: Grossi R, Lewenstein M (editors) 27th annual symposium on combinatorial pattern matching (CPM 2016). Leibniz International Proceedings in Informatics. Schloss Dagstuhl—Leibniz-Zentrum für Informatik. Dagstuhl Publishing; 2016. p. 12. doi:10.4230/LIPIcs.CPM.2016.12.
3. Henzinger MR, King V, Warnow T. Constructing a tree from homeomorphic subtrees, with applications to computational evolutionary biology. Algorithmica. 1999;24:1–13. doi: 10.1007/PL00009268. [Cross Ref]
4. Steel MA. The complexity of reconstructing trees from qualitative characters and subtrees. J Classif. 1992;9:91–116. doi: 10.1007/BF02618470. [Cross Ref]
5. Baum BR. Combining trees as a way of combining data sets for phylogenetic inference, and the desirability of combining gene trees. Taxon. 1992;41:3–10. doi: 10.2307/1222480. [Cross Ref]
6. Ragan MA. Phylogenetic inference based on matrix representation of trees. Mol Phylogenet Evol. 1992;1:53–58. doi: 10.1016/1055-7903(92)90035-F. [PubMed] [Cross Ref]
7. Bininda-Emonds ORP, Cardillo M, Jones KE, MacPhee RDE, Beck RMD, Grenyer R, Price SA, Vos RA, Gittleman JL, Purvis A. The delayed rise of present-day mammals. Nature. 2007;446:507–512. doi: 10.1038/nature05634. [PubMed] [Cross Ref]
8. Page RM. Taxonomy, supertrees, and the tree of life. In: Bininda-Emonds ORP, editor. Phylogenetic supertrees: combining information to reveal the tree of life. Dordrecht: Kluwer; 2004. pp. 247–265.
9. Sanderson MJ. Phylogenetic signal in the eukaryotic tree of life. Science. 2008;321(5885):121–123. doi: 10.1126/science.1154449. [PubMed] [Cross Ref]
10. Sayers EW, et al. Database resources of the national center for biotechnology information. Nucl Acids Res. 2009;37(Database issue):5–15. doi: 10.1093/nar/gkn741. [PMC free article] [PubMed] [Cross Ref]
11. The Angiosperm Phylogeny Group et al. An update of the Angiosperm Phylogeny Group classification for the orders and families of flowering plants: APG IV. Bot J Linn Soc. 2016;181:1–20. doi: 10.1111/boj.12385. [Cross Ref]
12. Hinchliff CE, Smith SA, Allman JF, Burleigh JG, Chaudhary R, Coghill LM, Crandall KA, Deng J, Drew BT, Gazis R, Gude K, Hibbett DS, Katz LA, Laughinghouse HD, IV, McTavish EJ, Midford PE, Owen CL, Reed RH, Reesk JA, Soltis DE, Williams T, Cranston KA. Synthesis of phylogeny and taxonomy into a comprehensive tree of life. Proc Natl Acad Sci. 2015;112(41):12764–12769. doi: 10.1073/pnas.1423041112. [PubMed] [Cross Ref]
13. Bordewich M, Evans G, Semple C. Extending the limits of supertree methods. Ann Comb. 2006;10:31–51. doi: 10.1007/s00026-006-0272-z. [Cross Ref]
14. Semple C, Steel M. Phylogenetics. Oxford lecture series in mathematics. Oxford: Oxford University Press; 2003.
15. Daniel P, Semple C. Supertree algorithms for nested taxa. In: Bininda-Emonds ORP, editor. Phylogenetic supertrees: combining information to reveal the tree of life. Dordrecht: Kluwer; 2004. pp. 151–171.
16. Berry V, Semple C. Fast computation of supertrees for compatible phylogenies with nested taxa. Syst Biol. 2006;55(2):270–288. doi: 10.1080/10635150500541649. [PubMed] [Cross Ref]
17. Bryant D, Lagergren J. Compatibility of unrooted phylogenetic trees is FPT. Theor Comput Sci. 2006;351:296–302. doi: 10.1016/j.tcs.2005.10.033. [Cross Ref]
18. Smith SA, Brown JW, Hinchliff CE. Analyzing and synthesizing phylogenies using tree alignment graphs. PLoS Comput Biol. 2013;9(9):1003223. doi: 10.1371/journal.pcbi.1003223. [PMC free article] [PubMed] [Cross Ref]
19. Pe’er I, Pupko T, Shamir R, Sharan R. Incomplete directed perfect phylogeny. SIAM J Comput. 2004;33(3):590–607. doi: 10.1137/S0097539702406510. [Cross Ref]
20. Holm J, de Lichtenberg K, Thorup M. Poly-logarithmic deterministic fully-dynamic algorithms for connectivity, minimum spanning tree, 2-edge, and biconnectivity. J ACM. 2001;48(4):723–760. doi: 10.1145/502090.502095. [Cross Ref]
21. Even S, Shiloach Y. An on-line edge-deletion problem. J ACM. 1981;28(1):1–4. doi: 10.1145/322234.322235. [Cross Ref]
22. Thorup M. Near-optimal fully-dynamic graph connectivity. In: Proceedings of the 32nd annual ACM symposium on theory of computing. ACM; 2000. p. 343–350.

Articles from Algorithms for Molecular Biology : AMB are provided here courtesy of BioMed Central