在Prolog中生成整数的最佳方法

时间:2015-10-11 09:55:37

标签: prolog

我想生成整数,我正在寻找最佳方法。例如:

int

现在我只是使用?- number2(N). N = 0; N = 1; N = 2; ... (and so on)

length/2

但我认为应该有更好的方法(不创建临时列表)。我可能会根据number2(N) :- length(_, N). 的代码自己编写一些代码,但我正在寻找采用已有的内置谓词的解决方案。是否有任何内置谓词比length/2更好?我找不到那样的东西。

3 个答案:

答案 0 :(得分:3)

Carlo解决方案的尾递归替代方案是:

next_integer(I) :-
    next_integer(0, I).

next_integer(I, I).
next_integer(I, J) :-
    I2 is I + 1,
    next_integer(I2, J).

示例查询:

?- next_integer(I).
I = 0 ;
I = 1 ;
I = 2 ;
I = 3 ;
...

您也可以从零以外的整数开始。例如:

?- next_integer(-5, I).
I = -5 ;
I = -4 ;
I = -3 ;
I = -2 ;
I = -1 ;
I = 0 ;
I = 1 ;
I = 2 ;
I = 3 ;
...

答案 1 :(得分:3)

很难找到最佳解决方案;并且可能不值得努力。毕竟,现在有三个建议,对于一个或另一个案例都是不正确的:

?- time( (number2_gk(N), N == 10000) ). % your original
% 20,002 inferences, 0.007 CPU in 0.007 seconds (99% CPU, 3006132 Lips)
N = 10000 

?- time( (number2_cc(N), N == 10000) ). % quadratic overhead
% 50,025,001 inferences, 28.073 CPU in 28.196 seconds (100% CPU, 1781945 Lips)
N = 10000 

?- time( (next_integer(N), N == 10000) ).
% 20,002 inferences, 0.011 CPU in 0.011 seconds (100% CPU, 1822247 Lips)
N = 10000 

但是,number2_cc(-1)next_integer(-1)只是循环,length/2实际上应该产生域错误,就像SICStus and many other systems那样。

正如您所看到的,CC的解决方案比您原来的解决方案更糟糕。

在下列情况下,mat的建议也会产生不同的行为:

goal_expansion(length(Ls,L), between(0,infinite,L)) :-
   var_property(Ls, fresh(true)).

as(N) :-
   length(L,N),
   phrase(a, L).

a --> [a], a.
a --> [].

目标as(N)现在循环而不是枚举所有N

如果您真的坚持改进,请使用library(clpfd)考虑以下尾递归解决方案:

nat(N) :-
   nat(N, 0).

nat(N, N0) :-
  N #>= N0,
  (  N = N0
  ;  N1 is N0+1,
     nat(N, N1)
  ).

?- time( (nat(N), N == 10000) ).
% 1,850,152 inferences, 0.544 CPU in 0.545 seconds (100% CPU, 3399793 Lips)

这只是对以下查询的改进。否则只是浪费资源。

?- N in 1..2, nat(N).

答案 2 :(得分:3)

保持/ 3纯,即只有整数参数,
我已经开始在上面提供以下谓词/ 2
在库中(源代码见here):

/**
 * above(L, X):
 * The predicate succeeds for every integer X above the integer L.
 */
% above(+Integer, -Integer)

所以如果你真的想要生成整数,那么 而不是自然数字,你可以使用:

gen_int(X) :-
    above(0, Y),
    (X is Y; X is -Y-1).

以上将给出0,-1,1,-2等。如果你想要 生成包括零的自然数,您可以使用:

gen_nat(X) :-
    above(0, X).

以上将给出0,1,2等......名称gen_int / 1
和gen_nat / 1由SICStus Prolog批准,见here

希望这有帮助。

再见