Search code examples
prologclpfd

ECLiPSe Prolog - IC library: Lists of integers as variables


In the ic library, one can create a variable with a domain like so:

X #:: [1..10] % Variable X with domain the integers from  1 to 10.

It is also possible to create 2 variables with the same domain like so:

[X,Y] #:: [1..10]

How can I create 2 variables that have as a domain a list of integers?

More specifically, if I have a set of integers S, how can I make two variables that each has a subset (P1, P2) of S as to ensure that P1 and P2 have no common elements and that P1 + P2 = S?


Solution

  • You can use lib(ic_sets) in this way:

    :- lib(ic).
    :- lib(ic_sets).
    
    test(X,Y):-
        LT = [1,2,3,4,5,6,7],
    
        LA in_set_range []..LT,
        LB in_set_range []..LT,
    
        length(LT,N),
    
        #(LA /\ LB,0),
        #(LA \/ LB,N),
    
        insetdomain(LA,_,_,_),
        insetdomain(LB,_,_,_),
    
        X #:: LA,
        Y #:: LB.
    

    LT is the list with the integer you want (it doesn't have to be a list of consecutive integers). in_set_range sets the domain of the two lists. Then #(LA /\ LB,0) constraints the interseption between the two sets to be empty (no common elements) and #(LA \/ LB,N) constraints the union of the two sets to have the length N of the starting list (i.e. number of element in the domain of LA + number of element in the domain of LB must be N). insetdomain/4 instantiates the set and X #:: LA sets the domain of X.

    ?- test(X, Y).
    X = X{1 .. 6}
    Y = 7
    Yes (0.00s cpu, solution 1, maybe more)
    X = X{[1 .. 5, 7]}
    Y = 6
    Yes (0.00s cpu, solution 2, maybe more)
    X = X{1 .. 5}
    Y = Y{[6, 7]}
    Yes (0.00s cpu, solution 3, maybe more)
    and so on...