Search code examples
prologclpfd

Getting intervals with CLP


I would like to get the non-discontinued intervals of variable domains in a prolog environment.

For example, I have a variable X which is constrained to take some values in its domain. Let's say X has an initial domain [0..20] and it is constrained to (not) have 5, 8, 9 as values. So X has the new domain [0..4, 6, 7, 10..20]. I would like to get non-discontinued intervals in this domain as a list [[0..4], [6,7], [10..20]].

In SWI-Prolog, using clpfd library when I run the following goal:

X in 0..20, X #\= 5, X #\= 8, X #\= 9.

Answer is:

X in 0..4\/6..7\/10..20.

So far so good. But I don't know how I can get this domain as a list of intervals. Is there a way to do it?


Solutions with other Prolog implementations and their respective CLP/FD libraries are also welcome.


Solution

  • Using fd_dom/2, it is possible to get the domain of the variable. Then a DCG rule can be used to parse the domain which is in form of L1..U1\/L2..U2\/... .

    An example DCG rule for getting domain as a list of integers is given in SWI-Prolog manual (link). With a little modification it can be used to get the intervals:

    dom_intervals(Dom, Intervals) :- phrase(dom_intervals1(Dom), Intervals).
    
    dom_intervals1(I)           -->  {integer(I)}, [I].
    dom_intervals1(L..U)        --> [L..U].
    dom_intervals1(D1 \/ D2)    --> dom_intervals1(D1), dom_intervals1(D2).
    

    Finally this query can be used:

    X in 0..20, X #\= 5, X #\= 8, X #\= 9, fd_dom(X, D), dom_intervals(D, Intervals).


    Though clpfd is not mentioned in YAP-prolog manual, it is possible to do the same with YAP-prolog too.