Esempio n. 1
0
    def resolve_goal_with_rule(self, goal, rule):
        """
        This is a specialization of
        :func:`etb.datalog.inference.Inference.resolve_goal` where we have a
        fixed rule that we examine (does the head of that rule match the goal,
        if so, we add a pending rule). This is used in
        :func:`etb.datalog.inference.Inference.add_rule`.

        :parameters:
            - `goal`: a goal is an internal representation of a literal, i.e.,
              a list of integers.
            - `rule`: a rule is an internal representation of a rule, i.e., a
              list of literals (each literal is a list of integers).

        :returntype:
            `True` if the function managed to match the `goal` with the head of
            the `rule`; `False` otherwise

        """
        self.notify()
        result = False
        off = model.offset(rule)
        disjoint_candidate = model.shift_literal(goal, off)
        subst = model.get_unification_l(disjoint_candidate, rule[0])
        if model.is_substitution(subst):
            result = True
            new_clause = model.apply_substitution_c(subst, rule, self.term_factory)
            self.add_pending_rule(new_clause, model.create_resolution_top_down_explanation(rule, goal), goal)

        self.log.debug('inference.resolve_goal_with_rule: setting {0}: RESOLVED'
                       .format(goal))
        self.set_goal_to_resolved(goal)
        
        return result
Esempio n. 2
0
    def resolve_goal(self, goal):
        """
        When adding a `goal`, we do 2 things:
            - we check the Datalog rules (the KB rules  -- *not* the pending
              rules but the rules and facts that make up the actual KB), and
              introduce any pending rules if we find rules for which the head
              matches the goal. Note that
              :func:`etb.datalog.inference.Inference.add_pending_rule` will
              introduce a new goal consisting of its first body literal (thus
              obtaining a top-down push of goals).
            - we check whether any existing claims match this goal via
              :func:`etb.datalog.inference.Inference.resolve_goal_with_existing_claims`.

        :parameters:
            - `goal`: a goal is an internal representation of a literal, i.e.,
              a list of integers.

        :returntype:
            `True` if the function managed to resolve the goal with any pending
            rule or any claim; `False` otherwise

        """
        self.log.debug('inference.resolve_goal: goal {0}'.format(self.term_factory.close_literal(goal)))
        self.notify()
        result = False
        # Try to resolve with Rules
        candidate_rules = index.get_candidate_matchings(self.logical_state.db_get_rules_index(), goal)
        for candidate in candidate_rules:
            # self.log.debug('inference.resolve_goal: candidate {0}'
            #                      .format([str(c) for c in self.term_factory.close_literals(candidate)]))
            off = model.offset(candidate)
            disjoint_goal = model.shift_literal(goal, off)
            
            subst = model.get_unification_l(candidate[0], disjoint_goal)
            self.log.debug('inference.resolve_goal: subst {0}'
                          .format(dict([(self.term_factory.get_symbol(v),
                                         str(self.term_factory.get_symbol(a))) for v, a in subst.items()])))
            if model.is_substitution(subst):
                result = True
                pending_rule = model.apply_substitution_c(subst, candidate, self.term_factory)
                self.log.info('unify goal {1}\n  with rule {2}\n  yields pending rule {0}'
                              .format([str(c) for c in
                                       self.term_factory.close_literals(pending_rule)],
                                      self.term_factory.close_literal(goal),
                                      [str(c) for c in
                                       self.term_factory.close_literals(candidate)]))
                explanation = model.create_resolution_top_down_explanation(candidate, goal)
                self.add_pending_rule(pending_rule, explanation, goal)

        # Try to resolve with Claims
        resolved_with_claims = True #self.resolve_goal_with_existing_claims(goal)
        if resolved_with_claims:
            result = True

        # when we try to resolve we set it as RESOLVED
        # self.log.debug('inference.resolve_goal: setting {0}: RESOLVED'
        #                      .format(self.term_factory.close_literal(goal)))
        self.set_goal_to_resolved(goal)

        return result
Esempio n. 3
0
 def propagate_claim_to_pending_clause(self, claim, claim_expl, candidate):
     """
     Propagation step from a claim for a subgoal for a pending rule (candidate)
     to the generate a new pending rule. 
     """
     clause = claim.clause if isinstance(claim, graph.PendingRule) else claim
     self.log.debug('inference.propagate_claim_to_pending_clause: claim = {0}, candidate = {1}'
                   .format(self.term_factory.close_literals(clause),
                           self.term_factory.close_literals(candidate.clause)))
     subst = model.get_unification_l(clause[0],candidate.clause[1])
     self.log.debug('inference.resolve_claim: candidate {0!s}: {1}'
                   .format([str(c) for c in self.term_factory.close_literals(candidate.clause)], subst))
     if model.is_substitution(subst):
         new_clause = model.remove_first_body_literal(candidate.clause, subst, self.term_factory)
         cand_expl = self.logical_state.db_get_explanation(candidate)
         assert cand_expl[0] != "None"
         #claim_expl = self.logical_state.db_get_explanation(claim)
         assert claim_expl[0] != "None"
         explanation = model.create_resolution_bottom_up_explanation(candidate, claim, claim_expl)
         # NSH: db_add_claim_to_goal has already been done above
         # update the subgoal (candidate[1]) with the found claim
         # self.logical_state.db_add_claim_to_goal(candidate[1], claim)
         self.increase_subgoalindex(candidate)
         candidate_annotation = self.logical_state.db_get_annotation(candidate)
         parent_goal = candidate_annotation.goal
         self.add_pending_rule(new_clause, explanation, parent_goal)
Esempio n. 4
0
    def is_entailed(self, goal):
        """
        Check whether goal is entailed or not.

        .. warning::
            Used only for unit tests
        """
        candidate_claims = index.get_candidate_specializations(self.logical_state.db_claims, goal)
        for claim in candidate_claims:
            if model.is_substitution( model.get_unification_l(claim.clause[0], goal)):
                return True
        return False
Esempio n. 5
0
    def resolve_pending_rule(self, rule):
        """
        This is symmetrical to a part of what
        :func:`etb.datalog.inference.Inference.resolve_claim` does: when adding
        a pending rule, we try to resolve any existing claims with the first
        body literal of that pending rule, and you add a new pending rule (or
        claim if the resulting pending rule became a fact).

        :parameters:
            - `rule`: an internal representation of a rule, i.e., a list of
              literals (which are lists of integers). The first element of the
              list is the head of the rule.

        :returntype:
            `None`
        """
        self.log.debug('inference.resolve_pending_rule {0}'
                      .format([str(c) for c in self.term_factory.close_literals(rule)]))
        self.notify()
        candidate_claims = index.get_candidate_specializations(self.logical_state.db_get_claims_index(), rule[1])

        for candidate in candidate_claims:
            subst = model.get_unification_l(candidate[0], rule[1])
            # self.log.debug('inference.resolve_pending_rule candidate {0}'
            #               .format([str(c) for c in self.term_factory.close_literals(candidate)]))
            # self.log.debug('inference.resolve_pending_rule subst {0}'
            #               .format(dict([(self.term_factory.get_symbol(v),
            #                              str(self.term_factory.get_symbol(a))) for v, a in subst.items()])))
            if model.is_substitution(subst):
                new_clause = model.remove_first_body_literal(rule,subst, self.term_factory)
                rule_expl = self.logical_state.db_get_explanation(rule)
                assert rule_expl[0] != "None"
                cand_expl = self.logical_state.db_get_explanation(candidate)
                assert cand_expl[0] != "None"
                explanation = model.create_resolution_bottom_up_explanation(rule, candidate)
                # self.log.debug('inference.resolve_pending_rule new_clause {0}: {1}'
                #                      .format(new_clause, explanation))
                self.logical_state.db_add_claim_to_goal(rule[1], candidate, explanation)
                if model.is_fact(new_clause):
                    self.add_claim(new_clause, explanation)
                    # increase the propogation index also for claims (not only
                    # for pending rules)
                    self.increase_subgoalindex(rule)
                else:
                    self.add_pending_rule(new_clause, explanation)
Esempio n. 6
0
    def resolve_goal_with_existing_claims(self, goal):
        """
        Try to resolve a `goal` with any existing claims. In other words, verify
        whether the `goal` can be solved by any existing claims`.

        :parameters:
            - `goal`: a goal is an internal representation of a literal, i.e.,
              a list of integers.

        :returntype:
            - `True` if at least one claim was found to be a solution for the
              `goal`; `False` otherwise.

        """
        self.notify()
        result = False
        candidate_claims = index.get_candidate_matchings(self.logical_state.db_get_claims_index(), goal)
        for candidate in candidate_claims:
            subst = model.get_unification_l(candidate.clause[0], goal)
            if model.is_substitution(subst):
                self.logical_state.db_add_claim_to_goal(goal, candidate)
                result = True
        return result