Python 我的A-star实施似乎非常缓慢,需要建议和帮助来说明我做错了什么
我对Dijkstra和A-Star实现的测试表明,我的A-Star实现大约慢了2倍。通常,Dijkstra和A-star的等效实现应该会看到A-star击败Dijkstra。但这里的情况并非如此,因此我对A-star的实现提出了质疑。所以我希望有人告诉我,我在实现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__
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]+参数