【问题标题】:Finding Minimum hamming distance of a set of strings in python在python中找到一组字符串的最小汉明距离
【发布时间】:2014-08-28 18:02:04
【问题描述】:

我有一组 n (~1000000) 个字符串(DNA 序列)存储在一个列表中。我必须找到列表中所有序列的最小汉明距离。我实现了一个幼稚的蛮力算法,已经运行了一天多,还没有给出解决方案。我的代码是

dmin=len(trans[0])
for i in xrange(len(trans)):
    for j in xrange(i+1,len(trans)):
            dist=hamdist(trans[i][:-1], trans[j][:-1])
            if dist < dmin:
                    dmin = dist

有没有更有效的方法来做到这一点?这里 hamdist 是我编写的用于查找汉明距离的函数。这是

def hamdist(str1, str2):
    diffs = 0
    if len(str1) != len(str2):
        return max(len(str1),len(str2))
    for ch1, ch2 in zip(str1, str2):
        if ch1 != ch2:
          diffs += 1
    return diffs

【问题讨论】:

  • 除了优化汉明函数外,比较的次数没有什么可做的。但是,如果您告诉我们您要达到的目标,也许有一个启发式解决方案不会经过所有比较
  • 谢谢。我必须找出一组 DNA 序列的最小距离是否高于阈值。 (如果是,那么我知道估计算法返回了可靠的值。)
  • 你可以使用itertools goodness 来缩短你的代码;你的嵌套循环可以只是for s1, s2 in combinations(trans, 2)hamdist 函数可以使用 return sum(islice(1 for ch1, ch2 in izip(str1, str2) if ch1 != ch2), prevMin))
  • @FrerichRaabe 非常感谢。 Itertools 帮助我显着加快了实施速度。

标签: python algorithm bigdata hamming-distance


【解决方案1】:

找出所有字符串的汉明距离并将其存储在一个数组中。 类似的东西

    distance=[]
    for i in trans:
      distance.append(hamdist(i))

然后计算它们的最小值

    minimum =min(distance)

【讨论】:

  • 汉明距离是在两个字符串之间,而不是字符串的属性
【解决方案2】:

一些想法:

1) sklearn.metrics.hamming_loss 可能比您的实现更高效,即使您必须将字符串转换为数组。

2) 你所有的字符串都是唯一的吗?如果是这样,请删除重复项。

你也可以试试sklearn.metrics.pairwise.pairwise_distances,例如:

In [1]: from sklearn.metrics.pairwise import pairwise_distances

In [2]: from sklearn.metrics import hamming_loss

In [3]: a = np.array([[3,4,5], [3,4,4],[3,1,1]])

In [4]: import numpy as np

In [5]: a = np.array([[3,4,5], [3,4,4],[3,1,1]])

In [6]: pairwise_distances(metric=hamming_loss)

In [7]: pairwise_distances(a, metric=hamming_loss)
Out[7]: 
array([[ 0.        ,  0.33333333,  0.66666667],
       [ 0.33333333,  0.        ,  0.66666667],
       [ 0.66666667,  0.66666667,  0.        ]])

我没有看到只计算上三角形的标志,但这仍然应该比循环更快。

【讨论】:

  • 数组中的所有字符串都是不同的。我只在 i
  • OP不是已经在看左上三角了吗?他的第二个循环是for j in xrange(**i+1**,len(trans)):
【解决方案3】:

您可以通过添加一个包含到目前为止的最小距离的可选参数来优化您的hamdist 函数,这样如果diffs 达到该值,您将停止计算距离,因为这种比较会给您比最低:

def hamdist(str1, str2,prevMin=None):
    diffs = 0
    if len(str1) != len(str2):
        return max(len(str1),len(str2))
    for ch1, ch2 in zip(str1, str2):
        if ch1 != ch2:
            diffs += 1
            if prevMin is not None and diffs>prevMin:
                return None
    return diffs 

您需要调整主循环以使用来自hamdistNone 返回值:

dmin=len(trans[0])
for i in xrange(len(trans)):
    for j in xrange(i+1,len(trans)):
            dist=hamdist(trans[i][:-1], trans[j][:-1])
            if dist is not None and dist < dmin:
                    dmin = dist

【讨论】:

  • 谢谢。我没想过优化 hamdist()。这似乎是我在这里唯一能做的事情。
【解决方案4】:

正如this answer 中提到的,没有比二次运行时间更好的通用方法。您需要利用数据的结构。例如,如果最大允许汉明距离的阈值 t 与字符串 n 的长度相比较小(例如 t=100,n=1000000),您可以执行以下操作:随机选择 k 列(例如 k=1000),将字符串限制为这些列,并将它们散列到存储桶中。然后,您只需要在每个存储桶内进行成对比较,前提是两个具有最小汉明距离的字符串仅在未选择的列中不匹配。例如,大约 90% 的概率是这样的,你可以通过重复这个过程得到任意低的错误概率。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-11-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-06-07
    • 2014-01-28
    相关资源
    最近更新 更多