[英]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.