Python 我的A-star实施似乎非常缓慢,需要建议和帮助来说明我做错了什么

Python 我的A-star实施似乎非常缓慢,需要建议和帮助来说明我做错了什么,python,algorithm,performance,graph-algorithm,a-star,Python,Algorithm,Performance,Graph Algorithm,A Star,我对Dijkstra和A-Star实现的测试表明,我的A-Star实现大约慢了2倍。通常,Dijkstra和A-star的等效实现应该会看到A-star击败Dijkstra。但这里的情况并非如此,因此我对A-star的实现提出了质疑。所以我希望有人告诉我,我在实现A-star的过程中做错了什么 这是我的密码: from copy import deepcopy from math import inf, sqrt import maze_builderV2 as mb if __name__

我对Dijkstra和A-Star实现的测试表明,我的A-Star实现大约慢了2倍。通常,Dijkstra和A-star的等效实现应该会看到A-star击败Dijkstra。但这里的情况并非如此,因此我对A-star的实现提出了质疑。所以我希望有人告诉我,我在实现A-star的过程中做错了什么

这是我的密码:

from copy import deepcopy
from math import inf, sqrt
import maze_builderV2 as mb

if __name__ == '__main__':
    order = 10
    space = ['X']+['_' for x in range(order)]+['X']
    maze = [deepcopy(space) for x in range(order)]
    maze.append(['X' for x in range(order+2)])
    maze.insert(0, ['X' for x in range(order+2)])

    finalpos = (order, order)

    pos = (1, 1)

    maze[pos[0]][pos[1]] = 'S'  # Initializing a start position
    maze[finalpos[0]][finalpos[1]] = 'O'  # Initializing a end position

    mb.mazebuilder(maze=maze)

    def spit():
        for x in maze:
            print(x)

    spit()
    print()

    mazemap = {}

    def scan():  # Converts raw map/maze into a suitable datastructure.
        for x in range(1, order+1):
            for y in range(1, order+1):
                mazemap[(x, y)] = {}
                t = [(x-1, y), (x+1, y), (x, y-1), (x, y+1)]
                for z in t:
                    if maze[z[0]][z[1]] == 'X':
                        pass
                    else:
                        mazemap[(x, y)][z] = [sqrt((pos[0]-z[0])**2+(pos[1]-z[1])**2),
                                            sqrt((finalpos[0]-z[0])**2+(finalpos[1]-z[1])**2)] # Euclidean distance to destination (Heuristic)

    scan()

    unvisited = deepcopy(mazemap)
    distances = {}
    paths = {}

    # Initialization of distances:
    for node in unvisited:
        if node == pos:
            distances[node] = [0, sqrt((finalpos[0]-node[0])**2+(finalpos[1]-node[1])**2)]
        else:
            distances[node] = [inf, inf]

    while unvisited != {}:
        curnode = None
        for node in unvisited:
            if curnode == None:
                curnode = node
            elif (distances[node][0]+distances[node][1]) < (distances[curnode][0]+distances[curnode][1]):
                curnode = node
            else:
                pass

        for childnode, lengths in mazemap[curnode].items():
            # Length to nearby childnode - G length, Euclidean (Heuristic) length from curnode to finalpos - H length
            # G length + H length < Euclidean length to reach that childnode directly + Euclidean length to finalpos from that childnode = Better path found, update known distance and paths
            if lengths[0] + lengths[1] < distances[childnode][0] + distances[childnode][1]:
                distances[childnode] = [lengths[0], lengths[1]]
                paths[childnode] = curnode

        unvisited.pop(curnode)

    def shortestroute(paths, start, end):
        shortestpath = []
        try:
            def rec(start, end):
                if end == start:
                    shortestpath.append(end)
                    return shortestpath[::-1]
                else:
                    shortestpath.append(end)
                    return rec(start, paths[end])
            return rec(start, end)
        except KeyError:
            return False

    finalpath = shortestroute(paths, pos, finalpos)

    if finalpath:
        for x in finalpath:
            if x == pos or x == finalpos:
                pass
            else:
                maze[x[0]][x[1]] = 'W'
    else:
        print("This maze not solvable, Blyat!")
        print()

    spit()
从复制导入deepcopy
从数学导入inf,sqrt
将maze_builderV2作为mb导入
如果uuuu name uuuuuu='\uuuuuuu main\uuuuuuu':
订单=10
空格=['X']+['.'表示范围内的X(顺序)]+['X']
迷宫=[范围内x的深度复制(空格)(顺序)]
maze.append(['X'表示范围内的X(顺序+2)])
迷宫.插入(0,['X'表示范围内的X(顺序+2)])
finalpos=(订单,订单)
位置=(1,1)
迷宫[pos[0]][pos[1]]='S'#初始化起始位置
迷宫[finalpos[0]][finalpos[1]='O'#初始化结束位置
mb.mazebuilder(maze=maze)
def spit():
对于迷宫中的x:
打印(x)
吐
打印()
mazemap={}
def scan():#将原始地图/迷宫转换为合适的数据结构。
对于范围内的x(1,订单+1):
对于范围(1,订单+1)内的y:
mazemap[(x,y)]={}
t=[(x-1,y),(x+1,y),(x,y-1),(x,y+1)]
对于t中的z:
如果迷宫[z[0]][z[1]=='X':
通过
其他:
mazemap[(x,y)][z]=[sqrt((位置[0]-z[0])**2+(位置[1]-z[1])**2),
sqrt((finalpos[0]-z[0])**2+(finalpos[1]-z[1])**2)]#到目的地的欧几里德距离(启发式)
扫描()
未访问=深度复制(mazemap)
距离={}
路径={}
#距离初始化:
对于未访问的节点:
如果节点==位置:
距离[node]=[0,sqrt((最终用户[0]-节点[0])**2+(最终用户[1]-节点[1])**2)]
其他:
距离[节点]=[inf,inf]
未经访问时!={}:
curnode=None
对于未访问的节点:
如果curnode==无:
curnode=节点
elif(距离[node][0]+距离[node][1])<(距离[curnode][0]+距离[curnode][1]):
curnode=节点
其他:
通过
对于childnode,mazemap[curnode]中的长度。项()
#从curnode到finalpos的长度-G长度,从curnode到finalpos的欧几里德(启发式)长度-H长度
#G长度+H长度<直接到达该子节点的欧几里德长度+从该子节点到达最终节点的欧几里德长度=找到更好的路径,更新已知距离和路径
如果长度[0]+长度[1]<距离[childnode][0]+距离[childnode][1]:
距离[childnode]=[Length[0],Length[1]]
路径[childnode]=curnode
unvisited.pop(curnode)
def短路由(路径、开始、结束):
最短路径=[]
尝试:
def rec(开始、结束):
如果结束==开始:
最短路径追加(结束)
返回最短路径[:-1]
其他:
最短路径追加(结束)
返回记录(开始,路径[结束])
返回记录(开始、结束)
除KeyError外:
返回错误
finalpath=短路由(路径、位置、最终路径)
如果最终路径:
对于finalpath中的x:
如果x==pos或x==finalpos:
通过
其他:
迷宫[x[0]][x[1]]='W'
其他:
打印(“这个迷宫不可解,布莱亚特!”)
打印()
吐
对于那些觉得我的代码太混乱,无法阅读我为帮助阅读而添加的注释的人。。。以下是我的代码要点:

  • 创建一个mazemap(字典中的所有坐标及其连接的相邻坐标以及从该相邻点到起始位置(G成本)和最终位置(H成本)的欧氏距离)
  • 选择“开始位置”作为当前节点。到其他节点的所有距离都初始化为无穷大
  • 对于每个节点,我们比较总路径成本,即G成本+H成本。选择总成本最低的节点作为下一个当前节点。每次选择新的当前节点时,我们都会将该节点添加到一个字典中,该字典会跟踪该节点是通过哪个节点到达的,以便更容易回溯并找到路径
  • 该过程将继续,直到当前节点成为最终位置
如果有人能帮我,那就太好了

编辑:由于有人询问迷宫构建算法,这里是:

# Maze generator - v2: Generates mazes that look like city streets (more or less...)

from copy import deepcopy
from random import randint, choice

if __name__ == "__main__":
    order = 10

    space = ['X']+['_' for x in range(order)]+['X']
    maze = [deepcopy(space) for x in range(order)]
    maze.append(['X' for x in range(order+2)])
    maze.insert(0, ['X' for x in range(order+2)])

    pos = (1, 1)
    finalpos = (order, order)

    maze[pos[0]][pos[1]] = 'S'  # Initializing a start position
    maze[finalpos[1]][finalpos[1]] = 'O'  # Initializing a end position

    def spit():
         for x in maze:
             print(x)

    blocks = []
    freespaces = [(x, y) for x in range(1, order+1) for y in range(1, order+1)]

    def blockbuilder(kind):
        param1 = param2 = 0
        double = randint(0, 1)
        if kind == 0:
            param2 = randint(3, 5)
            if double:
                param1 = 2
            else:
                param1 = 1
        else:
            param1 = randint(3, 5)
            if double:
                param2 = 2
            else:
                param2 = 1
        for a in range(blockstarter[0], blockstarter[0]+param2):
            for b in range(blockstarter[1], blockstarter[1]+param1):
                if (a+1, b) in blocks or (a-1, b) in blocks or (a, b+1) in blocks or (a, b-1) in blocks or (a, b) in blocks or (a+1, b+1) in blocks or (a-1, b+1) in blocks or (a+1, b-1) in blocks or (a-1, b-1) in blocks:
                    pass
                else:
                    if a > order+1 or b > order+1:
                        pass
                    else:
                        if maze[a][b] == 'X':
                            blocks.append((a, b))
                        else:
                            spaces = [(a+1, b), (a-1, b), (a, b+1), (a, b-1)]
                            for c in spaces:
                                if maze[c[0]][c[1]] == 'X':
                                    break
                                else:
                                    maze[a][b] = 'X'
                                    blocks.append((a, b))

    for x in range(1, order+1):
        for y in range(1, order+1):
            if (x, y) in freespaces:
                t = [(x+1, y), (x-1, y), (x, y+1), (x, y-1)]
                i = 0
                while i < len(t):
                    if maze[t[i][0]][t[i][1]] == 'X' or (t[i][0], t[i][1]) == pos or (t[i][0], t[i][1]) == finalpos:
                        del t[i]
                    else:
                        i += 1
                if len(t) > 2:
                    blockstarter = t[randint(0, len(t)-1)]
                    kind = randint(0, 1)  # 0 - vertical, 1 - horizontal
                    blockbuilder(kind)
                else:
                    pass

    # rch = choice(['d', 'u', 'r', 'l'])
    b = 0
    while b < len(blocks):
        block = blocks[b]
        t = {'d': (block[0]+2, block[1]), 'u': (block[0]-2, block[1]),
             'r': (block[0], block[1]+2), 'l': (block[0], block[1]-2)}
        rch = choice(['d', 'u', 'r', 'l'])
        z = t[rch]
        # if z[0] > order+1 or z[1] > order+1 or z[0] < 1 or z[1] < 1:
        # Decreased chance of having non solvable maze being generated...
        if z[0] > order-2 or z[1] > order-2 or z[0] < 2+2 or z[1] < 2+2:
            pass
        else:
            if maze[z[0]][z[1]] == 'X':
                if randint(0, 1):
                    set = None
                    if rch == 'u':
                        set = (z[0]+1, z[1])
                    elif rch == 'd':
                        set = (z[0]-1, z[1])
                    elif rch == 'r':
                        set = (z[0], z[1]-1)
                    elif rch == 'l':
                        set = (z[0], z[1]+1)
                    else:
                        pass
                    if maze[set[0]][set[1]] == '_':
                        # Checks so that no walls that block the entire way are formed
                        # Makes sure maze is solvable
                        sets, count = [
                            (set[0]+1, set[1]), (set[0]-1, set[1]), (set[0], set[1]+1), (set[0], set[1]-1)], 0
                        for blyat in sets:
                            while blyat[0] != 0 and blyat[1] != 0 and blyat[0] != order+1 and blyat[1] != order+1:
                                ch = [(blyat[0]+1, blyat[1]), (blyat[0]-1, blyat[1]),
                                      (blyat[0], blyat[1]+1), (blyat[0], blyat[1]-1)]
                                suka = []
                                for i in ch:
                                    if ch not in suka:
                                        if maze[i[0]][i[1]] == 'X':
                                            blyat = i
                                            break
                                        else:
                                            pass
                                        suka.append(ch)
                                    else:
                                        pass
                                else:
                                    blyat = None
                                if blyat == None:
                                    break
                                else:
                                    pass
                            else:
                                count += 1
                        if count < 1:
                            maze[set[0]][set[1]] = 'X'
                            blocks.append(set)
                        else:
                            pass
                    else:
                        pass
                else:
                    pass
        b += 1

    mazebuilder(maze, order)
    spit()

#迷宫生成器-v2:生成看起来像城市街道的迷宫(或多或少…)
从复制导入deepcopy
从随机导入randint,选择
如果名称=“\uuuuu main\uuuuuuuu”:
订单=10
空格=['X']+['.'表示范围内的X(顺序)]+['X']
迷宫=[范围内x的深度复制(空格)(顺序)]
maze.append(['X'表示范围内的X(顺序+2)])
迷宫.插入(0,['X'表示范围内的X(顺序+2)])
位置=(1,1)
finalpos=(订单,订单)
迷宫[pos[0]][pos[1]]='S'#初始化起始位置
迷宫[finalpos[1]][finalpos[1]]='O'#初始化结束位置
def spit():
对于迷宫中的x:
打印(x)
块=[]
自由空间=[(x,y)表示范围(1,顺序+1)中的x,表示范围(1,顺序+1)中的y]
def区块构建器(种类):
param1=param2=0
double=randint(0,1)
如果种类==0:
param2=randint(3,5)
如果加倍:
参数1=2
其他:
参数1=1
其他:
param1=randint(3,5)
如果加倍:
参数2=2
其他:
参数2=1
对于范围内的(块启动器[0],块启动器[0]+参数