def unifyWithOccursCheck(E1, E2, functionList, variableList, atomList):
    # check if empty List
    if checkIfEitherEmpty(E1, E2,):
        return unify(None,None,variableList)


    if checkIfValid(E1,functionList, variableList, atomList) or checkIfValid(E2,functionList, variableList, atomList):
        if E1 == E2:
            return unify(None,None,variableList)

        if str(E1) in variableList:

            if E1 in E2:
                #assignment  will lead to infinite loop hence exit with occurs check error
                return exit("Violates Occurs Check ")
            else:
                return unify(E2, E1,variableList)
        if str(E2) in variableList:

            if E2 in E1:
                # assignment  will lead to infinite loop hence exit with occurs check error
                return exit("Violates Occurs Check ")
            else:
                return unify(E1, E2,variableList)
        if not E1 in variableList and not  E2 in variableList:
            return exit("Nope , cannot be unified!")
    # recusrisve funtion to get assignments
    SUBS1 = unifyWithOccursCheck(E1[0], E2[0], functionList, variableList, atomList)

    TE1 = SUBS1.unifyTerms(E1[1:])
    TE2 = SUBS1.unifyTerms(E2[1:])
    #recusrisve funtion to get assignments
    SUBS2 = unifyWithOccursCheck(TE1, TE2, functionList, variableList, atomList)

    return SUBS1.unifyTerms(SUBS2)
示例#2
0
def resolve(rgoal, clause):
    rgoal = rgoal.copy()
    clause = clause.copy()
    if len(rgoal.get_terms()) > len(clause.get_terms()):
        return resolve(clause, rgoal)
    if not is_suitable(rgoal, clause):
        return False
    theta = Substitution()
    for goal_term in rgoal.get_terms():
        op = goal_term.get_op()
        suitable_terms = clause.find_term_by_op(op)
        if suitable_terms == False:
            continue
        for suitable_term in suitable_terms:
            if goal_term.isNegative == suitable_term.isNegative:
                continue
            theta = Substitution()
            unify(goal_term, suitable_term, theta)
            if theta is not False:
                clause.remove(suitable_term)
                rgoal.remove(goal_term)
                break
    result = CNF(rgoal.get_terms() + clause.get_terms())
    for term in result.terms:
        theta.SUBST(term)
    return result
示例#3
0
 def may_triggered(self, new_facts):
     # Check if any fact pi in new_facts is unified with a premise in rule
     for new_fact in new_facts:
         for premise in self.premises:
             if unify(new_fact, premise, Substitution()):
                 return True
     return False
示例#4
0
def forward(facts, kb):
    '''An exhaustive forward chaining algorithm for first-order definite clauses'''
    # each production is [antecedent_list, consequent_literal, triggers]
    stack = list(facts)
    productions = [[parse.antecedent(k), parse.consequent(k), []] for k in kb]
    entailed = []
    while len(stack) > 0:
        current = stack.pop(0)
        for prod in productions:
            for ant in prod[0]:
                theta = unify.unify(current, ant)
                if theta != None:
                    new_consequent = unify.subst(theta, prod[1])
                    new_triggers = prod[2] + [current]
                    if len(prod[0]) == 1: # last one
                        entailed.append([new_consequent,
                                         new_triggers])
                        stack.append(new_consequent)
                    else:
                        new_antecedent = list(prod[0])
                        new_antecedent.remove(ant)
                        new_antecedent = [unify.subst(theta, x) for x in new_antecedent]
                        productions.append([new_antecedent,
                                            new_consequent,
                                            new_triggers])
    return entailed
示例#5
0
def and_or_leaflists(remaining, indexed_kb, depth, antecedents = [], assumptions = []):
    '''Returns list of all entailing sets of leafs in the and-or backchaining tree'''
    if depth == 0 and len(antecedents) > 0: # fail
        return [] # (empty) list of lists
    elif len(remaining) == 0: # done with this level
        if len(antecedents) == 0: # found one
            return [assumptions] # list of lists
        else:
            return and_or_leaflists(antecedents, indexed_kb, depth - 1, [], assumptions)
    else: # more to go on this level
        literal = remaining[0] # first of remaining
        predicate = literal[0]
        if predicate not in indexed_kb:
            return and_or_leaflists(remaining[1:], indexed_kb, depth, antecedents, [literal] + assumptions) # shift literal to assumptions
        else:
            revisions = [] 
            for rule in indexed_kb[predicate]: # indexed by predicate of literal
                theta = unify.unify(literal, parse.consequent(rule))
                if theta != None:
                    if depth == 0: # no depth for revision
                        return [] # (empty) list of lists
                    revisions.append([unify.subst(theta, remaining[1:]), # new remaining with substitutions
                                      indexed_kb,
                                      depth,
                                      unify.standardize(unify.subst(theta, parse.antecedent(rule))) +
                                      unify.subst(theta, antecedents),  # new antecedents with substitutions
                                      unify.subst(theta, assumptions)]) # new assumptions with substitutions
            return itertools.chain(*[and_or_leaflists(*rev) for rev in revisions]) # list of lists (if any)
示例#6
0
def and_or_leaflists(remaining, indexed_kb, depth, antecedents = [], assumptions = []):
    '''Returns list of all entailing sets of leafs in the and-or backchaining tree'''
    if depth == 0 and len(antecedents) > 0: # fail
        return [] # (empty) list of lists
    elif len(remaining) == 0: # done with this level
        if len(antecedents) == 0: # found one
            return [assumptions] # list of lists
        else:
            return and_or_leaflists(antecedents, indexed_kb, depth - 1, [], assumptions)
    else: # more to go on this level
        literal = remaining[0] # first of remaining
        predicate = literal[0]
        if predicate not in indexed_kb:
            return and_or_leaflists(remaining[1:], indexed_kb, depth, antecedents, [literal] + assumptions) # shift literal to assumptions
        else:
            revisions = [] 
            for rule in indexed_kb[predicate]: # indexed by predicate of literal
                theta = unify.unify(literal, parse.consequent(rule))
                if theta != None:
                    if depth == 0: # no depth for revision
                        return [] # (empty) list of lists
                    revisions.append([unify.subst(theta, remaining[1:]), # new remaining with substitutions
                                      indexed_kb,
                                      depth,
                                      unify.standardize(unify.subst(theta, parse.antecedent(rule))) +
                                      unify.subst(theta, antecedents),  # new antecedents with substitutions
                                      unify.subst(theta, assumptions)]) # new assumptions with substitutions
            return itertools.chain(*[and_or_leaflists(*rev) for rev in revisions]) # list of lists (if any)
示例#7
0
def contains(
        conj,
        lit):  # where conj is the list of entailed, lit is an answer literal.
    for c in conj:
        if unify.unify(lit, c):
            return True
    return False
示例#8
0
def run_unification(slices):
    # Executes the unification script with
    # the generated slice files (containing
    # line numbers).
    # Saves the output in the path specified
    # in global variables.

    if len(slices) < 1:
        return 1

    check_and_remove(unification_output)

    raw_args = ["--file"]

    for slice in slices:
        raw_args.append(slice)

    raw_args.append(f"-o={unification_output}")

    unification_args = unify.parser.parse_args(raw_args)

    global created_files
    created_files.append(unification_output)

    return unify.unify(unification_args)
示例#9
0
def forward(facts, kb):
    '''An exhaustive forward chaining algorithm for first-order definite clauses'''
    # each production is [antecedent_list, consequent_literal, triggers]
    stack = list(facts)
    productions = [[parse.antecedent(k), parse.consequent(k), []] for k in kb]
    entailed = []
    while len(stack) > 0:
        current = stack.pop(0)
        for prod in productions:
            for ant in prod[0]:
                theta = unify.unify(current, ant)
                if theta != None:
                    new_consequent = unify.subst(theta, prod[1])
                    new_triggers = prod[2] + [current]
                    if len(prod[0]) == 1: # last one
                        entailed.append([new_consequent,
                                         new_triggers])
                        stack.append(new_consequent)
                    else:
                        new_antecedent = list(prod[0])
                        new_antecedent.remove(ant)
                        new_antecedent = [unify.subst(theta, x) for x in new_antecedent]
                        productions.append([new_antecedent,
                                            new_consequent,
                                            new_triggers])
    return entailed
示例#10
0
def resolve(query, kb):
    threshold = kb.size
    tbu = indexed_kb()
    query = cleanup_query(query)
    query[0]["truth"] = not query[0]["truth"]
    tbu.add(query, occur_check=True)
    iter = 0
    #print query
    start = time.time()
    while not tbu.empty():
        iter += 1
        x, parent = tbu.pop()
        if not sanity_check(parent, kb, threshold):
            continue
        #print "Popped: ", x
        for x_pred in x:
            if not x_pred["truth"]:
                indices = get_indices(kb.true, x_pred["name"])
            else:
                indices = get_indices(kb.false, x_pred["name"])
            #print "X_pred is ", x_pred, indices
            for index in indices:
                y = kb.all[index]
                for y_pred in y:
                    sub = unify(x_pred, y_pred)
                    if sub is not None:
                        resolved_sentence = get_resolved_sentence(
                            copy.deepcopy(x), copy.deepcopy(y),
                            copy.deepcopy(x_pred), copy.deepcopy(y_pred), sub)
                        if resolved_sentence == []:
                            return True
                        if isTrue(resolved_sentence):
                            return False
                        resolved_sentence = standardize(resolved_sentence)
                        new_parent = copy.deepcopy(parent)
                        if index not in new_parent:
                            new_parent[index] = 0
                        new_parent[index] += 1
                        tbu.add(resolved_sentence,
                                new_parent,
                                occur_check=True,
                                verbose=False)
                        print tbu.size, iter
                        if len(resolved_sentence) > 10000:
                            print "x: ", x
                            print "y: ", y
                            print "sub: ", sub
                            print "Resolved: ", resolved_sentence
                            print tbu.size
                            print '\n'
                            xxx = input()
        end = time.time()
        if (end - start) > 10:
            print "Breaking out in 10 seconds"
            break
        x = standardize(x)
        kb.add(x, occur_check=True)
    return False
示例#11
0
def subst(facts_1, facts_2):  # Generalized Modus Ponens
    if len(facts_1) != len(facts_2):
        return False

    for f1, f2 in zip(facts_1, facts_2):
        if f1.get_predicate() != f2.get_predicate():
            return False

    return unify(facts_1, facts_2, Substitution())
示例#12
0
def mergethetas(thetaset):
    '''Merge all substitutions into a single dictionary, or None if not consistent'''
    x = []
    y = []
    for theta in thetaset:
        for var in theta:
            x.append(var)
            y.append(theta[var])
    return unify.unify(x, y)
示例#13
0
def mergethetas(thetaset):
    '''Merge all substitutions into a single dictionary, or None if not consistent'''
    x = []
    y = []
    for theta in thetaset:
        for var in theta:
            x.append(var)
            y.append(theta[var])
    return unify.unify(x,y)
示例#14
0
def resolution(expr1, expr2):
    if expr1.name != expr2.name:
        return False, ''
    elif expr1.sign != 1 - expr2.sign:
        return False, ''
    else:
        sub = unify(expr1, expr2)
        if sub == 'Fail':
            return False, ''
        else:
            return True, sub
示例#15
0
def fol_fc_ask(kb, alpha):
    res = set()

    while True:
        new_facts = set()

        for rule in KnowledgeBase.getRule():
            count_premises = rule.count_premises()

            facts = kb.getFact()

            premises = itertools.permutations(facts, count_premises)

            for tuple_premises in premises:
                premises_ = [premise for premise in tuple_premises]

                theta = unify(rule.premise, premises_, Substitution())

                if not theta:
                    continue

                new_fact = rule.get_conclusion()
                theta.SUBST(new_fact)

                if new_fact not in new_facts and new_fact not in kb.getFact():
                    new_facts.add(new_fact)
                    phi = unify(new_fact, alpha, Substitution())
                    if phi:
                        if phi.empty():
                            for f in new_facts:
                                kb.appendFact(f)
                            res.add('true')
                            return res
                        res.add(phi)
            if not new_facts:
                if not res:
                    res.add('false')
                return res
            for f in new_facts:
                kb.appendFact(f)
示例#16
0
def crunch(conjunction): # returns a list of all possible ways to unify conjunction literals
    conjunction = [k for k,v in itertools.groupby(sorted(conjunction))] # remove duplicates
    res = [conjunction] # start with one solution
    pairs = itertools.combinations(conjunction, 2)
    thetas = [theta for theta in [unify.unify(p[0], p[1]) for p in pairs] if theta is not None]
    ps = powerset(thetas)
    for thetaset in ps: 
        if len(thetaset) > 0:
            consistent = mergethetas(thetaset)
            if consistent:
                rewrite = [k for k,v in itertools.groupby(sorted(unify.subst(consistent, conjunction)))]
                if rewrite not in res: # expensive!
                    res.append(rewrite)
    return res
示例#17
0
def cruncher(conjunction, idx = 0):
    if idx >= len(conjunction) - 1: # last one
        return [[k for k,v in itertools.groupby(sorted(conjunction))]] # dedupe literals in solution
    else:
        res = []
        for subsequent in range(idx + 1,len(conjunction)): 
            theta = unify.unify(conjunction[idx], conjunction[subsequent])
            if theta:

                new_conjunction = unify.subst(theta,
                                              conjunction[0:subsequent] +
                                              conjunction[(subsequent + 1):len(conjunction)])
                res.extend(cruncher(new_conjunction, idx))
        res.extend(cruncher(conjunction, idx + 1))
        return res
示例#18
0
def evaluate(solution, gold): # simpler, faster, permissive
    '''Calculates precision, recall, and f1 score of solution given gold-standard literals'''
    if len(solution) == 0:
        raise ValueError('The solution is zero-length')
    if len(gold) == 0:
        raise ValueError('The gold is zero-length')
    goldcount = float(len(gold))
    solutioncount = float(len(solution))
    unifiableInGold = 0.0
    unifiableInSolution = 0.0
    for sliteral in solution:
        for gliteral in gold:
            if unify.unify(sliteral, gliteral) != None:
                unifiableInSolution += 1.0
                break;
    for gliteral in gold:
        for sliteral in solution:
            if unify.unify(sliteral, gliteral) != None:
                unifiableInGold += 1.0
                break;

    # precision is unifiable in solution / solution count
    precision = unifiableInSolution / solutioncount
    # recall is unifiable in gold / gold count
    recall = unifiableInGold / goldcount
    # f1 is harmonic mean
    f1 = 2.0 * (precision * recall) / (precision + recall)
    print("goldcount", goldcount,
          "solutioncount", solutioncount,
          "unifiableInSolution", unifiableInSolution,
          "unifiableInGold", unifiableInGold,
          "precision", precision,
          "recall", recall,
          "f1", f1)

    return(precision, recall, f1)
示例#19
0
def is_suitable(rgoal, clause):
    if len(rgoal.get_terms()) > len(clause.get_terms()):
        return is_suitable(clause, rgoal)
    for goal_term in rgoal.get_terms():
        op = goal_term.get_op()
        suitable_terms = clause.find_term_by_op(op)
        if suitable_terms == False:
            continue
        else:
            for suitable_term in suitable_terms:
                if goal_term.isNegative == suitable_term.isNegative:
                    continue
                else:
                    theta = Substitution()
                    if unify(goal_term, suitable_term, theta) is not False:
                        return True
    return False
示例#20
0
def successors(node):
   # node.state is a list of clauses, with the first one the current
   # clause

   def resolvent (parent1,parent2,lit1,lit2,uresult):
      both = parent1.cl + parent2.cl
      new = []
      for b in both:
         if not b == lit1 and not b == lit2:
            newsentence = applySubs (b.sentence, uresult)
            new = new +[ Literal(b.neg,b.pred,newsentence)]
      new111 =  Clause(new,[parent1.id,parent2.id])
      return new111

   succs = []
   sos = [];
   #see if any clause in the current states sos can cancel out any other 
   #clauses in the current KB
   for sos_clause in node.sos:

     #target is the clause in the KB being compared to sos_clause
     for target in node.state:

       #compare literals
       for lit1 in target.cl:
         for lit2 in sos_clause.cl:
           if not lit1.neg == lit2.neg and lit1.pred == lit2.pred:
             uresult = unify(lit1.sentence,lit2.sentence)
             if not uresult == 'fail':
               #resolve
               #create a new successor state and an updated sos for it
               new_clause = resolvent(sos_clause, target, lit1, lit2, uresult);
               new_sos = [new_clause] + node.sos;
               newsucc = [new_clause] + node.state;
               sos += [new_sos];
               succs += [newsucc]

   #return a tuple of successor states paired with that states set of support
   return (succs, sos)
示例#21
0
def crunch(
    conjunction
):  # returns a list of all possible ways to unify conjunction literals
    conjunction = [k for k, v in itertools.groupby(sorted(conjunction))
                   ]  # remove duplicates
    res = [conjunction]  # start with one solution
    pairs = itertools.combinations(conjunction, 2)
    thetas = [
        theta for theta in [unify.unify(p[0], p[1]) for p in pairs]
        if theta is not None
    ]
    ps = powerset(thetas)
    for thetaset in ps:
        if len(thetaset) > 0:
            consistent = mergethetas(thetaset)
            if consistent:
                rewrite = [
                    k for k, v in itertools.groupby(
                        sorted(unify.subst(consistent, conjunction)))
                ]
                if rewrite not in res:  # expensive!
                    res.append(rewrite)
    return res
示例#22
0
	def unification(self, triple):
		if len(triple) == 3:
			t1 = triple[0]
			r = triple[1]
			t2 = triple[2]
			t1 = t1 if isvar(t1) else self.term.get_term_id(t1)
			r  = r  if isvar(r)  else self.relation.get_relation_id(r)
			t2 = t2 if isvar(t2) else self.term.get_term_id(t2)
			generator = self.find(t1, r, t2)
			for item in generator:
				ans = unify(item, self.parse_triple_to_id(triple), {})
				if isinstance(ans, dict):
					for key in ans.keys():
						if 'T' in ans[key]:
							ans[key] = self.term.get_term_name(ans[key])
						else:
							ans[key] = self.relation.get_relation_name(ans[key])
					yield ans
				else:
					print triple, "unable to unify:", ans
					yield False
		else:
			yield False
def forward_chaining(kb, alpha):
    res = set()
    ## Check if alpha is proved in knowledge base
    for fact in kb.facts:
        phi = unify(fact, alpha, Substitution())
        if phi:
            if phi.empty():
                res.add('true')
                return res
            res.add(phi)

    last_generated_facts = kb.facts.copy()

    while True:
        new_facts = set()

        # Optimize: Incremental forward chaining
        # At iteration t, check a rule only if its premises includes at least
        # a conjunct pi that unified with the fact pi' newly inferred at iteration t - 1
        for rule_predicate in kb.rules:
            rule = kb.get_rule(rule_predicate)
            if not rule.may_triggered(last_generated_facts):
                continue

            num_premises = rule.get_num_premises()
            # Get facts that relevant to the current rule
            potential_facts = kb.get_potential_facts(rule)

            # Check if rule contains premises with the same predicate
            if not rule.dup_predicate:
                potential_premises = itertools.combinations(
                    sorted(potential_facts), num_premises)
            else:
                # Assumption on order of premises may failed on something like grandparent rule with two parent relations
                potential_premises = itertools.permutations(
                    potential_facts, num_premises)

            for tuple_premises in potential_premises:
                fact_premises = [premise for premise in tuple_premises]

                # get a subtitution of kb.facts (relevant to rule) in rule premises
                theta = subst(rule.premises, fact_premises)
                if not theta:
                    continue

                # subtitute theta to conclusion
                new_fact = rule.conclusion.copy()
                theta.substitute(new_fact)

                # if new fact is not a changed_name clause from a clause in kb
                if new_fact not in new_facts and new_fact not in kb.facts:
                    new_facts.add(new_fact)  # add new fact to fact list
                    phi = unify(
                        new_fact, alpha,
                        Substitution())  # unify new_fact with the query
                    if phi:  # if is a "true" answer or a substitution
                        if phi.empty():
                            kb.facts.update(new_facts)
                            res.add('true')
                            return res
                        res.add(phi)

        last_generated_facts = new_facts
        if not new_facts:  # if new_facts is an empty set
            if not res:  # if res is an empty set too. This mean no satisfied substitution
                res.add('false')
            return res
        kb.facts.update(new_facts)
示例#24
0
def backward_chaining(kb, alpha, theta):

    # check if alpha is empty
    if len(alpha) == 0:
        return theta

    # local variable to get answer
    answer = Substitution();

    # pop a sub goal
    sub_goal = alpha.pop()

    # *********************************************************************
    # if alpha is proved in knowledge base
    # check if alpha is a fact
    if sub_goal.predicate in kb.fact_predicate:
        # if theta set is include substitutions
        if len(theta) != 0:
            satisfy_element_index = []
            sub_satisfied_theta_list = []
            # substitute these substitution onto sub_goal
            k = 0
            while k < len(theta):
                subst_value = theta[k]
                phi = sub_goal.copy()
                subst_value.substitute(phi)
                # check for if phi has a varialbe or not. Ex : "parent(X,harry_potter)."
                if utils.is_contain_variable(phi):
                    for fact in kb.facts:
                        sub_theta = unify(phi, fact, Substitution())
                        if not sub_theta:
                            continue
                        # if sub_theta is a successful substitution
                        sub_phi = phi.copy()
                        sub_theta.substitute(sub_phi)
                        if sub_phi in kb.facts:
                            if sub_theta not in sub_satisfied_theta_list:
                                sub_satisfied_theta_list.append(sub_theta)
                    k += 1

                # else, phi is a fact to check true or false
                else:
                    if phi in kb.facts:     # if sub_goal is proven in kb, then return
                        satisfy_element_index.append(k)
                    k += 1

            # add satisfied element with index in list
            if len(satisfy_element_index) != 0:
                new_theta = []
                for i in satisfy_element_index:
                    new_theta.append(theta[i])
                # update theta
                theta = new_theta
                return backward_chaining(kb, alpha, theta)

            if len(sub_satisfied_theta_list) != 0:
                theta = sub_satisfied_theta_list
            return backward_chaining(kb, alpha, theta)

        # Pre-check if current facts are enough to answer/ find a substitution for sub_goal
        count = 0
        for fact in kb.facts:
            phi = unify(fact, sub_goal, Substitution())
            if phi:
                count += 1
                if phi.empty():     # if sub_goal is proven in kb. There is no sub_goal adding. This sub_goal is done
                    return backward_chaining(kb,alpha,theta)
                else:
                    theta.append(phi)


        return backward_chaining(kb, alpha, theta)


    # *********************************************************************
    # if alpha is a rule
    if sub_goal.predicate in kb.rule_conclusion_predicate:
        # get rule of sub_goal
        rule = kb.get_rule(sub_goal.predicate)
        num_premise = rule.get_num_premises()

        # get a list contains rule's premises
        premise_list = []
        i = 0
        while i < num_premise:
            premise_list.append(rule.premises[i])
            i += 1

        conclusion = rule.conclusion
        sub_theta = unify(conclusion, sub_goal, Substitution())
        subs_value_for_premise = []
        for premise in premise_list:
            temp_premise = premise.copy()
            sub_theta.substitute(temp_premise)
            subs_val = unify(premise, temp_premise, Substitution())
            subs_value_for_premise.append(subs_val)

        i = 0
        while i < len(premise_list):
            subs_val = subs_value_for_premise[i]
            premise = premise_list[i]
            subs_val.substitute(premise)
            alpha.append(premise)
            i += 1
        return backward_chaining(kb, alpha, theta)

    #return  res
示例#25
0
文件: core.py 项目: eigenhombre/logpy
 def goal_eq(s):
     result = unify(u, v, s)
     if result is not False:
         yield result
示例#26
0
文件: core.py 项目: danielggc/python
 def goal_eq(s):
     result = unify(u, v, s)
     if result is not False:
         yield result
示例#27
0
def contextual_and_or_leaflists(remaining,
                                indexed_kb,
                                depth,
                                context,
                                antecedents=[],
                                assumptions=[]):
    '''Returns list of all entailing sets of leafs in the and-or backchaining tree, with belief context'''
    if depth == 0 and len(antecedents) > 0:  # fail
        return []  # (empty) list of lists
    elif len(remaining) == 0:  # done with this level
        if len(antecedents) == 0:  # found one
            return [assumptions]  # list of lists
        else:
            return contextual_and_or_leaflists(antecedents, indexed_kb,
                                               depth - 1, context, [],
                                               assumptions)
    else:  # more to go on this level
        literal = remaining[0]  # first of remaining
        predicate = literal[0]

        if predicate not in indexed_kb:
            return contextual_and_or_leaflists(
                remaining[1:], indexed_kb, depth, context, antecedents,
                [literal] + assumptions)  # shift literal to assumptions
        else:
            revisions = []
            for rule in indexed_kb[
                    predicate]:  # indexed by predicate of literal
                theta = unify.unify(literal, parse.consequent(rule))
                if theta != None:
                    if depth == 0:  # no depth for revision
                        return []  # (empty) list of lists
                    revisions.append([
                        unify.subst(
                            theta,
                            remaining[1:]),  # new remaining with substitutions
                        indexed_kb,
                        depth,
                        context,
                        unify.standardize(
                            unify.subst(theta, parse.antecedent(rule))) +
                        unify.subst(
                            theta,
                            antecedents),  # new antecedents with substitutions
                        unify.subst(theta, assumptions)
                    ])  # new assumptions with substitutions
            for contextliteral in context:
                theta = unify.unify(literal, contextliteral)
                if theta != None:  # literal unifies with context
                    #print(str(literal) + " unifies with " + str(contextliteral) + " with theta " + str(theta) + " creating " + str(unify.subst(theta, literal)))
                    revisions.append([
                        unify.subst(
                            theta,
                            remaining[1:]),  # new remaining with substitutions
                        indexed_kb,
                        depth,
                        context,  # not revised
                        unify.subst(theta, antecedents),  # antecedents
                        unify.subst(theta, assumptions)  # assumptions
                    ])
                    # should we "break" here now that we've found one?
            return itertools.chain(*[
                contextual_and_or_leaflists(*rev) for rev in revisions
            ])  # list of lists (if any)
示例#28
0
def contains(conj, lit): # where conj is the list of entailed, lit is an answer literal.
    for c in conj:
        if unify.unify(lit, c):
            return True
    return False
示例#29
0
def forward_chaining(kb, alpha):
    res = set()
    # Pre-check if current facts are enough to answer
    for fact in kb.facts:
        phi = unify(fact, alpha, Substitution())
        if phi:
            if phi.empty():
                res.add('true')
                return res
            res.add(phi)

    last_generated_facts = kb.facts.copy()

    while True:
        new_facts = set()

        # Optimize: Incremental forward chaining
        # At iteration t, check a rule only if its premises includes at least
        # a conjunct pi that unified with the fact pi' newly inferred at iteration t - 1
        for rule in kb.rules:
            if not rule.may_triggered(last_generated_facts):
                continue

            num_premises = rule.get_num_premises()
            # Get facts that relevant to the current rule
            potential_facts = kb.get_potential_facts(rule)

            # Check if rule contains premises with the same predicate
            if not rule.dup_predicate:
                potential_premises = itertools.combinations(
                    sorted(potential_facts), num_premises)
            else:
                # Assumption on order of premises may failed on something like grandparent rule with two parent relations
                potential_premises = itertools.permutations(
                    potential_facts, num_premises)

            for tuple_premises in potential_premises:
                premises = [premise for premise in tuple_premises]
                theta = subst(rule.premises, premises)
                if not theta:
                    continue

                new_fact = rule.conclusion.copy()
                theta.substitute(new_fact)

                if new_fact not in new_facts and new_fact not in kb.facts:
                    new_facts.add(new_fact)
                    phi = unify(new_fact, alpha, Substitution())
                    if phi:
                        if phi.empty():
                            kb.facts.update(new_facts)
                            res.add('true')
                            return res
                        res.add(phi)

        last_generated_facts = new_facts
        if not new_facts:
            if not res:
                res.add('false')
            return res
        kb.facts.update(new_facts)