Prolog 如何避免使用整数基本情况的非终止?

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 ->

我想编写一个递归到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这样的子句根本不会改变终止。