229 lines
6.1 KiB
Prolog
229 lines
6.1 KiB
Prolog
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
% four aProbLog example programs corresponding to the four inference settings, all using the ProbLog graph
|
|
% (comment out all but one of the four cases to run)
|
|
% $Id: aProbLog_examples.pl 6460 2011-07-27 14:09:46Z bernd $
|
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
|
|
:- use_module('../aproblog').
|
|
:- use_module(library(lists)).
|
|
|
|
%%%%
|
|
% shared background knowledge
|
|
%%%%
|
|
% definition of acyclic path using list of visited nodes
|
|
path(X,Y) :- path(X,Y,[X],_).
|
|
|
|
path(X,X,A,A).
|
|
path(X,Y,A,R) :-
|
|
X\==Y,
|
|
edge(X,Z),
|
|
absent(Z,A),
|
|
path(Z,Y,[Z|A],R).
|
|
|
|
% using directed edges in both directions
|
|
edge(X,Y) :- dir_edge(Y,X).
|
|
edge(X,Y) :- dir_edge(X,Y).
|
|
|
|
% checking whether node hasn't been visited before
|
|
absent(_,[]).
|
|
absent(X,[Y|Z]):-X \= Y, absent(X,Z).
|
|
|
|
%/*
|
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
%%% case 1: disjoint & neutral sums, bottleneck semiring %%%
|
|
% ?- aproblog_label(path(1,6),L).
|
|
% L = 7
|
|
:- set_aproblog_flag(disjoint_sum,true).
|
|
:- set_aproblog_flag(neutral_sum,true).
|
|
|
|
semiring_zero(-inf).
|
|
semiring_one(inf).
|
|
label_negated(_W,N) :-
|
|
semiring_one(N).
|
|
semiring_addition(A,B,C) :-
|
|
C is max(A, B).
|
|
semiring_multiplication(A,B,C) :-
|
|
C is min(A,B).
|
|
|
|
9::dir_edge(1,2).
|
|
8::dir_edge(2,3).
|
|
6::dir_edge(3,4).
|
|
7::dir_edge(1,6).
|
|
5::dir_edge(2,6).
|
|
4::dir_edge(6,5).
|
|
7::dir_edge(5,3).
|
|
2::dir_edge(5,4).
|
|
|
|
%%% end case 1 %%%
|
|
%*/
|
|
|
|
/*
|
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
%%% case 2: disjoint & non-neutral sums, most likely interpretation semiring %%%
|
|
% ?- aproblog_label(path(1,6),L).
|
|
% L = 0.0508032-[[e16],not[e54],[e53],not[e65],[e34],[e23],[e26],[e12]]
|
|
:- set_aproblog_flag(disjoint_sum,true).
|
|
:- set_aproblog_flag(neutral_sum,false).
|
|
|
|
% fact labels of form prob-[variable] with a unique "variable" for each fact
|
|
% "practical" approach
|
|
% - resolves ties by taking first interpretation
|
|
% - uses arbitrary list order instead of some canonical representation
|
|
semiring_zero(0-[]).
|
|
semiring_one(1-[]).
|
|
label_negated(W-[A],WW-[not(A)]) :-
|
|
WW is 1-W.
|
|
semiring_addition(A-L,B-LL,C-LLL) :-
|
|
C is max(A, B),
|
|
(
|
|
C =:= A
|
|
->
|
|
LLL = L
|
|
;
|
|
LLL = LL
|
|
).
|
|
semiring_multiplication(A-L,B-LL,C-LLL) :-
|
|
C is A*B,
|
|
append(L,LL,LLL).
|
|
|
|
0.9-[[e12]]::dir_edge(1,2).
|
|
0.8-[[e23]]::dir_edge(2,3).
|
|
0.6-[[e34]]::dir_edge(3,4).
|
|
0.7-[[e16]]::dir_edge(1,6).
|
|
0.5-[[e26]]::dir_edge(2,6).
|
|
0.4-[[e65]]::dir_edge(6,5).
|
|
0.7-[[e53]]::dir_edge(5,3).
|
|
0.2-[[e54]]::dir_edge(5,4).
|
|
%%% end case 2 %%%
|
|
*/
|
|
|
|
/*
|
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
%%% case 3: non-disjoint & neutral sums, gradient semiring %%%
|
|
% ?- aproblog_label(path(1,6),L).
|
|
% L = (0.8667952,[0.185328,0.039744,0.00259200000000001,0.444016,0.2064096,0.079488,0.038016,0.00777600000000005])
|
|
:- set_aproblog_flag(disjoint_sum,false).
|
|
:- set_aproblog_flag(neutral_sum,true).
|
|
|
|
% vector version for parallel computation: first argument is probability, second argument is an ordered list of gradients w.r.t. the different facts (0/1)
|
|
% as length varies, zero/one are still non-vector, thus different cases needed in definitions below
|
|
semiring_zero((0,0)).
|
|
semiring_one((1,0)).
|
|
% inverting base cases and lists
|
|
label_negated((P,0),(P2,0)) :-
|
|
!,
|
|
P2 is 1-P.
|
|
label_negated((P,1),(P2,-1)) :-
|
|
!,
|
|
P2 is 1-P.
|
|
label_negated((P,[]),(P2,[])) :-
|
|
!,
|
|
P2 is 1-P.
|
|
label_negated((P,[0|R]),(P2,[0|R2])) :-
|
|
!,
|
|
label_negated((P,R),(P2,R2)).
|
|
label_negated((P,[1|R]),(P2,[-1|R2])) :-
|
|
label_negated((P,R),(P2,R2)).
|
|
|
|
% addition is per element on lists
|
|
% both are lists
|
|
semiring_addition((A1,[FA|RA]),(B1,[FB|RB]),(C1,Res)) :-
|
|
!,
|
|
C1 is A1 + B1,
|
|
sum_lists_per_el([FA|RA],[FB|RB],Res).
|
|
% one is a neutral element
|
|
semiring_addition((A1,[FA|RA]),(B1,B2),(C1,Res)) :-
|
|
!,
|
|
C1 is A1 + B1,
|
|
sum_lists_per_el_constant([FA|RA],B2,Res).
|
|
semiring_addition((A1,A2),(B1,[FB|RB]),(C1,Res)) :-
|
|
!,
|
|
C1 is A1 + B1,
|
|
sum_lists_per_el_constant([FB|RB],A2,Res).
|
|
% both are neutral elements
|
|
semiring_addition((A1,A2),(B1,B2),(C1,C2)) :-
|
|
C1 is A1 + B1,
|
|
C2 is A2 + B2.
|
|
|
|
sum_lists_per_el([],[],[]).
|
|
sum_lists_per_el([F|R],[FF|RR],[FFF|RRR]) :-
|
|
FFF is F+FF,
|
|
sum_lists_per_el(R,RR,RRR).
|
|
|
|
sum_lists_per_el_constant([],_,[]).
|
|
sum_lists_per_el_constant([F|R],C,[FFF|RRR]) :-
|
|
FFF is F+C,
|
|
sum_lists_per_el_constant(R,C,RRR).
|
|
|
|
% similar for multiplication, but need to pass on probabilities as well for product rule
|
|
semiring_multiplication((A1,[FA|RA]),(B1,[FB|RB]),(C1,Res)) :-
|
|
!,
|
|
C1 is A1 * B1,
|
|
mult_lists_per_el([FA|RA],[FB|RB],A1,B1,Res).
|
|
semiring_multiplication((A1,[FA|RA]),(B1,B2),(C1,Res)) :-
|
|
!,
|
|
C1 is A1 * B1,
|
|
mult_lists_per_el_constant([FA|RA],B2,A1,B1,Res).
|
|
semiring_multiplication((A1,A2),(B1,[FB|RB]),(C1,Res)) :-
|
|
!,
|
|
C1 is A1 * B1,
|
|
mult_lists_per_el_constant([FB|RB],A2,B1,A1,Res).
|
|
semiring_multiplication((A1,A2),(B1,B2),(C1,C2)) :-
|
|
C1 is A1*B1,
|
|
C2 is A1*B2 + A2*B1.
|
|
|
|
mult_lists_per_el([],[],_,_,[]).
|
|
mult_lists_per_el([F|R],[FF|RR],P,PP,[FFF|RRR]) :-
|
|
FFF is PP*F+FF*P,
|
|
mult_lists_per_el(R,RR,P,PP,RRR).
|
|
|
|
mult_lists_per_el_constant([],_,_,_,[]).
|
|
mult_lists_per_el_constant([F|R],C,P,PP,[FFF|RRR]) :-
|
|
FFF is F*PP+P*C,
|
|
mult_lists_per_el_constant(R,C,P,PP,RRR).
|
|
|
|
(0.9,[1,0,0,0,0,0,0,0])::dir_edge(1,2).
|
|
(0.8,[0,1,0,0,0,0,0,0])::dir_edge(2,3).
|
|
(0.6,[0,0,1,0,0,0,0,0])::dir_edge(3,4).
|
|
(0.7,[0,0,0,1,0,0,0,0])::dir_edge(1,6).
|
|
(0.5,[0,0,0,0,1,0,0,0])::dir_edge(2,6).
|
|
(0.4,[0,0,0,0,0,1,0,0])::dir_edge(6,5).
|
|
(0.7,[0,0,0,0,0,0,1,0])::dir_edge(5,3).
|
|
(0.2,[0,0,0,0,0,0,0,1])::dir_edge(5,4).
|
|
|
|
%%% end case 3 %%%
|
|
*/
|
|
|
|
/*
|
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
%%% case 4: non-disjoint & non-neutral sums, expectation semiring %%%
|
|
% ?- aproblog_label(path(1,6),L).
|
|
% L = (0.8667952,4.357428)
|
|
:- set_aproblog_flag(disjoint_sum,false).
|
|
:- set_aproblog_flag(neutral_sum,false).
|
|
|
|
% fact labels are tuples of (probability, probability*value)
|
|
% NB: this assumes that negative facts have value (and thus expected value) 0
|
|
|
|
semiring_zero((0,0)).
|
|
semiring_one((1,0)).
|
|
label_negated((P,_),(Q,0)) :- Q is 1-P.
|
|
semiring_addition((A1,A2),(B1,B2),(C1,C2)) :-
|
|
C1 is A1+B1,
|
|
C2 is A2+B2.
|
|
semiring_multiplication((A1,A2),(B1,B2),(C1,C2)) :-
|
|
C1 is A1*B1,
|
|
C2 is A1*B2+B1*A2.
|
|
|
|
% positive edges have value 1
|
|
(0.9,0.9*1)::dir_edge(1,2).
|
|
(0.8,0.8*1)::dir_edge(2,3).
|
|
(0.6,0.6*1)::dir_edge(3,4).
|
|
(0.7,0.7*1)::dir_edge(1,6).
|
|
(0.5,0.5*1)::dir_edge(2,6).
|
|
(0.4,0.4*1)::dir_edge(6,5).
|
|
(0.7,0.7*1)::dir_edge(5,3).
|
|
(0.2,0.2*1)::dir_edge(5,4).
|
|
|
|
%%% end case 4 %%%
|
|
*/ |