Prolog 中 N 个相关事件的析取概率
Probability of a disjunction on N dependent events in Prolog
有人知道在哪里可以找到用于计算 N 个相关事件的析取概率的 Prolog 算法吗?对于 N = 2,我知道 P(E1 OR E2) = P(E1) + P(E2) - P(E1) * P(E2),所以可以这样做:
prob_disjunct(E1, E2, P):- P is E1 + E2 - E1 * E2
但是当输入是一个列表时,这个谓词如何泛化到 N 个事件呢?也许有一个包可以做到这一点?
种类regards/JCR
我对Prolog一无所知,但无论如何写出多个独立项的析取概率很方便 p_m = Pr(S_1 or S_2 or S_3 or ... or S_m) 递归为
p_m = Pr(S_m) + p_{m - 1} (1 - P(S_m))
你可以通过剥离最后一项来证明这一点——看看 Pr((S_1 or ... or S_{m - 1}) or S_m) 然后写根据通常的公式,写作 Pr(A or B) = Pr(A) + Pr(B) - Pr(A) Pr(B) = Pr(B) + Pr(A) (1 - Pr(B) )), 对于 A 和 B 独立。
上面的公式是我论文中的C.3.10项:http://riso.sourceforge.net/docs/dodier-dissertation.pdf这是一个简单的结果,我想这一定是一些教科书上的习题,虽然我不记得见过它。
Robert Dodier 的回答中的递归公式直接转化为
p_or([], 0).
p_or([P|Ps], Or) :-
p_or(Ps, Or1),
Or is P + Or1*(1-P).
虽然这很好用,例如
?- p_or([0.5,0.3,0.7,0.1],P).
P = 0.9055
铁杆 Prolog 程序员不禁注意到定义不是 tail-recursive。这实际上只有在处理非常长的列表时才会成为问题,但由于列表元素的顺序无关紧要,因此很容易扭转局面。这是一种标准技术,使用辅助谓词和 "accumulator pair" 个参数:
p_or(Ps, Or) :-
p_or(Ps, 0, Or).
p_or([], Or, Or).
p_or([P|Ps], Or0, Or) :-
Or1 is P + Or0*(1-P),
p_or(Ps, Or1, Or). % tail-recursive call
对于任何事件 E,我会为互补事件写 E'(即 E' 发生当且仅当 E 不发生)。
那么我们有:
P(E') = 1 - P(E)
(A union B)' = A' inter B'
A and B are independent iff A' and B' are independent
so 对于独立的 E1..En
P( E1 union .. union En ) = 1 - P( E1' inter .. inter En')
= 1 - product{ i<=i<=n | 1 - P(E[i])}
有人知道在哪里可以找到用于计算 N 个相关事件的析取概率的 Prolog 算法吗?对于 N = 2,我知道 P(E1 OR E2) = P(E1) + P(E2) - P(E1) * P(E2),所以可以这样做:
prob_disjunct(E1, E2, P):- P is E1 + E2 - E1 * E2
但是当输入是一个列表时,这个谓词如何泛化到 N 个事件呢?也许有一个包可以做到这一点?
种类regards/JCR
我对Prolog一无所知,但无论如何写出多个独立项的析取概率很方便 p_m = Pr(S_1 or S_2 or S_3 or ... or S_m) 递归为
p_m = Pr(S_m) + p_{m - 1} (1 - P(S_m))
你可以通过剥离最后一项来证明这一点——看看 Pr((S_1 or ... or S_{m - 1}) or S_m) 然后写根据通常的公式,写作 Pr(A or B) = Pr(A) + Pr(B) - Pr(A) Pr(B) = Pr(B) + Pr(A) (1 - Pr(B) )), 对于 A 和 B 独立。
上面的公式是我论文中的C.3.10项:http://riso.sourceforge.net/docs/dodier-dissertation.pdf这是一个简单的结果,我想这一定是一些教科书上的习题,虽然我不记得见过它。
Robert Dodier 的回答中的递归公式直接转化为
p_or([], 0).
p_or([P|Ps], Or) :-
p_or(Ps, Or1),
Or is P + Or1*(1-P).
虽然这很好用,例如
?- p_or([0.5,0.3,0.7,0.1],P).
P = 0.9055
铁杆 Prolog 程序员不禁注意到定义不是 tail-recursive。这实际上只有在处理非常长的列表时才会成为问题,但由于列表元素的顺序无关紧要,因此很容易扭转局面。这是一种标准技术,使用辅助谓词和 "accumulator pair" 个参数:
p_or(Ps, Or) :-
p_or(Ps, 0, Or).
p_or([], Or, Or).
p_or([P|Ps], Or0, Or) :-
Or1 is P + Or0*(1-P),
p_or(Ps, Or1, Or). % tail-recursive call
对于任何事件 E,我会为互补事件写 E'(即 E' 发生当且仅当 E 不发生)。 那么我们有:
P(E') = 1 - P(E)
(A union B)' = A' inter B'
A and B are independent iff A' and B' are independent
so 对于独立的 E1..En
P( E1 union .. union En ) = 1 - P( E1' inter .. inter En')
= 1 - product{ i<=i<=n | 1 - P(E[i])}