[英]Internal workings of ic_global/occurrences/3
对于 QuasiGroup 完成问题,我实现了两个模型。 其中之一是仅基于通道约束的模型(基于 Dotu 的一项研究)。 另一种是基于每个值都需要出现在任何行/列中这一事实的模型。 这是一个小脚本:
flag :- fail.
:- lib(ic).
:- import occurrences/3 from ic_global.
test :-
O is 9, % Order of the puzzle
dim(Variables, [O,O]), Variables :: 1..O,
6 is Variables[1,1], 8 is Variables[6,2],
dim(Dual1, [O,O]), Dual1 :: 1..O,
dim(Dual2, [O,O]), Dual2 :: 1..O,
(flag ->
(multifor([I,V], 1, O), param(Variables, O) do
ic_global:occurrences(V, Variables[I,1..O], 1),
ic_global:occurrences(V, Variables[1..O,I], 1)
)
;
(multifor([I,J,K], 1, O), param(Variables, Dual1, Dual2) do
#=(Variables[I,J], K, Bool),
#=(Dual1[I,K], J, Bool),
#=(Dual2[J,K], I, Bool)
)
),
search(Variables, 0, input_order, indomain, complete, [backtrack(Backtracks)]),
write(Variables), nl,
write('Backtracks : '), write(Backtracks), nl.
我在一堆基准测试(超过 10 个谜题)上进行了尝试。 回溯的总数大于 500,但令我震惊的是两个模型中的数量相同。 集合中每个问题的回溯次数也相同。
上面的小脚本也报告了相同数量的回溯。 我很好奇为什么会发生这种情况。 ic_global:occurrences/
做了什么使它表现得如此相似(虽然它有点慢)?
出现次数/ 3约束实现弧一致性,即它急切地从其参数变量的域中删除所有在约束的任何解决方案中都没有出现的值。
如果您可以为整个问题建立弧一致性,那么任何搜索过程都会找到具有绝对最少回溯数的解决方案:第一个解决方案具有 0 个回溯,第二个解决方案在 1 个回溯后,N-1 个回溯后的第 N 个。 这通常不会实现,因为即使您使用所有单独实现弧一致性的约束对问题进行建模,也不意味着您对整个问题具有弧一致性。
存在这些全局约束的一个主要原因是它们通常可以比许多小约束的结合实现更高级别的一致性。 有鉴于此,值得注意的是,您的“双重”公式似乎与基于事件的公式表现相同。
我对您的程序进行了一些扩展,并查看了许多可以使用可用全局约束轻松编写的替代公式:
:- lib(ic).
:- lib(ic_global).
:- lib(ic_global_gac).
test(Model) :-
O is 9, % Order of the puzzle
dim(Variables, [O,O]), Variables :: 1..O,
6 is Variables[1,1], 8 is Variables[6,2],
(Model=occ ->
(multifor([I,V], 1, O), param(Variables, O) do
ic_global:occurrences(V, Variables[I,1..O], 1),
ic_global:occurrences(V, Variables[1..O,I], 1)
)
;Model=gcc ->
(for(V, 1, O), foreach(gcc(1,1,V),Bounds) do true ),
(for(I, 1, O), param(Variables, O, Bounds) do
ic_global_gac:gcc(Bounds, Variables[1..O,I]),
ic_global_gac:gcc(Bounds, Variables[I,1..O])
)
;Model=gcm ->
(for(V, 1, O), foreach(gcc(1,1,V),Bounds) do true ),
(for(_, 1, O), foreach(Bounds,RowColBounds), param(Bounds) do true ),
ic_global_gac:gcc_matrix(RowColBounds, RowColBounds, Variables)
;Model=ad(Strength) ->
(for(I, 1, O), param(Variables,O,Strength) do
Strength:alldifferent(Variables[1..O,I]),
Strength:alldifferent(Variables[I,1..O])
)
;Model=adm ->
ic_global:alldifferent_matrix(Variables)
;Model=dual ->
dim(Dual1, [O,O]), Dual1 :: 1..O,
dim(Dual2, [O,O]), Dual2 :: 1..O,
(multifor([I,J,K], 1, O), param(Variables, Dual1, Dual2) do
#=(Variables[I,J], K, Bool),
#=(Dual1[I,K], J, Bool),
#=(Dual2[J,K], I, Bool)
)
),
search(Variables, 0, input_order, indomain, complete, [backtrack(Backtracks)]),
( foreacharg(Row,Variables) do writeln(Row) ),
write('Backtracks : '), write(Backtracks), nl.
对于您的小型测试实例,它们的行为如下:
Goal #backtracks until first solution
test(occ) 3
test(gcc) 0
test(gcm) 0
test(ad(ic)) 29
test(ad(ic_global)) 0
test(ad(ic_global_gac)) 0
test(adm) 0
test(dual) 3
对于更大的问题实例,您可能会发现更多有趣的差异。 然而, adm
和gcm
模型(其中整个问题用单个约束表示)应该总是表现出最小的回溯行为。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.