关系序言和位掩码操作
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 系统的一致性程度在很大程度上取决于实际用例。毕竟,完全一致性是不可判定的。因此,在某些情况下,我们会期望得到更精确的结果。这是一个权衡 运行- 和开发时间的问题。如果您有令人信服的用例,请联系系统开发人员。
在这种特殊情况下,您最好使用模运算和加法。
我正在尝试关系序言。我的部分程序需要处理位掩码。然而,似乎序言代码处理位生成,例如设置位或清除位在关系上不起作用 - 即它仅在设置位时起作用,但在另一个方向上不起作用,识别设置了哪个位。
例如:
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 系统的一致性程度在很大程度上取决于实际用例。毕竟,完全一致性是不可判定的。因此,在某些情况下,我们会期望得到更精确的结果。这是一个权衡 运行- 和开发时间的问题。如果您有令人信服的用例,请联系系统开发人员。
在这种特殊情况下,您最好使用模运算和加法。