class EarlyEagerBeamSearch(AbstractSearch): """A beam search that prunes early (after each state expansion) and eagerly (weeding out worse successors)""" def __init__(self, state, beamsize, **kwargs): assert isinstance(state, AbstractSearchState) self.beamsize = beamsize super(EarlyEagerBeamSearch, self).__init__(**kwargs) self.fringe = PriorityQueue(state, lambda x: x.score, self.minimize, length=0, blockworse=False, blockequal=False, duplicates=kwargs['duplicates'] if 'duplicates' in kwargs else False) self.incomplete = True def prune(self, state): if self.debug: l = len(self.fringe) print("\t[pynlpl debug] pruning with beamsize " + str(self.beamsize) + "...", end="", file=stderr) self.fringe.prunebyscore(state.score(), retainequalscore=True) self.fringe.prune(self.beamsize) if self.debug: print(" (" + str(l) + " to " + str(len(self.fringe)) + " items)", file=stderr)
def searchtop(self, n=10): """Return the top n best resulta (or possibly less if not enough is found)""" solutions = PriorityQueue([], lambda x: x.score, self.minimize, length=n, blockworse=False, blockequal=False, duplicates=False) for solution in self: solutions.append(solution) return solutions
def __init__(self, state, beamsize, **kwargs): assert isinstance(state, AbstractSearchState) self.beamsize = beamsize super(EarlyEagerBeamSearch, self).__init__(**kwargs) self.fringe = PriorityQueue(state, lambda x: x.score, self.minimize, length=0, blockworse=False, blockequal=False, duplicates=kwargs['duplicates'] if 'duplicates' in kwargs else False) self.incomplete = True
class EarlyEagerBeamSearch(AbstractSearch): """A beam search that prunes early (after each state expansion) and eagerly (weeding out worse successors)""" def __init__(self, state, beamsize, **kwargs): assert isinstance(state, AbstractSearchState) self.beamsize = beamsize super(EarlyEagerBeamSearch,self).__init__(**kwargs) self.fringe = PriorityQueue(state, lambda x: x.score, self.minimize, length=0, blockworse=False, blockequal=False,duplicates= kwargs['duplicates'] if 'duplicates' in kwargs else False) self.incomplete = True def prune(self, state): if self.debug: l = len(self.fringe) print("\t[pynlpl debug] pruning with beamsize " + str(self.beamsize) + "...",end="",file=stderr) self.fringe.prunebyscore(state.score(), retainequalscore=True) self.fringe.prune(self.beamsize) if self.debug: print(" (" + str(l) + " to " + str(len(self.fringe)) + " items)",file=stderr)
def __init__(self, state, **kwargs): assert isinstance(state, AbstractSearchState) super(HillClimbingSearch, self).__init__(**kwargs) self.fringe = PriorityQueue([state], lambda x: x.score, self.minimize, length=0, blockworse=True, blockequal=False, duplicates=False)
def __init__(self, states, beamsize, **kwargs): if isinstance(states, AbstractSearchState): states = [states] else: assert all((isinstance(x, AbstractSearchState) for x in states)) self.beamsize = beamsize if 'eager' in kwargs: self.eager = kwargs['eager'] else: self.eager = False super(BeamSearch, self).__init__(**kwargs) self.incomplete = True self.duplicates = kwargs[ 'duplicates'] if 'duplicates' in kwargs else False self.fringe = PriorityQueue(states, lambda x: x.score, self.minimize, length=0, blockworse=False, blockequal=False, duplicates=self.duplicates)
def __iter__(self): """Generator yielding *all* valid goalstates it can find""" i = 0 while len(self.fringe) > 0: i += 1 if self.debug: print("\t[pynlpl debug] *************** STARTING ROUND #" + str(i) + " ****************", file=stderr) b = 0 #Create a new empty fixed-length priority queue (this implies there will be pruning if more items are offered than it can hold!) successors = PriorityQueue([], lambda x: x.score, self.minimize, length=self.beamsize, blockworse=False, blockequal=False, duplicates=self.duplicates) while len(self.fringe) > 0: b += 1 if self.debug: print("\t[pynlpl debug] *************** ROUND #" + str(i) + " BEAM# " + str(b) + " ****************", file=stderr) #if self.debug: print >>stderr,"\t[pynlpl debug] FRINGE: ", self.fringe state = self.poll(self.fringe)() if self.debug: try: print("\t[pynlpl debug] CURRENT STATE (depth " + str(state.depth()) + "): " + str(state), end="", file=stderr) except AttributeError: print("\t[pynlpl debug] CURRENT STATE: " + str(state), end="", file=stderr) print(" hash=" + str(hash(state)), file=stderr) try: print(" score=" + str(state.score()), file=stderr) except: pass if not self.usememory or (self.usememory and not hash(state) in self._visited): self.traversed += 1 #Evaluate state if state.test(self.goalstates): if self.debug: print("\t[pynlpl debug] Valid goalstate, yielding", file=stderr) self.solutions += 1 #counts the number of solutions yield state elif self.debug: print("\t[pynlpl debug] (no goalstate, not yielding)", file=stderr) if self.eager: score = state.score() #Expand the specified state and offer to the fringe statecount = offers = 0 for j, s in enumerate(state.expand()): statecount += 1 if self.debug >= 2: print("\t[pynlpl debug] (Round #" + str(i) + " Beam #" + str(b) + ") Expanded state #" + str(j + 1) + ", offering to successor pool: " + str(s), end="", file=stderr) try: print(s.score(), end="", file=stderr) except: print("ERROR SCORING!", end="", file=stderr) pass if not self.maxdepth or s.depth() <= self.maxdepth: if not self.eager: #use all successors (even worse ones than the current state) offers += 1 accepted = successors.append(s) else: #use only equal or better successors if s.score() >= score: offers += 1 accepted = successors.append(s) else: accepted = False if self.debug >= 2: if accepted: print(" ACCEPTED", file=stderr) else: print(" REJECTED", file=stderr) else: if self.debug >= 2: print(" REJECTED, MAXDEPTH EXCEEDED.", file=stderr) elif self.debug: print( "\t[pynlpl debug] Not offered to successor pool, maxdepth exceeded", file=stderr) if self.debug: print("\t[pynlpl debug] Expanded " + str(statecount) + " states, " + str(offers) + " offered to successor pool", file=stderr) if self.keeptraversal: self._traversal.append(state) if self.usememory: self._visited[hash(state)] = True self.prune( state ) #calls prune method (does nothing by default in this search!!!) else: if self.debug: print( "\t[pynlpl debug] State already visited before, not expanding again... (hash=" + str(hash(state)) + ")", file=stderr) #AFTER EXPANDING ALL NODES IN THE FRINGE/BEAM: #set fringe for next round self.fringe = successors #Pruning is implicit, successors was a fixed-size priority queue if self.debug: print("\t[pynlpl debug] (Round #" + str(i) + ") Implicitly pruned with beamsize " + str(self.beamsize) + "...", file=stderr) #self.fringe.prune(self.beamsize) if self.debug: print(" (" + str(offers) + " to " + str(len(self.fringe)) + " items)", file=stderr) if self.debug: print("\t[pynlpl debug] Search complete: " + str(self.solutions) + " solution(s), " + str(self.traversed) + " states traversed in " + str(i) + " rounds with " + str(b) + " beams", file=stderr)
def __init__(self, state, beamsize, **kwargs): assert isinstance(state, AbstractSearchState) self.beamsize = beamsize super(EarlyEagerBeamSearch,self).__init__(**kwargs) self.fringe = PriorityQueue(state, lambda x: x.score, self.minimize, length=0, blockworse=False, blockequal=False,duplicates= kwargs['duplicates'] if 'duplicates' in kwargs else False) self.incomplete = True
def __iter__(self): """Generator yielding *all* valid goalstates it can find""" i = 0 while len(self.fringe) > 0: i +=1 if self.debug: print("\t[pynlpl debug] *************** STARTING ROUND #" + str(i) + " ****************",file=stderr) b = 0 #Create a new empty fixed-length priority queue (this implies there will be pruning if more items are offered than it can hold!) successors = PriorityQueue([], lambda x: x.score, self.minimize, length=self.beamsize, blockworse=False, blockequal=False,duplicates= self.duplicates) while len(self.fringe) > 0: b += 1 if self.debug: print("\t[pynlpl debug] *************** ROUND #" + str(i) + " BEAM# " + str(b) + " ****************",file=stderr) #if self.debug: print >>stderr,"\t[pynlpl debug] FRINGE: ", self.fringe state = self.poll(self.fringe)() if self.debug: try: print("\t[pynlpl debug] CURRENT STATE (depth " + str(state.depth()) + "): " + str(state),end="",file=stderr) except AttributeError: print("\t[pynlpl debug] CURRENT STATE: " + str(state),end="",file=stderr) print(" hash="+str(hash(state)),file=stderr) try: print(" score="+str(state.score()),file=stderr) except: pass if not self.usememory or (self.usememory and not hash(state) in self._visited): self.traversed += 1 #Evaluate state if state.test(self.goalstates): if self.debug: print("\t[pynlpl debug] Valid goalstate, yielding",file=stderr) self.solutions += 1 #counts the number of solutions yield state elif self.debug: print("\t[pynlpl debug] (no goalstate, not yielding)",file=stderr) if self.eager: score = state.score() #Expand the specified state and offer to the fringe statecount = offers = 0 for j, s in enumerate(state.expand()): statecount += 1 if self.debug >= 2: print("\t[pynlpl debug] (Round #" + str(i) +" Beam #" + str(b) + ") Expanded state #" + str(j+1) + ", offering to successor pool: " + str(s),end="",file=stderr) try: print(s.score(),end="",file=stderr) except: print("ERROR SCORING!",end="",file=stderr) pass if not self.maxdepth or s.depth() <= self.maxdepth: if not self.eager: #use all successors (even worse ones than the current state) offers += 1 accepted = successors.append(s) else: #use only equal or better successors if s.score() >= score: offers += 1 accepted = successors.append(s) else: accepted = False if self.debug >= 2: if accepted: print(" ACCEPTED",file=stderr) else: print(" REJECTED",file=stderr) else: if self.debug >= 2: print(" REJECTED, MAXDEPTH EXCEEDED.",file=stderr) elif self.debug: print("\t[pynlpl debug] Not offered to successor pool, maxdepth exceeded",file=stderr) if self.debug: print("\t[pynlpl debug] Expanded " + str(statecount) + " states, " + str(offers) + " offered to successor pool",file=stderr) if self.keeptraversal: self._traversal.append(state) if self.usememory: self._visited[hash(state)] = True self.prune(state) #calls prune method (does nothing by default in this search!!!) else: if self.debug: print("\t[pynlpl debug] State already visited before, not expanding again... (hash=" + str(hash(state)) +")",file=stderr) #AFTER EXPANDING ALL NODES IN THE FRINGE/BEAM: #set fringe for next round self.fringe = successors #Pruning is implicit, successors was a fixed-size priority queue if self.debug: print("\t[pynlpl debug] (Round #" + str(i) + ") Implicitly pruned with beamsize " + str(self.beamsize) + "...",file=stderr) #self.fringe.prune(self.beamsize) if self.debug: print(" (" + str(offers) + " to " + str(len(self.fringe)) + " items)",file=stderr) if self.debug: print("\t[pynlpl debug] Search complete: " + str(self.solutions) + " solution(s), " + str(self.traversed) + " states traversed in " + str(i) + " rounds with " + str(b) + " beams",file=stderr)
def searchtop(self,n=10): """Return the top n best resulta (or possibly less if not enough is found)""" solutions = PriorityQueue([], lambda x: x.score, self.minimize, length=n, blockworse=False, blockequal=False,duplicates=False) for solution in self: solutions.append(solution) return solutions
def test_append_maximized_fixedlength(self): """Fixed-length priority queue (max)""" global values pq = PriorityQueue(values, lambda x: x, False, 4, False, False) result = list(iter(pq)) self.assertEqual(result, maxtomin[:4])
def test_append_minimized_blockworse(self): """Minimized PriorityQueue (with blockworse)""" global values pq = PriorityQueue(values, lambda x: x, True, 0, True, False) result = list(iter(pq)) self.assertEqual(result, [1, 3])
def test_append_maximized_blockworse_blockequal(self): """Maximized PriorityQueue (with blockworse + blockequal)""" global values pq = PriorityQueue(values, lambda x: x, False, 0, True, True) result = list(iter(pq)) self.assertEqual(result, [8, 6, 3])
def test_append_maximized(self): """Maximized PriorityQueue""" global values pq = PriorityQueue(values, lambda x: x, False, 0, False, False) result = list(iter(pq)) self.assertEqual(result, maxtomin)