RError.com

RError.com Logo RError.com Logo

RError.com Navigation

  • 主页

Mobile menu

Close
  • 主页
  • 系统&网络
    • 热门问题
    • 最新问题
    • 标签
  • Ubuntu
    • 热门问题
    • 最新问题
    • 标签
  • 帮助
主页 / 问题 / 753397
Accepted
Viktor Tomilov
Viktor Tomilov
Asked:2020-12-04 13:29:46 +0000 UTC2020-12-04 13:29:46 +0000 UTC 2020-12-04 13:29:46 +0000 UTC

在生物信息学中加载树木。第 1 部分。精确搜索

  • 772

该主题是作为讨论线程创建的。它提出了几个问题,因此您可以同时回答所有问题和其中一个问题。我给出了一些问题的答案,而不是它是正确的事实。如果有很多兴趣,您可以尝试组织聊天进行讨论。

生物信息学中最常见的任务:在字符串中查找子字符串。在大多数情况下,这是以一种标准方式实现的,不需要大量资源,也不值得详细考虑。但是,在我看来,有一类问题可以通过使用加载的树来加速/简化。
在本主题中,我们将仅考虑精确搜索。

术语解释:

参考:一个长的 DNA 序列,通常包含部分染色体或整个染色体/基因组的转录本。表示(通常)由 A、G、T、C(表示不同的核苷酸)和 N 组成的字符串 - 一个字符,表示任何核苷酸,或不存在确切信息。示例:AAGGCCTCGTCNTTNNGCCC...
模式(或读取):一个短的 DNA 序列,一个包含与上述相同字符的字符串,长度从 1(当然没有意义,但它发生)到几千的合理值。我们主要处理 30 到 300 个字母的长度,但还有其他任务。
回文-互补字符串,即 根据特殊规则倒序(从末尾读取字符串,按规则替换字母:A -> T,C -> G,G -> C,T -> A,N -> N)

对于航班的分析,我们将考虑人类第8条染色体作为参考(A:43333530,C:29030173,G:29103787,T:43300646,N:370500条,总共145138636个字母)。为简单起见,读取长度为 100 个字母。

马上我会告诉我我将在 Delphi 上编写代码。总的来说,我不在乎 - Delphi、c++、c# 或 java,但 Delphi 对我来说更熟悉。

问题 1. 创建树形结构。类或链表。

2个树实现选项:

班级

  type
    AGTCIndex = (A, C, G, T);
  TTrie = class
     fAmI: integer; // кто я - на всякий случай
     fParent: TTrie; // ссылка на родительский узел
     fChildren:array[AGTCIndex] of TTrie; // ссылка на узлы потомков
     fCount: array of longint; // для адресации 145 миллионов хватит. Вот если бы работали с геномом секвойи, стоило бы использовать int64 :)
     <...>
   end;

或链表

  type
    AGTCIndex = (A, C, G, T);
    pTrie = ^TTrie;
    TTrie = record
     fAmI: integer; // кто я - на всякий случай
     fParent: pTrie; // ссылка на родительский узел
     fChildren:array[AGTCIndex] of pTrie; // ссылка на узлы потомков
     fCount: array of longint; 
   end;

在我看来,链表更适合我们的任务:内存消耗更少,工作速度更快(我们不要在不必要的调用上浪费时间)。当然,为方便起见,我们将列表包装在一个类中。

问题二、内存消耗

在标准方法中,将花费 145 戈比的内存——这就是一条线需要多少。您可以使用半字节表示(描述及其工作原理)来欺骗和使用 2 倍。

在使用树的情况下,成本将至少为 100 * 145138636 * 16 或至少 230 GB。一切,羊皮得不偿失。可以使用的最大值为 32 GB。我们得出结论,只要参考的长度不超过 1600 万,这种方法是适用的。
原则上,这里也实现了半字节的方法。它甚至可以带来超过 2 倍的收益。但恐怕带来的不便多于好处。如果有其他意见 - 请提出意见。

问题3:精细的搜索性能

在标准方法中,在参考中找到所有包含的模式大约需要 |length(reference)*ln(length(pattern)|。如果并行化,那么内核每增加一倍大约要快 1.6 倍。

在使用树的情况下,根据我的计算,只有在前额上至少需要 O(100 * 长度)才能进行构造。使用阅读框可以减少到 O(30*length)。并行方法还将内核每增加一倍,该过程就会加快 1.6 倍。

总的来说,我们有:创建一棵树比使用标准方法搜索一个模式要多花大约 500 到 1000 倍的时间。但是,由于在已经形成的树中搜索要快得多,而且它允许您并行获取额外的数据,所以我们有: 当引用被重复使用时,创建树的好处是实现的,并且用于不同的模式。评价:至少500次。适用范围:精确映射、仪器数据的流式处理等。

没错,互补搜索存在一个小问题。事实上,我们将不得不从孩子到父母,这会有点慢。

如果主题很有趣,您可以继续进行模糊搜索,这通常更相关和更有趣。

更新 1

创建了一个聊天室

更新 2

**相对于按位表示。大声推理(几乎与树木无关)**

为什么不节省内存和时间,并使用半字节甚至四分之一字节表示?
- 我不确定。我还没有遇到过使用类似方法的单一 GNU 软件(关于付费软件 - 见下文)。所有人都否认兼容性和不愿意为按位工作编写复杂的例程。而最近他们也回答——“内存降价了”。

  • 我对为什么每个人都不使用按位方法的看法:

    1. 兼容性并不是特别重要。毕竟,无损转换:您可以随时转换回来。但!通常,相同的程序不仅用于在 DNA 内进行搜索,还用于在蛋白质序列、基因依赖性等内进行搜索。在那里 - 拉丁字母是不够的。

    2. AGTC 是一个非常特殊的情况。还有甲基化核苷酸、双脱氧核苷酸、“可疑”核苷酸等等。那些。“字母”远不止 4 个字母。因此,例程是“为一切”创建的。

在上面的第一个链接上,我举了一个使用半字节表示的例子,我在 2004 年“开发”了一个完整的基因组 triter(Windows 下的第一个 - 我有点自豪:))是创建于 2006 年。然后内存很少,处理器非常愚蠢。主要思想:A=0001b,C=0010b,G=0100b,T=1000b。然后掩码非常成功地叠加在一次搜索多个选项上:N = 1111b、R(A 或 G)= 0101b、Y(C 或 T)= 1010b 等。在 SSE2 中实现了一个大字(64 或 128 位)的半字节移位,它允许您一次处理多达 32 个字母。
所以,关于这个实现,我怀疑这种方法至少用在一个商业包中:) 但是,我并不感到抱歉,特别是因为这种方法是表面上的。

更新 3

发布了问题的第二部分:生物信息学中的加载树。第 2 部分。模糊搜索

java
  • 4 4 个回答
  • 10 Views

4 个回答

  • Voted
  1. Best Answer
    Mike
    2020-12-06T17:03:36Z2020-12-06T17:03:36Z

    树已经很好地证明了自己,因为在只有可能键的子集的情况下,它们具有相当经济的内存消耗。假设我们需要在 3 个级别上制作一棵树。如果我们只有 AAA、ACA、GCC 选项,我们将在第一级只有两个节点“A”和“G”,在第二级有 3 个节点,“A”、“C”(对于 A)、“C” '(对于 G)和第三级 3 节点。3个核苷酸有64个可能的关键选择,总共8个节点是一个很好的结果。

    现在让我们对第 8 条染色体的文本进行统计分析……我们主要感兴趣的是所有可能的键值与真实键值的比率。参考文献中多达 11 个字母序列,几乎存在所有可能的核苷酸排列变体。在 11 个字母中,在 400 万个可能的值中,只有 24 万个缺失(约 6%)。那些。我们需要为 11 个核苷酸的索引链创建大约 400 万个节点。

    同时,通过制作类型化数组 ( of TTrie),您可能假设链接将存储在那里。引用是指向进程内存中地址的指针。如果您创建一个索引并立即使用它,那么一切都会好起来的。但是索引成本很高,能够将其存储在磁盘上会很好。但是你不能把地址放在磁盘上的物理内存中,你需要以某种方式序列化对象,当从磁盘读取时,用物理地址重新创建它们......此外,如果为每个对象单独分配内存,那么内存经理开销出现。结果,一个节点不会像您建议的那样花费您 16 个字节,而最多花费 30 个字节...

    因此,对于第一个问题“上述哪种存储方法更好”的答案不是以上任何一种。你自己回答了第二个问题——内存成本太疯狂了。在第三个问题中,问题本身是缺失的,这是对索引将花费大量时间的事实的陈述(顺便说一下,通过“O”进行的评估过于近似。考虑到维护此类的间接费用)语言结构)

    结合上述内容,我得出的结论是,存储这种树的初始级别的唯一紧凑方法是一个带有指向 400 万个可能键的指针的公共数组。其中只有 6% 的元素是空的。表中的索引将是由 11 个字母组成的键,以数字系统表示,其基数与字母表的大小相同(在我们的例子中,每个字母 2 位)。在文本中单个 N 的情况下,我们将它们视为所有 4 个可能的键。我们将存储多于一个 N 的区域作为区域列表(在考虑的第 8 条染色体示例中,只有 12 个这样的区域)。数组中的指针可以指向“继续”那些 11 个字符序列的树节点。或者,例如,直接到遇到此类序列的地址列表。仅对于某些键,列表非常大(11 A 和 11 T 分配有 106k 个条目)。总共有大约 740 个密钥(400 万个),包含 3000 多个地址列表。

    我使用上述方法实现了索引和搜索。在指针后面,我直接存储地址列表,在搜索时,我使用它们的快速比较(指针的并行、同步移位)。他提供了 N 区域的工作,但直到最后都没有开始实施。主索引所需的内存为 32 MB。为了存储地址列表,每个地址使用 4 个字节,即 参考长度 * 4。对于 141MB 的输入文件,索引文件的总大小为 581MB。索引时间(对于 2 次参考通过)约为 30 秒(包括刷新到磁盘)。顺便说一句,这样的索引可以用来快速构建树。搜索算法没有优化,一个核心每秒只能处理大约 10-15000 个请求。免费搜索也没有实现,我看到这样一个选项,如何为互补键创建一个 16 Mb 的转换表,并通过相同的索引进行搜索,并将模式中的偏移量重新计算为相反的顺序。资源:索引、搜索(由 gcc 在 linux 下构建)

    • 7
  2. santavital
    2020-12-04T15:18:13Z2020-12-04T15:18:13Z

    鉴于在这种特殊情况下,关键点(在我看来)是数据的大小,我建议优化这个特殊因素;(为了分析航班,我们将考虑人类第8条染色体作为参考(A:43333530,C:29030173,G:29103787,T:43300646,N:370500条,总共145138636个字母))让我们创建五个数组A , C, G, T, N 维度为 145138636 位 ... 对应数组中的第 1 位表示该位置存在核苷酸;

    • 4
  3. Barmaley
    2020-12-04T18:17:29Z2020-12-04T18:17:29Z

    我会建议以下方式。由于只有4个核苷酸:A, C, G, T和+第五个不定核苷酸N,那么基于逻辑上的5-teric数字系统本身就0=A, 1=C, 2=G, 3=T, 4=N可以分别将包含1.45亿个序列的第8条染色体编码为5-teric number,占据145/ 8 * 5 内存百万 = 90 兆字节。

    在这种情况下,对子字符串的搜索会退化为对 5 位掩码的搜索

    在Java中,这相对容易实现BigInteger

    • 1
  4. Vlad Chapl
    2020-12-05T17:33:06Z2020-12-05T17:33:06Z

    我会给出一个更有趣的方向:模糊搜索。也许你还没有看到这个https://habrahabr.ru/post/115147/方法(“MinHash - 识别相似集合”)。如果我们稍微修改一下,考虑人类基因组有很多很多与单词重叠的窗口,那么在索引之后我们可以相对快速地搜索到我们需要的窗口(这不一定是完全匹配的)。这种方法也适用于SQL,虽然我的速度不是很快。(即最好提前计算计算复杂度。)

    • 1

相关问题

Sidebar

Stats

  • 问题 10021
  • Answers 30001
  • 最佳答案 8000
  • 用户 6900
  • 常问
  • 回答
  • Marko Smith

    Python 3.6 - 安装 MySQL (Windows)

    • 1 个回答
  • Marko Smith

    C++ 编写程序“计算单个岛屿”。填充一个二维数组 12x12 0 和 1

    • 2 个回答
  • Marko Smith

    返回指针的函数

    • 1 个回答
  • Marko Smith

    我使用 django 管理面板添加图像,但它没有显示

    • 1 个回答
  • Marko Smith

    这些条目是什么意思,它们的完整等效项是什么样的

    • 2 个回答
  • Marko Smith

    浏览器仍然缓存文件数据

    • 1 个回答
  • Marko Smith

    在 Excel VBA 中激活工作表的问题

    • 3 个回答
  • Marko Smith

    为什么内置类型中包含复数而小数不包含?

    • 2 个回答
  • Marko Smith

    获得唯一途径

    • 3 个回答
  • Marko Smith

    告诉我一个像幻灯片一样创建滚动的库

    • 1 个回答
  • Martin Hope
    Air 究竟是什么标识了网站访问者? 2020-11-03 15:49:20 +0000 UTC
  • Martin Hope
    Алексей Шиманский 如何以及通过什么方式来查找 Javascript 代码中的错误? 2020-08-03 00:21:37 +0000 UTC
  • Martin Hope
    Qwertiy 号码显示 9223372036854775807 2020-07-11 18:16:49 +0000 UTC
  • Martin Hope
    user216109 如何为黑客设下陷阱,或充分击退攻击? 2020-05-10 02:22:52 +0000 UTC
  • Martin Hope
    Qwertiy 并变成3个无穷大 2020-11-06 07:15:57 +0000 UTC
  • Martin Hope
    koks_rs 什么是样板代码? 2020-10-27 15:43:19 +0000 UTC
  • Martin Hope
    user207618 Codegolf——组合选择算法的实现 2020-10-23 18:46:29 +0000 UTC
  • Martin Hope
    Sirop4ik 向 git 提交发布的正确方法是什么? 2020-10-05 00:02:00 +0000 UTC
  • Martin Hope
    faoxis 为什么在这么多示例中函数都称为 foo? 2020-08-15 04:42:49 +0000 UTC
  • Martin Hope
    Pavel Mayorov 如何从事件或回调函数中返回值?或者至少等他们完成。 2020-08-11 16:49:28 +0000 UTC

热门标签

javascript python java php c# c++ html android jquery mysql

Explore

  • 主页
  • 问题
    • 热门问题
    • 最新问题
  • 标签
  • 帮助

Footer

RError.com

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

帮助

© 2023 RError.com All Rights Reserve   沪ICP备12040472号-5