рассуждение в сети убеждений с прологом

У меня проблема с Прологом для моего финального проекта. Я пытаюсь рассуждать о схеме нарушения системы поезда, используя байесовскую сеть и пролог. У меня байесовская сеть выглядит следующим образом: Изображение байесовской сети

Я читал книги Ивана Братко «Прологовое программирование для искусственного интеллекта, третье дополнение» и нашел, как представлять байесовскую сеть в Прологе. Вы можете увидеть код Prolog следующим образом:

%here is the rule for reasoning in bayesian network from the book :
prob([X|Xs],Cond,P) :- !,
prob(X, Cond, Px),
prob(Xs, [X|Cond], PRest),
P is Px * PRest.

prob([],_,1):- !.

prob(X, Cond, 1) :-
    member(X, Cond),!.



prob(X, Cond, 0) :-
    member(\+ X, Cond), !.

prob(\+ X, Cond, P) :- !,
    prob(X, Cond, P0),
    P is 1-P0.

%Use Bayes rule if condition involves a descendant of X
prob(X, Cond0, P):-
    delete(Y, Cond0, Cond),
    predecessor(X,Y),!,             %Y is a descendant of X
    prob(X, Cond, Px),
    prob(Y, [X|Cond], PyGivenX),
    prob(Y, Cond, Py),
    P is Px * PyGivenX / Py.        %Assuming Py > 0

%Cases when condition does not involves a descendant

prob(X, Cond, P) :-
    p(X, P),!.                      % X a root cause - its probability given

prob(X, Cond, P) :- !,
    findall((CONDi, Pi), p(X,CONDi,Pi), CPlist),        %Condition on parents
    sum_probs(CPlist, Cond, P).

sum_probs([],_,0).
sum_probs([(COND1,P1) | CondsProbs], COND, P) :-
    prob(COND1, COND, PC1),
    sum_probs(CondsProbs, COND, PRest),
    P is P1 * PC1 + PRest.


predecessor(X, \+ Y) :- !,          %Negated variable Y
    predecessor(X,Y).

predecessor(X,Y) :-
    parent(X,Y).

predecessor(X,Z) :-
    parent(X,Y),
    predecessor(Y,Z).

member(X, [X|_]).
member(X, [_|L]) :-
    member(X,L).

delete(X, [X|L], L).
delete(X, [Y|L], [Y|L2]) :-
    delete(X, L, L2). 

Вот также некоторые реализации информации о байесовской сети в прологе (я добавляю только некоторые из них, потому что они были слишком длинными):

p(static_inverter, [overhead_line], 0.005050505).
p(static_inverter, [\+ overhead_line], 0.000213767).

p(ac, [static_inverter], 0.5).
p(ac, [\+ static_inverter], 0.029749692).

p(door, [compressor], 0.026315789).
p(door, [\+ compressor], 0.006821).

p(horn, [compressor], 0.026315789).
p(horn, [\+ compressor], 0.000206697).

p(brake, [compressor], 0.026315789).
p(brake, [\+ compressor], 0.004340637).

p(switch, [signal, service_table], 0.5).
p(switch, [\+ signal, service_table], 0.346153846).
p(switch, [signal, \+ service_table], 0.054098361).
p(switch, [\+ signal, \+ service_table], 0.041364933).

p(overhead_line, [fire, fallen_tree], 0.5).
p(overhead_line, [fire, \+ fallen_tree], 0.005882353).
p(overhead_line, [\+ fire, fallen_tree], 0.304878049).
p(overhead_line, [\+ fire, \+ fallen_tree], 0.038850284).

p(pantograph, [overhead_line, fallen_tree], 0.038461538).
p(pantograph, [overhead_line, \+ fallen_tree], 0.002702703).
p(pantograph, [\+ overhead_line, fallen_tree], 0.017241379).
p(pantograph, [\+ overhead_line, \+ fallen_tree], 0.00440955).

полный код вы можете найти на здесь

к сожалению, у меня проблема, когда я пытаюсь рассуждать о некоторых вероятностях, например:

?- prob(series, [horn], P).
?- prob(series, [brake], P).
?- prob(pantograph, [overhead_line], P).

Сказали что ошибка такая:

ERROR: Arithmetic: evaluation error: `zero_divisor'
ERROR: In:
ERROR:   [27] _43124 is 0.045454539961694*0/0
ERROR:   [25] prob([compressor],[\+brake,traction|...],_43166) at d:/kuliah/tugas/semester 8/for ta/[2] ta program/reasoningtraindisruptionwithprolog/rules.pl:2
ERROR:   [24] sum_probs([(...,0.026315789),...],[\+brake,traction|...],_43216) at d:/kuliah/tugas/semester 8/for ta/[2] ta program/reasoningtraindisruptionwithprolog/rules.pl:37
ERROR:   [22] prob([horn,door|...],[\+brake,traction|...],_43278) at d:/kuliah/tugas/semester 8/for ta/[2] ta program/reasoningtraindisruptionwithprolog/rules.pl:2
ERROR:   [21] prob([\+brake,horn|...],[traction,wiper|...],_43334) at d:/kuliah/tugas/semester 8/for ta/[2] ta program/reasoningtraindisruptionwithprolog/rules.pl:3
ERROR:   [20] prob([traction,...|...],[wiper,speedometer|...],_43390) at d:/kuliah/tugas/semester 8/for ta/[2] ta program/reasoningtraindisruptionwithprolog/rules.pl:3

Кто-нибудь может помочь мне исправить эту ошибку? Заранее спасибо.


person yunitarp    schedule 09.06.2018    source источник
comment
Вам нужно проверить свою математику. Вы делите на ноль. Я не думаю, что кто-то будет просматривать весь ваш автономный код, чтобы найти причину за вас. Какую отладку вы сделали?   -  person lurker    schedule 10.06.2018
comment
Я уже использую трассировку для отладки, но до сих пор не нашел, какая часть кода делает его делением на ноль. Нет результата трассировки, указывающего на то, что он разделен на нулевое число.   -  person yunitarp    schedule 10.06.2018
comment
что произойдет, если вы просто попытаетесь исправить проблемную строку с помощью теста? Py > 0, P is Px * PyGivenX / Py.   -  person CapelliC    schedule 10.06.2018


Ответы (2)


После введения теста на безопасность,

...
prob(Y, Cond, Py),
Py > 0,
P is Px * PyGivenX / Py.        %Assuming Py > 0

и исправил опечатку и несколько singleton-предупреждений в вашем коде github, я есть такие результаты:

?- prob(series, [horn], P).
false.

?- prob(series, [brake], P).
P = 0.086661842800551.

?- prob(pantograph, [overhead_line], P).
false.

Итак, теперь вы можете попытаться понять, почему код выдает false вместо P = 0.0...

person CapelliC    schedule 10.06.2018
comment
Большое спасибо за ответ, теперь я знаю, где я должен исправить свой код :) - person yunitarp; 10.06.2018

Я понимаю, почему intrpreter получает ответ с ошибкой zero_divisor, потому что, когда я запрашиваю с помощью:

?- prob(series, [horn], P).
?- prob(series, [brake], P).
?- prob(pantograph, [overhead_line], P)

Все они обработаны правилом:

prob(X, Cond0, P):-
    delete(Y, Cond0, Cond),
    predecessor(X,Y),!,             %Y is a descendant of X
    prob(X, Cond, Px),
    prob(Y, [X|Cond], PyGivenX),
    prob(Y, Cond, Py),
    P is Px * PyGivenX / Py.        %Assuming Py > 0

Принимая во внимание, что они должны обрабатываться с помощью правила ниже:

prob(X, Cond, P) :-
    p(X, P),!.                      % X a root cause - its probability given

prob(X, Cond, P) :- !,
    findall((CONDi, Pi), p(X,CONDi,Pi), CPlist),        %Condition on parents
    sum_probs(CPlist, Cond, P).

Поскольку запрос не включает потомка X

Любая идея, чтобы различать оба правила? Потому что я все еще использую оба правила рекурсивно позже?

Я уже пытаюсь добавить условие parent(X, Cond0) в prob(X, Cond0, P), но когда я запрашиваю условие с участием потомка X, ответ неверен

person yunitarp    schedule 10.06.2018
comment
Я не смотрел весь код, но, может быть, вы можете просто добавить Py > 0 после вызова prob/4, где вы вычисляете Py. - person Tomas By; 10.06.2018
comment
Да, я добавляю Py ‹› 0 и создаю новый предикат prob/4, и он работает, большое спасибо :) - person yunitarp; 10.06.2018