Prolog 如何避免使用整数基本情况的非终止?
我想编写一个递归到0的谓词,但它始终无法终止。我使用故障切片将其缩小为:Prolog 如何避免使用整数基本情况的非终止?,prolog,failure-slice,Prolog,Failure Slice,我想编写一个递归到0的谓词,但它始终无法终止。我使用故障切片将其缩小为: f(a, 0). f(b, 0). f(X, Y) :- false. 当我将文件加载为swipl-f test.pl,然后在提示符中运行f(X,0)。时,我得到了输出X=a,但我没有看到X=b,也没有得到新的提示符。我希望它的行为像A是1+1,在这里我得到A=2.,带有一个句点和一个新的?-提示符 我能让它像这样工作,但它看起来不干净: f(X, 0) :- X = x. f(X, Y) :- Y == 0 ->
f(a, 0).
f(b, 0).
f(X, Y) :- false.
当我将文件加载为swipl-f test.pl
,然后在提示符中运行f(X,0)。
时,我得到了输出X=a
,但我没有看到X=b
,也没有得到新的提示符。我希望它的行为像A是1+1
,在这里我得到A=2.
,带有一个句点和一个新的?-
提示符
我能让它像这样工作,但它看起来不干净:
f(X, 0) :- X = x.
f(X, Y) :- Y == 0 -> false; (NewY is Y - 1, f(X, NewY)).
对于列表,我可以将更一般的情况写成f(X,[a | B])
,以确保它仅在列表至少有一个元素时适用。我能做些类似的事情来确保这里更一般的情况只适用于Y
不是0的情况吗
我已经看过了,虽然它暗示了正确的方向,但这也不起作用:
:- use_module(library(clpfd)).
int_int_prod(_, 0, 0).
int_int_prod(Num1, Num2, Result) :-
Num2 #> 0,
NewNum2 #= Num2 - 1,
int_int_prod(Num1, NewNum2, NewResult),
Result #= Num1 + NewResult.
?- int_int_prod(0, 0, X).
运行f(X,0)
,您将返回X=a
。注意空白处。系统等待您的命令
如果按
在键盘上,它以X=b
响应。这是你不想发生的事吗?(另一个选项是:按
)。毕竟,您的定义确实为该查询提供了两种解决方案,X=a
和X=b
。为什么Prolog应该跳过第二个呢?不应该
另一件事是,它仍然等待(在SWI中测试,通过[user]
从提示符加载)第二个结果之后的用户响应。要消除这一点,只需删除第三条。无论如何,这完全是多余的:显式失败与在找不到更多匹配子句时失败具有相同的效果
如果没有第三条,f(X,Y):-false。
,终止将改进:
6 ?- f(X,0).
X = a ;
X = b.
% ^^ no white space, no waiting, immediate termination.
你能发布实际的非工作代码吗?我怀疑您的故障切片应用程序有问题(我真的不知道在提供的示例中如何出现非终止),但我可能可以在不应用该技术的情况下帮助调试代码。我发布的代码无法为我终止。我得到一个输出,
X=X
,但它没有停止。我确实设法让它工作了,所以我将编辑我所做的。您希望谓词做什么?对于直到0的递归,您将有一个基本情况f(x,0)。
并且您的递归情况将是f(x,Y):-Y>0,Y1是Y-1,f(x,Y)。
或者更好,因为您正在使用CLP(FD)对整数进行推理:f(x,Y):-Y(x,Y):-Y)。。。你期望得到什么样的结果?你得到了什么?关系int_int_prod/3
是什么意思?我加载了第一个片段,它在我的机器上终止(没有递归,它必须终止)。您是否重新启动了Prolog解释器,并在没有先前尝试的旧代码的情况下进行了尝试?第一个子句的主体是否打算将变量X
与常量X
统一起来(注意不同的情况)?在这种情况下,最好把它写成事实f(x,0)。
或者至少为了清楚起见重命名变量。谢谢@安德烈皮尔斯,不客气!顺便说一句,这确实表明了正确提问的重要性。如果你从一开始就把所有信息都包括在内,你会更快得到答案。:)快乐的小径!终止改进:这是一种非常不寻常的终止用法。我更愿意说,像f(X,Y):-false这样的子句根本不会改变终止。