Search code examples
prolograngeconstraint-programmingclpfd

Prolog: Constraining the elements of a list to be within a range


Are there any ways to constrain the elements of a list to be within a range, something that would look more like 1-6, instead of using between(1, 6, X)?


Solution

  • The clpfd library, has an ins/2 predicate, where you can specify - for a list of variables - the range of the elements.

    Like:

    all_between(Low, High, Vars) :-
        Vars ins Low..High.
    

    When calling all_between(1,6,[X1,X2,X3]). we get:

    X1 in 1..6,
    X2 in 1..6,
    X3 in 1..6.
    

    In case we want to enumerate over the elements, we can use label(L). as well, to assign values:

    all_between_enumerate(Low, High, Vars) :-
        Vars ins Low..High,
        label(Vars).
    

    For all_between_enumerate(1,2,[X1,X2,X3]). this generates:

    ?- all_between_enumerate(1,2,[X1,X2,X3]).
    X1 = X2, X2 = X3, X3 = 1 ;
    X1 = X2, X2 = 1,
    X3 = 2 ;
    X1 = X3, X3 = 1,
    X2 = 2 ;
    X1 = 1,
    X2 = X3, X3 = 2 ;
    X1 = 2,
    X2 = X3, X3 = 1 ;
    X1 = X3, X3 = 2,
    X2 = 1 ;
    X1 = X2, X2 = 2,
    X3 = 1 ;
    X1 = X2, X2 = X3, X3 = 2.
    

    In case you already added constraints to the variables, like X1 #< X3, these are taken into account as well:

    ?- X1 #< X3, all_between_enumerate(1,2,[X1,X2,X3]).
    X1 = X2, X2 = 1,
    X3 = 2 ;
    X1 = 1,
    X3 = X2, X2 = 2.