Search code examples
prologclpfdconstraint-programming

Prolog Constraint Programing finding even and odd numbers


I need to create a predicate:

applyConstraints(L)

That applies constraints to the variables in L such that no two contiguous elements in L are both odd or even how can I do that? With a fixed size L it's simple but what about a variable size L? I need that to be done using sicstus-prolog clpfd library.


Solution

  • Inspired by @MatsCarlsson's version, I tried to minimize the number of constrained variables involved:

    applyConstraints(Xs) :-
       S #\= R,
       applyConstraints(Xs, S, R).
    
    applyConstraints([], _, _).
    applyConstraints([X|Xs], S, R) :-
       X mod 2 #= S,
       applyConstraints(Xs, R, S).
    

    Edit: This version has one flaw for the goal applyConstraints([]) which is not readily visible. In fact, one needs to switch to full_answer mode in SICStus like so:

    | ?- applyConstraints([]).
    yes
    | ?- assertz(clpfd:full_answer).
    yes
    | ?- applyConstraints([]).
    clpfd:(_A#\=_B),
    _A in inf..sup,
    _B in inf..sup ? ;
    no
    

    So we have this useless constraint hanging around which might eat up resources. To overcome this deficiency, some special casing is needed:

    applyConstraints([]).
    applyConstraints([X|Xs]) :-
       X mod 2 #= S,
       S #\= R,
       applyConstraints(Xs, R, S).
    

    Note 1 — in SWI or YAP there is no direct way to switch full answer mode on. The only way to get hold of the problem is to wrap the query around call_residue_vars/2 like so:

    ?- applyConstraints([]).
    true.
    
    ?- call_residue_vars(applyConstraints([]),RVs).
    RVs = [_G794, _G797],
    _G794#\=_G797.
    

    Note 2 — Thanks to @mat, there is similar functionality since SWI 7.3 (remember that SWI 7 needs --traditional for compatibility):

    ?- set_prolog_flag(toplevel_residue_vars, true).
    true.
    
    ?- applyConstraints([]).
    % with detached residual goals
    _G430#\=_G433.
    

    (It is not quite clear what "detached" should mean in this context, after all, the residual goals have to be true, to make the answer true. So there is no detachement involved.)