我在堆栈上找到了这个:可逆的“二进制到数字”谓词
但是我不明白
:- use_module(library(clpfd)).
binary_number(Bs0, N) :-
reverse(Bs0, Bs),
binary_number(Bs, 0, 0, N).
binary_number([], _, N, N).
binary_number([B|Bs], I0, N0, N) :-
B in 0..1,
N1 #= N0 + (2^I0)*B,
I1 #= I0 + 1,
binary_number(Bs, I1, N1, N).
查询示例:
?- binary_number([1,0,1], N).
N = 5.
?- binary_number(Bs, 5).
Bs = [1, 0, 1] .
有人可以解释一下我的代码吗
特别是:binary_number([], _, N, N).
(_)
另外,library(clpfd)有什么作用?
又为什么reverse(Bs0, Bs)
呢?我拿走了它仍然可以正常工作...
提前
在原始的中binary_number([], _, N, N).
,这_
意味着您无需关心变量的值是多少。如果您使用过binary_number([], X, N, N).
(不关心是什么X
),Prolog会发出单例变量警告。同样,该谓词从句中说的是,当第一个参数为[]
(空列表)时,则第3个和第4个参数是统一的。
如评论中所述,use_module(library(clpfd))
使Prolog将库用于有限域上的约束逻辑编程。您也可以通过Google搜索“ prolog clpfd”找到很多很好的信息。
通常,在Prolog中,比较的算术表达式需要完全实例化这些表达式:
X + Y =:= Z + 2. % Requires X, Y, and Z to be instantiated
Prolog会评估并进行比较,得出正确或错误。如果未实例化这些变量中的任何一个,将引发错误。同样,对于赋值,is/2
谓词要求右侧表达式必须完全实例化且所有实例化的特定变量都可以求值:
Z is X + Y. % Requires X and Y to be instantiated
使用CLPFD,您可以为您提供Prolog“探索”解决方案。然后,您可以进一步指定要将变量限制到的域。所以,可以说X + Y #= Z + 2
和前导可以枚举可能的解决方案X
,Y
以及Z
。
顺便说一句,可以对原始实现进行一些重构,以避免每次取幂并消除reverse
:
:- use_module(library(clpfd)).
binary_number(Bin, N) :-
binary_number(Bin, 0, N).
binary_number([], N, N).
binary_number([Bit|Bits], Acc, N) :-
Bit in 0..1,
Acc1 #= Acc*2 + Bit,
binary_number(Bits, Acc1, N).
这对于以下查询非常有效:
| ?- binary_number([1,0,1,0], N).
N = 10 ? ;
no
| ?- binary_number(B, 10).
B = [1,0,1,0] ? ;
B = [0,1,0,1,0] ? ;
B = [0,0,1,0,1,0] ? ;
...
但是,正如评论中指出的那样,它存在终止问题,例如,@false提出了Bs = [1|_], N #=< 5, binary_number(Bs, N).
一种解决方案,该解决方案只是修改了上述内容有助于解决这些终止问题。为了方便起见,我将在此处重申该解决方案:
:- use_module(library(clpfd)).
binary_number(Bits, N) :-
binary_number_min(Bits, 0,N, N).
binary_number_min([], N,N, _M).
binary_number_min([Bit|Bits], N0,N, M) :-
Bit in 0..1,
N1 #= N0*2 + Bit,
M #>= N1,
binary_number_min(Bits, N1,N, M).
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句