Search code examples
prologclpfd

CLPFD ins operator yields not sufficiently instantiated error


So, my goal is to make a map colourer in Prolog. Here's the map I'm using:

enter image description here

And this are my colouring constraints:

colouring([A,B,C,D,E,F]) :- 
    maplist( #\=(A), [B,C,D,E] ),
    maplist( #\=(B), [C,D,F]),
    C #\= D,
    maplist( #\=(D), [E,F]),
    E #\= F.

Where [A,B,C,D,E,F] is a list of numbers(colors) from 1 to n.

So I want my solver to, given a List of 6 colors and a natural number N, determine the colors and N constraints both ways, in a way that even the most general query could yield results:

regions_ncolors(L,N) :- colouring(L), L ins 1..N, label(L).

Where the most general query is regions_ncolors(L,N).

However, the operator ins doesn't seem to accept a variable N, it instead yields an argument not sufficiently instantiated error. I've tried using this solution instead:

int_cset_(N,Acc,Acc) :- N #= 0.
int_cset_(N,Acc,Cs) :- N_1 #= N-1, int_cset_(N_1,[N|Acc],Cs).
int_cset(N,Cs) :- int_cset_(N,[],Cs).

% most general solver
regions_ncolors(L,N) :- colouring(L), int_cset(N,Cs), subset(L,Cs), label(L).

Where the arguments in int_cset(N,Cs) is a natural number(N) and the counting set Sn = {1,2,...,N}

But this solution is buggy as regions_ncolors(L,N). only returns the same(one) solution for all N, and when I try to add a constraint to N, it goes in an infinite loop.

So what can I do to make the most general query work both ways(for not-instantiated variables)?

Thanks in advance!

Btw, I added a swi-prolog tag in my last post although it was removed by moderation. I don't know if this question is specific to swi-prolog which is why I'm keeping the tag, just in case :)


Solution

  • Your colouring is too specific, you encode the topology of your map into it. Not a problem as is, but it defeats of the purpose of then having a "most general query" solution for just any list.

    If you want to avoid the problem of having a free variable instead of a list, you could first instantiate the list with length/2. Compare:

    ?- L ins 1..3.
    ERROR: Arguments are not sufficiently instantiated
    ERROR: In:
    ERROR:   [16] throw(error(instantiation_error,_86828))
    ERROR:   [10] clpfd:(_86858 ins 1..3) ...
    

    Is that the same problem as you see?

    If you first make a list and a corresponding set:

    ?- length(L, N), L ins 1..N.
    L = [],
    N = 0 ;
    L = [1],
    N = 1 ;
    L = [_A, _B],
    N = 2,
    _A in 1..2,
    _B in 1..2 ;
    L = [_A, _B, _C],
    N = 3,
    _A in 1..3,
    _B in 1..3,
    _C in 1..3 .
    
    

    If you use length/2 like this you will enumerate the possible lists and integer sets completely outside of the CLP(FD) labeling. You can then add more constraints on the variables on the list and if necessary, use labeling.

    Does that help you get any further with your problem? I am not sure how it helps for the colouring problem. You would need a different representation of the map topology so that you don't have to manually define it within a predicate like your colouring/1 you have in your question.