谓词必须适用于列表中的所有元素

时间:2014-12-03 15:23:10

标签: prolog

我有一套事实:

likes(john,mary).
likes(mary,robert).
likes(robert,kate).
likes(alan,george).
likes(alan,mary).
likes(george,mary).
likes(harry,mary).
likes(john,alan).

现在我想写一个关系,如果likes(X,A)为真,它将检查输入列表的所有元素X.如果likes(X,A)对于列表L中的所有元素X都为真,则我的关系应返回true。 如果我试试这个:

relat(X) :- member(A,[john,alan,george,harry]), likes(A,X).

但输出是

?- relat(mary).
true ;
true ;
true ;
true.

我想写它,一旦发现likes(john,mary),likes(alan,mary),likes(george,mary),likes(harry,mary)都是真的,它就会返回一个真值。 如何解决这个问题?

3 个答案:

答案 0 :(得分:5)

在SWI-Prolog中,您可以使用forall/2

?- forall(member(A, [john, alan, george, harry]), likes(A, mary)).
true.
?- forall(member(A, [john,alan,george,harry,marys_ex]), likes(A, mary)).
false.

答案 1 :(得分:2)

使用library(lambda)

liked_byall(X, Ps) :-
   maplist(X+\P^likes(P,X), Ps).

同样没有lambdas:

liked_byall(X, Ps) :-
   maplist(liked(X), Ps).

liked(X, P) :-
   likes(P, X).

同样:

liked_byall(_X, []).
liked_byall(X, [P|Ps]) :-
   likes(P, X),
   liked_byall(X, Ps).

根据上述定义,您可以提出更为一般性的问题,例如"某些人喜欢谁?"

?- liked_byall(N,[john, alan, george, harry]).
N = mary ;
false.

通过以下定义,这些一般性问题不再可能。

liked_byall(X, Ps) :-
   \+ ( member(P, Ps), \+ likes(P, X) ).

如果X是基础且Ps是地面列表,则第二个定义才有意义。我们可以按如下方式确保:

liked_byall(X, Ps) :-
   ( ground(X+Ps) -> true ; throw(error(instantiation_error,_)) ),
   length(Ps,_),
   \+ ( member(P, Ps), \+ likes(P, X) ).

这些额外的检查确保了以下荒谬案例不成功:

 ?- liked_byall(mary, nonlist).

其他合法案件不会产生错误答案:

 ?- liked_byall(N,[john, alan, george, harry]), N = the_grinch.
 N = the_grinch.

答案 2 :(得分:2)

使用标准列表处理,您可以执行以下操作:

helper(X, []).                                    % No one left to check
helper(X, [H|L]) :- likes(H, X), helper(X, L).    % Check head, then rest

relat(X) :- helper(X, [john,alan,george,harry]).

演示:

| ?- relat(harry).

no
| ?- relat(mary). 

true ? ;

no
| ?-