简体   繁体   English

ic_global/occurrences/3 的内部工作原理

[英]Internal workings of ic_global/occurrences/3

For the QuasiGroup completion problem I implemented two models.对于 QuasiGroup 完成问题,我实现了两个模型。 One of them is a model based on nothing but channeling constraints (based on a study by Dotu).其中之一是仅基于通道约束的模型(基于 Dotu 的一项研究)。 The other one is a model based on the fact that every value needs to occur in ever row/column.另一种是基于每个值都需要出现在任何行/列中这一事实的模型。 Here's a little script :这是一个小脚本:

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.

I tried it out on a bunch of benchmarks (more than 10 puzzles).我在一堆基准测试(超过 10 个谜题)上进行了尝试。 The total number of backtracks is larger than 500 but what struck me was that the number is the same in both models.回溯的总数大于 500,但令我震惊的是两个模型中的数量相同。 The number of backtracks for each problem in the set is the same, too.集合中每个问题的回溯次数也相同。

The little script above also reports the same number of backtracks.上面的小脚本也报告了相同数量的回溯。 I'm curious why this happens.我很好奇为什么会发生这种情况。 What doesic_global:occurrences/ do that makes it behave so similarly (though it is a little slower)? ic_global:occurrences/做了什么使它表现得如此相似(虽然它有点慢)?

The occurrences/3 constraint achieves arc-consistency , ie it eagerly removes, from the domains of its argument variables, all values that do not occur in any solution to the constraint. 出现次数/ 3约束实现弧一致性,即它急切地从其参数变量的域中删除所有在约束的任何解决方案中都没有出现的值。

If you can establish arc-consistency for your whole problem, then any search procedure will find solutions with the absolute minimum number of backtracks: first solution with 0 backtracks, second solution after 1 backtrack, Nth after N-1 backtracks.如果您可以为整个问题建立弧一致性,那么任何搜索过程都会找到具有绝对最少回溯数的解决方案:第一个解决方案具有 0 个回溯,第二个解决方案在 1 个回溯后,N-1 个回溯后的第 N 个。 This isn't often achieved, because even when you model the problem with a conjunction of constraints that all achieve arc-consistency individually, that doesn't mean you have arc-consistency over the problem as a whole.这通常不会实现,因为即使您使用所有单独实现弧一致性的约束对问题进行建模,也不意味着您对整个问题具有弧一致性。

One major reason for the existence of these global constraints is that they can usually achieve higher levels of consistency than a conjunction of many small constraints.存在这些全局约束的一个主要原因是它们通常可以比许多小约束的结合实现更高级别的一致性。 In this light, it is remarkable that your "dual" formulation seems to behave identical to the occurrences-based one.有鉴于此,值得注意的是,您的“双重”公式似乎与基于事件的公式表现相同。

I have expanded your program a bit, and looked at a number of alternative formulations that can be easily written using the available global constraints:我对您的程序进行了一些扩展,并查看了许多可以使用可用全局约束轻松编写的替代公式:

:- 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.

With your small test instance, these behave as follows:对于您的小型测试实例,它们的行为如下:

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 

With larger problem instances you might find more interesting differences.对于更大的问题实例,您可能会发现更多有趣的差异。 However, the adm and gcm models (where the whole problem is represented with a single constraint) should always exhibit the minimal backtracking behaviour.然而, admgcm模型(其中整个问题用单个约束表示)应该总是表现出最小的回溯行为。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM