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(integer),_Env,Bounds) :- nonvar(AVL), AVL=avl_set(A), !,
avl_min(A,int(Min)), %min_of_explicit_set_wf(Val,int(Min),no_wf_available),
avl_max(A,int(Max)), Bounds = binterval(Min,Max,1).
infer_set_bounds(value(AVL),set(string),_Env,Bounds) :- nonvar(AVL), AVL=avl_set(A), !,
findall(Nr,(avl_member(string(S),A), get_string_nr(S,Nr)),Nrs),
min_member(Min,Nrs), max_member(Max,Nrs), Bounds = binterval(Min,Max,1).
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