Пролог: ошибки объединения или возврата в программе

У меня есть простая база знаний, которая кодирует генеалогическое древо. Некоторые важные правила в этом представлении заключаются в следующем:

% fathers
father(michael,cathy).
father(michael,sharon).
father(charles_gordon,michael).
father(charles_gordon,julie).
father(charles,charles_gordon).
father(jim,melody).
father(jim,crystal).
father(elmo,jim).
father(greg,stephanie).
father(greg,danielle).
% mothers
mother(melody,cathy).
mother(melody,sharon).
mother(hazel,michael).
mother(hazel,julie).
mother(eleanor,melody).
mother(eleanor,crystal).
mother(crystal,stephanie).
mother(crystal,danielle).
% parents
parent(X,Y) :- father(X,Y).
parent(X,Y) :- mother(X,Y).
% men
male(michael).
male(charles_gordon).
male(charles).
male(jim).
male(elmo).
male(greg).
% women
female(cathy).
female(sharon).
female(julie).
female(hazel).
female(eleanor).
female(melody).
female(crystal).
female(stephanie).
female(danielle). 

person(X) :- male(X) ; female(X).
parent(X,Y) :- father(X,Y) ; mother(X,Y).          % X is parent of Y
child(X,Y) :- parent(Y,X).
elder(X,Y) :-   parent(X,Y).                       % X is an elder of Y, meaning X is a parent or an ancestor of Y
elder(X,Y) :-   parent(X,Z), elder(Z,Y).
junior(X,Y) :-  child(X,Y).                        % X is a junior of Y, meaning X is a child or some descendant of Y
junior(X,Y) :-  child(X,Z), junior(Z,Y).

Я пытаюсь найти ближайшего старшего между двумя людьми (предикат ne(X,Y,Z)). Этот человек Z является старшим из X и Y, и никто из младших Z не является также старшим из ОБОИХ X и Y.

Моя попытка выглядит так:

ne(X,Y,Z) :-    person(X),
            person(Y),
            X \= Y,
            elder(Z,X),
            elder(Z,Y),
            junior(A,Z),
            not(elder(A,X)),
            not(elder(A,Y)).

но это как-то неправильно, потому что всякий раз, когда я запускаю ?- ne(stephanie,cathy,Z)., я получаю

Z = jim ;
Z = jim ;
Z = jim ;
Z = jim ;
Z = elmo ;
Z = elmo ;
Z = elmo ;
Z = elmo ;
Z = eleanor ;
Z = eleanor ;
Z = eleanor ;
Z = eleanor ;

но я должен получить только один ответ, и я не могу понять, что не так. Спасибо!


person DarkyTheOdd    schedule 09.09.2014    source источник
comment
В вашей программе довольно много избыточности. Вы определили parent/2 дважды. Кроме того, человек может быть мужчиной или женщиной, но тогда почему тогда у вас есть father/2 и mother/2, а не только parent/2? Или один и тот же человек может быть мужчиной и матерью? В любом случае, проследите свою программу, и вы можете понять, что не так. И не игнорируйте предупреждения времени компиляции.   -  person    schedule 09.09.2014
comment
Спасибо за комментарий. Я полагаю, мне следует изучить предупреждения об одноэлементных переменных и т.п.   -  person DarkyTheOdd    schedule 09.09.2014


Ответы (1)


из этого графика

введите описание изображения здеськажется, этот ответ правильный

?- ne(stephanie,cathy,A).
A = eleanor ;
A = jim.

вот моя попытка ne/3

ne(X,Y,Z) :-
    setof(A, (
        elder(A, X),
        elder(A, Y),
        X \= Y,
        \+ (elder(A, T), elder(T, X) , elder(T, Y) ))
    , As), member(Z, As).

не уверен, что это лучший способ...

Setof/3 (объединенный с member/2) используется для устранения повторяющихся ответов, так как мы получаем

?- aggregate(count,A^ne(stephanie,cathy,A),N).
N = 32.

с этой основной логикой

ne(X,Y,A) :-
        elder(A, X),
        elder(A, Y),
        X \= Y,
        \+ (elder(A, T), elder(T, X) , elder(T, Y)).

обратите внимание, что переменная A локально заменяет исходную Z

изменить

Я не учел остроумный комментарий @Boris, но после удаления повторяющегося определения parent/2 трюк setof/3+member/2 стал бесполезным.

person CapelliC    schedule 09.09.2014
comment
Спасибо за ответ. Моя попытка была неправильной, потому что она печатает Элеонору, Джима и Элмо, которые являются всеми старшими, которых они (Стефани и Кэти) имеют вместе (Элеонора, Джим и Элмо). Что он должен сделать, так это просто напечатать Элеонору и Джима. Я попробовал вашу реализацию, но, похоже, она не привязывала ни одну из переменных? (он печатает «true» бесконечно). - person DarkyTheOdd; 09.09.2014