我正在研究一个A-Star算法来解决8道难题。我的大部分算法都失败了,但我在输出方面遇到了问题。它可以很好地解决这个问题[0,1,2,3,8,4,6,7,5],但当涉及到更复杂的问题时,例如[6,4,0,1,5,3,7,8,2],它一直在同一条路径上循环,似乎没有找到解决方案。如果你能给我指导或指出我哪里出错了,请帮忙。非常感谢。
代码如下:
from math import sqrt
import time
#fring- to keep the nodes
#expand: the function to expand one node at a time
#heuristic: calculate the cheapest cost
#f()- total cost
#h()- the number index to the goal
#expanded_nodes- have all the visited
startime = time.time_ns()
def astar(puzzle):
#intializing the variables
cost = 0
node = Node(puzzle,cost)
loop = True
#the possible nodes
fringe = []
#After expanding the list
expanded = []
# maybe need it keep it for now
visit = set() #keep track of all the visit
#the goal state
goal = [0,1,2,3,4,5,6,7,8]
#possible combination move
possible_move = [[1,3],[0,2,4],[1,5],[0,4,6],[1,3,5,7],[2,4,8],[3,7],[4,6,8],[5,7]]
#intialization of the first node
fringe = [node]
#print('state:'+str(node.state))
#start the loop
while loop:
print('\nthe state of this game position is:\n ' + str(node.state) +"\n\n")
#find the lowest cost in the fringe then expand the lowest cost node
min_cost = fringe[0].cost
min_node = fringe[0]
for node in fringe[:]:
if node.cost < min_cost:
min_cost = node.cost
min_node = node
#append the node that was just expaneded into the expanded list but keep the list not expaneded in fringe
expanded.append(min_node)
print('the min node '+str(min_node.state)+'\nthe cheapest cost: '+ str(min_cost))
#removes the min cost node from fringe
for node in fringe[:]:
if node.state == min_node.state:
fringe.remove(node)
#when there is a solution in the expanded
for node in expanded:
if node.state == goal:
loop = False
#traverse the nodes that was expanded and add the children to the fringe
for node in expanded[:]:
#append all the successor/children and set the children's parent to fringe
blank = node.state.index(8)
print('the index of the blank is '+ str(blank))
print('\n')
possible_pos = possible_move[blank]
print('possible pos '+ str(possible_pos))
for i in possible_pos:
print('\n')
possible_sw = node.state[:]
print('index swap = '+ str(i))
possible_sw[blank] = possible_sw[i]
possible_sw[i] = 8
print('the child node is ' + str(possible_sw))
node.cost = manhattan(possible_sw, goal)
fringe.append(Node(possible_sw,node.cost,node))
print('the cost this node state: '+ str(node.cost))
expanded.pop(0)
#finding the solution
move = 0
while node.parent:
expanded.append(node.state.index(8))
node = node.parent
move += 1
print('moves made '+ str(move))
expanded.reverse()
print('moves list '+ str(expanded))
endtime = time.time_ns()
executionTime = ( endtime - startime)
print('Execution time in ns: ' + str(executionTime))
return expanded
#Try the Manhattan Distance
def manhattan(a, b):
return sum(abs(val1-val2) for val1, val2 in zip(a,b))
class Node:
def __init__(self,state,cost,parent = None):
self.parent = parent
self.state = state
self.cost = cost
self.children = []
#test case
p = [0, 1, 2, 3, 4, 5, 6, 8, 7]
p = [0, 1, 2, 3, 8, 4, 6, 7, 5]
#p= [6, 4, 0, 1, 5, 3, 7, 8, 2]
#p = [1, 8, 2, 0, 3, 5, 6, 4, 7]
print("++++++++++A*++++++++++++")
astar(p)