我有一组n(~1000000)字符串(DNA序列)存储在列表trans中。我必须找到列表中所有序列的最小汉明距离。我实施了一个天真的暴力算法,它运行了一天多,还没有给出解决方案。我的代码是
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
答案 0 :(得分:6)
您可以通过添加包含目前已达到的最小距离的可选参数来优化您的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
您需要调整主循环以使用None
的{{1}}返回值:
hamdist
答案 1 :(得分:4)
一些想法:
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. ]])
我没有看到只能计算上三角形的标志,但这仍然应该比循环更快。
答案 2 :(得分:3)
如this answer中所述,没有比二次运行时间更好的一般方法。您需要利用数据结构。例如,如果最大允许汉明距离的阈值t与字符串n的长度相比较小(例如t = 100,n = 1000000),则可以执行以下操作:随机选择k列(例如k = 1000),将字符串限制为这些列,并将它们哈希到桶中。然后,您需要在每个桶中进行成对比较,假设两个字符串的汉明距离最小,仅在非选定列中不匹配。例如,大概有90%的概率是正确的,你可以通过重复这个过程来获得任意低的错误概率。
答案 3 :(得分:-1)
找到所有字符串的汉明距离并将其存储在数组中。 像
这样的东西 distance=[]
for i in trans:
distance.append(hamdist(i))
然后将它们的最小值调整为
minimum =min(distance)