我确实有一个(希望)python中的递归函数的小问题。我写了一个短序列比对算法,优化了给定替换矩阵和间隙成本(n)的两个列表的对齐。该函数工作正常并返回合理的对齐分数。
然而,我还需要最终采用的最佳路径,这导致了对齐得分。由于我不熟悉递归编程,我不知道该函数如何组装和返回路径。
a = ['a','b','c','d','e']
b = ['a','c','d','a','e']
c = ['c','a','b','c','a']
s = {}
for i in ['a','b','c','d','e','f']:
s[i] = {}
for j in ['a','b','c','d','e','f']:
if i == j:
s[i][j] = 0.0
else:
s[i][j] = 1.0
n = 0.5
def f(l1,l2,i,j):
if i > 0 and j > 0:
sub = f(l1,l2,i-1,j-1) + s[l1[i]][l2[j]]
lag1 = f(l1,l2,i,j-1) + n
lag2 = f(l1,l2,i-1,j) + n
fval = min(sub,lag1,lag2)
elif i > 0:
fval = f(l1,l2,i-1,j) + n
elif j > 0:
fval = f(l1,l2,i,j-1) + n
else:
fval = s[l1[0]][l2[0]]
result = []
return fval
def align(l1,l2):
score = f(l1,l2,len(l1)-1,len(l2)-1)
print score
align(a,b)
align(a,c)
align(b,c)
有没有人知道我如何回归路径?优选地,输出是包含路径中每个步骤的(i,j) - 元组的列表。
答案 0 :(得分:1)
您可以使用与递归一起传递的列表结构来跟踪路径。在每个步骤中,将当前部分添加到路径中,附加任何递归结果,然后将列表传递回调用者。以下是对f
和align
函数的修改:
def f(l1,l2,i,j, path=None):
path = [] if path is None else path[:]
path += [(i,j)]
if i > 0 and j > 0:
sub, subpath = f(l1,l2,i-1,j-1)
sub += s[l1[i]][l2[j]]
lag1, lag1path = f(l1,l2,i,j-1)
lag1 += n
lag2, lag2path = f(l1,l2,i-1,j)
lag2 += n
fval = min(sub,lag1,lag2)
if fval == sub:
path.extend(subpath)
elif fval == lag1:
path.extend(lag1path)
else:
path.extend(lag2path)
elif i > 0:
fval, ipath = f(l1,l2,i-1,j)
fval += n
path.extend(ipath)
elif j > 0:
fval, jpath = f(l1,l2,i,j-1)
fval += n
path.extend(jpath)
else:
fval = s[l1[0]][l2[0]]
return fval, path
def align(l1,l2):
score, path = f(l1,l2,len(l1)-1,len(l2)-1)
print '{} : {}'.format(score, path)
这会产生以下输出:
1.0 : [(4, 4), (3, 3), (3, 2), (2, 1), (1, 0), (0, 0)]
3.0 : [(4, 4), (3, 3), (2, 3), (1, 2), (0, 1), (0, 0)]
3.0 : [(4, 4), (3, 4), (2, 3), (1, 3), (0, 2), (0, 1), (0, 0)]
请注意,我没有对此进行优化以减少列表复制的数量。此外,在您的第一种情况下,如果sub
,lag1
或lag2
相等,它只返回该顺序中第一个的路径,如果它们似乎是任意选择得分相等。