【问题标题】:Prolog: Unification or Backtracking errors in programProlog:程序中的统一或回溯错误
【发布时间】:2014-09-09 11:30:14
【问题描述】:

我有一个对家谱进行编码的简单知识库。此表示中的一些重要规则如下:

% 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))。这个人ZXY的长辈,Z的无后辈也是XY的长辈。

我的尝试如下所示:

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 ;

但我应该只得到一个答案,我不知道出了什么问题。谢谢!

【问题讨论】:

  • 你的程序有相当多的冗余。您已经定义了两次parent/2。此外,“人”是“男性”或“女性”,但那为什么你有 father/2mother/2 而不仅仅是 parent/2?或者同一个“人”可以是“男性”和“母亲”吗?无论哪种方式,跟踪您的程序,您可能会“找出”问题所在。并且不要忽略编译时警告。
  • 感谢您的评论。我想我应该研究一下单例变量警告等

标签: prolog backtracking unification family-tree


【解决方案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 (joined with 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 技巧变得无用。

【讨论】:

  • 感谢您的回答。我的尝试是不正确的,因为它打印出 eleanor、jim 和 elmo,它们是他们(stephanie 和 cathy)共同拥有的所有长辈(eleanor、jim 和 elmo)。它应该做的只是打印埃莉诺和吉姆。我尝试了您的实现,但它似乎没有绑定任何变量? (它会无限打印“真”)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-07-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多