如何为给定外群的一组物种生成所有可能的纽维克树排列?

2023-12-31

如何为给定外群的一组物种生成所有可能的纽维克树排列?

对于那些不知道什么是 Newick 树格式的人,可以在以下位置找到一个很好的描述:https://en.wikipedia.org/wiki/Newick_format https://en.wikipedia.org/wiki/Newick_format

我想为给定外群的一组物种创建所有可能的纽维克树排列。我期望处理的叶节点数量很可能是 4、5 或 6 个叶节点。

“软”和“硬”多瓣都是允许的。https://en.wikipedia.org/wiki/Polytomy#Soft_polytomies_vs._hard_polytomies https://en.wikipedia.org/wiki/Polytomy#Soft_polytomies_vs._hard_polytomies https://biology.stackexchange.com/questions/23667/evidence-discussions-of-hard-polytomy https://biology.stackexchange.com/questions/23667/evidence-discussions-of-hard-polytomy

下面显示的是理想的输出,其中“E”设置为外群

理想输出:

((("A","B","C"),("D"),("E"));
((("A","B","D"),("C"),("E"));
((("A","C","D"),("B"),("E"));
((("B","C","D"),("A"),("E"));
((("A","B")("C","D"),("E"));
((("A","C")("B","D"),("E"));
((("B","C")("A","D"),("E"));
(("A","B","C","D"),("E"));
(((("A","B"),"C"),"D"),("E"));

然而,我使用 itertools 提供的任何可能的解决方案,特别是 itertools.permutations,都遇到了等效输出的问题。我想到的最后一个想法涉及如下所示的等效输出。

等效输出:

((("C","B","A"),("D"),("E"));
((("C","A","B"),("D"),("E"));
((("A","C","B"),("D"),("E"));

这是我的解决方案想法的开始。但是,除了 itertools 之外,我现在不太确定如何解决这个问题。

import itertools

def Newick_Permutation_Generator(list_of_species, name_of_outgroup)
    permutations_list =(list(itertools.permutations(["A","B","C","D","E"])))

    for given_permutation in permutations_list:
        process(given_permutation)

Newick_Permutation_Generator(["A","B","C","D","E"], "E")

作为叶子集合的递归集合的树

让我们暂时搁置 newick 表示,并考虑该问题的可能的 python 表示。

一棵有根的树可以被视为一棵集合的递归层次结构(组(组...))叶子。集合是无序的,这非常适合描述树中的分支:{{{"A", "B"}, {"C", "D"}}, "E"}应该是一样的{{{"C", "D"}, {"B", "A"}}, "E"}.

如果我们考虑初始的叶子集{"A", "B", "C", "D", "E"},以“E”为外群的树是以下形式的集合的集合{tree, "E"} where trees 取自可以从叶子集合构建的树集合{"A", "B", "C", "D"}。我们可以尝试写一个递归trees函数来生成这组树,我们的总树集将表示如下:

{{tree, "E"} for tree in trees({"A", "B", "C", "D"})}

(这里,我使用的是集合理解 https://en.wikipedia.org/wiki/List_comprehension#Set_comprehension符号。)

实际上,python 不允许集合的集合,因为集合的元素必须是“可散列的”(也就是说,python 必须能够计算对象的一些“散列”值,以便能够检查它们是否属于集)。碰巧Python集合没有这个属性。幸运的是,我们可以使用一个类似的数据结构,名为frozenset https://docs.python.org/3/library/stdtypes.html#frozenset,其行为非常像一个集合,但无法修改并且是“可散列的”。因此,我们的树集将是:

all_trees = frozenset(
    {frozenset({tree, "E"}) for tree in trees({"A", "B", "C", "D"})})

实施trees功能

现在让我们重点关注trees功能。

对于每一个可能的分割(分解为一组不相交的子集,包括所有元素)的叶子集,我们需要为分区的每个部分找到所有可能的树(通过递归调用)。对于给定的分区,我们将为跨其各个部分的子树的每个可能组合创建一棵树。

例如,如果一个分区是{"A", {"B", "C", "D"}},我们将考虑可以由部分组成的所有可能的树"A"(其实只是叶子"A"本身),以及可以由部分组成的所有可能的树{"B", "C", "D"}(那是,trees({"B", "C", "D"}))。然后,通过获取其中一个元素仅来自的所有可能对来获得该分区的可能树"A",另一个来自trees({"B", "C", "D"}).

这可以推广到具有两个以上部分的分区,并且product函数来自itertools这里似乎很有用。

因此,我们需要一种方法来生成一组叶子的可能分区。

生成集合的分区

这里我做了一个partitions_of_set函数改编自这个解决方案 https://stackoverflow.com/a/30134039/1878788:

# According to https://stackoverflow.com/a/30134039/1878788:
# The problem is solved recursively:
# If you already have a partition of n-1 elements, how do you use it to partition n elements?
# Either place the n'th element in one of the existing subsets, or add it as a new, singleton subset.
def partitions_of_set(s):
    if len(s) == 1:
        yield frozenset(s)
        return
    # Extract one element from the set
    # https://stackoverflow.com/a/43804050/1878788
    elem, *_ = s
    rest = frozenset(s - {elem})
    for partition in partitions_of_set(rest):
        for subset in partition:
            # Insert the element in the subset
            try:
                augmented_subset = frozenset(subset | frozenset({elem}))
            except TypeError:
                # subset is actually an atomic element
                augmented_subset = frozenset({subset} | frozenset({elem}))
            yield frozenset({augmented_subset}) | (partition - {subset})
        # Case with the element in its own extra subset
        yield frozenset({elem}) | partition

为了检查获得的分区,我们创建一个函数来使它们更容易显示(这对于稍后创建树的 newick 表示也很有用):

def print_set(f):
    if type(f) not in (set, frozenset):
        return str(f)
    return "(" + ",".join(sorted(map(print_set, f))) + ")"

我们测试分区是否有效:

for partition in partitions_of_set({"A", "B", "C", "D"}):
    print(len(partition), print_set(partition))

Output:

1 ((A,B,C,D))
2 ((A,B,D),C)
2 ((A,C),(B,D))
2 ((B,C,D),A)
3 ((B,D),A,C)
2 ((A,B,C),D)
2 ((A,B),(C,D))
3 ((A,B),C,D)
2 ((A,D),(B,C))
2 ((A,C,D),B)
3 ((A,D),B,C)
3 ((A,C),B,D)
3 ((B,C),A,D)
3 ((C,D),A,B)
4 (A,B,C,D)

实际代码trees功能

现在我们可以写出tree功能:

from itertools import product
def trees(leaves):
    if type(leaves) not in (set, frozenset):
        # It actually is a single leaf
        yield leaves
        # Don't try to yield any more trees
        return
    # Otherwise, we will have to consider all the possible
    # partitions of the set of leaves, and for each partition,
    # construct the possible trees for each part
    for partition in partitions_of_set(leaves):
        # We need to skip the case where the partition
        # has only one subset (the initial set itself),
        # otherwise we will try to build an infinite
        # succession of nodes with just one subtree
        if len(partition) == 1:
            part, *_ = partition
            # Just to be sure the assumption is correct
            assert part == leaves
            continue
        # We recursively apply *tree* to each part
        # and obtain the possible trees by making
        # the product of the sets of possible subtrees.
        for subtree in product(*map(trees, partition)):
            # Using a frozenset guarantees
            # that there will be no duplicates
            yield frozenset(subtree)

测试它:

all_trees = frozenset(
    {frozenset({tree, "E"}) for tree in trees({"A", "B", "C", "D"})})

for tree in all_trees:
    print(print_set(tree) + ";")

Output:

(((B,C),A,D),E);
((((A,B),D),C),E);
((((B,D),A),C),E);
((((C,D),A),B),E);
(((A,D),B,C),E);
((A,B,C,D),E);
((((B,D),C),A),E);
(((A,B,C),D),E);
((((A,C),B),D),E);
((((C,D),B),A),E);
((((B,C),A),D),E);
(((A,B),C,D),E);
(((A,C),(B,D)),E);
(((B,D),A,C),E);
(((C,D),A,B),E);
((((A,B),C),D),E);
((((A,C),D),B),E);
(((A,C,D),B),E);
(((A,D),(B,C)),E);
((((A,D),C),B),E);
((((B,C),D),A),E);
(((A,B),(C,D)),E);
(((A,B,D),C),E);
((((A,D),B),C),E);
(((A,C),B,D),E);
(((B,C,D),A),E);

我希望结果是正确的。

这种方法要正确执行有点棘手。我花了一些时间才弄清楚如何避免无限递归(当分区时会发生这种情况){{"A", "B", "C", "D"}}).

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何为给定外群的一组物种生成所有可能的纽维克树排列? 的相关文章

随机推荐

  • 冲突的类型和先前的 x 声明在这里......什么?

    当我有时间的时候 我已经自学了几个月的 C 语言 但我遇到了一个我不知道如何解决的问题 具体来说 当我尝试使用 gcc 编译它时 我得到 geometry c 8 error conflicting types for trapezoid
  • 来自带有时区和夏令时的字符串的 Qt QDateTime

    我正在从字符串插入时间 QDateTime time QDateTime fromString Wed Mar 26 22 37 40 2019 GMT 08 qDebug lt
  • 从通知区域发出的卡通语音气泡叫什么?如何创建一个?

    谁能告诉我以下弹出窗口的名称是什么 如何为我的应用程序创建这样的弹出窗口 To be more specific this is indeed called a Notification http msdn microsoft com en
  • Clojure中如何加载程序资源

    如何在 Clojure 程序中加载图标 字符串 图形元素 脚本等程序资源 我使用的项目布局类似于许多 Java 项目中的布局 其中有一个 资源 目录挂在 源 目录下 jar 文件是从源代码创建的并包含资源 但我似乎无法像在 Java 中那样
  • 将 JWK json 转换为公钥 golang (lestrrat-go)

    我使用 JWKS 格式从身份验证服务提供公钥 该公钥可用于验证来自该身份验证服务的令牌 但是 要执行验证 我需要从 JWK 重建公钥 我该如何转换它 type JWKeys struct Keys JWKey json keys type
  • 多选到数组

  • 使用 SharePoint 客户端对象模型检查列表列是否存在?

    使用 SharePoint 2010 中的客户端对象模型 C 如何确定给定列表中是否存在指定的列 字段 名称 谢谢 魔术安迪 刚刚在搜索相同的东西时发现了这个 但看起来 Sharepoint 2010 有内置的东西 至少对于服务器模型 li
  • 图像未通过 android webview 加载

    我有一个加载网页的网络视图 有时该网页中有图片 但是 我遇到了 2 个图像无法加载的情况 并且每个情况都给出了不同的结果 结果 1 网页已加载 但图像未加载 使用的格式 jpeg 结果 2 网页已加载 但图像未加载 然而 在该图像所在的位置
  • 转义保留字

    Sitecore 提供了一种转义 Sitecore 查询中包含不喜欢字符的单词的方法 此类字符包括连字符和空格 为了简化我的生活 我编写了一个简单的辅助函数 可以转义 Sitecore 查询的每个部分 并且它运行良好一段时间 public
  • Spring Security仅用于授权。外部认证

    正如标题所述 我正在开发一个 Web 应用程序 该应用程序从外部应用程序接收用户身份验证信息 我的应用程序的弹簧控制器获取用户信息并将其存储在会话中 我想在 Spring Security 中对这个用户进行身份验证 然后使用他的角色授予 拒
  • 获取作为输入文本字段的数据表单元格值

    我正在使用 javascript 数据源生成 DataTable 这data从对 nodejs 的 ajax 调用返回 该调用查询 SQL Server DB 表并返回 2 列 均为数值数据 我再添加 2 列来保存输入字段 默认值为 0 以
  • IP 本地化:映射 ip->location 随着时间的推移而固定?

    我正在管理一个网络平台 想要获取一些统计数据 了解我的用户来自哪里 我可以存储远程 IP 并且我知道有本地化服务可以将 IP 映射到地理位置 这个映射是如何完成的 是否有固定的表 哪个IP地址分配给哪个地区 我必须在访问时请求映射还是可以在
  • 如何禁用或忽略 Dependabot 拉取请求?

    我们希望使用 Dependabot 来了解更新的依赖项 但我们不希望 Dependabot 自行创建拉取请求 也不希望自动构建 我们使用 GitHub 进行代码 使用 Azure DevOps 进行构建 文档中没有明确的提示 https d
  • 生成密码重置密码

    我正在做一个允许用户重置密码的模块 我注意到大多数网站都提供了一个确认链接 其中包含具有唯一哈希值的查询字符串 我的问题是 每次同一用户请求忘记密码时 如何生成这个唯一的哈希值 我应该将此哈希存储在数据库中并稍后使用它进行验证吗 会安全吗
  • 在 SQL Server 中强制部分连接顺序

    Edit 人们很难理解我想要什么 这里有一些漂亮的图片 详细地解释了它 首次加入交易 to Strange 到目前为止的结果 Customer Invoice TransactionID Mass Length LeptonNumber I
  • C++ 参数传递查询(包括代码示例和输出)

    我再次来到这里是因为 C 的课程材料根本没有教得很好 该问题给出了使用几个函数定义和对这些函数的调用 并期望我们说明输出以及到底发生了什么 我已经执行了这些功能 并试图对正在发生的事情提出一些理由 但如果有人可以帮助我 我将非常感激 函数定
  • 如何从列表理解而不是嵌套列表中获得平坦的结果?

    我有一个清单A 和一个函数f其中需要一个项目A并返回一个列表 我可以使用列表理解来转换所有内容A like f a for a in A 但这会返回一个列表列表 假设我的输入是 a1 a2 a3 导致 b11 b12 b21 b22 b31
  • 是否可以保存一组断点?

    我有一组断点 用于调试一个问题 当我想调试其他东西时 这些断点很烦人 所以我需要禁用 删除它们 但是 我觉得我可能希望稍后能够重新创建第一组断点 是否可以保存所有当前活动的断点 以便只需一次操作即可在不同组断点之间切换 如果我有 30 个断
  • 安装 ffi 时出错

    似乎可以解决这个问题 gem install ffi Building native extensions This could take a while ERROR Error installing ffi ERROR Failed to
  • 如何为给定外群的一组物种生成所有可能的纽维克树排列?

    如何为给定外群的一组物种生成所有可能的纽维克树排列 对于那些不知道什么是 Newick 树格式的人 可以在以下位置找到一个很好的描述 https en wikipedia org wiki Newick format https en wi