def nRankedHistoriesCladeOnlyRoot(n, c) : """ Number of ranked histories of a labeled tree with a total of n+c taxa, where the common ancestor of taxa from c taxa is the root. """ return prod([k*(k+1)//2L for k in range(2,c)]) * \ prod([k*(k+3)//2L for k in range(c-1,n+c-1)])
def numberOfLabeledForests(forest) : """ Number of labeled ranked forests having the same unranked topology as forest.""" # number of ranked possibilities for each tree z = [_LHsize(x) for x in forest] # prune single lineages u = [(n,k) for n,k in z if n > 0] # same logic as for a single tree n,k = sum([x[0] for x in u]), prod([x[1] for x in u]) return fac(n)//k
def _LHsize(p) : """ Number of labeled ranked histories of trees with the same unranked topology as p. Result is returned indirectly as a pair (n,s), where n is the number of internal nodes and s is the number of ranked topologies which map to a single unranked topology. Therefore the result is n!/s. """ # leaf - no internal nodes, 1 to 1 mapping # allow string leafs (i.e. anything which is not a list is a leaf) isl = isinstance(p, list) if isl and len(p) == 1 or not isl : return (0,1) # get counts from all trees in forest q = [_LHsize(x) for x in p] #total number of internal nodes in tree s = sum([x[0] for x in q])+1 #s! ways to arrange, removed multiple counting return s, s * prod([x[1] for x in q])
def nForestRankedTopologies(n1, n2, k) : """ Number of ranked histories of a labeled forest with 1+k trees, the first tree on n1 taxa, the remaining k on a total of n2 taxa. """ return choose(n1+n2-k-2, n1-2) * prod([long(c2(x)) for x in range(3, n1+1) + range(k+1, n2+1)])
def nRankedCombineWithClade(nc, no) : """ Number of ranked ways no taxa can be combined with a nc taxa tree into a tree. """ return prod([k*(k+nc) for k in range(2,no+1)]) // 2L**(no-1) \ if no > 0 else 1
def nLabeledHistories(n, k=1) : """ Total number of ranked histories of (labeled) k-forests with total of n tips.""" assert n >= k return prod([long(c2(x)) for x in range(n, k, -1)])