如果你的RNA是不是非常长(基地大概OK千;数十万绝对不是OK),你可以摆脱一个简单的为O(n^3)算法。 O(n^3)意味着执行时间在最坏情况下与基数的立方成正比。作者提到嵌套循环暗示着这个简单但相当慢的方法。
def find_loops(rna, min_pairs=3, min_loop=3):
n = len(rna)
result = []
for loop_start in xrange(min_pairs, n - min_pairs - min_loop + 1):
for loop_end in xrange(loop_start + min_loop, n - min_pairs):
if (loop_end - loop_start < min_loop + 2 or
not base_pair(rna[loop_start], rna[loop_end - 1])):
max_pairs = min(loop_start, n - loop_end)
for k in xrange(max_pairs):
if not base_pair(rna[loop_start - k - 1], rna[loop_end + k]):
break
else:
k = max_pairs
if k >= min_pairs:
result.append((loop_start - k, k, loop_end - loop_start))
return result
def base_pair(x, y):
return (x == 'A' and y == 'U' or
x == 'C' and y == 'G' or
x == 'G' and y == 'C' or
x == 'U' and y == 'A')
此遍历所有可能的开始和RNA环的端部,然后走开从电势环的端部,在两个方向上,只要该碱仍然配对。当它到达一对不匹配的基地时,它停止并检查它是否至少有最少数量的对。如果有,它会将循环添加到结果列表中。
第一if
目的是避免可能被“拉链”更紧密的上市循环。如条件所示,如果循环可能太短(小于5个碱基)或其末端不匹配,则循环可以将而不是拉得更紧。
结果是形式为(start_pos, pair_count, loop_length)
的每个可能循环的元组列表。这意味着从碱基编号start_pos
开始的pair_count
碱基序列后面是碱基的循环,接着是反向的互补序列。序列的反义拷贝从基地start_pos + pair_count + loop_length
开始。第一个基数是0,而不是1(我们是程序员)。
一个例子可以说明清楚:print find_loops('GGGGAUUACAGCGUGUAAUCAAUA')
回报[(4, 3, 13), (3, 7, 3)]
,也就是说,它发现两个循环:
- 在第4位,三个基地,
AUU
,附上的13个基地的循环,并绑定到AAU
在位置20;
- 在位置3,7个碱基,
GAUUACA
,包围的三个基地一个循环,和在位置13
结合UGUAAUC
没有第一if
,该函数也将返回像(3,6环,5)(即位置3的GAUUAC
包含5个碱基的环,并在位置14处与GUAAUC
结合),其与上面的(3,7,3)是相同的环,只是没有像将要去除的那样拉紧。
希望这会有所帮助。如果你需要更快的算法,我相信有一个动态编程解决方案可以处理更长的字符串。让我知道,我会考虑它。虽然...
我不知道你在找什么。你能举一些短期投入和预期的相应产出的例子,推理吗? – 2012-04-24 22:59:28
这里你不会有太多的运气,要求为你写代码。你尝试了什么?出了什么问题,什么让你感到困惑? – 2012-04-24 22:59:29
如果这是一个研究问题,而不是作业,我强烈建议biopython。它已经有方便的方法来转录,翻译,反向补充等。 – 2012-04-24 23:59:54