Back to the early proposal for a “declaration” of disjoint intervals, consider a predicate disjoint_union/3
which takes some variable A
, the subdomains definition Type(Subs)
(Subs
is a sequence of sub-ranges), and a sub-domain selector variable As
. If it succeeds, the effect of disjoint_union
is to apply all the necessary mutual constraints. Example:
?- disjoint_union(X,real((1,3),(8,10)),SX).
SX::integer(1, 2),
X::real(1, 10).
To support labelling, the selector can be used to enumerate the sub-domains. Or if X
is narrowed, SX
will narrow accordingly, which may constrain other dependant values (cost, speed, …):
?- disjoint_union(X,real((1,3),(8,10)),SX), enumerate(SX).
SX = 1,
X::real(1, 3) ;
SX = 2,
X::real(8, 10).
?- disjoint_union(X,real((1,3),(8,10)),SX), {X>=5}.
SX = 2,
X::real(8, 10).
Note these are all just constraints, not declarations that impose an execution order so:
?- {X>=5}, disjoint_union(X,real((1,3),(8,10)),SX).
SX = 2,
X::real(8, 10).
Subdomain selectors can be used to enforce mutual constraints:
?- disjoint_union(X,real((1,3),(8,10)),SX), disjoint_union(Y,real((1,3),(8,10)),SY), {SX<>SY}, enumerate([SX,SY]).
SX = 1,
SY = 2,
X::real(1, 3),
Y::real(8, 10) ;
SX = 2,
SY = 1,
X::real(8, 10),
Y::real(1, 3).
The implementation of disjoint_union/3
is pretty simple (uses “,
” as synonym for “and
” - will be available in v0.9.9):
disjoint_union(A,Doms,As) :-
Doms=..[Type|Subs],
dj_constraints(Subs,A,As, 1,Len, 1.0Inf,-1.0Inf,Min,Max, Cs),
As::integer(1,Len),
Dom=..[Type,Min,Max], A::Dom,
{Cs}.
dj_constraints([R],A,As, N,N, MinIn,MaxIn, Min,Max, C) :- % last in `or`
dj_constraint(R,A,As, N, MinIn,MaxIn, Min,Max, C),
!.
dj_constraints([R|Subs],A,As, N,Len, MinIn,MaxIn, Min,Max, C or Cs) :- % `or` sequence
dj_constraint(R,A,As, N, MinIn,MaxIn, NxtMin,NxtMax, C),
!,
NxtN is N+1,
dj_constraints(Subs,A,As, NxtN,Len, NxtMin,NxtMax, Min,Max, Cs).
dj_constraints([L,H],A,As, N,N, MinIn,MaxIn, Min,Max, C) :- % in case of naked bounds
dj_constraint((L,H),A,As, N, MinIn,MaxIn, Min,Max, C).
dj_constraint((L,H),A,As, N, MinIn,MaxIn, Min,Max, (As==N, L=<A,A=<H)) :-
Min is min(MinIn,L), Max is max(MaxIn,H).
This is an interesting application of mixed mode constraints that should be added to the clpBNR User Guide, but I’d like to find a simple concrete problem example, e.g., in a text book or academic paper. Any suggestions welcome.