2014-12-03 53 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 
| ?- 
相關問題