汉明距离的逆

时间:2013-11-12 22:16:19

标签: python string algorithm bioinformatics hamming-distance

*这是一个简短的介绍,具体问题在最后一段以粗体显示。

我试图生成具有给定汉明距离的所有字符串,以有效地解决生物信息学分配。

这个想法是,给定一个字符串(即' ACGTTGCATGTCGCATGATGCATGAGAGCT'),搜索单词的长度(即4)以及在字符串中搜索该单词时可接受的不匹配(即1) ),返回最频繁的单词或“变异”字样。词语的

要清楚,给定字符串中的长度为4的单词可以是这个(在' []'之间):

[ACGT]TGCATGTCGCATGATGCATGAGAGCT #ACGT

A[CGTT]GCATGTCGCATGATGCATGAGAGCT #CGTT

或者

ACGTTGCATGTCGCATGATGCATGAG[AGCT] #AGCT

我所做的是(并且它的效率非常低,而且当单词需要有10个字符时它真的很慢)会生成具有给定距离的所有可能的单词:

itertools.imap(''.join, itertools.product('ATCG', repeat=wordSize))

然后搜索并比较给定字符串中的每个单词,如果生成的单词(或其变异)出现在循环中:

wordFromString = givenString[i:i+wordSize]
mismatches = sum(ch1 != ch2 for ch1, ch2 in zip(wordFromString, generatedWord))
if mismatches <= d:
    #count that generated word in a list for future use
    #(only need the most repeated)

我想要做的是,不是生成所有可能的单词,而是仅生成给定字符串中出现的具有给定数量的不匹配的单词的突变,换句话说,给出汉明距离和单词,返回所有可能的具有该(或更小)距离的变异单词,然后使用它们在给定字符串中进行搜索。

我希望我很清楚。谢谢。

6 个答案:

答案 0 :(得分:18)

def mutations(word, hamming_distance, charset='ATCG'):
    for indices in itertools.combinations(range(len(word)), hamming_distance):
        for replacements in itertools.product(charset, repeat=hamming_distance):
            mutation = list(word)
            for index, replacement in zip(indices, replacements):
                mutation[index] = replacement
            yield "".join(mutation)

此函数生成汉明距离小于或等于给定数字的单词的所有突变。它相对有效,并且不检查无效的单词。但是,有效突变可以出现不止一次。如果您希望每个元素都是唯一的,请使用设置

答案 1 :(得分:5)

让给定的汉明距离为 D ,让 w 为“word”子串。从 w ,您可以通过深度限制depth-first search生成距离≤ D 的所有单词:

def dfs(w, D):
    seen = set([w])      # keep track of what we already generated
    stack = [(w, 0)]

    while stack:
        x, d = stack.pop()
        yield x

        if d == D:
            continue

        # generate all mutations at Hamming distance 1
        for i in xrange(len(x)):
            for c in set("ACGT") - set(x[i])
                 y = x[:i] + c + x[i+1:]
                 if y not in seen:
                     seen.add(y)
                     stack.append((y, d + 1))

(这绝不会很快,但它可以作为灵感。)

答案 2 :(得分:5)

如果我正确理解您的问题,您需要确定基因组G中得分最高的k-mers。 k-mer的分数是它在基因组中出现的次数加上汉明距离小于m的任何k-mer也出现在基因组中的次数。请注意,这假设您只对基因组中出现的k-mers感兴趣(正如@j_random_hacker所指出的那样)。

您可以通过四个基本步骤解决此问题:

  1. 识别基因组中的所有k-mers G
  2. 计算每个k-mer出现在G中的次数。
  3. 对于k-mers的每对(K1K2),如果汉明距离小于{{1},则增加K1K2的计数}}。
  4. 找到m k-mer及其计数。
  5. 以下是Python代码示例:

    max

答案 3 :(得分:2)

以下是我认为您要解决的问题是:您有一个长度为n的“基因组”,并且您希望在此基因组中找到最常出现的k-mer,其中“大约出现” “表示汉明距离&lt; = d。这个k-mer实际上不需要在基因组中的任何地方完全(例如对于基因组ACCA,k = 3和d = 1,最好的k聚体是CCC,出现两次)。

如果您从字符串中的某个k-mer生成汉明距离&lt; = d的所有k-mers,然后在字符串中搜索每个k-me,就像您现在正在做的那样,那么您添加了一个不必要的搜索时间的O(n)因子(除非你使用the Aho-Corasick algorithm同时搜索所有这些因素,但这在这里是过度的。)

你可以通过遍历基因组做得更好,并且在每个位置i,从基因组中的位置i开始生成距离k-mer距离<= d的所有k聚体的集合,并且递增每个人的柜台。

答案 4 :(得分:1)

def generate_permutations_close_to(initial = "GACT",charset="GACT"):
    for i,c in enumerate(initial):
         for x in charset:
             yield initial[:i] + x + inital[i+1:]

将生成dist为1的排列(它也将重复包含重复)

获取2中的所有内容...然后将每个第一个解决方案称为初始猜测

答案 5 :(得分:0)

这里有正确的答案,它们大量利用了python的神奇功能,几乎可以为你做任何事情。我将尝试用数学和算法来解释事物,以便您可以将它应用于您想要的任何语言。

因此,您的案例{a1, a2, ... a_a}中有一个字母a{'A', 'C', 'G', 'T'}的基数),基数为4.您有一个长度为k的字符串,而您想要生成汉明距离小于或等于d的所有字符串。

首先,你有多少人?答案不依赖于您选择的字符串。如果您选择了一个刺痛,您将拥有C(d, k)(a-1)^d个字符串,其字符串的汉明距离为d。所以字符串的总数是:

enter image description here

它几乎每个参数都呈指数级增长,所以你不会有任何类型的快速算法来查找所有的单词。

那么你将如何得到一个能够生成所有字符串的算法呢?请注意,很容易生成一个字符串,该字符串距离您的最多一个汉明距离。您只需要迭代字符串中的所有字符,并为每个字符尝试字母表中的每个字母。正如您将看到的,一些单词将是相同的。

现在要生成距离字符串两个汉明距离的所有字符串,您可以应用相同的函数,为前一次迭代中的每个单词生成一个汉明距离字。

所以这是一个伪代码:

function generateAllHamming(str string, distance int): 
    alphabet = ['A', ...]// array of letters in your alphabet
    results = {} // empty set that will store all the results
    prev_strings = {str} // set that have strings from the previous iterations
    // sets are used to get rid of duplicates

    if distance > len(str){ distance = len(str)} // you will not get any new strings if the distance is bigger than length of the string. It will be the same all possible strings.

    for d = 0; d < distance; d++ {
        for one_string in prev_strings {
            for pos = 0; pos < len(one_string); pos++ {
                for char in alphabet {
                    new_str = substitute_char_at_pos(one_string, char, pos)
                    add new_str to set results 
                }
            }
        }

        populate prev_strings with elements from results
    }

    return your results
}