1
votes

How can one tell Prolog/CLPFD to only use certain number of domain only as last resource?

E.g. : domain from 0...8. I want Prolog to use 0 only if there's no other option. I used the 'down' option for labeling, but too many 0's are assigned.

Context: Hoo-Doo game -> Generate 8x8 board solution where any column,row or diagonal have the numbers from 1-8 without repeating (Sudoku like). One must use two transparent pieces (represented by 0, which can be anywhere) in order to complete the solution.

Here's the code:

...

setDomain(H,BoardSize), 
maplist(all_distinct,H), 
IndexI is BoardSize - 1, 
IndexJ is BoardSize - 2,
checkDiagonalsLR(H,IndexI,IndexJ,BoardSize), %calls the all_distinct
IndexJ2 is BoardSize - 1,
checkDiagonalsRL(H,1,IndexJ2,BoardSize), %calls the all_distinct
transpose(H,Columns), maplist(all_distinct,Columns), 
useLabeling(Columns,BoardSize), printBoard(Columns).

useLabeling([],N).
useLabeling([H|T],N) :- labeling([down],H), useLabeling(T,N).
1
Please add your code to the question.Daniel Lyons

1 Answers

3
votes

One way is to use Boolean variables Bs and reified constraints so that B_i is 1 iff V_i is zero:

(V_i #= 0) #<==> B_i

the sum of the B_i variables is then the number N of zeroes that occur in your solution:

sum(Bs, #=, N)

Then, you can use labeling/2 in such a way that N is minimal:

labeling([min(N)], Vs)

This works (with small adjustments) for example in SICStus and SWI.