在代码底部运行的示例需要很长时间才能在我的机器上解决:
dumrat@dumrat:~/programming/python$ time python camels.py [['F', 'F', 'F', 'G', 'B', 'B', 'B'], ['F', 'F', 'G', 'F', 'B', 'B', 'B'], ['F', 'F', 'B', 'F', 'G', 'B', 'B'], ['F', 'F', 'B', 'F', 'B', 'G', 'B'], ['F', 'F', 'B', 'G', 'B', 'F', 'B'], ['F', 'G', 'B', 'F', 'B', 'F', 'B'], ['G', 'F', 'B', 'F', 'B', 'F', 'B'], ['B', 'F', 'G', 'F', 'B', 'F', 'B'], ['B', 'F', 'B', 'F', 'G', 'F', 'B'], ['B', 'F', 'B', 'F', 'B', 'F', 'G'], ['B', 'F', 'B', 'F', 'B', 'G', 'F'], ['B', 'F', 'B', 'G', 'B', 'F', 'F'], ['B', 'G', 'B', 'F', 'B', 'F', 'F'], ['B', 'B', 'G', 'F', 'B', 'F', 'F'], ['B', 'B', 'B', 'F', 'G', 'F', 'F']] real 0m20.883s user 0m20.549s sys 0m0.020s
这是代码:
import Queue fCamel = 'F' bCamel = 'B' gap = 'G' def solution(formation): return len([i for i in formation[formation.index(fCamel) + 1:] if i == bCamel]) == 0 def heuristic(formation): fCamels, score = 0, 0 for i in formation: if i == fCamel: fCamels += 1; elif i == bCamel: score += fCamels; else: pass return score def getneighbors (formation): igap = formation.index(gap) res = [] # AB_CD --> A_BCD | ABC_D | B_ACD | ABD_C def genn(i,j): temp = list(formation) temp[i], temp[j] = temp[j], temp[i] res.append(temp) if(igap > 0): genn(igap, igap-1) if(igap > 1): genn(igap, igap-2) if igap < len(formation) - 1: genn(igap, igap+1) if igap < len(formation) - 2: genn(igap, igap+2) return res class node: def __init__(self, a, g, p): self.arrangement = a self.g = g self.parent = p def astar (formation, heuristicf, solutionf, genneighbors): openlist = Queue.PriorityQueue() openlist.put((heuristicf(formation), node(formation, 0, None))) closedlist = [] while 1: try: f, current = openlist.get() except IndexError: current = None if current is None: print "No solution found" return None; if solutionf(current.arrangement): path = [] cp = current while cp != None: path.append(cp.arrangement) cp = cp.parent path.reverse() return path #arr = current.arrangement closedlist.append(current) neighbors = genneighbors(current.arrangement) for neighbor in neighbors: if neighbor in closedlist: pass else: openlist.put((current.g + heuristicf(neighbor), node(neighbor, current.g + 1, current))) #sorted(openlist, cmp = lambda x, y : x.f > y.f) def solve(formation): return astar(formation, heuristic, solution, getneighbors) print solve([fCamel, fCamel, fCamel, gap, bCamel, bCamel, bCamel]) #print solve([fCamel, fCamel, fCamel, fCamel, gap, bCamel, bCamel, bCamel, bCamel])
每只只供三只骆驼。我想至少这样做4次。该测试用例仍在运行(现在:()已经大约5分钟了。如果完成,我将对其进行更新。
我应该怎么做才能改善这段代码?(通常以性能为依据,但也欢迎其他建议)。
我以前也被这个绊倒了。这里的瓶颈实际上是if neighbor in closedlist。
if neighbor in closedlist
该in语句是如此易于使用,你忘记了它是线性搜索,而当你在列表上进行线性搜索时,它的添加速度很快。你可以做的是将closedlist转换为set对象。这样可以保留其项目的哈希值,因此in操作员的效率比列表高得多。但是,列表不是可散列的项目,因此你必须将配置更改为元组而不是列表。
closedlist
如果的顺序对closedlist算法至关重要,则可以为in运算符使用一个集合,并为结果保留一个并行列表。
我尝试了一个简单的实现,包括aaronasterling的namedtuple技巧,它在第一个示例中的执行时间为0.2秒,在第二个示例中的执行时间为2.1秒,但是我没有尝试验证第二个较长示例的结果。
aaronasterling
namedtuple