在编写 A * Search 算法后,我一直在苦苦挣扎,因为当城市数量大于8
时,算法将不会返回任何答案(或者说是非常缓慢)。
城市存储在二维数组中,其中点cityList[x][y]
是城市x
和城市y
之间的距离(它也与cityList[y][x]
相同)
由于我必须同时使用city
类和每条路线的开头来记住路线长度以及已经尝试过哪条路线,所以有点麻烦。
还为添加的每个城市创建了新路线。
任何人都可以帮助优化它或确保它可以在越来越多的城市中运作。
class city(object):
def __init__(self, number):
self.number = number
global size
self.possibleChildren = []
for i in range(0,size):
if i != number:
self.possibleChildren.append(i)
def getNo(self):
return self.number
def getSize(self):
return len(self.possibleChildren)
def getOptions(self, i):
self.i = i
return self.possibleChildren[self.i]
def deleteNo(self, option):
self.option = option
if(self.option in self.possibleChildren):
self.possibleChildren.remove(self.option)
def addFinalStep(self, beginning):
self.beginning = beginning
self.possibleChildren.append(self.beginning)
def Astar():
routeList = []
#routeList[i][0] = distance travelled, routeList[i][1] = number of cities past
for i in range(0, size):
newRoute = []
newCity = city(i)
newRoute.append(0)
newRoute.append(1)
newRoute.append(newCity)
routeList.append(newRoute)
while True:
toUse = 0
smallest = -2
#Now search through the routeList to find the shortest route length
for i in range(0, len(routeList)):
#getSize() checks if there are any cities that can be visited by
this route that have not already been tried, this list is
stored in the city class
if routeList[i][1 + routeList[i][1]].getSize() != 0:
if routeList[i][0] < smallest or smallest == -2:
smallest = routeList[i][0]
toUse = i
elif routeList[i][1 + routeList[i][1]].getSize() == 0:
routeList.remove(i)
routeRec = []
#Creates the new route
for i in range (0, len(routeList[toUse])):
routeRec.append(routeList[toUse][i])
currentCity = routeRec[1 + routeRec[1]]
possibleChildren = []
for i in range(0, currentCity.getSize()):
possibleChildren.append(currentCity.getOptions(i))
smallest = 0
newCityNo = 2
for i in range(0, size):
if(i in possibleChildren):
#Finds the closest city
if smallest > cityList[currentCity.getNo()][i] or smallest == 0:
newCityNo = i
smallest = cityList[currentCity.getNo()][i]
#If the new city to visit is the same as the first, the algorithm
#has looped to the beginning and finished
if newCityNo == routeRec[2].getNo():
print("Tour Length")
print(routeRec[0] + smallest)
print("Route: ")
for i in range(2,len(routeRec)):
print(routeRec[i].getNo())
return(routeRec[0] + smallest)
#deletes all cities that have been tried
routeList[toUse][1 + routeRec[1]].deleteNo(newCityNo)
nextCity = city(newCityNo)
#deletes all cities that are already in the route
for i in range(2, 2 + routeRec[1]):
nextCity.deleteNo(routeRec[i].getNo())
#When the route is full, it can return to the first city
routeRec[1] = routeRec[1] + 1
print(routeRec[1])
if routeRec[1] == size:
#first city added to potential cities to visit
nextCity.addFinalStep(routeRec[2].getNo())
routeRec.append(nextCity)
routeRec[0] = routeRec[0] + smallest
routeList.append(routeRec)
答案 0 :(得分:0)
你需要在这里做一些分解。 您需要数据结构来保存和获取要扩展的节点,在本例中为堆。 您还需要一些启发式,您可以将其作为参数传递。
实施A *
# A* Algorithm
# heuristic - Heuristic function expecting state as operand
# world - Global
# sstate - Start state
# endstate - End state, state to find
# expandfn - function(world, state) returning array of tuples (nstate, cost)
# where nstate is the state reached from expanded state and cost is the 'size'
# of the edge.
def Astar(heuristic, world, sstate, endstate, expandfn):
been = set()
heap = Heap()
end = None
# We hape tuples (state, pathlen, parent state tuple) in heap
heap.push((sstate, 0, None), 0) # Heap inserting with weight 0
while not heap.isempty():
# Get next state to expand from heap
nstate = heap.pop()
# If already seen state not expand
if nstate[0] in been:
continue
# If goal reached
if nstate[0] === endstate:
end = nstate
break
# Add state as expanded
been.add(nstate[0])
# For each state reached from current state
for expstate in expandfn(world, nstate[0]):
pathlen = nstate[1] + expstate[1]
# Expanding state with heap weight 'path length + heuristic'
heap.push((expstate[0], pathlen, nstate), pathlen + heuristic(expstate[0]))
# End of while loop
if end is None:
return None
# Getting path from end node
pathlen = end[1]
res = []
while end[2] is not None:
res.append(end[0])
end = end[2]
res.reverse()
return res, pathlen