findall参数没有充分实例化

时间:2018-04-07 13:20:08

标签: prolog instantiation-error

我已将代码简化为;

findall(T,(T > 0, T < 50),List).

为什么会因给定错误而失败。

2 个答案:

答案 0 :(得分:3)

以下是您的代码进一步简化:

?- T > 0.
ERROR: >/2: Arguments are not sufficiently instantiated

&#34; classic&#34;像<>之类的比较操作需要将所有参数完全实例化为基础术语;特别是,它们不能是未绑定的变量。 (对于is/2运算符右侧的术语也是如此。)

您可以将这些运算符用作生成器。以下是可能原因的一个例子:

?- T = 1, T > 0.
T = 1.

?- T = 0.1, T > 0.
T = 0.1.

?- T = 0.01, T > 0.
T = 0.01.

?- T = 0.001, T > 0.
T = 0.001.

>运算符适用于多种不同类型的数字,包括浮点数。如果我们希望它是一个逻辑上合理的生成器,它必须能够生成它在上面的例子中接受的所有浮点数。这几乎肯定不是你想要的。

有几种方法可以获得你想要的东西。因为你可能只想要整数,你可以使用许多Prolog系统(包括SWI)提供的between/3谓词:

?- between(1, 49, T).
T = 1 ;
T = 2 ;
T = 3 ;
T = 4 .

?- findall(T, between(1, 49, T), List).
List = [1, 2, 3, 4, 5, 6, 7, 8, 9|...].

另一种可能性是使用约束编程库。以下是SWI-Prolog的clpfd库的一个示例会话:

?- use_module(library(clpfd)).
true.

?- T #> 0, T #< 50.
T in 1..49.

请注意,在这里,使用#>库中的#<clpfd代替<>,我们可以实际上甚至在未绑定的变量上指定这些约束。记住这些约束以供以后使用,但它们枚举T的实际值。你可以在算术和比较中使用它们,即使它没有列举具体的值,系统有时也会正确推理出来!例如:

?- T #> 0, T #< 50, X #= T - 50, X #> 50.
false.

要获取实际值,可以调用枚举它们的特定谓词:

?- T #> 0, T #< 50, indomain(T).
T = 1 ;
T = 2 ;
T = 3 ;
T = 4 .

所有这些为您的问题提供了另一种可能的解决方案:

?- findall(T, (T #> 0, T #< 50, indomain(T)), List).
List = [1, 2, 3, 4, 5, 6, 7, 8, 9|...].

答案 1 :(得分:0)

如果你想过滤,那么写这样:

bagof(T,(member(T,[0,-4,34,15,76,100,200,43,21]),T>0,T<50),List).

列表将是[34,15,43,21]。 (虽然我没有测试)

如果你只是想要1到49,请忽略这个答案(其他人已经回答)