有四个篮子,每个篮子都有独特的颜色。我写了一个prolog程序,根据一些事实和规则告诉颜色oder。这是.pl文件:
iright(L, R, [L | [R | _]]).
iright(L, R, [_ | Rest]) :- iright(L, R, Rest).
nextto(L, R, List) :- iright(L, R, List).
nextto(L, R, List) :- iright(R, L, List).
myprogram(Data) :- =(Data, [_,red,_,_]),
\+nextto(red,blue,Data), % blue is not next to red
iright(red,green,Data), %green is right to red
member(red,Data),
member(blue,Data),
member(green,Data),
member(yellow,Data).
iright和nextto谓词是正确的。我的查询是myprogram(Data)
,我希望结果应该是
Data = [yellow,red, green, blue]?
yes
但实际上提示显示
| ?- myprogram(Data).
no
我知道问题是否定,但是如何以及为何如此。 Plz帮助。
当我使用trace.
1 1 Call: myprogram(_16) ?
2 2 Call: \+nextto(red,blue,[_46,red,_50,_52]) ?
3 3 Call: nextto(red,blue,[_46,red,_50,_52]) ?
4 4 Call: iright(red,blue,[_46,red,_50,_52]) ?
5 5 Call: iright(red,blue,[red,_50,_52]) ?
5 5 Exit: iright(red,blue,[red,blue,_52]) ?
4 4 Exit: iright(red,blue,[_46,red,blue,_52]) ?
3 3 Exit: nextto(red,blue,[_46,red,blue,_52]) ?
2 2 Fail: \+nextto(red,blue,[_46,red,_50,_52]) ?
1 1 Fail: myprogram(_16) ?
(2 ms) no
答案 0 :(得分:1)
如果您将\+nextto(red, blue, Data)
移至myprogram
的最后一行,则可以正常工作。
这有点不直观,但你需要考虑一下Prolog如何评估表达式&什么否定真的意味着什么。否定意味着“没有可能的方法来实现这一点”,而不是“对于一组特定的价值观而言,这不是真的”。如果您将程序剥离为简单:
myprogram(Data) :-
=(Data, [_,red,_,_]),
\+nextto(red,blue,Data).
您仍会获得No.
。这是因为,根据您声明的内容,数据可以 [_, red, blue, _]
- 您会在Exit: iright(red,blue,[red,blue,_52])
看到此决定。 Prolog试图回溯,但没有别的东西可以尝试 - 你还没有约束任何_s具有特定值。
如果,OTOH,你把你的所有下一个,成员&在你的否定陈述之前的正确陈述中,有多种可能的解决方案(好吧,两个)在得到否定的表达式时尝试:Data = [blue,red,green,yellow]
和Data = [yellow,red,green,blue]
。在这一点上,当它看到否定时,它会“抛弃”红色与蓝色相邻的“分支”,但它能够回溯并具有可能使否定成为真实的世界状态。也就是说:
myprogram(Data) :-
=(Data, [_,red,_,_]),
iright(red,green,Data),
member(red,Data),
member(blue,Data),
member(green,Data),
member(yellow,Data),
\+nextto(red,blue,Data).
...为您提供所需的结果。
TL; DR - Prolog中的否定(以及切换,当你到达它们时)比你最初想象的要强大得多。确保在使用之前先确定了其他所有内容。