Пролог Найти все предикаты

Я пытаюсь найти всех братьев человека.. Я создал следующее правило..

    find_all_brothers(Z):- findall(X,brother(X,Z),X0),write(X0).

Однако это работает, если у человека более одного брата, он найдет только одного брата. Я предполагаю, что мне нужно как-то использовать рекурсию, но я немного застрял!


person bdavies6086    schedule 22.02.2014    source источник
comment
findall найдет их все. Можете ли вы показать, как выглядят ваши факты пролога для brother?   -  person lurker    schedule 22.02.2014
comment
Будет ли он!? О дорогой ха-ха! Хорошо, я добавлю их сейчас, спасибо! :)   -  person bdavies6086    schedule 22.02.2014
comment
Ну, в зависимости... см. мой ответ. :)   -  person lurker    schedule 22.02.2014


Ответы (1)


Если у вас есть такие отношения, как:

brother(sam, bill).
brother(bill, fred).

И вы хотите найти всех братьев Билла, вам нужно сделать немного больше:

find_all_brothers(Z) :-
    findall(X, (brother(X, Z) ; brother(Z, X)), X0), write(X0).

Чтобы избежать избыточных членов списка, setof будет сортировать и предоставлять только уникальные элементы:

find_all_brothers(Z) :-
    setof(X, (brother(X, Z) ; brother(Z, X)), X0), write(X0).
person lurker    schedule 22.02.2014
comment
@false да, я думал setof. Я не был уверен, было ли это необходимо в данном случае, в зависимости от того, как были установлены факты и правила ОП. setof конечно безопаснее. - person lurker; 22.02.2014
comment
Важен ли порядок решений? Важны ли избыточные решения? В этих случаях findall/3 будет в порядке. В противном случае setof/3 предпочтительнее, даже если он не работает в случае, когда Goal не работает. - person false; 22.02.2014
comment
Да, это хорошие вопросы, ответы на которые не обязательно ясны из исходного вопроса. - person lurker; 22.02.2014