ML-KULeuven / problog

ProbLog is a Probabilistic Logic Programming Language for logic programs with probabilities.

Home Page:https://dtai.cs.kuleuven.be/problog/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Grounding issue - NonGroundProbabilisticClause Exception

Dznan opened this issue · comments

The following code raises NonGroundProbabilisticClause Exception.

value(temperature, 4).
value(humidity, 100).
0.4 :: snow :-
    value(temperature, _temperature), _temperature < -1.0 ;
    value(humidity, _humidity), _humidity > 50.
query(snow).

What is the problem?

Information regarding the NonGroundProbabilisticClause Exception can be found here.

In order to understand the issue, realise that in the following example, the number of groundings for val(A) increases the probability of snow.

val(a).
val(b).
0.4::snow :- val(A).
query(snow).

Now, your program is equivalent to

value(temperature, 4).
value(humidity, 100).
0.4 :: snow :-
    value(temperature, A), A < -1.0 ;
    value(humidity, 100).
query(snow).

which is equivalent to

value(temperature, 4).
value(humidity, 100).
0.4 :: snow :-
    value(temperature, A), A < -1.0 ; true.
query(snow).

which has the same issue as

value(temperature, 4).
0.4 :: snow :- value(temperature, A) ; true.
query(snow).

The issue with this program is that the body is true due to the true part, and that A could be ground to whatever, e.g. if A = 5, then the body is still true. Looking back at my very first example program, where the probability increased with the number of groundings that made the body true, this raises the question what the correct probability should be. ProbLog requires that after grounding all probabilistic facts are ground (i.e. contain no variables), such that this problem does not occur. If after grounding not all probabilistic facts are ground, the NonGroundProbabilisticClause exception is raised.

How to fix it?

You can consider one of the solutions suggested here , hiding the non ground variable _temperature, from the probabilistic auxiliary fact introduced by this rule. Whether this solution is correct for you depends on the meaning/behavior you intended the program to have.

value(temperature, 4).
value(humidity, 100).
temp_low :- value(temperature, _temperature), _temperature < -1.0.
0.4 :: snow :-
    temp_low ;
    value(humidity, _humidity), _humidity > 50.
query(snow).

I am still confused about it

value(temperature, 4).
0.4 :: snow :- value(temperature, A) ; true.
query(snow).

I think the above code should be equivalent to the following code:

value(temperature, 4).
0.4 :: snow :- true.
query(snow).

and the result should be

{ snow: 0.4 }

It's not the same as

val(a).
val(b).
0.4::snow :- val(A).
query(snow).

I might have skimmed over this too fast, hopefully the following will help.

As explained on that page: "For each probabilistic clause, a new probabilistic fact is created which contains all variables used in the clause". This means that

value(temperature, 4).
0.4 :: snow :- value(temperature, A) ; true.
query(snow).

is equivalent to

value(temperature, 4).
0.4::snow_auxiliary(A).
snow :- snow_auxiliary(A), (value(temperature, A) ; true).
query(snow).

which is equivalent to

0.4::snow_auxiliary(A).
snow :- snow_auxiliary(A).
query(snow).

which, if you rename the predicate symbols, is equivalent to exactly the program described in the NonGroundProbabilisticClause error page

0.4 :: a(_).
b :- a(_).
query(b).

That program has a very different 'meaning' than

value(temperature, 4).
0.4 :: snow :- true.
query(snow).

Solution

If you intend to model that the probability of snow is 0.4 when the temperature is below -1, or humidity above 50, then the correct program is:

value(temperature, 4).
value(humidity, 100).
temp_low :- value(temperature, _temperature), _temperature < -1.0.
humidity_high :- value(humidity, _humidity), _humidity > 50.
0.4 :: snow :- temp_low ; humidity_high.
query(snow).

Note that there are now no free variables in the body of the annotated rule (probability in the head), so the auxiliary variable will not contain a free variable.

I might have skimmed over this too fast, hopefully the following will help.

As explained on that page: "For each probabilistic clause, a new probabilistic fact is created which contains all variables used in the clause". This means that

value(temperature, 4).

0.4 :: snow :- value(temperature, A) ; true.

query(snow).

is equivalent to

value(temperature, 4).

0.4::snow_auxiliary(A).

snow :- snow_auxiliary(A), (value(temperature, A) ; true).

query(snow).

which is equivalent to

0.4::snow_auxiliary(A).

snow :- snow_auxiliary(A).

query(snow).

which, if you rename the predicate symbols, is equivalent to exactly the program described in the NonGroundProbabilisticClause error page

0.4 :: a(_).

b :- a(_).

query(b).

That program has a very different 'meaning' than

value(temperature, 4).

0.4 :: snow :- true.

query(snow).

Solution

If you intend to model that the probability of snow is 0.4 when the temperature is below -1, or humidity above 50, then the correct program is:

value(temperature, 4).

value(humidity, 100).

temp_low :- value(temperature, _temperature), _temperature < -1.0.

humidity_high :- value(humidity, _humidity), _humidity > 50.

0.4 :: snow :- temp_low ; humidity_high.

query(snow).

Note that there are now no free variables in the body of the annotated rule (probability in the head), so the auxiliary variable will not contain a free variable.

Thanks, now I get it.

Before I close this, a slight clarification on the given solution

value(temperature, 4).
value(humidity, 100).
temp_low :- value(temperature, _temperature), _temperature < -1.0.
humidity_high :- value(humidity, _humidity), _humidity > 50.
0.4 :: snow :- temp_low ; humidity_high.
query(snow).

If the temperature is low or the humidity is high, the probability of snow will be 0.4. If you want the probability to increase when both the temperature is low, and the humidity is high, then you should have a separate rule for each:

value(temperature, -2). % temp_low is true
value(humidity, 100). % humidity_high is true
temp_low :- value(temperature, _temperature), _temperature < -1.0.
humidity_high :- value(humidity, _humidity), _humidity > 50.
0.4 :: snow1 :- temp_low ; humidity_high.
0.4 :: snow2 :- temp_low.
0.4 :: snow2 :- humidity_high.
query(snow1).% = 0.4
query(snow2).% = 0.64 = 0.4 + (1-0.4) x 0.4