def build(*clauses,**kwargs): priorLea = kwargs.get('priorLea',None) # TODO: check no other args !! # PY3: def build(*clauses,priorLea=None): elseClauseResults = tuple(result for (cond,result) in clauses if cond is None) if len(elseClauseResults) > 1: raise Lea.Error("impossible to define more than one 'other' clause") if len(elseClauseResults) == 1: if priorLea is not None: raise Lea.Error("impossible to define together prior probabilities and 'other' clause") elseClauseResult = elseClauseResults[0] else: elseClauseResult = None normClauseLeas = tuple((Lea.coerce(cond),Lea.coerce(result)) for (cond,result) in clauses if cond is not None) condLeas = tuple(condLea for (condLea,resultLea) in normClauseLeas) # check that conditions are disjoint for (condLea1,condLea2) in genPairs(condLeas): if (condLea1&condLea2).isFeasible(): raise Lea.Error("clause conditions are not disjoint") # build the OR of all given conditions orCondsLea = Lea.reduce(or_,condLeas) isClauseSetComplete = orCondsLea.isTrue() if priorLea is not None: # prior distribution: determine elseClauseResult if isClauseSetComplete: # TODO check priorLea equivalent to self raise Lea.Error("forbidden to define prior probabilities for complete clause set") (pTrue,count) = orCondsLea._p(True) pFalse = count - pTrue priorAleaDict = dict(priorLea.getAlea().genVPs()) priorAleaCount = sum(priorAleaDict.values()) normAleaDict = dict(Mlea(*(resultLea for (condLea,resultLea) in normClauseLeas)).getAlea().genVPs()) normAleaCount = sum(normAleaDict.values()) valuesSet = frozenset(chain(priorAleaDict.keys(),normAleaDict.keys())) vps = [] for value in valuesSet: priorP = priorAleaDict.get(value,0) condP = normAleaDict.get(value,0) p = priorP*count*normAleaCount - condP*pTrue*priorAleaCount if not(0 <= p <= pFalse*normAleaCount*priorAleaCount): # Infeasible : probability represented by p goes outside range from 0 to 1 priorPFraction = ProbFraction(priorP,priorAleaCount) lowerPFraction = ProbFraction(condP*pTrue,count*normAleaCount) upperPFraction = ProbFraction(condP*pTrue+pFalse*normAleaCount,count*normAleaCount) raise Lea.Error("prior probability of '%s' is %s, outside the range [ %s , %s ]"%(value,priorPFraction,lowerPFraction,upperPFraction)) vps.append((value,p)) elseClauseResult = Lea.fromValFreqs(*vps) elif elseClauseResult is None: # check that clause set is complete if not isClauseSetComplete: # TODO? : assume a uniform prior distribution ? ... which values ? raise Lea.Error("incomplete clause set requires 'other' clause or prior probabilities") if elseClauseResult is not None: elseCondLea = ~orCondsLea normClauseLeas += ((elseCondLea,Lea.coerce(elseClauseResult)),) # note that orCondsLea is NOT extended with rCondsLea |= elseCondLea # so, in case of else clause (and only in this case), orCondsLea is NOT certainly true return Blea(*(Ilea(resultLea,condLea) for (condLea,resultLea) in normClauseLeas))
def __init__(self,nextStateLeaPerState): ''' initializes Chain instance's attributes; nextStateLeaPerState is a sequence of tuples (stateObj,nextStateLea) where stateObj is a state object (e.g. a string) and nextStateLea is a Lea instance giving probabilities of transition from stateObj to each state object ''' object.__init__(self) self._stateObjs = tuple(stateObj for (stateObj,nextStateLea) in nextStateLeaPerState) self._stateAleaDict = dict((stateObj,StateAlea(Lea.coerce(stateObj),self)) for stateObj in self._stateObjs) self._state = StateAlea(Lea.fromVals(*self._stateObjs),self) iterNextStateData = ((self._state==stateObj,nextStateLea) for (stateObj,nextStateLea) in nextStateLeaPerState) self._nextStateBlea = Blea.build(*iterNextStateData)
def fromSeq(stateObjSeq): ''' returns a new Chain instance from given sequence of state objects the probabilities of state transitions are set according to transition frequencies in the given sequence ''' (fromStateObjIter,toStateObjIter) = tee(stateObjSeq); for _ in toStateObjIter: break nextStateObjsDict = dict() for (fromStateObj,toStateObj) in zip(fromStateObjIter,toStateObjIter): nextStateObjs = nextStateObjsDict.get(fromStateObj) if nextStateObjs is None: nextStateObjs = [] nextStateObjsDict[fromStateObj] = nextStateObjs nextStateObjs.append(toStateObj) nextStateNameAndObjs = list(nextStateObjsDict.items()) nextStateNameAndObjs.sort() nextStateLeaPerState = tuple((stateObj,Alea.fromVals(*nextStateObjs)) for (stateObj,nextStateObjs) in nextStateNameAndObjs) return Chain(nextStateLeaPerState)
def _buildClass(self): classAttrDict = dict(('__maxLength'+attrName,0) for attrName in self._attrNames) classAttrDict['__slots__'] = tuple(self._attrNames) self._class = type('',(_TemplateClass,),classAttrDict)