在 networkx/python 中为 * 搜索启发式分配 x,y 坐标

Assigning x,y coords in networkx/python for a* search heuristic

我正在尝试在一个6*6互连的节点网格上实现python中的a*搜索算法,使用networkx来组织节点并使用matplotlib来显示。我让它工作,所以它找到了最短路径,但没有启发式,它只是蛮力搜索 - 这太昂贵了。 我如何在创建节点时为我的节点分配 x,y 坐标,或者是否有任何其他方法可以使启发式工作? (我知道 networkx 有一个我可以使用的内置 a* 函数,但我想证明我可以实现该算法)

这是代码(Whosebug 格式有点混乱):

import networkx as nx
G=nx.Graph()

import matplotlib.pyplot as plt


def add_nodes():
    G.add_nodes_from([0, 1, 2, 3, 4, 5, \
         6, 7, 8, 9, 10, 11, \
         12, 13, 14, 15, 16, 17, \
         18, 19, 20, 21, 22, 23, \
         24, 25, 26, 27, 28, 29,\
         30, 31, 32, 33, 34, 35])


    c = 0
    for y in range (0,5):
        for x in range (0,5):
            G.add_node(c, pos=(x/10,y/10))
            c=c+1
#
#prev code for brute force search:
#https://pastebin.com/DT76bvw5
#node pos: 
#http://theory.stanford.edu/~amitp/GameProgramming/Heuristics.html
#http://zurb.com/forrst/posts/A_algorithm_in_python-B4c



for a in G.nodes():
    if a not in (5, 11, 17, 23,29, 35):
        G.add_edge(a, a+1)
    if a not in (30, 31, 32, 33, 34, 35):
        G.add_edge(a, a+6)
    if a not in (5, 11, 17, 23, 29, 30, 31, 32, 33, 34, 35):
        G.add_edge(a, a+7)
    if a not in (0, 6, 12, 18, 24, 30, 31, 32, 33, 34, 35):
        G.add_edge(a, a+5)

def heuristic(a, b):
    (x1, y1) = a
    (x2, y2) = b
    return abs(x1-x2) + abs(y1-y2)

#def cost (from_node, to_node):


def a_star_search(graph, start, end):    
    #initialise open list
    open_nodes = []
    #initialise closed list
    closed_nodes = {}
    #put starting node on open list
    open_nodes.append(start)
    #initialise cost list
    cost_so_far = {}
    #no previous path
    closed_nodes[start] = None
    cost_so_far[start] = 0


    #lists for colour:
    eVisited= []
    ePath = []


    #while open list is not empty
    while (len(open_nodes) != 0):
        #pop q off the open list
        current = open_nodes.pop()


        #for each neighbour

        for next in G.neighbors(current):
            new_cost = cost_so_far[current] + G[current][next]['weight']
            print('cost between '+ str(current) + ' and ' + str(next) + ' = ' + str(new_cost))
            if next not in cost_so_far or new_cost< cost_so_far[next]:
                cost_so_far[next] = new_cost
                print('minimal cost for start to ' + str(next) +  ' found')

                #assign colour to show it's been added
                eVisited.append((current, next))

                #priority = new_cost + heuristic(end, next)
                open_nodes.append(next) #(next, priority)
                closed_nodes[next] = current
                print('node connected: ' + str(next))

    print(closed_nodes)
    v = closed_nodes[end]
    ePath.append((end, closed_nodes[end]))
    while v != start:
        ePath.append((v, closed_nodes[v]))
        v = closed_nodes[v]
    print(ePath)
    return ePath, eVisited

add_nodes()
ePath, eVisited = a_star_search(G, 18, 3)
pos=nx.spectral_layout(G) #positions for all nodes(?)

#draw nodes
nx.draw_networkx_nodes(G, pos, node_size=300)


#draw edges
nx.draw_networkx_edges(G, pos, width=3)
nx.draw_networkx_edges(G, pos, edgelist=eVisited, width = 6, edge_color='g')
nx.draw_networkx_edges(G, pos, edgelist=ePath, width = 6, edge_color='b')

#labels
nx.draw_networkx_labels(G, pos, font_size=10, font_family='sans-serif')

plt.grid('on')

#disable axis
plt.axis('off')
#draw graph
plt.show()

您可以为每个节点分配一个位置:

for n in G:
    x, y = n // 6, n % 6  # row and column coordinates
    G.node[n]['pos'] = (x, y)

这样,您就可以访问 属性。

for n, data in G.nodes(data=True):
    print(n, data['pos'])
# (0, 0)
# (0, 1)
# (0, 2)
# ...

编辑:如前所述,对于以后发现此内容有用的人,可以使用以下内容绘制

nx.draw(G, pos=nx.get_node_attributes(G, 'pos'))