【问题标题】:Python Dijkstra Algorithm Memory Error?Python Dijkstra算法内存错误?
【发布时间】:2013-10-04 09:38:34
【问题描述】:

我已将this answer for Dijkstra Algorithm 复制并粘贴到我的项目中。经过几次简单的测试,似乎还可以。

在我的具体实现中,我需要算法返回一个节点列表。所以我必须修改原始代码,使其始终返回一个列表。更具体地说,我删除了那里的所有 return "string"。我修改的代码如下:

## using Dijkstra Algorithm ##
def choosePath(s, t):
    net = {'0':{'1':138, '9':150},
       '1':{'0':138, '2':178, '8':194},
       '2':{'1':178, '3':47.5},
       '3':{'2':47.5, '4':70},
       '4':{'3':70, '5':70},
       '5':{'4':70, '6':36},
       '6':{'5':36, '7':50},
       '7':{'6':50, '8':81},
       '8':{'7':81, '9':138, '1':194},
       '9':{'8':138, '0':150}}
    # sanity check
    if s == t:
        return []
    # create a labels dictionary
    labels={}
    # record whether a label was updated
    order={}
    # populate an initial labels dictionary
    for i in net.keys():
        if i == s: labels[i] = 0 # shortest distance form s to s is 0
        else: labels[i] = float("inf") # initial labels are infinity
    from copy import copy
    drop1 = copy(labels) # used for looping
    ## begin algorithm
    while len(drop1) > 0:
        # find the key with the lowest label
        minNode = min(drop1, key = drop1.get) #minNode is the node with the smallest label
        # update labels for nodes that are connected to minNode
        for i in net[minNode]:
            if labels[i] > (labels[minNode] + net[minNode][i]):
                labels[i] = labels[minNode] + net[minNode][i]
                drop1[i] = labels[minNode] + net[minNode][i]
                order[i] = minNode
        del drop1[minNode] # once a node has been visited, it's excluded from drop1
    ## end algorithm
    # print shortest path
    temp = copy(t)
    rpath = []
    path = []
    while 1:
        rpath.append(temp)
        if order.has_key(temp):
            temp = order[temp]
        if temp == s:
            rpath.append(temp)
            break
    for j in range(len(rpath)-1,-1,-1):
        path.append(rpath[j])
    return [junctions[int(elem)] for elem in path]

然后当我运行它时,我最终得到以下错误:

>>> Traceback (most recent call last):
  File "C:\Users\...\simulation.py", line 162, in choosePath
    rpath.append(temp)
MemoryError

显然,这是因为我删除了返回“字符串”行。但是,我没有找出哪个删除使它死亡。为什么会这样?

我怎样才能让它再次工作并且总是返回一个列表而不是我希望的字符串?

【问题讨论】:

  • 听起来确实像是在向rpath 添加节点,直到内存不足。我不确定为什么会发生这种情况,但也许您可以添加代码来捕获异常,如果它发生并打印出rpathorder 字典?这应该让您对出了什么问题有一个很好的了解。

标签: python


【解决方案1】:

我怀疑您的问题是您将错误的参数传递给函数。你想打电话给choosePath('0', '9')。字符串。不是整数。

有趣的是,如果您删除的程序的任何部分仍然存在,它就会捕获并停止程序。有了这部分,它会捕获您的输入是否错误。

if net.has_key(s)==False:
    return "There is no start node called " + str(s) + "."
if net.has_key(t)==False:
    return "There is no terminal node called " + str(t) + "."

有了这部分,它会捕获它是否永远无法解决。

else: return "There is no path from " + str(s) + " to " + str(t) + "."

完整性检查并不是绝对必要的,因为正如您所提到的,在您的网络中保证了一条路径。检查仍然很好,因为如果你真的选择改变周围的东西,你就会知道计算机会因为明显的错误而叫你出来。一种选择是用异常替换它们,因为除非出现严重错误,否则这些消息都不应该真正出现。这就是我在以下代码中选择的。

class NoPathException(Exception):
    pass

def choosePath(s, t):
    net = {'0':{'1':138, '9':150},
       '1':{'0':138, '2':178, '8':194},
       '2':{'1':178, '3':47.5},
       '3':{'2':47.5, '4':70},
       '4':{'3':70, '5':70},
       '5':{'4':70, '6':36},
       '6':{'5':36, '7':50},
       '7':{'6':50, '8':81},
       '8':{'7':81, '9':138, '1':194},
       '9':{'8':138, '0':150}}
    # sanity check
    if s == t:
        return []
    if not net.has_key(s):
        raise ValueError("start node argument not in net")
    if not net.has_key(t):
        raise ValueError("end node argument not in net")
    # create a labels dictionary
    labels={}
    # record whether a label was updated
    order={}
    # populate an initial labels dictionary
    for i in net.keys():
        if i == s: labels[i] = 0 # shortest distance form s to s is 0
        else: labels[i] = float("inf") # initial labels are infinity
    from copy import copy
    drop1 = copy(labels) # used for looping
    ## begin algorithm
    while len(drop1) > 0:
        # find the key with the lowest label
        minNode = min(drop1, key = drop1.get) #minNode is the nod2 with the smallest label
        # update labels for nodes that are connected to minNode
        for i in net[minNode]:
            if labels[i] > (labels[minNode] + net[minNode][i]):
                labels[i] = labels[minNode] + net[minNode][i]
                drop1[i] = labels[minNode] + net[minNode][i]
                order[i] = minNode
        del drop1[minNode] # once a node has been visited, it's excluded from drop1
    ## end algorithm
    # print shortest path
    temp = copy(t)
    rpath = []
    path = []
    while 1:
        rpath.append(temp)
        if order.has_key(temp):
            temp = order[temp]
        else:
            raise NoPathException("no path to solution")
        if temp == s:
            rpath.append(temp)
            break
    for j in range(len(rpath)-1,-1,-1):
        path.append(rpath[j])

    return path

测试

a = choosePath('3', '9')
print(a)
['3', '4', '5', '6', '7', '8', '9']

这是您要查找的输出吗?

【讨论】:

  • 这 3 行正是我删除的内容。但确实用字符串调用 choosePath('0', '9') 。另外,我认为我可以安全地删除 else 子句的原因是在我的问题中,总是保证存在一条路径。因此,我很困惑为什么这仍然出现。但无论如何,你已经给出了很好的建议。我会尝试异常捕获。或者我可以简单地将 return 替换为 print 对吗?
  • @perfectm1ng 我已经更新了答案。同样,用 print 替换 return 也不是最好的,原因之一是它不会离开函数。返回和异常都可以解决。
猜你喜欢
  • 1970-01-01
  • 2011-06-27
  • 2017-03-23
  • 1970-01-01
  • 1970-01-01
  • 2014-05-18
  • 1970-01-01
  • 2011-06-29
相关资源
最近更新 更多