Search code examples
prologclpfd

Prolog constraint logic programming - How to set a domain on a List of Domain Variables given a List of Integers?


Basically what I want to achieve is :

Given a list of domain Variables set these Variables with a domain relative to a List of Numbers. Example:

......

List=[A1,A2,A3],
domain(List,1,5],
setDomain(List,[1,2]),
labeling([],List). 

Result:

A1=1, A2=1, A3=1 or
A1=1, A2=1, A3=2 or
A1=1, A2=2, A3=1

and so on...

What I have tried:

setDomain(List,ListIntegers):-
  element(X, List, Element),
  member(Element,ListIntegers),

main(List):-
  List=[A1,A2,A3],
  domain(List,1,5],
  setDomain(List,[1,2]),
  labeling([],List). 

but not success...

Can anyone help understand how can I accomplish this?


Solution

  • In your solution, you're using labeling/2 but haven't defined its arguments using CLP(FD), so it doesn't do anything for you. It's not very clear from your question or simple example, but it sounds like you want a list of a given length whose elements are each taken from a domain consisting of an arbitrary list of elements?

    You could do so with something like this:

    member_(List, Element) :- member(Element, List).
    
    domain_list(Length, Domain, List) :-
        length(List, Length),
        maplist(member_(Domain), List).
    

    This would give:

    6 ?- domain_list(3, [1,3], L).
    L = [1, 1, 1] ;
    L = [1, 1, 3] ;
    L = [1, 3, 1] ;
    L = [1, 3, 3] ;
    L = [3, 1, 1] ;
    L = [3, 1, 3] ;
    L = [3, 3, 1] ;
    L = [3, 3, 3].
    
    7 ?-
    

    This also works for any kind of elements:

    7 ?- domain_list(3, [tom, a(b)], L).
    L = [tom, tom, tom] ;
    L = [tom, tom, a(b)] ;
    L = [tom, a(b), tom] ;
    L = [tom, a(b), a(b)] ;
    L = [a(b), tom, tom] ;
    L = [a(b), tom, a(b)] ;
    L = [a(b), a(b), tom] ;
    L = [a(b), a(b), a(b)].
    
    8 ?-
    

    If you wanted to use CLP(FD), you'd need to keep a couple of things in mind. CLP(FD) is for integer domains, and CLP(FD) has its own way of specifying domains, which is not in list form.

    For instance, if you wanted a list of length N whose elements were in the domain described by [1,2,3,5,6,8], you would write it as:

    length(List, N),
    List ins 1..3 \/ 5..6 \/ 8,
    label(List).
    

    Which would result in, for example:

    2 ?- length(List, 3), List ins 1..3 \/ 5..6 \/ 8, label(List).
    List = [1, 1, 1] ;
    List = [1, 1, 2] ;
    List = [1, 1, 3] ;
    List = [1, 1, 5] ;
    List = [1, 1, 6] ;
    List = [1, 1, 8] ;
    List = [1, 2, 1] ;
    List = [1, 2, 2]
    ...