infer_set_bounds(empty_set,set(integer),_,Bounds) :- !, Bounds = binterval(1,0,0).
infer_set_bounds(integer_set('NATURAL'),set(integer),_,Bounds) :- !, init_binterval(0,_,Bounds,1).
infer_set_bounds(integer_set('NATURAL1'),set(integer),_,Bounds) :- !, init_binterval(1,_,Bounds,1).
infer_set_bounds(value(AVL),set(Type),Env,Bounds) :- nonvar(AVL), AVL=avl_set(A), !,
infer_avl_set_bounds(Type,A,Env,Bounds).
infer_set_bounds(value(CS),set(integer),_Env,Bounds) :- nonvar(CS), is_interval_closure(CS,Low,Up),
number(Low), number(Up), !, init_binterval(Low,Up,Bounds,_).
infer_set_bounds(interval(A,B),_,Env,Bounds) :- !,
infer_scalar_bounds(A,Env,bint(BA)),
infer_scalar_bounds(B,Env,bint(BB)),
init_binterval(BA,BB,Bounds,_).
infer_set_bounds(intersection(A,B),_,Env,Bounds) :- !,
infer_set_bounds(A,Env,BoundsA),
infer_set_bounds(B,Env,BoundsB), % TODO: treat if one of the two calls fails
intersect_bounds(BoundsA,BoundsB,Bounds).
infer_set_bounds(union(A,B),_,Env,Bounds) :- !,
infer_set_bounds(A,Env,BoundsA),
infer_set_bounds(B,Env,BoundsB),
union_bounds(BoundsA,BoundsB,Bounds).
infer_set_bounds(set_extension(List),_,Env,Bounds) :- !,
(List = [A], infer_scalar_bounds(A,Env,bint(BA))
-> Bounds = binterval(BA,BA,1)
; maplist(infer_set_ext_el(Env,Bounds),List)
% TODO: use union code instead? we loose info that these are all the elements of the set
).
infer_set_bounds(identifier(A),Type,Env,Bounds) :- !,
lookup_id_bounds(A,Env,Type,Bounds).
infer_set_bounds(cartesian_product(A,B),_,Env,Bounds) :- !,
infer_set_bounds(A,Env,BoundsA),
infer_set_bounds(B,Env,BoundsB),
construct_bcart(A,B,BoundsA,BoundsB,Bounds).
infer_set_bounds(domain(A),_,Env,DomBounds) :- !,
infer_set_bounds(A,Env,bcart(DomBounds,_,NE)),
imply_non_empty(DomBounds,NE). % if domain is non-empty, then full relation must be non-empty
infer_set_bounds(range(A),_,Env,RanBounds) :- !,
infer_set_bounds(A,Env,bcart(_,RanBounds,NE)),
imply_non_empty(RanBounds,NE). % if range is non-empty, then full relation must be non-empty
infer_set_bounds(image(Rel,_Set),Type,Env,RanBounds) :- !,
infer_set_bounds(range(Rel),Type,Env,RanBounds). % we ignore Set
infer_set_bounds(reverse(Rel),_Type,Env,IBounds) :- !, % relational inverse
infer_set_bounds(Rel,Env,Bounds),
Bounds = bcart(BA,BB,NonEmptyAB),
IBounds = bcart(BB,BA,NonEmptyAB).
infer_set_bounds(closure(Rel),_Type,Env,Bounds) :- !, % transitive closure1
infer_set_bounds(Rel,Env,Bounds),
Bounds = bcart(_,_,_). % dom(closure1(r)) <: dom(r), ditto for ran
infer_set_bounds(iteration(Rel,_),_Type,Env,Bounds) :- !, % iterate operator
infer_set_bounds(Rel,Env,Bounds),
Bounds = bcart(_,_,_). % dom(iterate(r,n)) <: dom(r), for n>0, ditto for ran;
infer_set_bounds(S,_,_,_) :- functor(S,F,N), write(user_output,uncovered_set(F,N,S)), nl(user_output),fail.