Prolog谓词问题
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Prolog谓词问题相关的知识,希望对你有一定的参考价值。
我的部分工作有问题。我应该写一个谓词“友好”,当网络成员X被称为友好时,如果X喜欢支持他/她的每个人,那么这应该是真的。
编辑:在下面的例子中,巴里是友好的,因为喜欢巴里的人是卡拉和巴里喜欢卡拉回来的人。卡拉不是正确的答案,因为喜欢卡拉的人的名单是巴里,克拉克和奥利弗但卡拉只喜欢巴里和克拉克,所以卡拉不友好。
例如G = [人(kara,[巴里,克拉克]),人(布鲁斯,[克拉克,奥利弗]),人(巴里,[卡拉,奥利弗]),人(克拉克,[奥利弗,卡拉]),人(奥利弗,[kara])]
到目前为止我所拥有的;
friendly(G, X):-
member_(person(X, _), G),
likers(G, X, L),
likes_all(G, X, L).
% to get the list of members who like X;
likers(G, X, [Y|T]) :-
likes(G, Y, X),
select_(Y, G, G2),
likers(G2, X, T).
likers([], _, []).
likers([], _, _).
likers(_, _, []).
% select is used to remove the person from the list once visited.
select_(X, [person(X, _)|T], T).
select_(X, [H|T], [H|R]) :-
select_(X, T, R).
% to check whether X likes all the list of people that like X;
likes_all(G, X, [H|T]):-
likes(G, X, H),
likes_all(G, X, T).
likes_all(_, _, []).
likes_all(G, [H|T], X):-
likes(G, H, X),
likes_all(G, T, X).
likes_all(_, [],_).
likes(G, X, Y):-
member_(person(X, L), G),
member_(Y, L).
member_(X, [X|_]).
member_(X, [_|T]) :-
member_(X, T).
我的问题是它无法正常工作。见下面的示例输出。
所以,我不知道出了什么问题以及我该怎么做。我们不允许使用任何内置的谓词或控制操作符,所以没有!,;,=, =,+等,只有纯粹的序言。
任何前进的暗示都值得赞赏。
输出:
[debug] ?- friendly([person(kara, [barry, clark]),person(bruce, [clark, oliver]),person(barry, [kara, oliver]),person(clark, [oliver, kara]),person(oliver, [kara])], X).
X = kara ;
X = kara ;
X = kara ;
X = kara ;
X = kara ;
X = bruce ;
X = barry ;
X = barry ;
X = clark ;
X = clark ;
X = oliver ;
false.
我认为我的错误在于喜欢的功能。 “喜欢者”的输出:
?- likers([person(kara, [barry, clark]), person(bruce, [clark, oliver]), person(barry, [kara, oliver]), person(clark, [oliver, kara]), person(oliver, [kara])], kara, L).
L = [] ;
L = [barry] ;
L = [barry, clark] ;
L = [barry, clark, oliver] ;
L = [barry, oliver] ;
L = [barry, oliver, clark] ;
L = [clark] ;
L = [clark, barry] ;
L = [clark, barry, oliver] ;
L = [clark, oliver] ;
L = [clark, oliver, barry] ;
L = [oliver] ;
L = [oliver, barry] ;
L = [oliver, barry, clark] ;
L = [oliver, clark] ;
L = [oliver, clark, barry] ;
false.
在上面,正确的答案是L = [barry,clark,oliver]或其中一个组合。有没有办法在纯粹的prolog中得到它?
平静下来之后,还有一些谷歌,这里的回答应该是令人满意的。关键的想法是不仅传递我们感兴趣的人X
而且传递补充集(AEX
)。与此相比,相当于否定与X
的比较。
friendly(X) :-
G = [person(kara,[barry,clark]),
person(bruce,[clark,oliver]),
person(barry,[kara,oliver]),
person(clark,[oliver,kara]),
person(oliver,[kara])],
allppl(G,All),
mymember(person(X,Xs),G),
select(X,All,AEX),
likers(G,X,AEX,[],Fs),
subset(Fs,Xs).
获取所有人的列表:
allppl([person(P,_)|Rest],[P|Ps]) :-
allppl(Rest,Ps).
allppl([],[]).
这是我的老likers/4
加补充集。
likers([person(Y,Ys)|Rest],X,AEX,Fs0,Fs) :-
mymember(X,Ys),
likers(Rest,X,AEX,[Y|Fs0],Fs).
likers([person(_,Ys)|Rest],X,AEX,Fs0,Fs) :-
subset(Ys,AEX),
likers(Rest,X,AEX,Fs0,Fs).
likers([],_,_,Fs,Fs).
这里有一些辅助谓词。
select(X,[X|Xs],Xs).
select(X,[Y|Xs],[Y|Zs]) :-
select(X,Xs,Zs).
subset([],_).
subset([X|Xs],Ys) :-
mymember(X,Ys), subset(Xs,Ys).
mymember(X,[X|_]).
mymember(X,[_|Xs]) :-
mymember(X,Xs).
现在我明白了
?- friendly(X).
X = bruce ? ;
X = barry ? ;
no
以下是您的程序应该如何编写:
person(kara,[barry, clark]).
person(bruce,[clark,oliver]).
person(barry,[kara,oliver]).
person(clark,[oliver,kara]).
person(oliver,[kara]).
likes_back([],_).
likes_back([Y|Ys],X) :-
person(Y,Xs),
member(X,Xs),
likes_back(Ys,X).
friendly(X) :-
person(X,Ys),
likes_back(Ys,X).
?- friendly(X),write(X),nl,fail.
当我运行它时,我只得到kara
- 根据我对你提供的数据和规则的检查,这是正确的。
好的,如果我理解正确的话,这是一个解决方案。我认为没有人喜欢的人(布鲁斯)不被认为是友好的。
friendly(P) :-
person_likes(P,Ps),
findall(X,(person_likes(X,Zs),member(P,Zs)),Fs), Fs = [],
check_subset(Fs,Ps).
check_subset([X|Xs],Set) :-
memberchk(X,Set),
check_subset(Xs,Set).
check_subset([],_).
person_likes(kara,[barry,clark]).
person_likes(bruce,[clark,oliver]).
person_likes(barry,[kara,oliver]).
person_likes(clark,[oliver,kara]).
person_likes(oliver,[kara]).
结果:
?- friendly(X).
X = barry ? ;
no
如果您不被允许使用findall/3
,那么您需要自己编写另外三行代码。
你可以像这样写likers/4
:
likers([person(Y,Ys)|Rest],X,Fs0,Fs) :-
( memberchk(X,Ys) ->
Fs1 = [Y|Fs0]
; Fs1 = Fs0 ),
likers(Rest,X,Fs1,Fs).
likers([],_,Fs,Fs).
用第三个参数空列表调用它。
增加:不带分号:
likers([person(Y,Ys)|Rest],X,Fs0,Fs) :-
memberchk(X,Ys),
likers(Rest,X,[Y|Fs0],Fs).
likers([person(_,Ys)|Rest],X,Fs0,Fs) :-
+ memberchk(X,Ys),
likers(Rest,X,Fs0,Fs).
likers([],_,Fs,Fs).
以上是关于Prolog谓词问题的主要内容,如果未能解决你的问题,请参考以下文章