:- use_module( library(chr)). :- use_module( library(lists), [member/2, memberchk/2,select/3]). :- use_module( library(lists), [member/2,last/2,is_list/1,min_list/2, max_list/2, remove_duplicates/2]). handler domain. option(debug_compile,on). % for domain constraints operator( 700,xfx,'::'). operator( 600,xfx,':'). % for inequality constraints operator( 700,xfx,lt). operator( 700,xfx,le). operator( 700,xfx,ne). % X::Dom - X must be element of the finite domain Dom constraints (::)/2, le/2, lt/2, ne/2, add/3, mult/3. % special cases X::[] <=> fail. % intersection of domains for the same variable X::L1, X::L2 <=> is_list(L1), is_list(L2) | intersection(L1,L2,L) , X::L. X::L, X::Min:Max <=> is_list(L) | remove_lower(Min,L,L1), remove_higher(Max,L1,L2), X::L2. %interaction with inequalities X le Y, X::L1, Y::L2 ==> is_list(L1),is_list(L2), min_list(L1,MinX), min_list(L2,MinY), MinX > MinY | max_list(L2,MaxY), Y::MinX:MaxY. X le Y, X::L1, Y::L2 ==> is_list(L1),is_list(L2), max_list(L1,MaxX), max_list(L2,MaxY), MaxX > MaxY | min_list(L1,MinX), X::MinX:MaxY. %interaction with addition add(X,Y,Z), X::L1, Y::L2 ==> is_list(L1), is_list(L2) | all_addition(L1,L2,L3), Z::L3. %interaction with multiplication mult(X,Y,Z), X::L1, Y::L2 ==> is_list(L1), is_list(L2) | all_multiplication(L1,L2,L3), Z::L3. % Interval domain --------------------------------------------------------- % special cases failure @ X::A:B <=> A>B | fail. % intersection of domains for the same variable X::Min1:Max1 , X::Min2:Max2 <=> Min is max(Min1,Min2), Max is min(Max1,Max2), X::Min:Max. %interaction with inequalities X le Y, X::MinX:MaxX \ Y::MinY:MaxY <=> MinX > MinY | Y::MinX:MaxY. X le Y, Y::MinY:MaxY \ X::MinX:MaxX <=> MaxX > MaxY | X::MinX:MaxY. Y le X, X::MinX:MaxX <=> nonvar(Y), Y > MinX | X::Y:MaxX. X le Y, X::MinX:MaxX <=> nonvar(Y), Y < MaxX | X :: MinX:Y. %interaction with addition add(X,Y,Z), X::MinX:MaxX, Y::MinY:MaxY ==> MinZ is MinX+MinY, MaxZ is MaxX+MaxY, Z::MinZ:MaxZ. add(X,Y,Z), X::MinX:MaxX, Z::MinZ:MaxZ ==> MinY is MinZ-MaxX, MaxY is MaxZ-MinX, Y::MinY:MaxY. add(Y,X,Z), X::MinX:MaxX, Z::MinZ:MaxZ ==> MinY is MinZ-MaxX, MaxY is MaxZ-MinX, Y::MinY:MaxY. %interaction with multiplication mult_z @ mult(X,Y,Z), X::A:B, Y::C:D ==> M1 is A * C, M2 is A * D, M3 is B * C, M4 is B * D, min_list([M1,M2],MinM1M2), min_list([M3,M4],MinM3M4), min_list([MinM1M2,MinM3M4], M5), max_list([M1,M2],MaxM1M2), max_list([M3,M4],MaxM3M4), max_list([MaxM1M2,MaxM3M4],M6), Z::M5:M6. % INEQUALITIES =============================================================== % inequalities over numbers A le A <=> true. A le B,B le A <=> A=B. A le B <=> ground(A),ground(B) | A =< B. A lt A <=> fail. A lt B,B lt A <=> fail. A lt B <=> ground(A),ground(B) | A < B. A ne A <=> fail. A ne B \ B ne A <=> true. A ne B <=> ground(A),ground(B) | A =\= B. % remove*/3 auxiliary predicates ============================================= remove_lower(_,[],L1):- !, L1=[]. remove_lower(Min,[X|L],L1):- X@Max, !, remove_higher(Max,L,L1). remove_higher(Max,[X|L],[X|L1]):- remove_higher(Max,L,L1). intersection([], _, []). intersection([Head|L1tail], L2, L3) :- memberchk(Head, L2), !, L3 = [Head|L3tail], intersection(L1tail, L2, L3tail). intersection([_|L1tail], L2, L3) :- intersection(L1tail, L2, L3). all_addition(L1,L2,L3) :- setof(Z, X^Y^(member(X,L1), member(Y,L2), Z is X + Y), L3). all_multiplication(L1,L2,L3) :- setof(Z, X^Y^(member(X,L1), member(Y,L2), Z is X * Y), L3). % end of handler domain.chr ================================================= /* Examples | ?- X::[1,2,3,4,5,6,7], Y::[2,4,6,7,8,0], Y lt X, X::4:9. Y lt X, Y::[2,4,6,0], X::[4,5,6,7] ? | ?- X :: [4,6,7], Y :: [3,7], X le Y. X::[4,6,7], X le Y, Y::[7] ? | ?- X :: [2,3,4], Y :: [0,1], X le Y. no | ?- X :: [2,3,4,5], Y :: [1,2,3], X le Y. X le Y, Y::[2,3], X::[2,3] ? */ % ===========================================================================