def sample(self, model, queries=None): """Sample one assignment to the queries of the given model. Returns a tuple containing: queries : list of pairs (name, value) facts: list of probabilistic facts with their sampled value (name, value) probability: overall probability of the assignment """ engine = self db = engine.prepare(model) if queries == None: queries = [q[0] for q in engine.query(db, Term('query', None))] # if evidence == None : # evidence = engine.query(db, Term( 'evidence', None, None )) target = LogicFormula() for query in queries: target = engine.ground(db, query, target, label=target.LABEL_QUERY) # for query in evidence : # if str(query[1]) == 'true' : # target = engine.ground(db, query[0], target, label=LABEL_EVIDENCE_POS) # elif str(query[1]) == 'false' : # target = engine.ground(db, query[0], target, label=LABEL_EVIDENCE_NEG) # else : # target = engine.ground(db, query[0], target, label=LABEL_EVIDENCE_MAYBE) # Take into account remaining probabilities of no-choice nodes for annotated disjunctions. for k, p in self.groups.items(): if p != None: self.probability *= p translate = lambda x: (x[0], x[1] == 0) facts = [] for f, v in self.facts.items(): if v: if type(f) == tuple: node = db.get_node(f[0]) args = f[1] else: node = db.get_node(f) args = node.args if node.functor != 'query': if args: facts.append('%s(%s)' % (node.functor, ', '.join(map(str, args)))) else: facts.append('%s' % (node.functor)) result = map(translate, target.queries()), facts, self.probability self.reset() return result
def verify(self, examples, engine): if self.parent.verifications is not None: verifications = self.parent.verifications else: self.parent.verify(examples, engine) verifications = self.parent.verifications # check whether the literal is a body or a head literal # body literals are negated rule_literal = abs(self.literal) if not self.literal.is_negated(): head_literal = True else: head_literal = False verifies = False new_verifications = [] for k, (example, verification) in enumerate(zip(examples, verifications)): #print("-----------------------------------------------------") #print("testing",self,"on example",k+1) if verification: if hasattr(example, '_ground'): formula = example._ground formula.clear_queries() else: formula = LogicFormula() new_verification = [] for subst in verification: #print("rule_literal:",rule_literal) #print("original subst:",subst) if len(subst) < self.variable_count: subst = subst + [None ] * (self.variable_count - len(subst)) #print("new subst:",subst) literal = instantiate(rule_literal, subst) #print("literal:",literal) formula = engine.ground(example.database, literal, target=formula, label='query') #print("formula:",formula) for q, i in formula.queries(): subst_new = subst[:] #print("q:",q) try: unify(q, rule_literal, subst_new) #print("subst_new:",subst_new) #if len(set(subst_new)) == len(subst_new): if head_literal and i == 0: if None in subst_new: get_logger('claudette').error(' '.join( map(str, (list(example.database), self, failing, formula)))) raise RuntimeError( 'This shouldn\'t happen!') #print("head query",q,"evaluated to true") new_verification.append(subst_new) # the body literal evaluated in true elif not head_literal and i == 0: new_verification.append(subst_new) #print("body query",q,"evaluated to true") except UnifyError: # if we have a unify error then the literal is not unifyable with the query #print("unify error") pass #print("==========") example._ground = formula if str(rule_literal)[0] == '#': new_verifications.append([[]]) else: new_verifications.append(new_verification) #print("verification:",verification) #print("new_verification:",new_verification) if new_verification: verifies = True else: new_verifications.append([]) self.verifications = new_verifications return verifies
def evaluate(self, examples, engine): # UITLEG subst # bij elke refinement wordt er 1 predicaat toegevoegd aan de body of head (in ons geval enkel aan de body, aangezien we enkel in de modes '\+' gebruiken) # het toegevoegde predicaat zit vervat in 'rule_literal' # elke failing bevat een aantal lijsten, subst is telkens een pointer naar een van deze lijsten # het i-de element van subst is telkens de waarde van parameter Ai # Bv example: p(a). p(b). q(a,b) # huidige hypothese: p(A1) -> false # ----> rule_literal is dus p(A1)!! # de originele failing zou dan zijn [[]] (zie evaluate van EmptyClause) # de nieuwe failing is nu [[a],[b]] aangezien er in het voorbeeld twee keer p(A1) voorkomt # aangezien de body nu true en de head false (want die is altijd false in dit voorbeeld) dekt dit het voorbeeld niet # daarom staat er een 'if not head_literal and i == None' wat betekent dat als de rule_literal een body_literal is en als die true is in het voorbeeld # dan wordt het voorbeeld niet gedekt # gather the failings from the parent # the failings list contains for every example information about that example # if a failing element is just an empty list ([]) then the clause covers that example if self.parent.failings is not None: failings = self.parent.failings else: self.parent.evaluate(examples, engine) failings = self.parent.failings # check whether the literal is a body or a head literal # body literals are negated rule_literal = abs(self.literal) if not self.literal.is_negated(): head_literal = True else: head_literal = False # boolean indicating whether there is an example which is not covered by this clause fails = False # the list that will contain the updated failings # later on self.failings will be set to this list new_failings = [] # boolean indicating whether this clause is an improvement of its parent clause improvement = False if head_literal: improvement = True # loop through the examples and failings at the same time # 'example' contains the example and 'failing' contains information about coverage of the example by the parent for k, (example, failing) in enumerate(zip(examples, failings)): #print("-----------------------------------------------------") #print("testing",self,"on example",k+1) if failing: # equivalent to if 'failing != []' so if this if succeeds, the parent does not cover the example # TODO: find out why this is necessary if hasattr(example, '_ground'): formula = example._ground formula.clear_queries() else: formula = LogicFormula() # Load from cache # formula = LogicFormula() # construct a new list to store the failing information for this example # later on 'failing' will be replaced by 'new_failing' new_failing = [] # calculate the contents of new_failing for subst in failing: #print("rule_literal:",rule_literal) #print("original subst:",subst) # for every new variable this clause introduces, add a None element to the substances if len(subst) < self.variable_count: subst = subst + [None ] * (self.variable_count - len(subst)) improvement = True # adds a variable #print("new subst:",subst) # subst now contains a list where the ith element contains the value for the ith parameter of the rule_literal # bv. instantiate(pred(A1,A2,A3),[a,b,None]) would result in pred(a,b,_) literal = instantiate(rule_literal, subst) #print("literal:",literal) # formula contains a list queries # this list contains all the facts in the example of the literal # bv example: pred1(a). pred1(b). pred2(b). pred3(a,b). # literal = pred1(_) # queries: [pred1(a),pred1(b)] formula = engine.ground(example.database, literal, target=formula, label='query') #print("formula:",formula) # q is the query # if i == 0, the query is true # if i == None, the query is false # de uitbreiding van een clause dekt het positieve voorbeeld als rule_literal een body_literal is die naar false evalueert of # of als rule_literal een head_literal is die naar true evalueert for q, i in formula.queries(): # create a copy of the subst_new subst_new = subst[:] #print("q:",q) try: # try to unify the query with the rule literal and put the unifications in subst_new unify(q, rule_literal, subst_new) #print("subst_new:",subst_new) if len(set(subst_new)) == len(subst_new): # TODO check subst_new is all different # the head_literal evaluated to false if head_literal and i is None: if None in subst_new: get_logger('claudette').error(' '.join( map(str, (list(example.database), self, failing, formula)))) raise RuntimeError( 'This shouldn\'t happen!') #print("head query",q,"evaluated to false") new_failing.append(subst_new) # the body literal evaluated in true elif not head_literal and i == 0: new_failing.append(subst_new) #print("body query",q,"evaluated to true") except UnifyError: # if we have a unify error then the literal is not unifyable with the query #print("unify error") pass #print("==========") example._ground = formula new_failings.append(new_failing) #print("failing:",failing) #print("new_failing:",new_failing) # we check whether new_failing contains any items # if it doesn't then we know that the refinement covers the example if new_failing: # if new_failing contains less items than failing than this clause covers it 'more' than the parent so there is an improvement if len(new_failing) < len( failing ) or self.variable_count == 0: # the last statement is needed for terminal (otherwise terminal gives no contribution) improvement = True fails = True else: # new_failing == [] thus this example is now covered assert failing improvement = True # failing eliminated else: # the parent covers this example, so the refinement covers this to new_failings.append([]) self.failings = new_failings self.improvement = improvement # if fails is set to True, then the clause didn't cover a positive example so it is not a valid one and needs to be refined return not fails