2

我想有一个谓词isPowTwo/1,它适用于每一个二的幂。这是我的方法:

isPowTwo(N) :- N > 0, N is N /\ (-N).

它工作得很好,如果我给它整数:

?- isPowTwo(2).
true.

?- isPowTwo(4).
true.

?- isPowTwo(6).
false.

但是当我希望它用作生成器时它不起作用:

?- isPowTwo(N).
ERROR: >/2: Arguments are not sufficiently instantiated

如何编写一个按升序生成 2 次幂的谓词?

编辑:使用普通整数而不是皮亚诺数很重要。

4

2 回答 2

2

经验法则

你在推理整数吗?→ 使用 Prolog 系统的CLP(FD) 约束

示例解决方案

power_of_two(N) :-
    N #> 0,
    N #= 2^_。

示例查询和答案

具体整数

?- power_of_two(2)。
真的。

?- power_of_two(4)。
真的。

?- power_of_two(6)。
错误的。

最一般的查询

?- power_of_two(N)。
N 在 1..sup,
2^_G844#=N。

枚举

?- power_of_two(N), length(_, N)N = 1 ;
N = 2;
N = 4;
N = 8 ;
N = 16;
N = 32 ;
等等

结论

使用普通整数,没有 Peano 数。

约束允许我们以纯粹、通用和简洁的方式陈述解决方案。

于 2016-08-30T13:34:02.347 回答
0

我发现另一种方法可以很好地用作生成器(比使用length(_, N)作为目标的 CLP(FD) 版本更快),不使用clpfd,但如果用作验证器,则倾向于以无限循环结束:

isPowTwo(1).
isPowTwo(N) :- isPowTwo(N1), N is N1 * 2.

查看它的行为:

?- isPowTwo(N).
N = 1 ;
N = 2 ;
N = 4 ;
N = 8 ;
N = 16 ;
N = 32 ;
N = 64 ;
N = 128 ;
N = 256 ;
N = 512 ;
N = 1024 ;
...

?- isPowTwo(4).
true ;
... (infinite loop)

?- isPowTwo(3).
... (infinite loop)
于 2016-09-05T14:49:33.890 回答