def setParameter(self, name, value): name = name.lower() if name in ("size", "tabusize"): self._tabuList = TabuList(_parseSize(value)) elif name == "weight": if value in ("decreasing", "decr"): self.weight = self._decreasingWeight else: self.weight = lambda: 1 elif name == "name": self._name = value else: print __doc__ raise ValueError("Invalid param '%s' for %s" % (name, self.__class__.__name__))
def prepareForRun(self): # if no numtabu* params given, use infinite state tabulist if self._NUM_TABU_ACTIONS is None and self._NUM_TABU_STATES is None and self._NUM_TABU_TRANSITIONS is None: self.log("Using default: 'numtabustates:infinite'") self._NUM_TABU_STATES = INFINITY self._suggesters = [] # the funcs that suggest an action # order: action, state, transition if self._NUM_TABU_ACTIONS is not None: self._tabulist_action = TabuList(self._NUM_TABU_ACTIONS) self._suggesters.append(self._newAction) if self._NUM_TABU_STATES is not None: self._tabulist_state = TabuList(self._NUM_TABU_STATES) self._suggesters.append(self._newStateAction) if self._NUM_TABU_TRANSITIONS is not None: self._tabulist_transition = TabuList(self._NUM_TABU_TRANSITIONS) self._suggesters.append(self._newTransitionAction)
class TabuListUser: # The tabulist. # There's only 1 tabulist per process (it's a class variable). _THE_TABULIST = TabuList() # Locked when somebody's using the tabulist. _TABULIST_LOCK = Lock() # Number of connected TabuListUsers. _CONNECTED = 0 _CONN_LOCK = Lock() _PARAMS = None def __init__(self, params=None): TabuListUser._CONN_LOCK.acquire() TabuListUser._CONNECTED += 1 self._connNum = TabuListUser._CONNECTED if params is not None: TabuListUser._PARAMS = params TabuListUser._CONN_LOCK.release() def getParameters(self): return TabuListUser._PARAMS def connNum(self): return self._connNum def len(self): TabuListUser._TABULIST_LOCK.acquire() le = len(TabuListUser._THE_TABULIST) TabuListUser._TABULIST_LOCK.release() return le def add(self, item): TabuListUser._TABULIST_LOCK.acquire() TabuListUser._THE_TABULIST.add(item) TabuListUser._TABULIST_LOCK.release() def addMany(self, items): TabuListUser._TABULIST_LOCK.acquire() for item in items: TabuListUser._THE_TABULIST.add(item) TabuListUser._TABULIST_LOCK.release() def tabunessOf(self, items): """ Eg. If the 3 first items are tabu and the last one is not, returns: (True,True,True,False) """ TabuListUser._TABULIST_LOCK.acquire() to = tuple([i in TabuListUser._THE_TABULIST for i in items]) TabuListUser._TABULIST_LOCK.release() return to
def setParameter(self,name,value): name = name.lower() if name in ("size","tabusize"): self._tabuList = TabuList( _parseSize(value) ) elif name == "weight": if value in ("decreasing","decr"): self.weight = self._decreasingWeight else: self.weight = lambda: 1 elif name == "name": self._name = value else: print __doc__ raise ValueError( "Invalid param '%s' for %s"%(name,self.__class__.__name__))
def prepareForRun(self): # if no numtabu* params given, use infinite state tabulist if (self._NUM_TABU_ACTIONS is None and self._NUM_TABU_STATES is None and self._NUM_TABU_TRANSITIONS is None): self.log("Using default: 'numtabustates:infinite'") self._NUM_TABU_STATES = INFINITY self._suggesters = [] # the funcs that suggest an action # order: action, state, transition if self._NUM_TABU_ACTIONS is not None: self._tabulist_action = TabuList(self._NUM_TABU_ACTIONS) self._suggesters.append(self._newAction) if self._NUM_TABU_STATES is not None: self._tabulist_state = TabuList(self._NUM_TABU_STATES) self._suggesters.append(self._newStateAction) if self._NUM_TABU_TRANSITIONS is not None: self._tabulist_transition = TabuList(self._NUM_TABU_TRANSITIONS) self._suggesters.append(self._newTransitionAction)
class Guidance(GuidanceBase): def __init__(self): GuidanceBase.__init__(self) self._NUM_TABU_ACTIONS = None self._NUM_TABU_STATES = None self._NUM_TABU_TRANSITIONS = None self._tabulist_action = None self._tabulist_state = None self._tabulist_transition = None def setParameter(self, paramname, paramvalue): accepted = ("numtabuactions", "numtabustates", "numtabutransitions") if paramname == 'numtabuactions': self._NUM_TABU_ACTIONS = self._parseSize(paramname, paramvalue) elif paramname == 'numtabustates': self._NUM_TABU_STATES = self._parseSize(paramname, paramvalue) elif paramname == 'numtabutransitions': self._NUM_TABU_TRANSITIONS = self._parseSize(paramname, paramvalue) else: print __doc__ raise Exception( "Invalid parameter '%s' for tabuguidance. Accepted parameters: %s" % paramname, accepted) GuidanceBase.setParameter(self, paramname, paramvalue) def _parseSize(self, paramname, paramvalue): if paramvalue == float("infinity") or paramvalue is INFINITY or \ paramvalue in ("inf","infinite","infinity"): return INFINITY try: return int(paramvalue) except ValueError: raise Exception( "Tabuguidance: invalid '%s' value: %s. It should be a positive integer or 'infinite'." % (paramname, paramvalue)) def prepareForRun(self): # if no numtabu* params given, use infinite state tabulist if (self._NUM_TABU_ACTIONS is None and self._NUM_TABU_STATES is None and self._NUM_TABU_TRANSITIONS is None): self.log("Using default: 'numtabustates:infinite'") self._NUM_TABU_STATES = INFINITY self._suggesters = [] # the funcs that suggest an action # order: action, state, transition if self._NUM_TABU_ACTIONS is not None: self._tabulist_action = TabuList(self._NUM_TABU_ACTIONS) self._suggesters.append(self._newAction) if self._NUM_TABU_STATES is not None: self._tabulist_state = TabuList(self._NUM_TABU_STATES) self._suggesters.append(self._newStateAction) if self._NUM_TABU_TRANSITIONS is not None: self._tabulist_transition = TabuList(self._NUM_TABU_TRANSITIONS) self._suggesters.append(self._newTransitionAction) def markExecuted(self, transition): # special case: add the very first (source) state to the tabu-list statelist = self._tabulist_state if statelist and len(statelist) == 0: statelist.add(transition.getSourceState()) # add actions/states/transitions to tabulists if given tabulist exists if self._tabulist_action is not None: self._tabulist_action.add(str(transition.getAction())) if self._tabulist_state is not None: self._tabulist_state.add(str(transition.getDestState())) if self._tabulist_transition is not None: self._tabulist_transition.add(str(transition)) GuidanceBase.markExecuted(self, transition) def suggestAction(self, from_state): out_trans = from_state.getOutTransitions() random.shuffle(out_trans) for suggester in self._suggesters: action = suggester(out_trans) if action is not None: return action # no non-tabu actions found, a random action is our best suggestion... return out_trans[0].getAction() # out_trans has been shuffled def _newAction(self, trans): """returns a non-tabu action, or None""" for t in trans: if str(t.getAction()) not in self._tabulist_action: return t.getAction() return None def _newStateAction(self, trans): """returns an action leading to a non-tabu state, or None""" for t in trans: if str(t.getDestState()) not in self._tabulist_state: return t.getAction() return None def _newTransitionAction(self, trans): """returns an action of a non-tabu transition, or None""" for t in trans: if str(t) not in self._tabulist_transition: return t.getAction() return None
def __init__(self, paramStr): # default params: self.setParameter("weight", "decreasing") self._tabuList = TabuList() # user-given params: self.setParameterStr(paramStr)
class TabuRequirement(Requirement, object): """ """ def __new__(cls, tabuStr, unused=None): # TODO: improve parsing, parentheses, etc. if _RE_OR.search(tabuStr): return object.__new__(OrTabuRequirement) if _RE_WHILE.search(tabuStr): return object.__new__(WhileTabuRequirement) if _RE_SINGLE.match(tabuStr): return SingleTabuRequirement.__new__(cls, tabuStr) raise ValueError("Invalid tabu string: '%s'" % tabuStr) def __init__(self, paramStr): # default params: self.setParameter("weight", "decreasing") self._tabuList = TabuList() # user-given params: self.setParameterStr(paramStr) def setParameterStr(self, paramStr): if not paramStr: return for pair in paramStr.split(","): name, value = pair.split(":", 1) self.setParameter(name, value) def setParameter(self, name, value): name = name.lower() if name in ("size", "tabusize"): self._tabuList = TabuList(_parseSize(value)) elif name == "weight": if value in ("decreasing", "decr"): self.weight = self._decreasingWeight else: self.weight = lambda: 1 elif name == "name": self._name = value else: print __doc__ raise ValueError("Invalid param '%s' for %s" % (name, self.__class__.__name__)) def getPercentage(self): """ Doesn't actually return "coverage" per se, but is a function that's getting closer and closer to 1 as new items are found. This means that the more items have been found, the less a new one improves coverage. """ # the usual python floats have precision of ~16 digits, # -> tabulist sizes up to 16**10, so precision shouldn't be a problem return 1 - 1.0 / (self._tabuList.lenUnique() + 1) def getExecutionHint(self): raise NotImplementedError() def markExecuted(self, transition): # if using filterRelevant instead of filterNew, this would work a bit # differently in the case of a limited size tabulist. # not sure which is the best. see findnewcoverage_test.py. for item in self.filterNew(transition): #if self._tabuList._pushLevel == 0: # self.log("FOUND: %s" % (item,)) self._tabuList.add(item) # subclasses must implement filterRelevant # this is the func that yields all the things in the transition that # the TabuRequirement is interested in. (eg. aw for aw-requirement, etc.) def filterRelevant(self, transition): raise NotImplementedError() def filterNew(self, transition): """ yields all the new things found by executing the transition """ for item in self.filterRelevant(transition): if item not in self._tabuList: yield item def filterOld(self, transition): for item in self.filterRelevant(transition): if item in self._tabuList: yield item def transitionPoints(self, transition): """ how many points executing this transitition gives. point = (number of new items) * weight """ p = 0 for item in self.filterNew(transition): p += 1 return p * self.weight() def weight(self): return self._weight def _decreasingWeight(self): return 1.0 / (self._tabuList.lenUnique() + 1) def push(self): self._tabuList.push() def pop(self): self._tabuList.pop()
def __init__(self,paramStr): # default params: self.setParameter("weight","decreasing") self._tabuList = TabuList() # user-given params: self.setParameterStr(paramStr)
class TabuRequirement(Requirement,object): """ """ def __new__(cls,tabuStr,unused=None): # TODO: improve parsing, parentheses, etc. if _RE_OR.search(tabuStr): return object.__new__(OrTabuRequirement) if _RE_WHILE.search(tabuStr): return object.__new__(WhileTabuRequirement) if _RE_SINGLE.match(tabuStr): return SingleTabuRequirement.__new__(cls,tabuStr) raise ValueError("Invalid tabu string: '%s'" % tabuStr) def __init__(self,paramStr): # default params: self.setParameter("weight","decreasing") self._tabuList = TabuList() # user-given params: self.setParameterStr(paramStr) def setParameterStr(self,paramStr): if not paramStr: return for pair in paramStr.split(","): name,value = pair.split(":",1) self.setParameter(name,value) def setParameter(self,name,value): name = name.lower() if name in ("size","tabusize"): self._tabuList = TabuList( _parseSize(value) ) elif name == "weight": if value in ("decreasing","decr"): self.weight = self._decreasingWeight else: self.weight = lambda: 1 elif name == "name": self._name = value else: print __doc__ raise ValueError( "Invalid param '%s' for %s"%(name,self.__class__.__name__)) def getPercentage(self): """ Doesn't actually return "coverage" per se, but is a function that's getting closer and closer to 1 as new items are found. This means that the more items have been found, the less a new one improves coverage. """ # the usual python floats have precision of ~16 digits, # -> tabulist sizes up to 16**10, so precision shouldn't be a problem return 1 - 1.0/(self._tabuList.lenUnique()+1) def getExecutionHint(self): raise NotImplementedError() def markExecuted(self,transition): # if using filterRelevant instead of filterNew, this would work a bit # differently in the case of a limited size tabulist. # not sure which is the best. see findnewcoverage_test.py. for item in self.filterNew(transition): #if self._tabuList._pushLevel == 0: # self.log("FOUND: %s" % (item,)) self._tabuList.add(item) # subclasses must implement filterRelevant # this is the func that yields all the things in the transition that # the TabuRequirement is interested in. (eg. aw for aw-requirement, etc.) def filterRelevant(self,transition): raise NotImplementedError() def filterNew(self,transition): """ yields all the new things found by executing the transition """ for item in self.filterRelevant(transition): if item not in self._tabuList: yield item def filterOld(self,transition): for item in self.filterRelevant(transition): if item in self._tabuList: yield item def transitionPoints(self,transition): """ how many points executing this transitition gives. point = (number of new items) * weight """ p = 0 for item in self.filterNew(transition): p += 1 return p * self.weight() def weight(self): return self._weight def _decreasingWeight(self): return 1.0/(self._tabuList.lenUnique()+1) def push(self): self._tabuList.push() def pop(self): self._tabuList.pop()
class Guidance(GuidanceBase): def __init__(self): GuidanceBase.__init__(self) self._NUM_TABU_ACTIONS = None self._NUM_TABU_STATES = None self._NUM_TABU_TRANSITIONS = None self._tabulist_action = None self._tabulist_state = None self._tabulist_transition = None def setParameter(self, paramname, paramvalue): accepted = ("numtabuactions", "numtabustates", "numtabutransitions") if paramname == "numtabuactions": self._NUM_TABU_ACTIONS = self._parseSize(paramname, paramvalue) elif paramname == "numtabustates": self._NUM_TABU_STATES = self._parseSize(paramname, paramvalue) elif paramname == "numtabutransitions": self._NUM_TABU_TRANSITIONS = self._parseSize(paramname, paramvalue) else: print __doc__ raise Exception("Invalid parameter '%s' for tabuguidance. Accepted parameters: %s" % paramname, accepted) GuidanceBase.setParameter(self, paramname, paramvalue) def _parseSize(self, paramname, paramvalue): if paramvalue == float("infinity") or paramvalue is INFINITY or paramvalue in ("inf", "infinite", "infinity"): return INFINITY try: return int(paramvalue) except ValueError: raise Exception( "Tabuguidance: invalid '%s' value: %s. It should be a positive integer or 'infinite'." % (paramname, paramvalue) ) def prepareForRun(self): # if no numtabu* params given, use infinite state tabulist if self._NUM_TABU_ACTIONS is None and self._NUM_TABU_STATES is None and self._NUM_TABU_TRANSITIONS is None: self.log("Using default: 'numtabustates:infinite'") self._NUM_TABU_STATES = INFINITY self._suggesters = [] # the funcs that suggest an action # order: action, state, transition if self._NUM_TABU_ACTIONS is not None: self._tabulist_action = TabuList(self._NUM_TABU_ACTIONS) self._suggesters.append(self._newAction) if self._NUM_TABU_STATES is not None: self._tabulist_state = TabuList(self._NUM_TABU_STATES) self._suggesters.append(self._newStateAction) if self._NUM_TABU_TRANSITIONS is not None: self._tabulist_transition = TabuList(self._NUM_TABU_TRANSITIONS) self._suggesters.append(self._newTransitionAction) def markExecuted(self, transition): # special case: add the very first (source) state to the tabu-list statelist = self._tabulist_state if statelist and len(statelist) == 0: statelist.add(transition.getSourceState()) # add actions/states/transitions to tabulists if given tabulist exists if self._tabulist_action is not None: self._tabulist_action.add(str(transition.getAction())) if self._tabulist_state is not None: self._tabulist_state.add(str(transition.getDestState())) if self._tabulist_transition is not None: self._tabulist_transition.add(str(transition)) GuidanceBase.markExecuted(self, transition) def suggestAction(self, from_state): out_trans = from_state.getOutTransitions() random.shuffle(out_trans) for suggester in self._suggesters: action = suggester(out_trans) if action is not None: return action # no non-tabu actions found, a random action is our best suggestion... return out_trans[0].getAction() # out_trans has been shuffled def _newAction(self, trans): """returns a non-tabu action, or None""" for t in trans: if str(t.getAction()) not in self._tabulist_action: return t.getAction() return None def _newStateAction(self, trans): """returns an action leading to a non-tabu state, or None""" for t in trans: if str(t.getDestState()) not in self._tabulist_state: return t.getAction() return None def _newTransitionAction(self, trans): """returns an action of a non-tabu transition, or None""" for t in trans: if str(t) not in self._tabulist_transition: return t.getAction() return None