在 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).
我正在寻找的是尽可能稀疏的 X
和 Y
域的表示 - 在这种情况下,它将是 [= =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/1
、label/1
、labeling/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.
我正在探索像这样的约束的依赖结构:
assign(X,Y) :-
X in 1..5,
((X mod 2 #= 1) #=> Y in 2..3),
((X mod 2 #= 0) #=> Y #= 5).
我正在寻找的是尽可能稀疏的 X
和 Y
域的表示 - 在这种情况下,它将是 [= =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/1
、label/1
、labeling/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.