微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

修改后的背包问题陷入无限循环

如何解决修改后的背包问题陷入无限循环

我一直在尝试实现一个关于生物信息学改进的背包问题算法

在我看来,到目前为止,我已经非常接近解决方案,但是程序在某个点卡住了。

我有一个节点列表,这些节点具有(某种氨基酸的)质量、索引以及它们可以到达的节点列表。

节点

class Node():
def __init__(self,mass,index):
    self.mass = mass
    self.prev = []
    self.next = []
    self.index = index


def chainTo(self,next):
    self.next.append(next)
    next.prev.append(self)

目标是从给定的节点中找到可能的最长链,这样我就可以从它们的质量中找出它们代表的肽段。

为此,我编写了一个函数,如果 nodes[i].mass - nodes[j].mass 等于.txt 文件中预定义的一些氨基酸质量。

def createTree(masstable,massDev,aminoTable,extras):
    nodes = createNodes()

    for i in range(0,len(nodes)):
        for j in range(i+1,len(nodes)):
            findamino(nodes[i],nodes[j],masstable,extras)

    return nodes

def findamino(first,second,extras):
found = False
for amino,mass in masstable.items():
    for extra,extraMass in extras.items():
        #print(first.mass - second.mass)
        if ((mass + extraMass - massDev) <= abs(first.mass - second.mass) <= (mass + extraMass + massDev)):
            first.chainTo(second) #pravimo vezu
            #print(amino)
            aminoTable.update({(first,second) : amino})
            found = True
            break

return False if not found else True #ako ne nađe niti jednu mogućnost,vraća False

所以代码的最后和主要部分是遵循特定规则的树遍历算法:

  1. 从列表中取出第一个节点(如果它的下一个列表中没有节点,则取第二个,依此类推)
  2. 调用树遍历算法找到所有可能的路径(例如,如果节点[0]在其下一个列表中有节点[1]和节点[2],那么树遍历算法必须找到路径节点[ 0]->节点[1]和节点[0]->节点[2]
  3. 在所有生成的路径中,程序占用的路径最长
  4. 程序重复第 1 步,但它不会从列表中获取一个节点,而是获取最长找到路径中最后一个节点之后的节点
  5. 当涉及到最后一个节点时,它结束并返回最长可能链的列表。
def traverseRoot(root,chains):
    traverse(root,[],chains)

#node - čvor na kojem se nalazimo
#ako nema susjede,u chains dodajemo taj put
#ako ima,pokrecemo isti algoritam
def traverse(node,path,chains):
    path.append(node)
    if(len(node.next) == 0):
        chains.append(path)
    else:
        for i in node.next:
            print(str(i.mass) + " " + str(i.index))
            traverse(i,path.copy(),chains)


def start(nodes,extras):
        #IDEJA:
        #1. funkcija uzima prvi čvor (ukoliko nema prijelaze,uzima idući,pa idući,itd.)
        #2. nad tim čvorom provodi neku vrstu tree-traversing algoritma kako bi prošao sve puteve
        #3. uzima kao konačni put onaj koji je došao najdalje u listi / pokrio najviše čvorova
        #4. ponavlja sve počevši od prvog koraka samo što ne uzima prvi čvor nego onaj koji dolazi nakon zadnjeg u prethodno pronađenom putu
        #5. kad dođe do zadnjeg čvora,prestaje sa radom i vraća listu stvorenih lanaca po čijim čemo vezama gledati koje aminokiseline predstavljaju
        start = 0
        finalChains = []
        while(True):
            currentNodeChains = []
            found = False
            for i in range(start,len(nodes)):
                if(not nodes[i].next): #1.
                    continue
                else:
                    found = True
                    print(start)
                    traverseRoot(nodes[i],currentNodeChains) #2.
                    break
            
            if (not found):
                return finalChains
                
            #3.
            maxLen = 0
            maxChain = None
            for chain in currentNodeChains:
                if (len(chain) > maxLen):
                    maxLen = len(chain)
                    maxChain = chain
            if (maxChain != None):
                finalChains.append(maxChain)
                print([i for i in maxChain])
                print("-----------")
                start = maxChain[-1].index + 1 #4.
        return finalChains

我的整个问题是程序在某个点卡住了。

例如,我有 300 个节点,它在接近结束时陷入无限循环,在我运行它的示例中大约是第 280 个节点。

我怀疑它是否必须对我正在运行的这个特定示例执行某些操作,但更有可能在递归函数调用中的某处存在逻辑错误

如果有人知道问题出在哪里,我将不胜感激!

解决方法

在尝试调试代码时,问题似乎出在 Node 类中属性 next 的整个概念上。

当我打印出所有节点的下一个列表时,我发现同一节点多次出现,例如 [2,2,3,8,...] 所以当我转换 列表时设置它不再卡住了。

希望这对未来的人有所帮助。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。