我正在尝试关系序言。我的程序的一部分需要处理位掩码。然而,似乎prolog代码处理比特产生,例如设置一个比特或清除一个不相关的工作 - 即它只能用于设置一个位,但不能用于另一个方向,识别设置的位。
例如:
setbit(X, N, V) :-
N1 #= 1<< N,
V #= X \/ N1.
此代码仅在一个方向上工作,其中给出X和N并计算V.如果提供V和N,那么X不是派生的,而是左派作为未实例化的表达式。
这是否意味着使用位图和掩码进行计算超出了关系序言的范围。
?- setbit(0,1,X).
X = 2.
?- setbit(X, 1, 2).
2#=X\/2.
后者不会将X绑定到0。
谢谢,
丹尼尔
编辑:根据以下评论,以下代码非常有效:
setbit(X, N, V) :-
X in 0..1,
label([X]),
N1 #= 1<< N,
V #= X \/ N1.
clearbit(X, N, V) :-
X in 0..1,
label([X]),
current_prolog_flag(max_tagged_integer, MTI),
N1 #= MTI /\ \(1<<N),
% N1 #= 0xffffffffffffff /\ \(1<<N),
V #= X /\ N1
注意,current_prolog_flag - 它检索当前机器体系结构中适合一个字的最大整数 - 在64位上为54位,其余位用于内务处理。
答案 0 :(得分:3)
从给定的解决方案中,您无法断定它是唯一的解决方案。也就是说,来自
?- setbit(0,1,X).
X = 2.
你不能得出结论
?- setbit(X, 1, 2).
将X = 0
作为唯一解决方案。事实上,还有另一种解决方案,即
?- setbit(2, 1, 2).
true.
理想情况下,所有约束都将保持域一致性。在这个理想的世界里,我们会:
?- setbit(X, 1, 2).
X in 0\/2, % idealiter
2#=X\/2.
而不是
?- setbit(X, 1, 2).
2#=X\/2. % realiter
但首先,让我们意识到两个答案都是正确的!第二个答案与理想答案完全相同。然而,在第二种情况下找到具体的解决方案可能更昂贵。特别是,因为以下查询有答案:
?- setbit(X, 1, 2), X #> 2.
X in 3..sup,
2#=X\/2. % inconsistency
这个答案就像赢得你从未听说过的彩票的通知一样:
是的,恭喜!有一个解决方案, 提供所有这些精细打印,这个X在3..sup,2#= / 2有一个解决方案,否则它没有任何解决方案。所以不要抱怨,我们告诉过你。
也就是说,答案很可能恰好包含零解决方案。要绝对确定解决方案,您必须消除所有约束。最简单的方法是使用labeling/2
。 然而,labeling/2
仅针对有限域(CLPFD中的FD源自的地方)定义。但在这种情况下,X
并不局限于有限域 - 如果是这种情况,我们会有一个额外的约束,如X in 0..2
。
clpfd系统的一致性程度在很大程度上取决于实际用例。毕竟,完全一致性是不可判定的。因此总会出现我们期望得到更精确结果的情况。这是一个关于运行和开发时间权衡的问题。如果您有令人信服的用例,请联系系统开发人员。
在这种特殊情况下,你可能最好使用模数算术和加法。
答案 1 :(得分:1)
我在clpfd
并不擅长,但我认为这里的问题是你没有给予X 有限域或要求枚举其值。这有效:
?- setbit(X, 1, 2), X in 0..1, label([X]).
X = 0 ;
false.
那里的第二个表达式,X in 0..1
表示你希望X为0或1,第三个表示,&#34;给我X可以获得的值。&#34;