关系序言和位掩码操作

时间:2017-12-05 19:51:43

标签: prolog clpfd

我正在尝试关系序言。我的程序的一部分需要处理位掩码。然而,似乎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位,其余位用于内务处理。

2 个答案:

答案 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;