For the QuasiGroup completion problem I implemented two models. One of them is a model based on nothing but channeling constraints (based on a study by 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). The total number of backtracks is larger than 500 but what struck me was that the number is the same in both models. 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 does ic_global:occurrences/
do that makes it behave so similarly (though it is a little slower)?