听起来很傻,但是可以说我的谓词最大/ 2 返回列表中的最大元素...输出应如下所示:
?- largest([1,2,3,4,5], X).
X = 5.
false.
我实现了最大的,它像上面一样工作,只是它不输出“false”。我该怎么做,所以它也输出这个“假”。价值?这是我必须完成的一项烦人的任务。:(
听起来很傻,但是可以说我的谓词最大/ 2 返回列表中的最大元素...输出应如下所示:
?- largest([1,2,3,4,5], X).
X = 5.
false.
我实现了最大的,它像上面一样工作,只是它不输出“false”。我该怎么做,所以它也输出这个“假”。价值?这是我必须完成的一项烦人的任务。:(
这额外false.
或No
只是意味着运行程序的人要求获得所有可能的解决方案X
,而不仅仅是第一个可能的解决方案。
;
在大多数交互式 Prolog 解释器上,您可以通过按分号 ( ) 键来检查是否有其他解决方案。
听起来不可能,好像谓词失败,没有发生自由变量的绑定,请参阅
?- A=5.
A = 5.
?- A=5,false.
false.
然而
?- A=5;false.
A = 5 ;
false.
为此,您应该使您的谓词“最大”不确定。但对我来说,这似乎很愚蠢。
如果这是作业的一部分,则可能意味着您的谓词在回溯后不应产生第二个(可能不同的)结果。如果用户想要下一个解决方案,就会发生回溯,通常是按;。当解释器知道仍有未完全评估的路径时,解释器通常会指示另一个解决方案是可能的。
假设您有foo/1
如下谓词:
foo(1).
foo(Bar) :-
foo(Baz),
Bar is Baz + 1.
如果你问foo(Bar)
,口译员会回答Bar = 1
。反复按 后;,翻译返回Bar = 2
,Bar = 3
以此类推。
在您的示例中,查找列表中的最大值应该是确定性的。回溯不应产生不同的答案。
您可以将分配解释为您必须允许回溯但让它失败,或者根本不让它回溯也可以。
@aschepler 、@Xonix和@SQB之前的回答有些内容。
在这个答案中,我们使用clpfd来表达声明性整数算术。
:- use_module(library(clpfd)).
我们largest/2
使用内置谓词member/2
、库元谓词 maplist/2
和有限域约束进行定义(#>=)/2
:
largest(Zs, X) :-
member(X, Zs), % X is a member of the list Zs
maplist(#>=(X), Zs). % all Z in Zs fulfill X #>= Z
示例查询:
?- largest([1,2,3,4,5], X).
X = 5.
?- largest([1,2,3,4,5,4], X).
X = 5 ;
false.
?- largest([1,2,3,4,5,5], X).
X = 5 ;
X = 5.
?- largest([1,2,3,4,5,5,4], X).
X = 5 ;
X = 5 ;
false.
?- largest([A,B,C,D], X).
A = X, X#>=D, X#>=C, X#>=B ;
B = X, X#>=A, X#>=D, X#>=C ;
C = X, X#>=A, X#>=D, X#>=B ;
D = X, X#>=A, X#>=C, X#>=B.