Semantics of Rules with Probabilities

Annotated disjunctions and Probabilistic clauses

A ProbLog program consists of two parts: a set of ground probabilistic facts, and a logic program, i.e. a set of rules and (‘non-probabilistic’) facts. A ground probabilistic fact, written \(p\!::\!f\), is a ground fact f annotated with a probability \(p\). We allow syntactic sugar for compactly specifying an entire set of probabilistic facts with a single statement. Concretely, we allow what we call probabilistic clauses, which are statements of the form \(p\!::\!f :\!-\ body\), with body a conjunction of calls to non-probabilistic facts. Also annotated disjunctions can be expressed like this for probabilistic clauses: \(p_1\!::\!f_1; \dots; p_n\!::\!f_n :\!-\ body\). Or like this for probabilistic facts: \(p_1\!::\!f_1; \dots; p_n\!::\!f_n\).

Probabilistic clauses can always be rewritten a combination of probabilistic facts and non-probabilistic clauses (rules). Suppose the following annotated disjuction with a body:

0.7::red(X); 0.3::green(X) :- ball(X). ball(a). ball(b). ball(c). query(red(_)). query(green(_)).

This can be rewritten to an annotated disjuction without a body as follows:

0.7::choose_red(X); 0.3::choose_green(X). red(X) :- ball(X), choose_red(X). green(X) :- ball(X), choose_green(X). ball(a). ball(b). ball(c). query(red(_)). query(green(_)).

In previous work these extra predicates where referred to as choice nodes or choice predicates. If the head of the intensional annotated disjunction contains variables that do not appear in the body, they should also appear in the newly added choice predicates.

An annotated disjunction is handled by ProbLog natively but if needed, this can also be translated further into probabilistic facts:

0.7::choose_red_cprob(X). % 0.7 / (1.0 - 0.0) = 0.7 1.0::choose_green_cprob(X). % 0.3 / (1.0 - 0.7) = 1.0 choose_red(X) :- choose_red_cprob(X). choose_green(X) :- \+choose_red(X), choose_green_cprob(X). red(X) :- ball(X), choose_red(X). green(X) :- ball(X), choose_green(X). ball(a). ball(b). ball(c). query(red(_)). query(green(_)).

For more background, see:

  • D. Fierens, G. Van den Broeck, J. Renkens, D. Shterionov, B. Gutmann, I. Thon, G. Janssens and L. De Raedt. Inference and learning in probabilistic logic programs using weighted Boolean formulas. Theory and Practice of Logic Programming, 15:3, pp. 358 - 401, Cambridge University Press, 2015. PDF DOI
  • Semantics and conversions of probabilistic clauses

    This page is to clarify the meaning of probabilistic clauses in ProbLog. The semantics of ProbLog have since 2008 been formulated in terms of ground facts labeled with probabilities and logical rules (clauses without probabilities), while earlier publications have used labels on both rules and facts, where \(0.7::red(X) :\!- ball(X)\) was interpreted as the non-ground clause \(red(X) :\!- ball(X)\) being part of a randomly sampled Prolog program with probability 0.7 (in which case all balls would be red). This interpretation can easily be modeled with probabilistic facts and logical rules as follows:

    0.7::in. red(X) :- ball(X), in. ball(a). ball(b). ball(c). query(red(_)). green(X) :- ball(X), \+ red(X). query(green(_)). different_color(A,B) :- ball(A), ball(B), A@=<B, red(A), green(B). different_color(A,B) :- ball(A), ball(B), A@=<B, green(A), red(B). query(different_color(_,_)).

    If we want i.i.d. probabilities for all balls, we can use a non-ground labeled fact:

    0.7::in(_). red(X) :- ball(X), in(X). ball(a). ball(b). ball(c). query(red(_)). green(X) :- ball(X), \+ red(X). query(green(_)). different_color(A,B) :- ball(A), ball(B), A@=<B, red(A), green(B). different_color(A,B) :- ball(A), ball(B), A@=<B, green(A), red(B). query(different_color(_,_)).

    Probabilistic clauses provide syntactic sugar to directly use probabilities with rules. Just as non-ground probabilistic facts, non-ground probabilistic clauses represent the set of all their groundings, that is, the following program corresponds to the one with 0.7::in(_):

    0.7::red(X) :- ball(X). ball(a). ball(b). ball(c). query(red(_)). green(X) :- ball(X), \+ red(X). query(green(_)). different_color(A,B) :- ball(A), ball(B), A@=<B, red(A), green(B). different_color(A,B) :- ball(A), ball(B), A@=<B, green(A), red(B). query(different_color(_,_)).

    The version that randomly activates the non-ground rule cannot be modeled with a probabilistic clause, but requires the explicit encoding with 0.7::in.

    Note that all variables are taken into account when grounding a probabilistic clause, that is, in the following example, the probability of a ball being red increases with the number of games it was used for:

    0.7::red(X) :- ball_in_game(X,_). ball_in_game(a,g1). ball_in_game(b,g2). ball_in_game(b,g3). ball_in_game(c,g4). ball_in_game(c,g5). ball_in_game(c,g6). query(red(_)). green(X) :- ball_in_game(X,_), \+ red(X). query(green(_)). different_color(A,B) :- ball_in_game(A,_), ball_in_game(B,_), A@=<B, red(A), green(B). different_color(A,B) :- ball_in_game(A,_), ball_in_game(B,_), A@=<B, green(A), red(B). query(different_color(_,_)).

    whereas it doesn’t if we first project out the unused variable:

    0.7::red(X) :- ball(X). ball(X) :- ball_in_game(X,_). ball_in_game(a,g1). ball_in_game(b,g2). ball_in_game(b,g3). ball_in_game(c,g4). ball_in_game(c,g5). ball_in_game(c,g6). query(red(_)). green(X) :- ball(X), \+ red(X). query(green(_)). different_color(A,B) :- ball(A), ball(B), A@=<B, red(A), green(B). different_color(A,B) :- ball(A), ball(B), A@=<B, green(A), red(B). query(different_color(_,_)).

    Of course, probabilistic facts are not restricted to a single head, but, using annotated disjunctions, they also allow one to directly specify choices between several options

    0.7::red(X); 0.3::green(X) :- ball(X). 0.5::type(X,football) ; 0.3::type(X,basketball); 0.2::type(X,baseball) :- ball(X). ball(a). ball(b). ball(c). query(red(_)). query(green(_)). query(type(_,_)). different_color(A,B) :- ball(A), ball(B), A@=<B, red(A), green(B). different_color(A,B) :- ball(A), ball(B), A@=<B, green(A), red(B). query(different_color(_,_)).