关系序言和位掩码操作

relational prolog and bit mask manipulations

我正在尝试关系序言。我的部分程序需要处理位掩码。然而,似乎序言代码处理位生成,例如设置位或清除位在关系上不起作用 - 即它仅在设置位时起作用,但在另一个方向上不起作用,识别设置了哪个位。

例如:

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 位,其余位用于管理。

我不擅长 clpfd,但我认为这里的问题是您没有给 X 一个 有限域 或要求它的值是枚举。这有效:

?- setbit(X, 1, 2), X in 0..1, label([X]).
X = 0 ;
false.

那里的第二个表达式 X in 0..1 表示您希望 X 为零或一,第三个表达式表示 "give me the values X can obtain."

从给定的解决方案中,您不能断定它是唯一的解决方案。即来自

?- 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

这个答案读起来就像你从未听说过的中奖通知:

Yes, congratulation! There is a solution, provided all this fine print, this X in 3..sup, 2#=/2 has a solution, otherwise it does not have any solution. So don't complain, we told you so.

也就是说,答案很可能恰好包含零个解。要绝对确定解决方案,您必须消除所有限制。最简单的方法是使用 labeling/2然而labeling/2 仅针对有限域定义(这就是 CLPFD 中 FD 的来源)。但在这种情况下 X 不受限于有限域 - 如果是这种情况,我们将有一个额外的约束,如 X in 0..2.

clpfd 系统的一致性程度在很大程度上取决于实际用例。毕竟,完全一致性是不可判定的。因此,在某些情况下,我们会期望得到更精确的结果。这是一个权衡 运行- 和开发时间的问题。如果您有令人信服的用例,请联系系统开发人员。

在这种特殊情况下,您最好使用模运算和加法。