コード例 #1
0
    def valid_clause(self, clause: Clause) -> ValidClause:
        bound_vars: Set[Variable] = set()
        possibly_unbound_vars: Set[Variable] = set()
        subst: TermUnifier = UnionFindBasedUnifier()

        def add_set(a_x, a_set: Set):
            a_set.add(a_x)
            return a_set

        tv: TermVisitor = (TermVisitorBuilder().onVariable(add_set).or_(
            lambda a_x, a_set: a_set))
        TermHelpers.fold(
            HeadHelpers.force_positive_atom(clause.getHead()).getArgs(),
            tv,
            possibly_unbound_vars,
        )

        has_positive_atom_box: Box[bool] = Box(False)

        cv: PremiseVisitor = LocalCrashPremiseVisitor(
            tv,
            subst,
            has_positive_atom_box,
            bound_vars,
            possibly_unbound_vars,
            self.allowBinaryUnification,
            self.allowBinaryDisunification,
            self.allowNegatedBodyAtom,
        )

        p: Premise
        for p in clause.getBody():
            e: DatalogValidationException = p.accept_premise_visitor(cv, None)
            if e:
                raise e

        x: Variable
        for x in possibly_unbound_vars:
            if x not in bound_vars and not isinstance(subst.get(x), Constant):
                raise DatalogValidationException(
                    f"Every variable in a rule must be bound, but {x} is not bound in "
                    f"the rule {clause}. A variable X is bound if 1) it appears in a "
                    f"positive(non-negated) body atom or 2) it is explicitly unified "
                    f"with a constant(e.g. X=a) or with a variable that is bound "
                    f"(e.g. X=Y where Y is bound). ")

        new_body_list: List[Premise] = list(copy.deepcopy(clause.getBody()))
        if not has_positive_atom_box.value and new_body_list:
            new_body_list.insert(0, TrueAtom.getTrueAtom())
        new_body = tuple(new_body_list)
        return ValidClause(clause.getHead(), new_body)
コード例 #2
0
def test_error():
    x = Variable.create("X")
    y = Variable.create("Y")
    z = Variable.create("Z")
    w = Variable.create("W")
    p = PredicateSym.create("p", 2)
    q = PredicateSym.create("q", 2)
    qXY = PositiveAtom.create(q, [x, y])
    pXW = PositiveAtom.create(p, [x, w])
    qZW = PositiveAtom.create(q, [z, w])
    body = [qXY, qZW]

    cl = Clause(pXW, tuple(body))
    prog: UnstratifiedProgram = DatalogValidator(
    ).withBinaryUnificationInRuleBody().withBinaryDisunificationInRuleBody(
    ).validate({cl})
    annotator = SemiNaiveClauseAnnotator(list(prog.getIdbPredicateSyms()))
    it = iter(prog.getRules())
    rule = next(it)
    annotated = annotator.annotate_single(rule)
    assert str(annotated) == "[p(X, W) :- q(X, Y)<EDB>, q(Z, W)<EDB>.]"
コード例 #3
0
    def verify(body: List[Premise]):
        cl = Clause(pXW, tuple(body))
        prog: UnstratifiedProgram = DatalogValidator(
        ).withBinaryUnificationInRuleBody().withBinaryDisunificationInRuleBody(
        ).validate({cl})
        annotator = SemiNaiveClauseAnnotator(list(prog.getIdbPredicateSyms()))
        it = iter(prog.getRules())
        rule = next(it)
        annotated = annotator.annotate_single(rule)
        it_annotated = iter(annotated)
        ordered = next(it_annotated)

        def facts_func_result(fact, s, result):
            r = fact.applySubst(s)
            result.append(r)

        from functools import partial
        result = []
        facts_func = partial(facts_func_result, result=result)
        eval = ClauseEvaluator(ordered, facts_func, lambda atom, s: facts)

        eval.evaluate(qab)
        return result
コード例 #4
0
def test_evaluation_error():
    x = Variable.create("X")
    y = Variable.create("Y")
    z = Variable.create("Z")
    w = Variable.create("W")
    p = PredicateSym.create("p", 2)
    q = PredicateSym.create("q", 2)
    qXY = PositiveAtom.create(q, [x, y])
    pXW = PositiveAtom.create(p, [x, w])
    qZW = PositiveAtom.create(q, [z, w])
    body = [qXY, qZW]

    cl = Clause(pXW, tuple(body))
    prog: UnstratifiedProgram = DatalogValidator().withBinaryUnificationInRuleBody().withBinaryDisunificationInRuleBody().validate(
        {cl})
    annotator = SemiNaiveClauseAnnotator(list(prog.getIdbPredicateSyms()))
    it = iter(prog.getRules())
    rule = next(it)
    annotated = annotator.annotate_single(rule)
    it_annotated = iter(annotated)
    ordered = next(it_annotated)
    subst = ClauseSubstitution.make_with_seminaive_clause(ordered)
    assert subst.index == {z: 2, w: 3, x: 0, y: 1}
    assert str(subst) == "{ ^ <0> X -> None, Y -> None, <1> Z -> None, W -> None }"
コード例 #5
0
def get_head_predicate(clause: Clause):
    # OLD AbcDatalog code: Start
    # get_head_pred: HeadVisitor = LocalHeadVisitor()
    # return clause.getHead().accept_head_visitor(get_head_pred, None)
    # OLD AbcDatalog code: End
    return clause.getHead().getPred()
コード例 #6
0
def test_create_substitution_1():
    p0 = PredicateSym.create("p", 0)
    q2 = PredicateSym.create("q", 2)
    r2 = PredicateSym.create("r", 2)
    s3 = PredicateSym.create("s", 3)
    x: Variable
    y: Variable
    z: Variable
    x = Variable.create("X")
    y = Variable.create("Y")
    z = Variable.create("Z")
    a: Constant
    b: Constant
    a = Constant.create("a")
    b = Constant.create("b")
    idbPreds: List = [q2, s3]
    pAtom = PositiveAtom.create(p0, [])
    qAtom: Premise = PositiveAtom.create(q2, [x, y])
    rAtom: Premise = PositiveAtom.create(r2, [x, x])
    sAtom: Premise = PositiveAtom.create(s3, [a, x, z])
    u1: Premise = BinaryUnifier(x, b)
    u2: Premise = BinaryUnifier(z, z)
    validator: DatalogValidator = DatalogValidator().withBinaryUnificationInRuleBody()


    annotator: SemiNaiveClauseAnnotator = SemiNaiveClauseAnnotator(idbPreds)
    expected_value = "{ }"
    input_clause = {Clause(pAtom, tuple([pAtom]))} #ignore

    assert_annotation(validator, annotator, input_clause, expected_value)
    assert_annotation(validator, annotator, {Clause(pAtom, tuple([qAtom]))}, "{ ^ <0> X -> None, Y -> None }")
    l: List[Premise] = [qAtom, rAtom]

    assert_annotation(validator, annotator, {Clause(pAtom, tuple(l))}, "{ ^ <0> X -> None, Y -> None }")
    l[0], l[1] = l[1], l[0]

    assert_annotation(validator, annotator, [Clause(pAtom, tuple(l))], "{ ^ <0> X -> None, Y -> None }")
    l = [qAtom, sAtom]
    subst = clause_substitution(annotator, [Clause(pAtom, tuple(l))], validator)
    assert str(subst) == "{ ^ <0> X -> None, Y -> None, <1> Z -> None }"

    subst.add(x, a)

    assert str(subst) == "{ <0> X -> a, ^ Y -> None, <1> Z -> None }"

    with pytest.raises(AssertionError): #Correctly threw error when adding in wrong order"
        subst.add(z, a)
    subst.add(y, b)
    assert str(subst) == "{ <0> X -> a, Y -> b, ^ <1> Z -> None }"
    with pytest.raises(AssertionError): # Correctly threw error when adding in wrong order
        subst.add(x, a)
    subst.add(z, a)
    assert str(subst) == "{ <0> X -> a, Y -> b, <1> Z -> a }"
    with pytest.raises(AssertionError): # Correctly threw error when adding a variable not in substitution
        subst.add(Variable.create("w"), b)
    subst.resetState(0)
    assert not subst.get(x)
    subst.add(x, a)
    assert subst.get(x) == a
    subst.add(y, b)

    assert subst.get(x) == a
    assert subst.get(y) == b
    subst.add(z, a)
    assert subst.get(x) == a
    assert subst.get(y) == b
    assert subst.get(z) == a
    subst.resetState(1)
    assert subst.get(x) == a
    assert subst.get(y) == b
    assert not subst.get(z)
コード例 #7
0
    def sort(original: Clause, firstConjunctPos: int) -> SemiNaiveClause:
        # 		List<Premise> body = new ArrayList<>(original.getBody());
        body: List[Premise] = list(original.getBody())
        # 		if (body.isEmpty()) {
        # 			return new SemiNaiveClause(original.getHead(), body);
        # 		}
        if not body:
            return SemiNaiveClause(original.getHead(), body)
        # 		PremiseVisitor<Set<Variable>, Void> boundVarUpdater = new DefaultConjunctVisitor<Set<Variable>, Void>() {

        boundVarUpdater: PremiseVisitor[Set[Variable]] = LocalDefaultConjunctVisitor()
        # 			@Override
        # 			public Void visit(AnnotatedAtom atom, Set<Variable> boundVars) {
        # 				for (Term t : atom.getArgs()) {
        # 					if (t instanceof Variable) {
        # 						boundVars.add((Variable) t);
        # 					}
        # 				}
        # 				return null;
        # 			}
        #
        # 			@Override
        # 			public Void visit(BinaryUnifier u, Set<Variable> boundVars) {
        # 				for (Term t : u.getArgsIterable()) {
        # 					if (t instanceof Variable) {
        # 						boundVars.add((Variable) t);
        # 					}
        # 				}
        # 				return null;
        # 			}
        # 		};
        #

        # 		PremiseVisitor<Set<Variable>, Double> scorer = new CrashPremiseVisitor<Set<Variable>, Double>() {
        scorer: PremiseVisitor[Set[Variable], float] = LocalCrashPremiseVisitor()
        # 			@Override
        # 			public Double visit(AnnotatedAtom atom, Set<Variable> boundVars) {
        # 				int count = 0, total = 0;
        # 				for (Term t : atom.getArgs()) {
        # 					if (t instanceof Constant || boundVars.contains(t)) {
        # 						++count;
        # 					}
        # 					++total;
        # 				}
        # 				return (total == 0) ? 1.0 : count / total;
        # 			}
        #
        # 			@Override
        # 			public Double visit(BinaryUnifier u, Set<Variable> boundVars) {
        # 				for (Term t : u.getArgsIterable()) {
        # 					if (t instanceof Constant || boundVars.contains(t)) {
        # 						return Double.POSITIVE_INFINITY;
        # 					}
        # 				}
        # 				return Double.NEGATIVE_INFINITY;
        # 			}
        #
        # 			@Override
        # 			public Double visit(BinaryDisunifier u, Set<Variable> boundVars) {
        # 				for (Term t : u.getArgsIterable()) {
        # 					if (!(t instanceof Constant || boundVars.contains(t))) {
        # 						return Double.NEGATIVE_INFINITY;
        # 					}
        # 				}
        # 				return Double.POSITIVE_INFINITY;
        # 			}
        #
        # 			@Override
        # 			public Double visit(NegatedAtom atom, Set<Variable> boundVars) {
        # 				for (Term t : atom.getArgs()) {
        # 					if (!(t instanceof Constant || boundVars.contains(t))) {
        # 						return Double.NEGATIVE_INFINITY;
        # 					}
        # 				}
        # 				return Double.POSITIVE_INFINITY;
        # 			}
        # 		};
        #
        # 		Collections.swap(body, 0, firstConjunctPos);
        body[0], body[firstConjunctPos] = body[firstConjunctPos], body[0]
        # 		int size = body.size();
        size: int = len(body)
        # 		Set<Variable> boundVars = new HashSet<>();
        boundVars: Set[Variable] = set()
        # 		for (int i = 1; i < size; ++i) {
        for i in range(1, size):
            # 			body.get(i - 1).accept(boundVarUpdater, boundVars);
            body[i - 1].accept_premise_visitor(boundVarUpdater, boundVars)
            # 			int bestPos = -1;
            bestPos: int = -1
            # 			double bestScore = Double.NEGATIVE_INFINITY;
            bestScore: float = float("-inf")

            # 			for (int j = i; j < size; ++j) {
            j: int = i
            while j < size:
                # 				Double score = body.get(j).accept(scorer, boundVars);
                score: float = body[j].accept_premise_visitor(scorer, boundVars)
                # 				if (score > bestScore) {
                if score > bestScore:
                    # 					bestScore = score;
                    bestScore = score
                    # 					bestPos = j;
                    bestPos = j
                # 				}
                j += 1
            # 			}
            # 			assert bestPos != -1;
            assert bestPos != -1
            # 			Collections.swap(body, i, bestPos);
            body[i], body[bestPos] = body[bestPos], body[i]
        # 		}
        #
        # 		return new SemiNaiveClause(original.getHead(), body);
        return SemiNaiveClause(original.getHead(), tuple(body))
コード例 #8
0
    def annotate_single(self, original: ValidClause) -> List[SemiNaiveClause]:
        body: Tuple[Premise] = original.getBody()

        if not body:
            raise ValueError("Cannot annotate a bodiless clause")
        body2: List[Premise] = []
        idbPositions: List[int] = []
        edbPos: Box[int] = Box()

        def add_to_body2(atom, pos):
            if atom.getPred() in self.idbPreds:
                idbPositions.append(pos)
                body2.append(atom)
            else:
                if edbPos.value is None:
                    edbPos.value = pos
                body2.append(AnnotatedAtom(atom, Annotation.EDB))
            return None

        def simple_add_to_body2(premise, ignore):
            body2.append(premise)

        findIdbs: PremiseVisitor[int, None] = (
            PremiseVisitorBuilder()
            .onPositiveAtom(add_to_body2)
            .or_(simple_add_to_body2)
        )

        pos: int = 0
        c: Premise
        for c in body:
            c.accept_premise_visitor(findIdbs, pos)
            pos += 1
        # RA: something happens above c.accept_premise_visitor to change edPos value to 1
        # 		body = body2;
        body = tuple(body2)
        #
        # 		if (idbPositions.isEmpty()) {
        # 			if (edbPos.value == null) {
        # 				edbPos.value = 0;
        # 			}
        # 			return Collections.singleton(sort(new Clause(original.getHead(), body), edbPos.value));
        # 		}
        #

        if not idbPositions:
            if not edbPos.value:
                edbPos.value = 0
            # singleton_set = set()
            singleton_set = []
            # singleton_set.add(SemiNaiveClauseAnnotator.sort(Clause(original.getHead(), body), edbPos.value))
            singleton_set.append(
                SemiNaiveClauseAnnotator.sort(
                    Clause(original.getHead(), body), edbPos.value
                )
            )
            assert len(singleton_set) == 1, "Supposed to be a singleton set"
            return singleton_set

        # 		Set<SemiNaiveClause> r = new HashSet<>();
        #         r: Set[SemiNaiveClause] = set()
        r: List[SemiNaiveClause] = []

        def add1(l_newBody: List, atom, anno):
            l_newBody.append(AnnotatedAtom(atom, anno))
            return None

        def add2(l_newBody: List, premise, ignore):
            l_newBody.append(premise)
            return None

        # 		for (Integer i : idbPositions) {
        i: int
        for i in idbPositions:
            # 			List<Premise> newBody = new ArrayList<>();
            newBody: List[Premise] = []
            # 			PremiseVisitor<AnnotatedAtom.Annotation, Void> annotator = (new PremiseVisitorBuilder<AnnotatedAtom.Annotation, Void>())
            add1_l = lambda atom, anno: add1(newBody, atom, anno)
            add2_l = lambda premise, ignore: add2(newBody, premise, ignore)
            annotator: PremiseVisitor[Annotation, None] = (
                PremiseVisitorBuilder().onPositiveAtom(add1_l).or_(add2_l)
            )
            # 					.onPositiveAtom((atom, anno) -> {
            # 						newBody.add(new AnnotatedAtom(atom, anno));
            # 						return null;
            # 					}).or((premise, ignore) -> {
            # 						newBody.add(premise);
            # 						return null;
            # 					});

            # 			Iterator<Premise> it = body.iterator();
            # 			for (int j = 0; j < i; ++j) {
            # 				it.next().accept(annotator, AnnotatedAtom.Annotation.IDB);
            # 			}
            it = iter(body)
            item = None
            for j, _ in enumerate(body):
                if j >= i:
                    break
                item = next(it)
                item.accept_premise_visitor(annotator, Annotation.IDB)

            # 			it.next().accept(annotator, AnnotatedAtom.Annotation.DELTA);
            item = next(it)
            item.accept_premise_visitor(annotator, Annotation.DELTA)
            # 			while (it.hasNext()) {
            # 				it.next().accept(annotator, AnnotatedAtom.Annotation.IDB_PREV);
            # 			}
            while True:
                try:
                    item = next(it)
                    item.accept_premise_visitor(annotator, Annotation.IDB_PREV)
                except StopIteration:
                    break
            # 			r.add(sort(new Clause(original.getHead(), newBody), i));
            r.append(
                SemiNaiveClauseAnnotator.sort(
                    Clause(original.getHead(), tuple(newBody)), i
                )
            )
        # 		}
        r = unique(r)
        return r