在 Prolog 中生成整数的最佳方法 [英] Best way to generate integer numbers in Prolog
问题描述
我想生成整数,我正在寻找最好的方法来做到这一点.示例:
I want to generate integer numbers and I'm looking for the best way to do this. Example:
?- number2(N).
N = 0;
N = 1;
N = 2;
...
(and so on)
现在我只是使用length/2
:
number2(N) :- length(_, N).
但我认为应该有更好的方法(不创建临时列表).我可能可以根据 length/2
的代码自己编写一些代码,但我正在寻找使用现有内置谓词的解决方案.有没有比 length/2
更好的内置谓词?我找不到类似的东西.
But I think that there should be some better way (without creating temporary list). I could probably write some code myself basing on code of length/2
but I'm looking for solution that employs already existing, built-in predicates. Is there any built-in predicate that would work better than length/2
? I couldn't find anything like that.
推荐答案
你的解决方案很难超越;可能不值得付出努力.毕竟,现在有三种建议对于一种或另一种情况都是不正确的:
It is hard to top your solution ; and probably it is not worth the effort. After all, there are now three suggestions that all are incorrect for one case or another:
?- 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 和许多其他系统一样.
However, number2_cc(-1)
and next_integer(-1)
simply loop, length/2
actually should produce a domain error, like SICStus and many other systems do.
如您所见,CC 的解决方案比您原来的解决方案更糟糕.
As you can see, CC's solution is worse than your original one.
在以下情况下,mat 的建议也会产生不同的行为:
Also the suggestion by mat produces different behavior in the following situation:
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
.
The goal as(N)
now loops instead of enumerating all N
.
如果您真的坚持要改进,请考虑以下使用 library(clpfd)
的尾递归解决方案:
If you really insist on an improvement, consider the following tail-recursive solution using 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)
这只是对如下查询的改进.否则只会浪费资源.
Which is only an improvement for queries like the following. Otherwise it is just a waste of resources.
?- N in 1..2, nat(N).
这篇关于在 Prolog 中生成整数的最佳方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!