简单prolog程序过早返回false

简单prolog程序过早返回false,prolog,Prolog,我已经有一段时间没有用Prolog编程了。今天,我试着做一个简单的程序。它列出了谁属于同一个家庭的一些事实。如果两个人属于同一个家庭,他们就不能互相赠送礼物。我想得到所有的人(或至少一个人)的人被允许给一个礼物 family(john, jack). family(matt, ann). family(ann, jack). family(jordan, michael). family(michael, liz). sameFamily(X, Y) :- family(X, Y). sa

我已经有一段时间没有用Prolog编程了。今天,我试着做一个简单的程序。它列出了谁属于同一个家庭的一些事实。如果两个人属于同一个家庭,他们就不能互相赠送礼物。我想得到所有的人(或至少一个人)的人被允许给一个礼物

family(john, jack).
family(matt, ann).
family(ann, jack).
family(jordan, michael).
family(michael, liz).

sameFamily(X, Y) :-
  family(X, Y).
sameFamily(X, X) :-
  false.
sameFamilySym(X, Y) :-
  sameFamily(X, Y).
sameFamilySym(X, Y) :-
  sameFamily(Y, X).
sameFamilyTrans(X, Z) :-
  sameFamilySym(X, Y),
  sameFamilySym(Y, Z).

gift(X, Y) :-
  not(sameFamilyTrans(X, Y)).
一些查询if
sameFamilyTrans/2
返回
false
,而实际上它们应该返回
true

sameFamilyTrans/2
显然是错误的。我想我需要保留一个中间及物性的列表。大概是这样的:

sameFamilyTrans(X, Z, [Y|Ys]) :-
  sameFamilySym(X, Y, []),
  sameFamilyTrans(Y, Z, Ys).
但我不知道怎么称呼这个


另外,如果有什么不同的话,我正在使用SWI Prolog。

否定是以非常基本的方式在Prolog中实现的。只有当一个被否定的查询被充分实例化时,您才能从本质上得到一个有用的答案。为此,请定义一个关系
person/1
,该关系描述您考虑的所有人员。然后你可以写:

gift(X,Y) :-
   person(X),
   person(Y),
   \+ sameFamily(X,Y).

sameFamily/2的定义还有另一个问题

是的,你的思路是对的。诀窍是使用空累加器调用传递闭包,并在每个步骤中检查是否找到循环(即,我们以前是否见过该家族成员)。正如“false”所指出的,在进入not之前,需要先实例化这些人

总之,这是可行的:

family(john, jack).
family(matt, ann).
family(ann, jack).
family(jordan, michael).
family(michael, liz).

sameFamily(X, Y) :-
  family(X, Y).
sameFamilySym(X, Y) :-
  sameFamily(X, Y).
sameFamilySym(X, Y) :-
  sameFamily(Y, X).

sameFamilyTrans(X, Y, Acc) :-
  sameFamilySym(X, Y),
  not(member(Y,Acc)).

sameFamilyTrans(X, Z, Acc) :-
  sameFamilySym(X, Y),
  not(member(Y,Acc)),
  sameFamilyTrans(Y, Z, [X|Acc]).

person(X) :- family(X, _).
person(X) :- family(_, X).

gift(X, Y) :-
  person(X),
  person(Y),
  X \= Y,
  not(sameFamilyTrans(X, Y, [])).

一点背景:传递闭包实际上不是一阶可定义的(cf.)。所以这可能会有点棘手。

谢谢你的回答。我已经看过了
sameFamily/2
的定义,虽然它显然是错误的,但我还没有发现我的错误。你能给我指出正确的方向吗?我已经为它写了一个新的定义并更新了我的问题。@RaptorDotCpp:总是比较e解决方案集:
setof(A-B,samf(A,B),ABs)
找到了所有解决方案吗?找到了所有正确的解决方案,但也找到了其他解决方案。这些解决方案不应该在那里。@RaptorDotCpp:
sameFamilyTrans(X,Y)
失败。我知道这一点,但我不明白为什么。我是否需要以某种方式查询中间传递性?我将如何做?类似于我问题中的新代码?