Closed nathanielvirgo closed 2 years ago
Oh, actually the code in my previous post doesn't work as expected - w(S)=1/5 for each S between 0 and 5, but they are not mutually exclusive!
So I guess I have two questions: (i) how can I get a uniform distribution over 5 outcomes without typing "1/5" five times, and (ii) how can I replace the magic number 5 with some kind of declared constant?
A closely related question would be, what if I want to make a tunable distribution over n outcomes? That is, how can I replace the five-fold repetition with some "n" in the following code:
t(_)::w(1); t(_)::w(2); t(_)::w(3); t(_)::w(4); t(_)::w(5).
For your first question there are two directions. The first is not really uniform selection but introduces a variable in the rule you wrote:
1/Max::w(S) :- Max=5, between(1,Max,S).
The problem here is that w(1)
and w(2)
can be true at the same time. So it's not a uniform distributions over the values.
You thus probably you want to remember the choice you made and select just one value (thus build an annotated disjunction dynamically), in that case you can use the select_uniform
(or select_weighted
) from the lists
library:
:- use_module(library(lists)).
random_uniform_value(ID, Min, Max, Value) :-
findall(X, between(Min,Max,X), L),
select_uniform(ID, L, Value, _Rest).
w(Value) :- random_uniform_value(w, 1, 5, Value).
query(w(Value)).
https://dtai.cs.kuleuven.be/problog/editor.html#task=prob&hash=a4fba6fbb46b544cf90b153f5ce67eeb
Thanks @wannesm, that's really helpful - it's exactly what I wanted regarding a uniform distribution.
I'm still really hopeful that there's a way to do the weighted version, the equivalent of t(_)::w(1); t(_)::w(2); t(_)::w(3); t(_)::w(4); t(_)::w(5).
.
There's also the weighted version of the select_uniform
predicate:
select_weighted(+ID, +Weights, +Values, ?Value, ?Rest)
[note: this is a question rather than an issue; the project web page seems to say that's ok. If there's a mailing list etc. where I can ask instead, please let me know.]
This is probably a basic Prolog question rather than anything specific to ProbLog, but I'd like to have a random variable that's uniformly distributed over n outcomes. I've figured out that I can write
which gives me a uniform distribution over 5 outcomes. However, I can't figure out how to make that "5" into a global constant. I know that Prolog doesn't have variable assignment, but my knowledge is too basic to understand what I should do instead. What would be the usual way of achieving this?