图论DFS(Depth First Search)Algorithm深度优先搜索遍历空间平面图选择路径,networkx,Python

x33g5p2x  于2021-12-30 转载在 Go  
字(3.9k)|赞(0)|评价(0)|浏览(373)

图论DFS(Depth First Search)Algorithm深度优先搜索遍历空间平面图选择路径,networkx,Python

程序初始代码是模式0,即随机生成最多20个障碍物点,验证算法的效果。打红色X点表示此路不通。出发点是(1,1),终点是(5,7)。最终红色的点即为选出的路径,并用红色的粗线连起来。

import random

import networkx as nx
import matplotlib.pyplot as plt

WALKABLE = 'walkable'
PARENT = 'parent'
VISITED = 'visited'

def my_graph():
    M = 7
    N = 9
    G = nx.grid_2d_graph(m=M, n=N)
    pos = nx.spring_layout(G, iterations=100)

    nx.draw_networkx(G, pos=pos,
                     # labels=labels, #labels = dict(((i, j), 'Phil') for i, j in G.nodes())
                     font_size=8,
                     font_color='white',
                     node_color='green',
                     node_size=500,
                     width=1)

    START = (1, 1)
    GOAL = (M - 1 - 1, N - 1 - 1)

    # 0,随机生成障碍物点
    # 1,精心挑选的障碍物构成陷阱
    obstacle_mode = 0
    road_closed_nodes = []
    if obstacle_mode == 0:
        obstacle = 20  # 障碍物(断点、不可达点)数量
        road_closed_nodes = obstacle_nodes(G, START, GOAL, obstacle, M, N)
    elif obstacle_mode == 1:
        road_closed_nodes = dummy_nodes(G)

    nx.draw_networkx_nodes(
        G, pos,
        nodelist=road_closed_nodes,
        node_size=500,
        node_color="red",
        node_shape="x",
        # alpha=0.3,
        label='x'
    )

    dfs(G, START, GOAL)
    path = find_path_by_parent(G, START, GOAL)
    print('path', path)

    nx.draw_networkx_nodes(
        G, pos,
        nodelist=path,
        node_size=400,
        node_color="red",
        node_shape='o',
        # alpha=0.3,
        # label='NO'
    )

    # nx.draw_networkx_nodes(
    #     G, pos,
    #     nodelist=path,
    #     node_size=100,
    #     node_color="yellow",
    #     node_shape='*',
    #     # alpha=0.3,
    #     # label='NO'
    # )

    path_edges = []
    for i in range(len(path)):
        if (i + 1) == len(path):
            break
        path_edges.append((path[i], path[i + 1]))

    print('path_edges', path_edges)

    # 把path着色加粗重新描边
    nx.draw_networkx_edges(G, pos,
                           edgelist=path_edges,
                           width=8,
                           alpha=0.5,
                           edge_color="r")

    plt.axis('off')
    plt.show()

# 基于栈实深度优先遍历搜索
def dfs(G, START, GOAL):
    for n in G.nodes():
        G.nodes[n]['visited'] = False

    stack = []  # 用列表当作一个栈,只在栈顶操作(数组的第1个位置)
    stack.append(START)

    close_list = []

    while True:
        if len(stack) == 0:
            break

        print('-----')
        print('stack-', stack)

        visit_node = stack[0]
        G.nodes[visit_node]['visited'] = True
        print('访问', visit_node)

        if visit_node == GOAL:
            break

        close_list.append(visit_node)

        count = 0
        neighbors = nx.neighbors(G, visit_node)
        for node in neighbors:
            visited = G.nodes[node][VISITED]
            try:
                walkable = G.nodes[node][WALKABLE]
            except:
                walkable = True

            if (visited) or (node in stack) or (node in close_list) or (not walkable):
                continue

            G.nodes[node][PARENT] = visit_node
            stack.append(node)
            count = count + 1

        if count == 0:
            print(visit_node, '尽头')
            del (stack[0])
            print('弹出', visit_node)

        print('stack--', stack)

    return stack

def find_path_by_parent(G, START, GOAL):
    t = GOAL
    path = [t]
    is_find = False
    while not is_find:
        for n in G.nodes(data=True):
            if n[0] == t:
                parent = n[1][PARENT]
                path.append(parent)

                if parent == START:
                    is_find = True
                    break

                t = parent

    list.reverse(path)
    return path

# 障碍物点
def obstacle_nodes(G, START, GOAL, obstacle, M, N):
    road_closed_nodes = []
    for i in range(obstacle):
        n = (random.randint(0, M - 1), random.randint(0, N - 1))
        if n == START or n == GOAL:
            continue
        if n in road_closed_nodes:
            continue

        G.nodes[n][WALKABLE] = False
        road_closed_nodes.append(n)

    return road_closed_nodes

def dummy_nodes(G):
    fun_nodes = []

    n0 = (1, 2)
    G.nodes[n0][WALKABLE] = False
    fun_nodes.append(n0)

    n1 = (1, 3)
    G.nodes[n1][WALKABLE] = False
    fun_nodes.append(n1)
    n2 = (1, 4)
    G.nodes[n2][WALKABLE] = False
    fun_nodes.append(n2)
    n3 = (1, 5)
    G.nodes[n3][WALKABLE] = False
    fun_nodes.append(n3)
    n4 = (1, 6)
    G.nodes[n4][WALKABLE] = False
    fun_nodes.append(n4)
    n5 = (2, 6)
    G.nodes[n5][WALKABLE] = False
    fun_nodes.append(n5)
    n6 = (3, 6)
    G.nodes[n6][WALKABLE] = False
    fun_nodes.append(n6)
    n7 = (4, 6)
    G.nodes[n7][WALKABLE] = False
    fun_nodes.append(n7)
    n8 = (5, 6)
    G.nodes[n8][WALKABLE] = False
    fun_nodes.append(n8)
    n9 = (5, 5)
    G.nodes[n9][WALKABLE] = False
    fun_nodes.append(n9)
    n10 = (5, 4)
    G.nodes[n10][WALKABLE] = False
    fun_nodes.append(n10)
    n11 = (5, 3)
    G.nodes[n11][WALKABLE] = False
    fun_nodes.append(n11)
    n12 = (5, 2)
    G.nodes[n12][WALKABLE] = False
    fun_nodes.append(n12)

    return fun_nodes

if __name__ == '__main__':
    my_graph()

算法选路效果:

由于代码中对于随机生成的障碍物点限制不多(不等于出发点和终点即可),那么极大概率生成的点集把出发点到终点之间的路线堵死,最终选路选不出来,出于简单代码说明算法的目的,程序对这些情况未增加代码量规避处理。

现在,使用障碍物模式1,

obstacle_mode = 1

故意生成一组精心挑选的点,这些点形成一个凹形的围墙,围墙正面对出发点,同时把出发点改成(2,2),

START = (2, 2)

看看算法的表现:

算法走出的路线很聪明,机智的以捷径绕过围墙。

图论BFS(Breath First Search)Algorithm广度优先搜索遍历空间平面网格图路径选择,networkx,Python_Zhang Phil-CSDN博客

networkx图论Dijkstra Algorithm最短路径实现,Python_Zhang Phil-CSDN博客

相关文章