Пример #1
0
    def abduce(self, query, tablenames, find_all=True):
        """Compute additional literals.

        Computes additional literals that if true would make
        (some instance of) QUERY true.  Returns a list of rules
        where the head represents an instance of the QUERY and
        the body is the collection of literals that must be true
        in order to make that instance true.  If QUERY is a rule,
        each result is an instance of the head of that rule, and
        the computed literals if true make the body of that rule
        (and hence the head) true.  If FIND_ALL is true, the
        return list has at most one element.
        Limitation: every negative literal relevant to a proof of
        QUERY is unconditionally true, i.e. no literals are saved
        when proving a negative literal is true.
        """
        assert compile.is_datalog(query), "abduce requires a formula"
        if compile.is_atom(query):
            literals = [query]
            output = query
        else:
            literals = query.body
            output = query.head
        # We need all the variables we will be using in the output, which
        #   here is just the head of QUERY (or QUERY itself if it is an atom)
        abductions = self.top_down_abduction(
            output.variables(), literals, find_all=find_all,
            save=lambda lit, binding: lit.tablename() in tablenames)
        results = [compile.Rule(output.plug(abd.binding), abd.support)
                   for abd in abductions]
        self.log(query.tablename(), "abduction result:")
        self.log(query.tablename(), "\n".join([str(x) for x in results]))
        return results
Пример #2
0
    def update_would_cause_errors(self, events):
        """Return a list of PolicyException.

        Return a list of PolicyException if we were
        to apply the insert/deletes of policy statements dictated by
        EVENTS to the current policy.
        """
        self.log(None, "update_would_cause_errors %s", iterstr(events))
        errors = []
        for event in events:
            if not compile.is_datalog(event.formula):
                errors.append(PolicyException(
                    "Non-formula found: {}".format(
                        str(event.formula))))
            else:
                if event.formula.is_atom():
                    errors.extend(compile.fact_errors(
                        event.formula, self.theories, self.name))
                else:
                    errors.extend(compile.rule_errors(
                        event.formula, self.theories, self.name))
        # Would also check that rules are non-recursive, but that
        #   is currently being handled by Runtime.  The current implementation
        #   disallows recursion in all theories.
        return errors
Пример #3
0
    def update_would_cause_errors(self, events):
        """Return a list of PolicyException.

        Return a list of PolicyException if we were
        to apply the events EVENTS to the current policy.
        """
        self.log(None, "update_would_cause_errors %s", utility.iterstr(events))
        errors = []
        for event in events:
            if not compile.is_datalog(event.formula):
                errors.append(
                    exception.PolicyException("Non-formula found: {}".format(
                        str(event.formula))))
            else:
                if event.formula.is_atom():
                    errors.extend(
                        compile.fact_errors(event.formula, self.theories,
                                            self.name))
                else:
                    errors.extend(
                        compile.rule_head_has_no_theory(
                            event.formula,
                            permit_head=lambda lit: lit.is_update()))
                    # Should put this back in place, but there are some
                    # exceptions that we don't handle right now.
                    # Would like to mark some tables as only being defined
                    #   for certain bound/free arguments and take that into
                    #   account when doing error checking.
                    # errors.extend(compile.rule_negation_safety(event.formula))
        return errors
Пример #4
0
    def update_would_cause_errors(self, events):
        """Return a list of PolicyException.

        Return a list of PolicyException if we were
        to apply the events EVENTS to the current policy.
        """
        self.log(None, "update_would_cause_errors %s", iterstr(events))
        errors = []
        for event in events:
            if not compile.is_datalog(event.formula):
                errors.append(PolicyException(
                    "Non-formula found: {}".format(
                        str(event.formula))))
            else:
                if event.formula.is_atom():
                    errors.extend(compile.fact_errors(
                        event.formula, self.theories, self.name))
                else:
                    errors.extend(compile.rule_head_has_no_theory(
                        event.formula,
                        permit_head=lambda lit: lit.is_update()))
                    # Should put this back in place, but there are some
                    # exceptions that we don't handle right now.
                    # Would like to mark some tables as only being defined
                    #   for certain bound/free arguments and take that into
                    #   account when doing error checking.
                    # errors.extend(compile.rule_negation_safety(event.formula))
        return errors
Пример #5
0
    def update_would_cause_errors(self, events):
        """Return a list of PolicyException.

        Return a list of PolicyException if we were
        to apply the insert/deletes of policy statements dictated by
        EVENTS to the current policy.
        """
        self.log(None, "update_would_cause_errors %s", utility.iterstr(events))
        errors = []
        for event in events:
            if not compile.is_datalog(event.formula):
                errors.append(
                    exception.PolicyException("Non-formula found: {}".format(
                        str(event.formula))))
            else:
                if event.formula.is_atom():
                    errors.extend(
                        compile.fact_errors(event.formula, self.theories,
                                            self.name))
                else:
                    errors.extend(
                        compile.rule_errors(event.formula, self.theories,
                                            self.name))
        # Would also check that rules are non-recursive, but that
        #   is currently being handled by Runtime.  The current implementation
        #   disallows recursion in all theories.
        return errors
Пример #6
0
    def update(self, events):
        """Apply inserts/deletes described by EVENTS and return changes.

           Does not check if EVENTS would cause errors.
           """
        for event in events:
            assert compile.is_datalog(event.formula), "Non-formula not allowed: {}".format(str(event.formula))
            self.enqueue_any(event)
        changes = self.process_queue()
        return changes
Пример #7
0
    def update(self, events):
        """Apply inserts/deletes described by EVENTS and return changes.

           Does not check if EVENTS would cause errors.
           """
        for event in events:
            assert compile.is_datalog(
                event.formula), ("Non-formula not allowed: {}".format(
                    str(event.formula)))
            self.enqueue_any(event)
        changes = self.process_queue()
        return changes
Пример #8
0
    def update_would_cause_errors(self, events):
        """Return a list of PolicyException.

        Return a list of PolicyException if we were
        to apply the events EVENTS to the current policy.
        """
        self.log(None, "update_would_cause_errors %s", utility.iterstr(events))
        errors = []
        # compute new rule set
        for event in events:
            assert compile.is_datalog(event.formula), "update_would_cause_errors operates only on objects"
            self.log(None, "Updating %s", event.formula)
            if event.formula.is_atom():
                errors.extend(compile.fact_errors(event.formula, self.theories, self.name))
            else:
                errors.extend(compile.rule_errors(event.formula, self.theories, self.name))
        return errors
Пример #9
0
    def select(self, query, find_all=True):
        """Return list of instances of QUERY that are true.

        If FIND_ALL is False, the return list has at most 1 element.
        """
        assert compile.is_datalog(query), "Query must be atom/rule"
        if compile.is_atom(query):
            literals = [query]
        else:
            literals = query.body
        # Because our output is instances of QUERY, need all the variables
        #   in QUERY.
        bindings = self.top_down_evaluation(query.variables(), literals,
                                            find_all=find_all)
        # LOG.debug("Top_down_evaluation returned: %s", bindings)
        if len(bindings) > 0:
            self.log(query.tablename(), "Found answer %s",
                     "[" + ",".join([str(query.plug(x))
                                    for x in bindings]) + "]")
        return [query.plug(x) for x in bindings]
Пример #10
0
    def select(self, query, find_all=True):
        """Return list of instances of QUERY that are true.

        If FIND_ALL is False, the return list has at most 1 element.
        """
        assert compile.is_datalog(query), "Query must be atom/rule"
        if compile.is_atom(query):
            literals = [query]
        else:
            literals = query.body
        # Because our output is instances of QUERY, need all the variables
        #   in QUERY.
        bindings = self.top_down_evaluation(query.variables(),
                                            literals,
                                            find_all=find_all)
        # LOG.debug("Top_down_evaluation returned: %s", bindings)
        if len(bindings) > 0:
            self.log(
                query.tablename(), "Found answer %s",
                "[" + ",".join([str(query.plug(x)) for x in bindings]) + "]")
        return [query.plug(x) for x in bindings]
Пример #11
0
    def update_would_cause_errors(self, events):
        """Return a list of PolicyException.

        Return a list of PolicyException if we were
        to apply the events EVENTS to the current policy.
        """
        self.log(None, "update_would_cause_errors %s", iterstr(events))
        errors = []
        # compute new rule set
        for event in events:
            assert compile.is_datalog(event.formula), (
                "update_would_cause_errors operates only on objects")
            self.log(None, "Updating %s", event.formula)
            if event.formula.is_atom():
                errors.extend(
                    compile.fact_errors(event.formula, self.theories,
                                        self.name))
            else:
                errors.extend(
                    compile.rule_errors(event.formula, self.theories,
                                        self.name))
        return errors
Пример #12
0
    def abduce(self, query, tablenames, find_all=True):
        """Compute additional literals.

        Computes additional literals that if true would make
        (some instance of) QUERY true.  Returns a list of rules
        where the head represents an instance of the QUERY and
        the body is the collection of literals that must be true
        in order to make that instance true.  If QUERY is a rule,
        each result is an instance of the head of that rule, and
        the computed literals if true make the body of that rule
        (and hence the head) true.  If FIND_ALL is true, the
        return list has at most one element.
        Limitation: every negative literal relevant to a proof of
        QUERY is unconditionally true, i.e. no literals are saved
        when proving a negative literal is true.
        """
        assert compile.is_datalog(query), "Explain requires a formula"
        if compile.is_atom(query):
            literals = [query]
            output = query
        else:
            literals = query.body
            output = query.head
        # We need all the variables we will be using in the output, which
        #   here is just the head of QUERY (or QUERY itself if it is an atom)
        abductions = self.top_down_abduction(
            output.variables(),
            literals,
            find_all=find_all,
            save=lambda lit, binding: lit.table in tablenames)
        results = [
            compile.Rule(output.plug(abd.binding), abd.support)
            for abd in abductions
        ]
        self.log(query.tablename(), "abduction result:")
        self.log(query.tablename(), "\n".join([str(x) for x in results]))
        return results
Пример #13
0
    def test_type_checkers(self):
        """Test the type checkers, e.g. is_atom, is_rule."""
        atom = compile.Literal("p", [])
        atom2 = compile.Literal("q", [])
        atom3 = compile.Literal("r", [])
        lit = compile.Literal("r", [], negated=True)
        regular_rule = compile.Rule(atom, [atom2, atom3])
        regular_rule2 = compile.Rule(atom, [lit, atom2])
        multi_rule = compile.Rule([atom, atom2], [atom3])
        fake_rule = compile.Rule([atom, 1], [atom2])
        fake_rule2 = compile.Rule(atom, [atom2, 1])

        # is_atom
        self.assertTrue(compile.is_atom(atom))
        self.assertTrue(compile.is_atom(atom2))
        self.assertTrue(compile.is_atom(atom3))
        self.assertFalse(compile.is_atom(lit))
        self.assertFalse(compile.is_atom(regular_rule))
        self.assertFalse(compile.is_atom(regular_rule2))
        self.assertFalse(compile.is_atom(multi_rule))
        self.assertFalse(compile.is_atom(fake_rule))
        self.assertFalse(compile.is_atom(fake_rule2))
        self.assertFalse(compile.is_atom("a string"))

        # is_literal
        self.assertTrue(compile.is_literal(atom))
        self.assertTrue(compile.is_literal(atom2))
        self.assertTrue(compile.is_literal(atom3))
        self.assertTrue(compile.is_literal(lit))
        self.assertFalse(compile.is_literal(regular_rule))
        self.assertFalse(compile.is_literal(regular_rule2))
        self.assertFalse(compile.is_literal(multi_rule))
        self.assertFalse(compile.is_literal(fake_rule))
        self.assertFalse(compile.is_literal(fake_rule2))
        self.assertFalse(compile.is_literal("a string"))

        # is_regular_rule
        self.assertFalse(compile.is_regular_rule(atom))
        self.assertFalse(compile.is_regular_rule(atom2))
        self.assertFalse(compile.is_regular_rule(atom3))
        self.assertFalse(compile.is_regular_rule(lit))
        self.assertTrue(compile.is_regular_rule(regular_rule))
        self.assertTrue(compile.is_regular_rule(regular_rule2))
        self.assertFalse(compile.is_regular_rule(multi_rule))
        self.assertFalse(compile.is_regular_rule(fake_rule))
        self.assertFalse(compile.is_regular_rule(fake_rule2))
        self.assertFalse(compile.is_regular_rule("a string"))

        # is_multi_rule
        self.assertFalse(compile.is_multi_rule(atom))
        self.assertFalse(compile.is_multi_rule(atom2))
        self.assertFalse(compile.is_multi_rule(atom3))
        self.assertFalse(compile.is_multi_rule(lit))
        self.assertFalse(compile.is_multi_rule(regular_rule))
        self.assertFalse(compile.is_multi_rule(regular_rule2))
        self.assertTrue(compile.is_multi_rule(multi_rule))
        self.assertFalse(compile.is_multi_rule(fake_rule))
        self.assertFalse(compile.is_multi_rule(fake_rule2))
        self.assertFalse(compile.is_multi_rule("a string"))

        # is_rule
        self.assertFalse(compile.is_rule(atom))
        self.assertFalse(compile.is_rule(atom2))
        self.assertFalse(compile.is_rule(atom3))
        self.assertFalse(compile.is_rule(lit))
        self.assertTrue(compile.is_rule(regular_rule))
        self.assertTrue(compile.is_rule(regular_rule2))
        self.assertTrue(compile.is_rule(multi_rule))
        self.assertFalse(compile.is_rule(fake_rule))
        self.assertFalse(compile.is_rule(fake_rule2))
        self.assertFalse(compile.is_rule("a string"))

        # is_datalog
        self.assertTrue(compile.is_datalog(atom))
        self.assertTrue(compile.is_datalog(atom2))
        self.assertTrue(compile.is_datalog(atom3))
        self.assertFalse(compile.is_datalog(lit))
        self.assertTrue(compile.is_datalog(regular_rule))
        self.assertTrue(compile.is_datalog(regular_rule2))
        self.assertFalse(compile.is_datalog(multi_rule))
        self.assertFalse(compile.is_datalog(fake_rule))
        self.assertFalse(compile.is_datalog(fake_rule2))
        self.assertFalse(compile.is_datalog("a string"))

        # is_extended_datalog
        self.assertTrue(compile.is_extended_datalog(atom))
        self.assertTrue(compile.is_extended_datalog(atom2))
        self.assertTrue(compile.is_extended_datalog(atom3))
        self.assertFalse(compile.is_extended_datalog(lit))
        self.assertTrue(compile.is_extended_datalog(regular_rule))
        self.assertTrue(compile.is_extended_datalog(regular_rule2))
        self.assertTrue(compile.is_extended_datalog(multi_rule))
        self.assertFalse(compile.is_extended_datalog(fake_rule))
        self.assertFalse(compile.is_extended_datalog(fake_rule2))
        self.assertFalse(compile.is_extended_datalog("a string"))
Пример #14
0
    def test_type_checkers(self):
        """Test the type checkers, e.g. is_atom, is_rule."""
        atom = compile.Literal("p", [])
        atom2 = compile.Literal("q", [])
        atom3 = compile.Literal("r", [])
        lit = compile.Literal("r", [], negated=True)
        regular_rule = compile.Rule(atom, [atom2, atom3])
        regular_rule2 = compile.Rule(atom, [lit, atom2])
        multi_rule = compile.Rule([atom, atom2], [atom3])
        fake_rule = compile.Rule([atom, 1], [atom2])
        fake_rule2 = compile.Rule(atom, [atom2, 1])

        # is_atom
        self.assertTrue(compile.is_atom(atom))
        self.assertTrue(compile.is_atom(atom2))
        self.assertTrue(compile.is_atom(atom3))
        self.assertFalse(compile.is_atom(lit))
        self.assertFalse(compile.is_atom(regular_rule))
        self.assertFalse(compile.is_atom(regular_rule2))
        self.assertFalse(compile.is_atom(multi_rule))
        self.assertFalse(compile.is_atom(fake_rule))
        self.assertFalse(compile.is_atom(fake_rule2))
        self.assertFalse(compile.is_atom("a string"))

        # is_literal
        self.assertTrue(compile.is_literal(atom))
        self.assertTrue(compile.is_literal(atom2))
        self.assertTrue(compile.is_literal(atom3))
        self.assertTrue(compile.is_literal(lit))
        self.assertFalse(compile.is_literal(regular_rule))
        self.assertFalse(compile.is_literal(regular_rule2))
        self.assertFalse(compile.is_literal(multi_rule))
        self.assertFalse(compile.is_literal(fake_rule))
        self.assertFalse(compile.is_literal(fake_rule2))
        self.assertFalse(compile.is_literal("a string"))

        # is_regular_rule
        self.assertFalse(compile.is_regular_rule(atom))
        self.assertFalse(compile.is_regular_rule(atom2))
        self.assertFalse(compile.is_regular_rule(atom3))
        self.assertFalse(compile.is_regular_rule(lit))
        self.assertTrue(compile.is_regular_rule(regular_rule))
        self.assertTrue(compile.is_regular_rule(regular_rule2))
        self.assertFalse(compile.is_regular_rule(multi_rule))
        self.assertFalse(compile.is_regular_rule(fake_rule))
        self.assertFalse(compile.is_regular_rule(fake_rule2))
        self.assertFalse(compile.is_regular_rule("a string"))

        # is_multi_rule
        self.assertFalse(compile.is_multi_rule(atom))
        self.assertFalse(compile.is_multi_rule(atom2))
        self.assertFalse(compile.is_multi_rule(atom3))
        self.assertFalse(compile.is_multi_rule(lit))
        self.assertFalse(compile.is_multi_rule(regular_rule))
        self.assertFalse(compile.is_multi_rule(regular_rule2))
        self.assertTrue(compile.is_multi_rule(multi_rule))
        self.assertFalse(compile.is_multi_rule(fake_rule))
        self.assertFalse(compile.is_multi_rule(fake_rule2))
        self.assertFalse(compile.is_multi_rule("a string"))

        # is_rule
        self.assertFalse(compile.is_rule(atom))
        self.assertFalse(compile.is_rule(atom2))
        self.assertFalse(compile.is_rule(atom3))
        self.assertFalse(compile.is_rule(lit))
        self.assertTrue(compile.is_rule(regular_rule))
        self.assertTrue(compile.is_rule(regular_rule2))
        self.assertTrue(compile.is_rule(multi_rule))
        self.assertFalse(compile.is_rule(fake_rule))
        self.assertFalse(compile.is_rule(fake_rule2))
        self.assertFalse(compile.is_rule("a string"))

        # is_datalog
        self.assertTrue(compile.is_datalog(atom))
        self.assertTrue(compile.is_datalog(atom2))
        self.assertTrue(compile.is_datalog(atom3))
        self.assertFalse(compile.is_datalog(lit))
        self.assertTrue(compile.is_datalog(regular_rule))
        self.assertTrue(compile.is_datalog(regular_rule2))
        self.assertFalse(compile.is_datalog(multi_rule))
        self.assertFalse(compile.is_datalog(fake_rule))
        self.assertFalse(compile.is_datalog(fake_rule2))
        self.assertFalse(compile.is_datalog("a string"))

        # is_extended_datalog
        self.assertTrue(compile.is_extended_datalog(atom))
        self.assertTrue(compile.is_extended_datalog(atom2))
        self.assertTrue(compile.is_extended_datalog(atom3))
        self.assertFalse(compile.is_extended_datalog(lit))
        self.assertTrue(compile.is_extended_datalog(regular_rule))
        self.assertTrue(compile.is_extended_datalog(regular_rule2))
        self.assertTrue(compile.is_extended_datalog(multi_rule))
        self.assertFalse(compile.is_extended_datalog(fake_rule))
        self.assertFalse(compile.is_extended_datalog(fake_rule2))
        self.assertFalse(compile.is_extended_datalog("a string"))