我想生成整数,我正在寻找最佳方法。例如:
int
现在我只是使用?- number2(N).
N = 0;
N = 1;
N = 2;
...
(and so on)
:
length/2
但我认为应该有更好的方法(不创建临时列表)。我可能会根据number2(N) :- length(_, N).
的代码自己编写一些代码,但我正在寻找采用已有的内置谓词的解决方案。是否有任何内置谓词比length/2
更好?我找不到那样的东西。
答案 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。
希望这有帮助。
再见