SWI Prolog使用位移位CLPFD报告错误答案

SWI Prolog使用位移位CLPFD报告错误答案,prolog,clpfd,prolog-toplevel,Prolog,Clpfd,Prolog Toplevel,我在一个更大的代码库中遇到了这个问题,但将其简化为一个最小的可复制示例。以下是汇编程序的一些代码: :- use_module(library(clpfd)). bigconst(X) :- X #=< 0x3FF, X #>= 0. asm(instruction('ADD', [A]), R) :- bigconst(A), R #= 0b0000 + (A << 4). asm(instruction('SUB', [A]), R) :- bigco

我在一个更大的代码库中遇到了这个问题,但将其简化为一个最小的可复制示例。以下是汇编程序的一些代码:

:- use_module(library(clpfd)).

bigconst(X) :- X #=< 0x3FF, X #>= 0.

asm(instruction('ADD', [A]), R) :-
  bigconst(A),
  R #= 0b0000 + (A << 4).
asm(instruction('SUB', [A]), R) :-
  bigconst(A),
  R #= 0b0001 + (A << 4).
但在拆卸时似乎失败了:

?- asm(instruction('SUB', [5]), R).
R = 81.
?- asm(I, 81).
I = instruction('ADD', [_42146]),
_42146 in 0..1023,
81#=_42146<<4 .
?-asm(I,81)。
I=指令('ADD',[_42146]),
_0..1023中的42146,

81#=42146当我找到答案时,它是LOL。我用了很多奇怪的模式来解决一个问题,但这是我以前从未用过的。一旦我看到它的工作,我知道我有一个闪亮的工具箱新工具

对于CLP(FD)问题,它们通常可以双向工作,这正是您想要的。您遇到的第一个问题是,
bigcont(A)
,它的作用类似于guard语句。那就把它扔掉吧

接下来的事情是
R#=0b0000+(A
这是我的程序中的错误还是Prolog中的错误?我将如何修复它

这是您正在使用的顶级可用性缺陷。如果您仔细观察,您可能会发现一个小小的提示:

81#=_42146<<4 .
             ^ SPACE

另一种方法是加强约束,正如@Guy Coder所展示的那样。这可能会奏效(然后很好)但是理解起来更复杂。在某些情况下效率可能更低。这是一个真正的工程问题。在某些情况下,我们什么时候可以接受不一致性作为更快解决方案的代价?

根据您的编写方式,您的代码正是我所期望的。
B #= A >> 4.
?- X #= 64 >> 4.
X = 4.

?- 4 #= X >> 4.
4#=X>>4.
asm(instruction('ADD', [A]), R) :-
    R #= 0b0000 + (A << 4),
    A #= (R - 0b0000) >> 4.
?- asm(instruction('ADD', [5]), R).
R = 80.

?- asm(I,80).
I = instruction('ADD', [5]).
asm(instruction('SUB', [A]), R) :-
    R #= 0b0001 + (A << 4),
    A #= (R - 0b0001) >> 4.
?- asm(instruction('SUB', [5]), R).
R = 81.

?- asm(I,81).
I = instruction('SUB', [5]).
81#=_42146<<4 .
             ^ SPACE
?- asm(I,81), I = instruction(_,[R]).
   I = instruction('ADD', [R]),
   R in 0..1023,
   81#=R<<4
;  I = instruction('SUB', [R]),
   R in 0..1023,
   80#=R<<4.

?- asm(I,81), I = instruction(_,[R]), labeling([],[R]).
   I = instruction('SUB', [5]),
   R = 5
;  false.