在 Prolog 的 clpfd 中枚举域

Enumerating domains in Prolog's clpfd

我正在探索像这样的约束的依赖结构:

assign(X,Y) :- 
    X in 1..5, 
    ((X mod 2 #= 1) #=> Y in 2..3), 
    ((X mod 2 #= 0) #=> Y #= 5).

我正在寻找的是尽可能稀疏的 XY 域的表示 - 在这种情况下,它将是 [= =13=]。

这样做的一种方法是检测 #=> 左侧的所有变量,枚举它们的所有值并将它们收集并合并在一起,类似于 ?- assign(X, Y), findall(X-D, (indomain(X),fd_dom(Y,D)), C), do stuff with C,但也许有是更有效的方法?

我在尝试 label([X,Y]) 时也遇到了一个错误:当我在 Y 的域上添加另一个约束时,参数没有充分实例化,该错误消失了。

这个错误应该在什么时候发生?我觉得我对clpfd的机制和局限性了解不多,有什么资源可以借鉴吗?我已经了解了约束规划、弧一致性等基础知识

要避免 clpfd 枚举谓词(如 indomain/1label/1labeling/2 等)从 ever 抛出实例化错误,只需确保所有变量已分配一些有限执行任何枚举谓词之前。

那么直接把你写的东西翻译成代码怎么样?

assign(X,Y) :- X in 1\/3\/5, Y in 2..3.     %    X in {1,3,5} and Y in {2,3} 
assign(X,Y) :- X in 2..4,    Y in 5.        % or X in {2,4}   and Y = 5

一个简单的查询(使用 SWI-Prolog):

?- assign(X,Y), labeling([],[X,Y]).
  X = 1, Y = 2
; X = 1, Y = 3
; X = 3, Y = 2
; X = 3, Y = 3
; X = 5, Y = 2
; X = 5, Y = 3
; X = 2, Y = 5
; X = 3, Y = 5
; X = 4, Y = 5.