我最近开始尝试编写一个使用Zelle的python编程书中的graphics.py模块的程序。程序的想法是它创建一个图形窗口并接受两个点,即开始和结束。它绘制起点并进行bfs搜索,然后一旦到达终点,它就会绘制最短路径(无论如何还没有对角线)。它在技术上有效,但它非常慢,并且在前两到三次迭代中的任何地方都需要永远。我试着到处寻找具有快速查找的数据结构,以及实现节点以便允许回溯的有效方法,而我无法弄明白。我非常感谢任何帮助,向我解释我可以改进我的实施。
以下是python 3.5.2中的代码:
from graphics import *
from collections import deque
TITLE = "Breadth-First Search"
WIDTH = 500
HEIGHT = 500
win = GraphWin(TITLE, WIDTH, HEIGHT)
win.setCoords(0,0,20,20)
class Node:
def __init__(self, x, y, parent = None):
self.x = x
self.y = y
self.parent = parent
self.pos2D = Point(self.x, self.y)
self.pos2D.draw(win)
def getPos(self):
return (self.x, self.y)
def draw(self, win, color = None):
if color != None:
self.pos2D.undraw()
self.pos2D.setFill(color)
self.pos2D.draw(win)
return
self.pos2D.draw(win)
def neighbors(state):
return (Node(state.x, state.y+1, state), Node(state.x, state.y-1,
state), Node(state.x-1, state.y, state), Node(state.x+1, state.y,
state))
def drawPath(endState):
state.draw(win, 'red')
while state.parent != None:
state = state.parent
state.draw(win, 'red')
def bfs():
start = (10,10)
finish = (15,15)
explored = set()
frontier = deque()
frontier.append((Node(start[0], start[1])))
while len(frontier) != 0:
state = frontier.popleft()
explored.add(state)
if state.getPos() == finish:
break
for neighbor in neighbors(state):
if neighbor not in explored:
frontier.append(neighbor)
bfs()
答案 0 :(得分:1)
运行代码的主要延迟是此优化:
if neighbor not in explored:
frontier.append(neighbor)
因为它根本不起作用。在此处添加else:
子句以将单词skipped
打印到控制台,您将看到永远不会使用else:
。优化不起作用,因为您放入集合中的内容都是唯一的。 @ user2357112关于缺少__hash__
,__eq__
和__ne__
方法的评论是解决此问题的正确方法(我在下面使用了更简单的修复方法。)
次要延迟是您正在创建(和绘制)许多Node
个实例,而这些实例最终未被使用,因为它们已被探索过。
下面是代码的返工,试图解决这两个问题:
from collections import deque
from graphics import *
TITLE = "Breadth-First Search"
WIDTH, HEIGHT = 500, 500
class Node:
def __init__(self, x, y, parent=None):
self.x = x
self.y = y
self.parent = parent
self.pos2D = Point(self.x, self.y)
self.pos2D.draw(win)
def getPos(self):
return (self.x, self.y)
def unexplored_neighbors(state):
neighbors = []
for dx, dy in [(0, 1), (0, -1), (-1, 0), (1, 0)]:
if (state.x + dx, state.y + dy) not in explored:
neighbors.append(Node(state.x + dx, state.y + dy, state))
return neighbors
def bfs():
start = (10, 10)
finish = (15, 15)
frontier = deque()
frontier.append(Node(*start))
while frontier:
state = frontier.popleft()
if state.getPos() == finish:
break
explored.add((state.x, state.y))
for neighbor in unexplored_neighbors(state):
frontier.append(neighbor)
win = GraphWin(TITLE, WIDTH, HEIGHT)
win.setCoords(0, 0, 20, 20)
explored = set()
bfs()
win.getMouse()
win.close()
可以帮助您找到性能问题的是cProfile
模块:
# bfs()
import cProfile
cProfile.run('bfs()')
# win.getMouse()
# win.close()
中阅读