python - 如何在回溯中撤消?我在使用递归回溯方法时遇到问题

标签 python networkx backtracking branch-and-bound recursive-backtracking

好吧,我有这张图: Graf

我必须编写一个基于分支限界并使用回溯的代码,它必须显示匹配图形节点的最佳方式。所以在这个例子中,最优解一定是>> [(1,4),(2,3)]。但是我的算法显示了这个可能的解决方案,它不是最优的 >> [(1,2),(3,4)]。我认为问题可能出在“撤消”行,但我不确定...如果有人能帮我解决这个问题,我将不胜感激!

这是我的代码:

import networkx as nx
import sys
import matplotlib.pyplot as plt
import copy
import operator
from itertools import izip

def grouped(iterable, n):
    "s -> (s0,s1,s2,...sn-1), (sn,sn+1,sn+2,...s2n-1), (s2n,s2n+1,s2n+2,...s3n-1), ..."
    return izip(*[iter(iterable)]*n)

''' Method to create a Graf from a file '''
def leerGrafo():                                                                                                                   
    #name = raw_input("Enter the name of the Graph please: ")
    name = "grafo2.dat"                                                                        
    G = nx.read_edgelist(name,nodetype=int,data=(('weight',float),))
    return G    

''' Method to create the adjacency matrix '''
def matrixAdj(G):
    ''' Tener en cuenta: diagonal = 0, y no conex. = Inf '''
    nodes = G.number_of_nodes()
    edges = G.edges()

    listaAdj = [[float("Inf") for j in range(nodes)] for i in range(nodes)]

    for i in range(len(edges)):
        valor1,valor2 = edges[i][0],edges[i][1]
        listaAdj[valor1-1][valor2-1] = G.edge[valor1][valor2]['weight']
        listaAdj[valor2-1][valor1-1] = G.edge[valor1][valor2]['weight']

    return listaAdj

''' returns the weight from the adjacency matrix '''
def weight_of(s,G,son):
    return matrix[s-1][int(son)-1]

''' Backtracking Method '''
def backtracking(s,G,l,cMax,cMin,finalSol):
    # We insert the current valid node, from our current way
    l.append(s)
    # We iterate over the sons of our current node
    for son in G.neighbors(s):
        # If the current son is not one of the predecessors of the current node 's'...
        if not son in l:
            # We calculate the bound of the current son, adding the weight of his father (s) + the weight of the current son
            # Note: At the start (the first node), we add the lower bound + the weight of that node.
            c = weight_of(son,G,s) + cMin
            # If this bound is lesser or iqual than the upper bound...
            if c <= cMax:
                # If this current node is a leaf, means that we've found a possible way...
                if len(l)+1 == G.number_of_nodes():
                    # We insert this current node (son)
                    l.append(son)
                    # We update the upper bound with the bound of this current node
                    cMax = c
                    # We store a copy of our possible way
                    finalSol = copy.copy(l)
                    # We reset our list that conteins our possible way
                    l = []
                    return finalSol
                # Si no...seguimos recorriendo las ramas hasta encontrar un camino entero
                else:
                    backtracking(son,G,l,cMax,c,finalSol)
    # Undo
    del l[-1]

    return 

''' Main Function ''' 
def main():
    # We make the graf
    G1 = leerGrafo()
    global matrix
    # We create the adjacency matrix
    matrix = matrixAdj(G1)
    # We make a ordered list that contains just the weight of all nodes
    pesos = [a[2]['weight'] for a in sorted(G1.edges(data=True), key=lambda aux: aux[2])]
    # We calculate the default upper bound
    cotaMax = sum(pesos)
    # We calculate the lower bound
    cotaMin = pesos[0]
    l = []
    global finalSol
    finalSol = 0
    # We call the backtracking method
    bestSol = backtracking(G1.nodes()[0],G1,l,cotaMax,cotaMin,finalSol)
    # We print the solution
    print "Best Solution: "
    for x, y in grouped(bestSol, 2):
        print "(%d,%d)" % (x, y)

最佳答案

我想我开始看到这里的问题了,你的算法只选择一条路径,遇到的第一条路径,它需要检查所有路径并选择最小的路径,并且通过你的例子选择所有的最小路径到下一个节点的非行走路径...

这是我的解决方案

def minimun_path(s,G,camino,cMax,cMin):
    if len(camino) == G.number_of_nodes():
        # I found the complete path
        return camino
    temp = []
    for son in G.neighbors(s):
        # I record all path to a node not visited yet
        if son not in camino:
            peso = weight_of(son,G,s)+cMin
            temp.append( (son,peso) )
    if temp:
        # I choose a minimun of those
        sig,w = min( temp, key=lambda x:x[1])
    else:
        # I don't have where to go, so I stay put
        sig = s
    return minimun_path(sig,G,camino+(s,),cMax,cMin)

对于 camino 我使用元组而不是列表,作为一个不可变对象(immutable对象)我不会发现奇怪的边框效果,以防万一......

称之为

bestSol = minimun_path(G1.nodes()[0],G1,tuple(),cotaMax,cotaMin)

输出

Best Solution: 
(1,4)
(3,2)

关于python - 如何在回溯中撤消?我在使用递归回溯方法时遇到问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34475933/

相关文章:

python - 'can' t 分配给文字'意味着什么?

python - 如何在 NetworkX 中加载 .mtx 文件?

正则表达式调试

python - Flask 回调未通过 pytest 运行

python - 通过 python 访问谷歌帐户

python - 将元组分配给 pandas 数据帧的多个元素

java - m_coloring 的蒙特卡罗估计

python - 在 networkx 和 python 中查找距离内的节点

python - 突出显示 NetworkX 中的某些节点/边 - 使用 zip() 的问题

java - 这段示例代码中哪里发生了回溯?