Closed Dznan closed 2 years ago
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.
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).
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
The following code raises NonGroundProbabilisticClause Exception.