2014-12-03 29 views
0

我有一组事实:谓语必须是所有元素的真正在列表

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

现在我想写的关系,这将检查输入列表的所有元素X如果likes(X,A)是真实的。

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

但输出

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

我想写它这样的:如果我试试这个这是我的关系应该返回true,如果一旦likes(X,A)是在我的名单L. 所有元素X真一旦它发现likes(john,mary),likes(alan,mary),likes(george,mary),likes(harry,mary)全部为真,它将返回一个真。 如何解决这个问题?

回答

4

在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. 
+0

这是一个直接的解决方案。我没有受过关于forall/2的教育。谢谢@larsmans。 – na899 2014-12-03 17:21:22

2

使用library(lambda)

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

同样没有lambda表达式:

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

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

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 
| ?- 
相关问题