Python:递归:输出最佳路径

时间:2014-10-14 21:13:56

标签: python-2.7 recursion

我确实有一个(希望)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) - 元组的列表。

1 个答案:

答案 0 :(得分:1)

您可以使用与递归一起传递的列表结构来跟踪路径。在每个步骤中,将当前部分添加到路径中,附加任何递归结果,然后将列表传递回调用者。以下是对falign函数的修改:

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)]

请注意,我没有对此进行优化以减少列表复制的数量。此外,在您的第一种情况下,如果sublag1lag2相等,它只返回该顺序中第一个的路径,如果它们似乎是任意选择得分相等。