Dijkstra的算法,卡住了

时间:2018-03-08 01:32:46

标签: python dijkstra

这是我第一次尝试实施Dijkstra算法,所以也许我误解了它是如何完成的。也就是说,当所有节点具有相同的值1时,我能够使算法工作,但是如果我将节点更改为更高的值,例如接近开始的2(例如x = 5,y = 0)似乎陷入困境,认为没有解决方案。如果我把更高的价值放在更远的地方,它似乎就可以了。我已多次看过它,看看我是否错过了什么,但我不知所措。对我可能出错的任何帮助表示赞赏!

import sys
import copy

class Node:
    def __init__(self, x, y, cost, goal, start):
        self.x = x #pos X
        self.y = y #pos Y
        self.goal = goal #goal?
        self.start = start #start?
        self.cost = cost #cost of tile
        self.nodeID = "{}{}".format(str(x), str(y)) #unique node identifier

class NodeRecord:
    def __init__(self, x, y, cost, goal, start, connection, costSoFar):
        self.node = Node(x, y, cost, goal, start) #create new node for record
        self.connection = connection
        self.costSoFar = costSoFar

def pathfind(graph, startX, startY, arr):
    startRecord = NodeRecord(startX, startY, 0, False, True, None, 0)

    openList = []
    closedList = []
    openList.append(startRecord)

    while len(openList) > 0:
        current = smallestElement(openList)

        if current.node.goal == True:
            break

        connections = getConnections(current, arr) #gets adjacent nodes and stores in connections list

        #search connections for new nodes
        for connection in connections:
            endNodeCost = current.costSoFar + connection.node.cost

            if containsNode(connection.node.nodeID, closedList): #closed node, skip
                continue

            elif containsNode(connection.node.nodeID, openList): #worse route, skip
                if connection.node.cost <= endNodeCost:
                    continue

            #new node record found add it to list
            else:
                connection.node.goal = goalNode(connection.node.x, connection.node.y, arr)

                if containsNode(connection.node.nodeID, openList) == False:
                    openList.append(connection)

        #remove the connection from the open list and add it to the closed list
        tmpNode = openList[0]
        del openList[0]
        closedList.append(tmpNode)

    path = []
    if current.node.goal == False: #there is no possible solution
        print("No solution\n")

    else: #compile list of connections
        while current.node.start == False:
            path.append(current)
            current = current.connection

    #for i in closedList:   
    #   print("x: {} y: {} cost: {}".format(i.node.x, i.node.y, i.node.cost))

    return reversed(path)

def containsNode(nodeID, nodeList):
    for record in nodeList:
        if record.node.nodeID == nodeID:
            return True

    return False

def getConnections(current, arr):
    connections = []
    lastCost = current.costSoFar
    x = current.node.x
    y = current.node.y

    #add any valid connecting nodes from current node
    if outOfBounds(x + 1, y, arr) == False and arr[y][x + 1] != '#':
        currCost = getCost(x + 1, y, arr)
        node = NodeRecord(x + 1, y, currCost, goalNode(x + 1, y, arr), False, current, lastCost + currCost)
        connections.append(node)

    if outOfBounds(x - 1, y, arr) == False and arr[y][x - 1] != '#':
        currCost = getCost(x - 1, y, arr)
        node = NodeRecord(x - 1, y, currCost, goalNode(x - 1, y, arr), False, current, lastCost + currCost)
        connections.append(node)

    if outOfBounds(x, y + 1, arr) == False and arr[y + 1][x] != '#':
        currCost = getCost(x, y + 1, arr)
        node = NodeRecord(x, y + 1, currCost, goalNode(x, y + 1, arr), False, current, lastCost + currCost)
        connections.append(node)

    if outOfBounds(x, y - 1, arr) == False and arr[y - 1][x] != '#':
        currCost = getCost(x, y - 1, arr)
        node = NodeRecord(x, y - 1, currCost, goalNode(x, y - 1, arr), False, current, lastCost + currCost)
        connections.append(node)

    return connections

def getCost(x, y, arr):
    if isNum(arr[y][x]):
        return int(arr[y][x])

    #no cost for goal
    elif arr[y][x] == 'G':
        return 0

    #error
    return -1

def isNum(n):
    try:
        int(n)
        return True

    except ValueError:
        return False

def goalNode(x, y, arr):
    if arr[y][x] == 'G':
        return True

    return False

def outOfBounds(x, y, arr):
    if x >= len(arr[0]):
        return True

    elif x < 0:
        return True

    if y >= len(arr):
        return True

    elif y < 0:
        return True

    return False

def smallestElement(openList):
    tmpNode = NodeRecord(None, None, None, None, None, None, None)
    smallest = 99
    for i in openList:
        if i.node.cost < smallest:
            smallest = i.node.cost
            tmpNode = i

    return tmpNode

def getStart(arr):
    startX = 0
    startY = 0

    for j in range(0, 4):
        for i in range(0, 5):
            if arr[j][i] == 'S':
                startX = i
                startY = j

    coords = (startX, startY)
    return coords

def main():
    arr = [[]]

    tmp = ['S', '1', '1', '1', '1', '1', '1', '1', '1', '1']
    arr[0] = tmp
    tmp = ['1', '#', '#', '#', '#', '1', '1', '#', '1', '1']
    arr.append(tmp)
    tmp = ['1', '#', '1', '1', '1', '#', '1', '#', '1', '1']
    arr.append(tmp)
    tmp = ['1', '#', '1', '#', '1', '#', '1', '#', '1', '1']
    arr.append(tmp)
    tmp = ['1', '#', '1', '#', '1', '1', '1', '1', '1', '1']
    arr.append(tmp)
    tmp = ['1', '#', '1', '#', '#', '#', '#', '#', '#', '#']
    arr.append(tmp)
    tmp = ['1', '#', '1', '1', '1', '1', '1', '1', '1', 'G']
    arr.append(tmp)

    startCoord = getStart(arr)
    path = pathfind(arr, startCoord[0], startCoord[1], arr)
    for i in path:
        arr[i.node.y][i.node.x] = '@'

    for j in range(0, 7):
        for i in range(0, 10):          
            sys.stdout.write(arr[j][i])
        sys.stdout.write("\n")

if __name__ == "__main__":
    main()

1 个答案:

答案 0 :(得分:0)

我发现了这个问题,并希望将它发布给任何可能在将来犯同样错误的人。 问题出在这里。

    tmpNode = openList[0]
    del openList[0]
    closedList.append(tmpNode)

第一个节点被删除并添加到关闭列表而不是当前节点。这是我纠正它的方式。

    removeNode(current, openList)
    closedList.append(current)

    ...

def removeNode(node, openList):
pos = 0
for i in openList:
    if i.node.x == node.node.x and i.node.y == node.node.y:
        del openList[pos]
    pos += 1