1 % (c) 2009-2022 Lehrstuhl fuer Softwaretechnik und Programmiersprachen,
2 % Heinrich Heine Universitaet Duesseldorf
3 % This software is licenced under EPL 1.0 (http://www.eclipse.org/org/documents/epl-v10.html
4
5 :- module(ast_cleanup_for_smt, [smt_clean_up/2,
6 smt_clean_up/3,
7 smt_clean_up/4,
8 smt_clean_up_opts/4,
9 smt_clean_up_pre/4,
10 smt_clean_up_post/4]).
11
12 :- use_module(library(lists),[maplist/3,
13 append/2,
14 is_list/1]).
15 :- use_module(library(avl), [avl_to_list/2]).
16 :- use_module(probsrc(bsyntaxtree),[is_texpr/1,
17 add_texpr_infos/3,
18 remove_bt/4,
19 safe_create_texpr/4,
20 create_texpr/4,
21 get_texpr_expr/2,
22 get_texpr_type/2,
23 create_negation/2,
24 conjunct_predicates/2,
25 disjunct_predicates/2,
26 create_forall/3,
27 create_exists/3,
28 create_implication/3,
29 conjunction_to_list/2,
30 %create_couple/2,
31 syntaxtransformation/5,
32 unique_typed_id/3,
33 find_typed_identifier_uses/3,
34 %always_well_defined_or_disprover_mode/1,
35 is_pow_subset/2, is_pow1_subset/2,
36 %get_integer/2,
37 is_just_type/1]).
38 :- use_module(probsrc(solver_interface),[solve_predicate/3]).
39 :- use_module(probsrc(custom_explicit_sets),[is_interval_closure/3]).
40 :- use_module(probsrc(b_interpreter_components),[extract_equalities_in_quantifier/4]).
41 :- use_module(probsrc(error_manager), [add_internal_error/2,add_error_fail/3,add_message/2,add_message/3]).
42 :- use_module(probsrc(debug), [debug_println/2]).
43 :- use_module(probsrc(bsyntaxtree), [find_identifier_uses/3,find_typed_identifier_uses/2]).
44 :- use_module(probsrc(b_global_sets), [unfixed_deferred_set/1]).
45 :- use_module(probsrc(b_compiler), [b_compile/6]).
46 :- use_module(probsrc(preferences), [get_preference/2,temporary_set_preference/2,reset_temporary_preference/1]).
47 :- use_module(probsrc(store),[normalise_value_for_var/4]).
48 :- use_module(smt_solvers_interface(quantifier_instantiation)).
49 :- use_module(smt_solvers_interface(smt_common_predicates)).
50 :- use_module(smt_solvers_interface(ast_optimizer_for_smt)).
51 :- use_module(smt_solvers_interface(seq_rewriter)).
52 :- use_module(smt_solvers_interface(set_rewriter)).
53 :- use_module(cdclt_solver('cdclt_pred_to_sat'), [predicate_to_sat/6,add_wd_pos_to_pred/8]).
54 %:- use_module(probsrc('well_def/well_def_analyser'), [analyse_wd_for_expr/3]).
55 :- use_module(probsrc('debug'), [set_silent_mode/1]).
56
57 :- use_module(probsrc(module_information),[module_info/2]).
58 :- module_info(group,smt_solvers).
59 :- module_info(description,'This module implements transformations needed by the SMT-LIB translation.').
60
61 :- set_prolog_flag(double_quotes, codes).
62
63 :- dynamic translation_type/1.
64
65 %% smt_clean_up(+Ast, -Out).
66 smt_clean_up(Ast, Out) :-
67 smt_clean_up(axiomatic, Ast, Out).
68
69 %% smt_clean_up_opts(+TranslationType, +Ast, +Options, -Out).
70 % Cleanup without global state using Options instantiate_quantifier_limit(L).
71 smt_clean_up_opts(TranslationType, Ast, Options, Out) :-
72 smt_clean_up_pre(Ast, [], Options, CAst),
73 smt_clean_up_post(TranslationType, CAst, Options, Out).
74
75 %% smt_clean_up(+TranslationType, +Ast, -Out).
76 % Cleanup without global state.
77 smt_clean_up(TranslationType, Ast, Out) :-
78 smt_clean_up_pre(Ast, [], [], CAst),
79 smt_clean_up_post(TranslationType, CAst, [], Out).
80
81 %% smt_clean_up(+TranslationType, +Ast, +ProBState, -Out).
82 % Cleanup with global state.
83 smt_clean_up(TranslationType, Ast, ProBState, Out) :-
84 smt_clean_up_pre(Ast, ProBState, [], CAst),
85 smt_clean_up_post(TranslationType, CAst, [], Out).
86
87 get_ids_not_in_state([], _, Acc, Acc).
88 get_ids_not_in_state([IdName|T], State, Acc, IdsNotInState) :-
89 ( (
90 member(bind(IdName,_), State),
91 \+ unfixed_deferred_set(IdName)
92 )
93 -> get_ids_not_in_state(T, State, Acc, IdsNotInState)
94 ; get_ids_not_in_state(T, State, [IdName|Acc], IdsNotInState)
95 ).
96
97 %% smt_clean_up_pre(+Ast, +ProBState, +Options, -CleanAst).
98 % Cleanup without internal rewriting rules and independent of any translation type.
99 % WD conditions are added if the input is not well-defined.
100 smt_clean_up_pre(Ast, ProBState, _Options, CleanAst) :-
101 reset_optimizer_state,
102 ( get_preference(add_wd_pos_for_z3, true)
103 -> true
104 % this prints missing wd conditions
105 %set_silent_mode(on),
106 %analyse_wd_for_expr(Ast, _ResStr, IsWd),
107 %set_silent_mode(off)
108 ; IsWd = 'TRUE'
109 ),
110 rewrite_seq_to_set(IsWd, Ast, AstWithoutSeq),
111 ( IsWd == 'TRUE'
112 -> WDPred = AstWithoutSeq
113 ; add_wd_pos_to_pred(AstWithoutSeq, [], [], true, true, _, WDPred, TopLevelWdPred),
114 ( (
115 ground(TopLevelWdPred),
116 conjunction_to_list(TopLevelWdPred, TopLevelWDPOs),
117 member(b(falsity,_,_), TopLevelWDPOs)
118 )
119 -> add_error_fail(smt_clean_up_pre, 'Input is not well-defined and contradictory', [])
120 ; AstWithoutSeq \== WDPred
121 -> add_message(smt_clean_up_pre, 'Input not well-defined: automatically added WD POs')
122 ; true
123 )
124 ),
125 find_typed_identifier_uses(WDPred, TypedIds),
126 assert_state_id_values(TypedIds, ProBState),
127 assert_ground_id_values(0, WDPred),
128 replace_ids_with_ground_values(WDPred, 0, [], AstGroundOpt),
129 precompute_values_non_recursive([instantiate_quantifier_limit(0),instantiate_sets_limit(1000)], AstGroundOpt, AstGroundOpt2),
130 find_identifier_uses(AstGroundOpt2, [], UsedIds),
131 get_ids_not_in_state(UsedIds, ProBState, [], IdsNotInState),
132 temporary_set_preference(data_validation_mode, true),
133 catch(b_compile(AstGroundOpt2, IdsNotInState, ProBState, ProBState, AstOpt, no_wf_available),
134 enumeration_warning(_,_,_,_,_), % cancel if enumeration warning has occurred
135 AstOpt = AstGroundOpt2),
136 reset_temporary_preference(data_validation_mode),
137 temporary_set_preference(allow_improving_wd_mode, true),
138 b_ast_cleanup:clean_up(AstOpt, [], TCleanAst), !,
139 reset_temporary_preference(allow_improving_wd_mode),
140 CleanAst = TCleanAst.
141
142 %% smt_clean_up_post(+TranslationType, +CleanAst, +Options, -Out).
143 % Cleanup with translation type specific internal rewriting rules.
144 smt_clean_up_post(TranslationType, CleanAst, Options, Out) :-
145 atom(TranslationType),
146 retractall(translation_type(_)),
147 asserta(translation_type(TranslationType)),
148 internal_clean_up(CleanAst, TOut),
149 reset_optimizer_state, !,
150 ( ( memberchk(instantiate_quantifier_limit(IQLIMIT), Options),
151 IQLIMIT > 0
152 )
153 -> instantiate_quantifiers([instantiate_quantifier_limit(IQLIMIT),not_instantiate_unfixed_deferred_sets], TOut, Out)
154 ; Out = TOut
155 ).
156
157 internal_clean_up(ExprWithoutSeq,Out) :-
158 clean_up(ExprWithoutSeq,CExpr,[],AC,IDs),
159 !,
160 combine_pred_and_ac(CExpr,AC,IDs,Out).
161
162 clean_up(Expr,CExprOut,Path,ACOut,IDsOut) :-
163 cleanups(pre,Expr,[],TPExpr,Path,ACPre,IDsPre),
164 remove_bt(TPExpr,PExpr,LExpr,TLExpr),
165 syntaxtransformation(PExpr,Subs,_,NewSubs,LExpr),
166 functor(PExpr,F,N),
167 % recursively clean up sub-expressions
168 maplist(internal_clean_up,ACPre,ACPreClean),
169 clean_up_l(Subs,NewSubs,F/N,1,Path,ACL,IDsL),
170 maplist(internal_clean_up,ACL,ACLClean),
171 cleanups(post,TLExpr,[],CExpr,Path,ACPost,IDsPost),
172 maplist(internal_clean_up,ACPost,ACPostClean),
173 append([ACPreClean,ACLClean,ACPostClean],AC),
174 append([IDsPre,IDsL,IDsPost],IDs),
175 (AC \= [], get_texpr_type(CExpr,pred)
176 -> combine_pred_and_ac(CExpr,AC,IDs,CExprOut),
177 % the accumulator contains additional constraints and new existentially quantified vars IDs
178 IDsOut = [], ACOut = []
179 ; CExprOut = CExpr, ACOut = AC, IDsOut = IDs).
180
181 combine_pred_and_ac(Pred,AC,IDs,Out) :-
182 conjunct_predicates(AC,ACPred),
183 conjunct_predicates([Pred,ACPred],OutInnerPred),
184 extract_equalities_in_quantifier(IDs,OutInnerPred,I2,P2), % used in create_and_simplify_exists; can be expensive
185 create_exists(I2,P2,Out). % TO DO: use more intelligence from create_exists_opt or similar??
186
187 clean_up_l([],[],_Functor,_Nr,_Path,[],[]).
188 clean_up_l([Expr|Rest],[CExpr|CRest],Functor,ArgNr,Path,AC,IDs) :-
189 clean_up(Expr,CExpr,[arg(Functor,ArgNr)|Path],ACC,IDsC),
190 A1 is ArgNr+1,
191 clean_up_l(Rest,CRest,Functor,A1,Path,ACL,IDsL),
192 append(ACC,ACL,AC),
193 append(IDsC,IDsL,IDs).
194
195 cleanups(Phase,Expr,AppliedRules,Result,Path,ACS,IDs) :-
196 start_profile_rule(RuleInfos),
197 assure_single_rules(AppliedRules,Rule),
198 ( cleanup_phase(Phase,Expr,NExpr,Mode/Rule,Path,ACPhase,IDsPhase)
199 -> % try to apply a rule (matching the current phase)
200 ( Mode == single
201 -> AppRules = [Rule|AppliedRules] % if the rule is marked as "single", we add to the list of already applied rules
202 ; Mode == multi
203 -> AppRules = AppliedRules % if "multi", we do not add it to the list, the rule might be applied more than once
204 ; add_error_fail(ast_cleanup_for_smt,'Unexpected rule mode ',Mode)
205 ),
206 %format('Applied smt cleanup rule ~w (mode:~w)~n',[Rule,Mode]), translate:print_bexpr(NExpr),nl,
207 stop_profile_rule(Rule,Mode,Phase,Expr,RuleInfos),
208 cleanups(Phase,NExpr,AppRules,Result,Path,ACRec,IDsRec), % continue recursively with the new expression
209 append(ACPhase,ACRec,ACS),
210 append(IDsPhase,IDsRec,IDs)
211 ; % if no rule matches anymore,
212 stop_profile_rule(finalise,finished,Phase,Expr,RuleInfos),
213 Result = Expr, % we leave the expression unmodified
214 ACS = [], IDs = [],
215 Rule = none
216 ). % and unblock the co-routine (see assure_single_rules/2)
217
218 :- if(fail). % comment in to see expensive cleanup rules
219 start_profile_rule([R1,W1]) :- statistics(runtime,[R1,_]),statistics(walltime,[W1,_]).
220 stop_profile_rule(Rule,Mode,Phase,Expr,[R1,W1]) :-
221 statistics(runtime,[R2,_]),statistics(walltime,[W2,_]),
222 DeltaW is W2-W1, DeltaR is R2-R1,
223 (DeltaW < 20 -> true ; format('Firing SMT AST cleanup rule ~w (mode:~w) in phase ~w took ~w ms (~w ms walltime)~n',[Rule,Mode,Phase,DeltaR,DeltaW]), translate:print_span(Expr),nl),
224 runtime_profiler:register_profiler_runtime(Rule,unknown,DeltaR,DeltaW).
225 :- else.
226 start_profile_rule(_).
227 stop_profile_rule(_,_,_,_,_).
228 :- endif.
229
230
231 assure_single_rules([],_Rule) :- !.
232 assure_single_rules(AppliedRules,Rule) :-
233 assure_single_rules2(AppliedRules,Rule).
234 :- block assure_single_rules2(?,-).
235 assure_single_rules2(_AppliedRules,none) :- !.
236 assure_single_rules2(AppliedRules,Rule) :-
237 \+ member(Rule, AppliedRules).
238
239 cleanup_phase(Phase,OTExpr,NTExpr,Mode/Rule,Path,AC,IDs) :-
240 create_texpr(OExpr,OType,OInfo,OTExpr),
241 create_texpr(NExpr,NType,NInfo,NTExpr),
242 cleanup_phase2(Phase,OExpr,OType,OInfo,NExpr,NType,NInfo,Mode/Rule,Path,AC,IDs).
243 cleanup_phase2(pre,OExpr,OType,OInfo,NExpr,NType,NInfo,Mode/Rule,_Path,AC,IDs) :-
244 cleanup_pre(OExpr,OType,OInfo,NExpr,NType,NInfo,Mode_Rule,AC,IDs),
245 (functor(Mode_Rule,'/',2) -> Mode_Rule = Mode/Rule
246 ; add_internal_error('Illegal cleanup_pre rule, missing mode: ',Mode_Rule),fail).
247 cleanup_phase2(post,OExpr,OType,OInfo,NExpr,NType,NInfo,Mode/Rule,Path,AC,IDs) :-
248 cleanup_post_with_path(OExpr,OType,OInfo,NExpr,NType,NInfo,Mode_Rule,Path,AC,IDs),
249 (functor(Mode_Rule,'/',2)
250 -> Mode_Rule = Mode/Rule %,format(' cleanup_post Rule: ~w/~w~n',[Mode,Rule])
251 ; add_internal_error('Illegal cleanup_post rule, missing mode: ',Mode_Rule),fail).
252
253 replace_prob_closure_record_field(field(FName,Val), NField) :-
254 Val = closure(['_zzzz_unary'],[InnerType],_),
255 replace_prob_closure(Val, NVal),
256 !,
257 NField = field(FName,b(NVal,set(InnerType),[])).
258
259 replace_prob_closure(closure(['_zzzz_unary'],_,P), NExpr) :-
260 P = b(member(b(identifier('_zzzz_unary'),_,_),ClosurePred),pred,_),
261 find_typed_identifier_uses(ClosurePred, [], UsedIds),
262 UsedIds == [],
263 !,
264 get_texpr_expr(ClosurePred, NExpr).
265 replace_prob_closure(closure(['_zzzz_unary'],T,P), value(ComputedVal)) :-
266 normalise_value_for_var(solver_result, force, closure(['_zzzz_unary'],T,P), ComputedVal),
267 ComputedVal \== closure(['_zzzz_unary'],T,P).
268
269 % enforce well-definedness of division
270 cleanup_pre(div(A,B),integer,I,div(A,B),integer,[smt_wd_added|I],multi/div_wd,[AC],[]) :-
271 \+ member(smt_wd_added,I), !,
272 create_texpr(not_equal(B,b(integer(0),integer,[])),pred,[],AC).
273 % replace not_equal(..) by not(equal(..))
274 % and not_member(..) by not(member(..))
275 % and not_subset_strict(..) by not(subset_strict(..))
276 % and not_subset(..) by subset(..)
277 cleanup_pre(value(closure(['_zzzz_unary'],T,P)),Type,I,Expr,Type,I,multi/rewrite_prob_closure,[],[]) :-
278 replace_prob_closure(closure(['_zzzz_unary'],T,P), Expr).
279 cleanup_pre(union(A,B),Type,_,reflexive_closure(Rel),Type,I,multi/replace_not_equal,[],[]) :-
280 A = b(event_b_identity,_,_),
281 B = b(closure(Rel),Type,I).
282 cleanup_pre(not_equal(A,B),pred,I,negation(Equal),pred,[],multi/replace_not_equal,[],[]) :-
283 create_texpr(equal(A,B),pred,I,Equal).
284 cleanup_pre(not_member(A,B),pred,I,negation(Member),pred,[],multi/replace_not_member,[],[]) :-
285 create_texpr(member(A,B),pred,I,Member).
286 cleanup_pre(not_subset_strict(A,B),pred,I,negation(Subset),pred,[],multi/replace_not_subset_strict,[],[]) :-
287 create_texpr(subset_strict(A,B),pred,I,Subset).
288 cleanup_pre(greater(Card,Integer0),pred,I,Res,pred,I,multi/replace_card_0_with_neq_empty,[],[]) :-
289 % card(S) > 0 --> S /= {}
290 Card = b(card(Set),integer,_),
291 (Integer0 = b(integer(0),integer,_); Integer0 = b(value(int(0)),integer,_)),
292 !,
293 get_texpr_type(Set, SetType),
294 Res = not_equal(Set,b(empty_set,SetType,[])).
295 cleanup_pre(less(Integer0,Card),pred,I,Res,pred,I,multi/replace_card_0_with_neq_empty,[],[]) :-
296 % 0 < card(S) --> S /= {}
297 Card = b(card(Set),integer,_),
298 (Integer0 = b(integer(0),integer,_); Integer0 = b(value(int(0)),integer,_)),
299 !,
300 get_texpr_type(Set, SetType),
301 Res = not_equal(Set,b(empty_set,SetType,[])).
302 cleanup_pre(not_equal(Card,Integer0),pred,I,Res,pred,I,multi/replace_card_0_with_neq_empty,[],[]) :-
303 % card(S) /= 0 --> S /= {}
304 Card = b(card(Set),integer,_),
305 (Integer0 = b(integer(0),integer,_); Integer0 = b(value(int(0)),integer,_)),
306 !,
307 get_texpr_type(Set, SetType),
308 Res = not_equal(Set,b(empty_set,SetType,[])).
309 cleanup_pre(not_equal(Integer0,Card),pred,I,Res,pred,I,multi/replace_card_0_with_neq_empty,[],[]) :-
310 % 0 /= card(S) --> S /= {}
311 Card = b(card(Set),integer,_),
312 (Integer0 = b(integer(0),integer,_); Integer0 = b(value(int(0)),integer,_)),
313 !,
314 get_texpr_type(Set, SetType),
315 Res = not_equal(Set,b(empty_set,SetType,[])).
316 cleanup_pre(equal(Card,Integer0),pred,I,Res,pred,I,multi/replace_card_0_with_eq_empty,[],[]) :-
317 % card(S) = 0 --> S = {}
318 Card = b(card(Set),integer,_),
319 (Integer0 = b(integer(0),integer,_); Integer0 = b(value(int(0)),integer,_)),
320 !,
321 get_texpr_type(Set, SetType),
322 Res = equal(Set,b(empty_set,SetType,[])).
323 cleanup_pre(equal(Integer0,Card),pred,I,Res,pred,I,multi/replace_card_0_with_eq_empty,[],[]) :-
324 % 0 = card(S) --> S = {}
325 Card = b(card(Set),integer,_),
326 (Integer0 = b(integer(0),integer,_); Integer0 = b(value(int(0)),integer,_)),
327 !,
328 get_texpr_type(Set, SetType),
329 Res = equal(Set,b(empty_set,SetType,[])).
330 cleanup_pre(FiniteCardConstraint,pred,I,Res,pred,I,multi/RuleDescr,[],[]) :-
331 rewrite_finite_card(FiniteCardConstraint, Res, RuleDescr).
332 cleanup_pre(member(A,B),pred,I,Out,pred,I,multi/replace_member_interval,[],[]) :-
333 is_interval(B,Low,Up),
334 !, % A:Low..Up <==> A>=Low & A<=Up % important for e.g. :z3-cns mxint = 500 & goal : -mxint ..mxint
335 Out = conjunct(b(greater_equal(A,Low),pred,[]),b(greater_equal(Up,A),pred,[])).
336 cleanup_pre(member(A,B),pred,I,Out,pred,I,multi/replace_member_pow1_or_fin1,[],[]) :-
337 is_pow1_subset(B,Set),
338 get_texpr_type(Set, SetType),
339 !, % A:POW1(Set) <==> A <: Set & A /= {}
340 Out = conjunct(b(subset(A,Set),pred,[]),b(not_equal(A,b(set_extension([]),SetType,[])),pred,[])).
341 cleanup_pre(member(A,B),pred,I,Out,pred,I,multi/replace_member_pow_or_fin,[],[]) :-
342 is_pow_subset(B,Set),
343 !, % A:POW(Set) <==> A <: Set
344 % A/:POW(Set) <==> A /<: Set ; does not really seem to be necessary as negation rewritten before
345 Out = subset(A,Set).
346 cleanup_pre(member(A,B),pred,I,Disj,pred,I,multi/replace_finite_member_by_disj,[],[]) :-
347 % rewrite finite set membership to disjunction of equalities
348 B = b(value(avl_set(AvlSet)),set(InnerType),_),
349 !,
350 avl_to_list(AvlSet, EnumValueList),
351 findall(Equality, (member(EnumValue-_, EnumValueList), Equality = b(equal(A,b(value(EnumValue),InnerType,[])),pred,[])), Equalities),
352 disjunct_predicates(Equalities, DisjAst),
353 DisjAst = b(Disj,_,_).
354 cleanup_pre(not_subset(A,B),pred,I,negation(Subset),pred,[],multi/replace_not_subset,[],[]) :-
355 create_texpr(subset(A,B),pred,I,Subset).
356 % replace subset_strict by subset and not_equal
357 cleanup_pre(subset_strict(A,B),pred,I,conjunct(NotEqual,Subset),pred,[],multi/replace_not_member,[],[]) :-
358 create_texpr(subset(A,B),pred,I,Subset),
359 create_texpr(not_equal(A,B),pred,I,NotEqual).
360 cleanup_pre(equal(R,S),pred,I,POut,pred,I,multi/replace_struct_equality,[],[]) :-
361 % e.g., rewrite Dom = struct(f1:{1,2},f2:{1,2}) to Dom = {rec(f1:1,f2:1),rec(f1:1,f2:2),rec(f1:2,f2:1),rec(f1:2,f2:2)}
362 S = b(value(closure(['_zzzz_unary'],[record(_)],_)),_,_),
363 get_texpr_expr(R, identifier(IdName)),
364 get_texpr_type(R, set(record(FieldTypes))),
365 solver_interface:solve_predicate(b(equal(R,S),pred,I), Bindings, _),
366 member(bind(IdName,Set), Bindings),
367 % only for finite records
368 Set \= closure(_,_,_),
369 !,
370 POut = equal(R,b(value(Set),set(record(FieldTypes)),[])).
371 % replace membership in struct by equalities to avoid powerset construction
372 cleanup_pre(member(R,S),pred,I,POut,pred,I,multi/replace_struct_membership,[],[]) :-
373 % rewrite ProB closures introduced by b_compile/6
374 get_texpr_expr(R,identifier(_)),
375 S = b(value(ProBClosure),_,_),
376 replace_prob_closure(ProBClosure, ClosureExpr),
377 ClosureExpr = struct(Proto),
378 Proto = b(value(rec(Fields)),_,_),
379 ( maplist(replace_prob_closure_record_field, Fields, TFields)
380 -> NFields = TFields
381 ; NFields = Fields
382 ),
383 !,
384 maplist(rewrite_struct_ids(R),NFields,Constraints),
385 conjunct_predicates(Constraints,Conj),
386 get_texpr_expr(Conj,POut).
387 cleanup_pre(member(R,S),pred,I,POut,pred,I,multi/replace_struct_membership,[],[]) :-
388 get_texpr_expr(R,identifier(_)),
389 get_texpr_expr(S,struct(Proto)),
390 get_texpr_expr(Proto,value(rec(Fields))),
391 maplist(rewrite_struct_ids(R),Fields,Constraints),
392 conjunct_predicates(Constraints,Conj),
393 get_texpr_expr(Conj,POut).
394 cleanup_pre(member(E,S),pred,I,disjunct(M1,M2),pred,I,multi/split_union_in_member,[],[]) :-
395 get_texpr_expr(S,union(S1,S2)),
396 create_texpr(member(E,S1),pred,I,M1),
397 create_texpr(member(E,S2),pred,I,M2).
398 cleanup_pre(member(E,S),pred,I,conjunct(M1,M2),pred,I,multi/split_intersection_in_member,[],[]) :-
399 get_texpr_expr(S,intersection(S1,S2)),
400 create_texpr(member(E,S1),pred,I,M1),
401 create_texpr(member(E,S2),pred,I,M2).
402 cleanup_pre(member(E,S),pred,I,conjunct(M1,NotM2),pred,I,multi/split_set_subtraction_in_member,[],[]) :-
403 get_texpr_expr(S,set_subtraction(S1,S2)),
404 create_texpr(member(E,S1),pred,I,M1),
405 create_texpr(member(E,S2),pred,I,M2),
406 create_negation(M2,NotM2).
407 cleanup_pre(member(E,F),pred,I,C,pred,I,multi/rewrite_member_of_function,[],[]) :-
408 %translation_type(axiomatic),
409 rewrite_member_of_function(E,F,C).
410 cleanup_pre(member(E,S),pred,I,C,pred,I,multi/rewrite_member_to_disequalities,[],[]) :-
411 get_texpr_type(E,integer),
412 get_texpr_type(S,set(integer)),
413 rewrite_member_to_ge_le(E,S,C).
414 cleanup_pre(equal(S,GlobalIntSet),pred,I,C,pred,I,multi/rewrite_equal_to_disequalities,[],[]) :-
415 get_texpr_type(S,set(integer)),
416 get_texpr_expr(GlobalIntSet,integer_set(_)),
417 rewrite_equal_to_ge_le(S,GlobalIntSet,C).
418 cleanup_pre(subset(Sub,Super),pred,I,C,pred,I,multi/rewrite_subset_of_integer_set_or_interval,[],[]) :-
419 get_texpr_type(Sub,set(integer)),
420 (get_texpr_expr(Super,integer_set(_)) ; get_texpr_expr(Super,interval(_,_))),
421 rewrite_subset_of_integer_set(Sub,Super,C).
422 % if there are still interval nodes after the former rule, try to replace them by constants
423 cleanup_pre(interval(From,To),set(integer),I,NExpr,set(integer),I,multi/rewrite_constant_interval,[],[]) :-
424 precompute_values(b(interval(From,To),set(integer),I), [instantiate_quantifier_limit(0)], Precomputed),
425 Precomputed = b(TExpr,_,_),
426 TExpr \= interval(From,To),
427 !,
428 NExpr = TExpr.
429 % remaining intervals have to be rewritten to set comprehensions (introduced forall)
430 cleanup_pre(interval(From,To),set(integer),I,comprehension_set([UIdD],Pred),set(integer),I,multi/rewrite_interval_to_set_comprehension,[],[]) :-
431 translation_type(axiomatic),
432 unique_typed_id("_smt_tmp",integer,UIdD),
433 create_texpr(greater_equal(UIdD,From),pred,[],Pred1),
434 create_texpr(less_equal(UIdD,To),pred,[],Pred2),
435 conjunct_predicates([Pred1,Pred2],Pred).
436 % rewrite some operators to set comprehensions
437 % later rules will rewrite them again and introduce foralls
438 cleanup_pre(pow_subset(Set),set(set(T)),I,comprehension_set([UIdD],Pred),set(set(T)),I,multi/rewrite_pow_subset,[],[]) :-
439 translation_type(axiomatic),
440 unique_typed_id("_smt_tmp",set(T),UIdD),
441 create_texpr(subset(UIdD,Set),pred,[],Pred).
442 cleanup_pre(pow1_subset(Set),set(set(T)),I,comprehension_set([UIdD],Pred),set(set(T)),I,multi/rewrite_pow1_subset,[],[]) :-
443 translation_type(axiomatic),
444 unique_typed_id("_smt_tmp",set(T),UIdD),
445 create_texpr(subset(UIdD,Set),pred,[],PredSubset),
446 create_texpr(empty_set,set(T),[],EmptySet),
447 create_texpr(not_equal(UIdD,EmptySet),pred,[],PredNotEqual),
448 conjunct_predicates([PredSubset,PredNotEqual],Pred).
449 cleanup_pre(fin_subset(Set),set(set(T)),I,comprehension_set([UIdD],Pred),set(set(T)),I,multi/rewrite_fin_subset,[],[]) :-
450 unique_typed_id("_smt_tmp",set(T),UIdD),
451 create_texpr(subset(UIdD,Set),pred,[],Pred1),
452 create_texpr(finite(Set),pred,[],Pred2),
453 conjunct_predicates([Pred1,Pred2],Pred).
454 cleanup_pre(fin1_subset(Set),set(set(T)),I,comprehension_set([UIdD],Pred),set(set(T)),I,multi/rewrite_fin1_subset,[],[]) :-
455 unique_typed_id("_smt_tmp",set(T),UIdD),
456 create_texpr(subset(UIdD,Set),pred,[],PredSubset),
457 create_texpr(empty_set,set(T),[],EmptySet),
458 create_texpr(not_equal(UIdD,EmptySet),pred,[],PredNotEqual),
459 create_texpr(finite(Set),pred,[],PredIsFinite),
460 conjunct_predicates([PredSubset,PredNotEqual,PredIsFinite],Pred).
461 /*cleanup_pre(relations(SetA,SetB),Type,I,pow_subset(Cart),Type,I,multi/rewrite_relations,[],[]) :-
462 Type = set(IT),
463 Cart = b(cartesian_product(SetA,SetB),IT,[]).
464 cleanup_pre(partial_function(SetA,SetB),Type,I,comprehension_set([IdR],Body),Type,I,multi/rewrite_partial_function,[],[]) :-
465 translation_type(constructive),
466 Type = set(set(IT)),
467 unique_typed_id("_r", set(IT), IdR),
468 IT = couple(TA,TB),
469 get_texpr_type(SetB, TSetB),
470 TSetB = set(InnerSetTypeB),
471 Member = b(member(IdR,b(pow_subset(b(cartesian_product(SetA,SetB),set(IT),[])),set(set(IT)),[])),pred,[]),
472 Comp = b(composition(b(reverse(IdR),set(couple(TB,TA)),[]),IdR),set(couple(InnerSetTypeB,InnerSetTypeB)),[]),
473 Subset = b(subset(Comp,b(identity(SetB),set(couple(InnerSetTypeB,InnerSetTypeB)),[])),pred,[]),
474 Body = b(conjunct(Member,Subset),pred,[]).*/
475 % TO DO: rewrite all functions? -> problems with model translation; probably not worth it though
476 cleanup_pre(direct_product(SetA,SetB),Type,I,comprehension_set([UIdE,UIdF,UIdG],Pred),Type,I,multi/rewrite_direct_product,[],[]) :-
477 translation_type(axiomatic),
478 Type = set(couple(E,couple(F,G))),
479 % TODO: the typing of the comprehension set ids creates a set of couples with a different nesting !!
480 % {x,y,z|(x,y):a & (x,z):b} is not type compatible with a >< b
481 % this is corrected by the translation later to quantifiers
482 unique_typed_id("_smt_tmp",E,UIdE),
483 unique_typed_id("_smt_tmp",F,UIdF),
484 unique_typed_id("_smt_tmp",G,UIdG),
485 create_texpr(couple(UIdE,UIdF),couple(E,F),[],CEF),
486 create_texpr(couple(UIdE,UIdG),couple(E,G),[],CEG),
487 create_texpr(member(CEF,SetA),pred,[],M1),
488 create_texpr(member(CEG,SetB),pred,[],M2),
489 conjunct_predicates([M1,M2],Pred).
490 cleanup_pre(parallel_product(SetA,SetB),Type,I,comprehension_set([UIdE,UIdG,UIdF,UIdH],Pred),Type,I,multi/rewrite_parallel_product,[],[]) :-
491 translation_type(axiomatic),
492 Type = set(couple(couple(E,G),couple(F,H))),
493 % TODO: the typing of the comprehension set ids creates a set of couples with a different nesting !!
494 unique_typed_id("_smt_tmp",E,UIdE),
495 unique_typed_id("_smt_tmp",F,UIdF),
496 unique_typed_id("_smt_tmp",G,UIdG),
497 unique_typed_id("_smt_tmp",H,UIdH),
498 create_texpr(couple(UIdE,UIdF),couple(E,F),[],CEF),
499 create_texpr(couple(UIdG,UIdH),couple(G,H),[],CGH),
500 create_texpr(member(CEF,SetA),pred,[],M1),
501 create_texpr(member(CGH,SetB),pred,[],M2),
502 conjunct_predicates([M1,M2],Pred).
503 cleanup_pre(composition(Rel1,Rel2),set(couple(TD,TR)),I,comprehension_set([UIdD,UIdR],Pred),set(couple(TD,TR)),I,multi/rewrite_composition,[],[]) :-
504 % change in Z3: lambda inside recursive functions was declared unsupported until proper support is provided (see https://github.com/Z3Prover/z3/issues/5813)
505 % see mk_op_iteration_func_decl in /extensions/z3interface/src/cpp/main.cpp
506 %translation_type(axiomatic),
507 get_texpr_type(Rel1,set(couple(TD,TI))),
508 unique_typed_id("_smt_tmp",TD,UIdD),
509 unique_typed_id("_smt_tmp",TR,UIdR),
510 unique_typed_id("_smt_tmp",TI,UIdI),
511 create_texpr(couple(UIdD,UIdI),couple(TD,TI),[],CoupleDomToI),
512 create_texpr(couple(UIdI,UIdR),couple(TI,TR),[],CoupleIToRan),
513 create_texpr(member(CoupleDomToI,Rel1),pred,[],Member1),
514 create_texpr(member(CoupleIToRan,Rel2),pred,[],Member2),
515 conjunct_predicates([Member1,Member2],Inner),
516 create_exists([UIdI],Inner,Pred).
517 cleanup_pre(domain_restriction(Set,Rel),set(couple(TD,TR)),I,comprehension_set([UIdD,UIdR],Pred),set(couple(TD,TR)),I,multi/rewrite_domain_restriction,[],[]) :-
518 translation_type(axiomatic),
519 unique_typed_id("_smt_tmp",TD,UIdD),
520 unique_typed_id("_smt_tmp",TR,UIdR),
521 create_texpr(couple(UIdD,UIdR),couple(TD,TR),[],Couple),
522 create_texpr(member(Couple,Rel),pred,[],MemberOfRel),
523 create_texpr(member(UIdD,Set),pred,[],MemberOfSet),
524 conjunct_predicates([MemberOfRel,MemberOfSet],Pred).
525 cleanup_pre(domain_subtraction(Set,Rel),set(couple(TD,TR)),I,comprehension_set([UIdD,UIdR],Pred),set(couple(TD,TR)),I,multi/rewrite_domain_subtraction,[],[]) :-
526 translation_type(axiomatic),
527 unique_typed_id("_smt_tmp",TD,UIdD),
528 unique_typed_id("_smt_tmp",TR,UIdR),
529 create_texpr(couple(UIdD,UIdR),couple(TD,TR),[],Couple),
530 create_texpr(member(Couple,Rel),pred,[],MemberOfRel),
531 create_texpr(member(UIdD,Set),pred,[],MemberOfSet),
532 create_negation(MemberOfSet,NotMemberOfSet),
533 conjunct_predicates([MemberOfRel,NotMemberOfSet],Pred).
534 cleanup_pre(range_restriction(Rel,Set),set(couple(TD,TR)),I,comprehension_set([UIdD,UIdR],Pred),set(couple(TD,TR)),I,multi/rewrite_range_restriction,[],[]) :-
535 translation_type(axiomatic),
536 unique_typed_id("_smt_tmp",TD,UIdD),
537 unique_typed_id("_smt_tmp",TR,UIdR),
538 create_texpr(couple(UIdD,UIdR),couple(TD,TR),[],Couple),
539 create_texpr(member(Couple,Rel),pred,[],MemberOfRel),
540 create_texpr(member(UIdR,Set),pred,[],MemberOfSet),
541 conjunct_predicates([MemberOfRel,MemberOfSet],Pred).
542 cleanup_pre(range_subtraction(Rel,Set),set(couple(TD,TR)),I,comprehension_set([UIdD,UIdR],Pred),set(couple(TD,TR)),I,multi/rewrite_range_subtraction,[],[]) :-
543 translation_type(axiomatic),
544 unique_typed_id("_smt_tmp",TD,UIdD),
545 unique_typed_id("_smt_tmp",TR,UIdR),
546 create_texpr(couple(UIdD,UIdR),couple(TD,TR),[],Couple),
547 create_texpr(member(Couple,Rel),pred,[],MemberOfRel),
548 create_texpr(member(UIdR,Set),pred,[],MemberOfSet),
549 create_negation(MemberOfSet,NotMemberOfSet),
550 conjunct_predicates([MemberOfRel,NotMemberOfSet],Pred).
551 cleanup_pre(overwrite(Set1,Set2),set(couple(TD,TR)),I,union(Set2,DomSub),set(couple(TD,TR)),I,multi/rewrite_overwrite,[],[]) :-
552 create_texpr(domain(Set2),set(TD),[],DomainSet2),
553 create_texpr(domain_subtraction(DomainSet2,Set1),set(couple(TD,TR)),[],DomSub).
554 cleanup_pre(reverse(Set),set(couple(TA,TB)),I,UnwrappedId,set(couple(TA,TB)),I,multi/reverse_to_forall,[AC],[UId]) :-
555 translation_type(axiomatic),
556 % the reverse is replaced by an identifier (uid)
557 unique_typed_id("_smt_tmp",set(couple(TA,TB)),UId),
558 get_texpr_expr(UId,UnwrappedId),
559 % the identifer carries an additional constraint:
560 % !(ida,idb).((ida,idb) : set <-> (idb,ida) : uid)
561 unique_typed_id("_smt_tmp",TA,UIdA),
562 unique_typed_id("_smt_tmp",TB,UIdB),
563 create_texpr(couple(UIdA,UIdB),couple(TA,TB),[],CoupleAB),
564 create_texpr(couple(UIdB,UIdA),couple(TB,TA),[],CoupleBA),
565
566 create_texpr(member(CoupleAB,UId),pred,[],MemberA),
567 create_texpr(member(CoupleBA,Set),pred,[],MemberB),
568 create_implication(MemberA,MemberB,Direction1),
569 create_implication(MemberB,MemberA,Direction2),
570 % use two foralls instead of equivalence!
571 create_forall([UIdA,UIdB],Direction1,AC1),
572 create_forall([UIdA,UIdB],Direction2,AC2),
573 conjunct_predicates([AC1,AC2],AC).
574 cleanup_pre(cartesian_product(SetA,SetB),set(couple(TR,TD)),I,comprehension_set([UIdR,UIdD],Pred),set(couple(TR,TD)),I,multi/cartesian_product_to_set_comprehension,[],[]) :-
575 translation_type(axiomatic),
576 unique_typed_id("_smt_tmp",TD,UIdD),
577 unique_typed_id("_smt_tmp",TR,UIdR),
578 create_texpr(member(UIdR,SetA),pred,[],MemberOf1),
579 create_texpr(member(UIdD,SetB),pred,[],MemberOf2),
580 conjunct_predicates([MemberOf1,MemberOf2],Pred).
581 cleanup_pre(Input,pred,I,C,pred,I2,multi/function_application_in_predicate_position_1,[],[]) :-
582 Input =.. [Pred,E,Arg],
583 \+ is_list(E), % avoids quantifiers
584 is_texpr(E), is_texpr(Fun),
585 get_texpr_expr(E,function(Fun,Elem)),
586 get_texpr_type(Fun,set(couple(RanT,DomT))),
587 unique_typed_id("_smt_tmp",DomT,UId),
588 create_texpr(couple(Elem,UId),couple(RanT,DomT),[],Couple),
589 create_texpr(member(Couple,Fun),pred,[],CoupleInFun),
590 Output =.. [Pred,UId,Arg],
591 create_texpr(Output,pred,I,UIdInS),
592 conjunct_predicates([CoupleInFun,UIdInS],Inner),
593 create_exists([UId],Inner,b(C,pred,I2)).
594 cleanup_pre(Input,pred,I,C,pred,I2,multi/function_application_in_predicate_position_2,[],[]) :-
595 Input =.. [Pred,E,Arg],
596 \+ is_list(Arg), % avoids quantifiers
597 is_texpr(Arg), is_texpr(Fun),
598 get_texpr_expr(Arg,function(Fun,Elem)),
599 get_texpr_type(Fun,set(couple(RanT,DomT))),
600 unique_typed_id("_smt_tmp",DomT,UId),
601 create_texpr(couple(Elem,UId),couple(RanT,DomT),[],Couple),
602 create_texpr(member(Couple,Fun),pred,[],CoupleInFun),
603 Output =.. [Pred,E,UId],
604 create_texpr(Output,pred,I,UIdInS),
605 conjunct_predicates([CoupleInFun,UIdInS],Inner),
606 create_exists([UId],Inner,b(C,pred,I2)).
607 /*cleanup_pre(Expr,Type,I,NExpr,Type,I,multi/precompute_values,[],[]) :-
608 precompute_values_e(Expr, TNExpr),
609 Expr \= TNExpr,
610 !,
611 NExpr = TNExpr.*/
612 % in case the former two rules have not removed a function/2
613 cleanup_pre(function(F,X),Type,I,UnwrappedId,Type,I,multi/function_application_to_membership,[AC],[UId]) :-
614 unique_typed_id("_smt_tmp",Type,UId),
615 get_texpr_expr(UId,UnwrappedId),
616 get_texpr_type(F,set(FunType)),
617 create_texpr(couple(X,UId),FunType,[],CoupleInFunction),
618 create_texpr(member(CoupleInFunction,F),pred,[],AC).
619
620 % ----------------------------------------------------------------------------
621 % the following rules introduce new identifiers and quantifiers to define them
622 % thus, they should be the last rules executed and be avoided if possible
623 % some of the expressions that are rewritten here can be removed if they
624 % occur in another context, i.e. f(x) in the predicate f(x) : S
625 % see rules above
626 % ----------------------------------------------------------------------------
627 cleanup_pre(integer_set('INTEGER'),set(integer),I,UnwrappedId,set(integer),I,multi/rewrite_integer_set_if_above_fails,[AC],[UId]) :-
628 % the integer set is replaced by an identifier (uid)
629 unique_typed_id("_smt_tmp",set(integer),UId),
630 get_texpr_expr(UId,UnwrappedId),
631
632 % the identifer carries an additional constraint:
633 % !(id).(id : uid)
634 unique_typed_id("_smt_tmp",integer,IdToQuantify),
635
636 create_texpr(member(IdToQuantify,UId),pred,[],MemberIn),
637
638 create_forall([IdToQuantify],MemberIn,AC).
639 cleanup_pre(min_real(Set),real,I,UnwrappedId,real,I,multi/min_real_to_definition,Args,Ids) :-
640 cleanup_pre(min(Set),real,I,UnwrappedId,real,I,_,Args,Ids).
641 cleanup_pre(max_real(Set),real,I,UnwrappedId,real,I,multi/max_real_to_definition,Args,Ids) :-
642 cleanup_pre(max(Set),real,I,UnwrappedId,real,I,_,Args,Ids).
643 cleanup_pre(min(Set),IntOrReal,I,UnwrappedId,IntOrReal,I,multi/min_to_definition,[AC1,AC2],[UId]) :-
644 (IntOrReal == integer; IntOrReal == real),
645 unique_typed_id("_smt_tmp",IntOrReal,UId),
646 get_texpr_expr(UId,UnwrappedId),
647 % two axioms:
648 % !(x).(x : Set => uid <= x)
649 % #(x).(x : Set & uid = x)
650
651 unique_typed_id("_smt_tmp",IntOrReal,QuantifiedVar),
652
653 create_texpr(less_equal(UId,QuantifiedVar),pred,[],LessEqual),
654 create_texpr(equal(UId,QuantifiedVar),pred,[],Equal),
655 create_texpr(member(QuantifiedVar,Set),pred,[],QuantifiedInSet),
656
657 conjunct_predicates([QuantifiedInSet,Equal],ExistsInner),
658 create_implication(QuantifiedInSet,LessEqual,ForallInner),
659
660 create_exists([QuantifiedVar],ExistsInner,AC1),
661
662 create_forall([QuantifiedVar],ForallInner,AC2).
663 cleanup_pre(max(Set),IntOrReal,I,UnwrappedId,IntOrReal,I,multi/max_to_definition,[AC1,AC2],[UId]) :-
664 (IntOrReal == integer; IntOrReal == real),
665 unique_typed_id("_smt_tmp",IntOrReal,UId),
666 get_texpr_expr(UId,UnwrappedId),
667 % two axioms:
668 % !(x).(x : Set => uid >= x)
669 % #(x).(x : Set & uid = x)
670
671 unique_typed_id("_smt_tmp",IntOrReal,QuantifiedVar),
672
673 create_texpr(greater_equal(UId,QuantifiedVar),pred,[],GreaterEqual),
674 create_texpr(equal(UId,QuantifiedVar),pred,[],Equal),
675 create_texpr(member(QuantifiedVar,Set),pred,[],QuantifiedInSet),
676
677 conjunct_predicates([QuantifiedInSet,Equal],ExistsInner),
678 create_implication(QuantifiedInSet,GreaterEqual,ForallInner),
679
680 create_exists([QuantifiedVar],ExistsInner,AC1),
681
682 create_forall([QuantifiedVar],ForallInner,AC2).
683 cleanup_pre(card(Set),integer,I,UnwrappedId,integer,I,multi/card_to_exists,[AC1,AC2],[UId]) :-
684 unique_typed_id("_smt_tmp",integer,UId),
685 get_texpr_expr(UId,UnwrappedId),
686 get_texpr_type(Set,set(SetT)),
687 unique_typed_id("_smt_tmp",set(couple(integer,SetT)),ForExists),
688 create_texpr(interval(b(integer(1),integer,[]),UId),set(integer),[],Interval),
689 create_texpr(total_bijection(Interval,Set),set(set(couple(integer,SetT))),[],Bijection),
690 create_texpr(member(ForExists,Bijection),pred,[],MemberOf),
691 create_exists([ForExists],MemberOf,AC1),
692 % without the following constraint, the empty set could have any (negative) cardinality
693 create_texpr(greater_equal(UId,b(integer(0),integer,[])),pred,[],AC2).
694 cleanup_pre(finite(Set),pred,I,ExistsExpr,pred,I,multi/finite_to_forall,[],[]) :-
695 % #(b,f).(b:NATURAL & f: Set --> 0..b)
696 get_texpr_type(Set,set(ST)),
697 unique_typed_id("_smt_tmp",integer,IDB),
698 create_texpr(interval(b(integer(0),integer,[]),IDB),set(integer),[],Interval0ToB),
699 unique_typed_id("_smt_tmp",set(couple(ST,integer)),IDFun),
700 create_texpr(total_injection(Set,Interval0ToB),set(set(couple(ST,integer))),[],Functions),
701 create_texpr(member(IDFun,Functions),pred,[],Member),
702 create_exists([IDB,IDFun],Member,Exists),
703 get_texpr_expr(Exists,ExistsExpr).
704 cleanup_pre(comprehension_set(Identifiers,Pred),set(X),I,UnwrappedId,set(X),I,multi/comprehension_set_to_forall,[AC],[UId]) :-
705 % NOTE: currently the comprehension sets generated are not valid according to B typing rules
706 % expr_list_to_couple_expr corrects this
707 %(
708 translation_type(axiomatic),
709 %; translation_type(constructive), % we use Z3's lambda for constructive translation
710 % \+ (member(b(_,_,LambdaIdInfo), Identifiers), member(lambda_result(_), LambdaIdInfo))
711 %),
712 %print(X),nl, print(Identifiers),nl,
713 ( expr_list_to_couple_expr(Identifiers,X,IDCouple)
714 -> true
715 ; add_message(cleanup_pre, 'Could not transform comprehension_set into quantifiers:~n ', b(comprehension_set(Identifiers,Pred),set(X),I))
716 ),
717 % the set comprehension is replaced by an identifier (uid)
718 unique_typed_id("_smt_tmp",set(X),UId),
719 get_texpr_expr(UId,UnwrappedId),
720 % the identifer carries an additional constraint:
721 % !(id).(Pred(id) <-> id : uid)
722 create_texpr(member(IDCouple,UId),pred,[],MemberInComprehension),
723 create_implication(Pred,MemberInComprehension,Direction1),
724 create_implication(MemberInComprehension,Pred,Direction2),
725 % use two foralls instead of equivalence!
726
727 create_forall(Identifiers,Direction1,AC1),
728 create_forall(Identifiers,Direction2,AC2),
729 conjunct_predicates([AC1,AC2],AC).
730 /* doesn't seem to be correct, see :z3-double-check rx:BOOL <-> BOOL & not(( id(BOOL) ; rx) = rx)
731 cleanup_pre(identity(Set),set(couple(SetT,SetT)),I,UnwrappedId,set(couple(SetT,SetT)),I,multi/identity_to_forall,[AC],[UId]) :-
732 translation_type(axiomatic),
733 % the identity is replaced by an identifier (uid)
734 unique_typed_id("_smt_tmp",set(couple(SetT,SetT)),UId),
735 get_texpr_expr(UId,UnwrappedId),
736 % the identifer carries an additional constraint:
737 % !(id).(id : set <-> (id,id) : uid)
738 unique_typed_id("_smt_tmp",SetT,UIdInSet),
739 create_texpr(couple(UIdInSet,UIdInSet),couple(SetT,SetT),[],IdCouple),
740 create_texpr(member(UIdInSet,Set),pred,[],MemberInSet),
741 create_texpr(member(IdCouple,UId),pred,[],MemberInIdentity),
742 create_implication(MemberInIdentity,MemberInSet,Direction1),
743 create_implication(MemberInSet,MemberInIdentity,Direction2),
744 % use two foralls instead of equivalence!
745
746 create_forall([UIdInSet],Direction1,AC1),
747 create_forall([UIdInSet],Direction2,AC2),
748 conjunct_predicates([AC1,AC2],AC).*/
749 cleanup_pre(domain(Set),set(TD),I,UnwrappedId,set(TD),I,multi/domain_to_forall,[AC],[UId]) :-
750 translation_type(axiomatic),
751 % the alternative translation of domain and range using lambda is not supported by the incremental solver
752 % because an existential quantification is used in the body of the lambda ("internalization of exists is not supported")
753 % we thus rewrite these operators here if the incremental solver is used, otherwise they are translated in z3interface/../main.cpp
754 % the domain is replaced by an identifier (uid)
755 get_texpr_type(Set,set(couple(TD,TR))),
756 unique_typed_id("_smt_tmp",set(TD),UId),
757 get_texpr_expr(UId,UnwrappedId),
758 % the identifer carries an additional constraint:
759 % !(id).(id : uid <-> #(idr) : (id,idr) : set)
760 unique_typed_id("_smt_tmp",TD,UIdInDomain),
761 unique_typed_id("_smt_tmp",TR,UIdInRange),
762
763 create_texpr(couple(UIdInDomain,UIdInRange),couple(TD,TR),[],CoupleDR),
764 create_texpr(member(CoupleDR,Set),pred,[],CoupleInSet),
765 create_exists([UIdInRange],CoupleInSet,ExistsRanElement),
766
767 create_texpr(member(UIdInDomain,UId),pred,[],MemberInDomain),
768
769 create_implication(ExistsRanElement,MemberInDomain,Direction1),
770 create_implication(MemberInDomain,ExistsRanElement,Direction2),
771 % use two foralls instead of equivalence!
772
773 create_forall([UIdInDomain],Direction1,AC1),
774 create_forall([UIdInDomain],Direction2,AC2),
775 conjunct_predicates([AC1,AC2],AC).
776 cleanup_pre(range(Set),set(TR),I,UnwrappedId,set(TR),I,multi/range_to_forall,[AC],[UId]) :-
777 (member(no_lambda_translation, I); translation_type(axiomatic)),
778 % the range is replaced by an identifier (uid)
779 get_texpr_type(Set,set(couple(TD,TR))),
780 unique_typed_id("_smt_tmp",set(TR),UId),
781 get_texpr_expr(UId,UnwrappedId),
782 % the identifer carries an additional constraint:
783 % !(id).(id : uid <-> #(idd) : (idd,id) : set)
784 unique_typed_id("_smt_tmp",TD,UIdInDomain),
785 unique_typed_id("_smt_tmp",TR,UIdInRange),
786
787 create_texpr(couple(UIdInDomain,UIdInRange),couple(TD,TR),[],CoupleDR),
788 create_texpr(member(CoupleDR,Set),pred,[],CoupleInSet),
789 create_exists([UIdInDomain],CoupleInSet,ExistsDomElement),
790
791 create_texpr(member(UIdInRange,UId),pred,[],MemberInRange),
792 create_implication(ExistsDomElement,MemberInRange,Direction1),
793 create_implication(MemberInRange,ExistsDomElement,Direction2),
794 % use two foralls instead of equivalence!
795
796 create_forall([UIdInRange],Direction1,AC1),
797 create_forall([UIdInRange],Direction2,AC2),
798 conjunct_predicates([AC1,AC2],AC).
799 cleanup_pre(image(Function,Set),set(TR),I,UnwrappedId,set(TR),I,multi/image_to_forall,[AC],[UId]) :-
800 translation_type(axiomatic),
801 % the image is replaced by an identifier (uid)
802 get_texpr_type(Function,set(couple(TD,TR))),
803 unique_typed_id("_smt_tmp",set(TR),UId),
804 get_texpr_expr(UId,UnwrappedId),
805 % the identifer carries an additional constraint:
806 % !(idr).(idr : uid <-> #(idd) : idd:set & (idd,idr) : function)
807 unique_typed_id("_smt_tmp",TD,UIdInDomain),
808 unique_typed_id("_smt_tmp",TR,UIdInRange),
809
810 create_texpr(couple(UIdInDomain,UIdInRange),couple(TD,TR),[],CoupleDR),
811 create_texpr(member(CoupleDR,Function),pred,[],CoupleInFunction),
812 create_texpr(member(UIdInDomain,Set),pred,[],DomElementInSet),
813 conjunct_predicates([CoupleInFunction,DomElementInSet],ExistsInner),
814 create_exists([UIdInDomain],ExistsInner,RHS),
815
816 create_texpr(member(UIdInRange,UId),pred,[],LHS),
817
818 create_implication(LHS,RHS,Direction1),
819 create_implication(RHS,LHS,Direction2),
820 % use two foralls instead of equivalence!
821
822 create_forall([UIdInRange],Direction1,AC1),
823 create_forall([UIdInRange],Direction2,AC2),
824 conjunct_predicates([AC1,AC2],AC).
825 cleanup_pre(external_pred_call('LEQ_SYM',_),pred,I,truth,pred,I,multi/remove_leq_sym,[],[]) :-
826 debug_println(19,'Ignoring LEQ_SYM predicate').
827
828 cleanup_post_with_path(OExpr,OType,OInfo,NExpr,NType,NInfo,Mode/Rule,_Path,[],[]) :-
829 cleanup_post(OExpr,OType,OInfo,NExpr,NType,NInfo,Mode/Rule).
830 % remove membership / subset if only used for typing
831 cleanup_post(subset(A,B),pred,I,truth,pred,[was(subset(A,B))|I],multi/remove_type_subset) :-
832 is_just_type(B), !.
833 cleanup_post(member(X,B),pred,I,truth,pred,[was(member(X,B))|I],multi/remove_type_member) :-
834 is_just_type(B), !.
835 cleanup_post(not_member(X,B),pred,I,falsity,pred,[was(not_member(X,B))|I],multi/remove_type_not_member) :-
836 is_just_type(B), !.
837
838 % using create_couple would be much easier:
839 %expr_list_to_couple_expr(Exprs,TypeOfCoupleExpr,Result) :- !, bsyntaxtree:create_couple(Exprs,Result).
840 % but we seem to need this more complex version due to the fact that some translation rules
841 % like for parallel or direct_product generate incorrect comprehension sets
842 expr_list_to_couple_expr(Exprs,TypeOfCoupleExpr,Result) :-
843 expr_list_to_couple_expr(Exprs,TypeOfCoupleExpr,[],Result).
844 expr_list_to_couple_expr([T],_Type,[],R) :- !, T=R.
845 expr_list_to_couple_expr([E|Es],couple(TA,TR),Rest,R) :-
846 get_texpr_type(E,TA),!, % type is matching
847 expr_list_to_couple_expr(Es,TR,Rest,RHS),
848 get_texpr_type(RHS,RHST), get_texpr_type(E,ET),
849 create_texpr(couple(E,RHS),couple(ET,RHST),[],R).
850 expr_list_to_couple_expr(Es,couple(TA,TR),Rest,R) :-
851 TA = couple(SA,SB),
852 expr_list_to_couple_expr(Es,SA,TRest,LHS),
853 !,
854 expr_list_to_couple_expr(TRest,SB,TRest2,RHS),
855 get_texpr_type(RHS,RHST), get_texpr_type(LHS,LHST),
856 create_texpr(couple(LHS,RHS),couple(LHST,RHST),[],R1),
857 expr_list_to_couple_expr(TRest2,TR,Rest,R2),
858 !,
859 get_texpr_type(R1,R1T), get_texpr_type(R2,R2T),
860 create_texpr(couple(R1,R2),couple(R1T,R2T),[],R).
861 expr_list_to_couple_expr([T|Ts],_Type,Ts,R) :- !, T=R.
862
863 is_interval(BT,Low,Up) :-
864 get_texpr_expr(BT,B),
865 ( B = interval(Low,Up) -> true
866 ; B = value(Val), nonvar(Val),
867 is_interval_closure(Val,L,U) ->
868 Low = b(integer(L),integer,[]),
869 Up = b(integer(U),integer,[])).
870
871
872 rewrite_subset_of_integer_set(Sub,Super,COut) :-
873 unique_typed_id("_smt_tmp",integer,ForAllVar),
874 create_texpr(member(ForAllVar,Sub),pred,[],LHS),
875 create_texpr(member(ForAllVar,Super),pred,[],RHS), % will be replaced by another rule
876 create_implication(LHS,RHS,Inner),
877 create_forall([ForAllVar],Inner,C),
878 get_texpr_expr(C,COut).
879
880 rewrite_struct_ids(Record,field(Id,TPowerset),Constraint) :-
881 % b_compile/6 might have transformed ASTs to values
882 TPowerset \= b(_,_,_),
883 !,
884 get_texpr_type(Record,record([field(_,IdType)|_])),
885 Powerset = b(value(TPowerset),set(IdType),[]),
886 create_texpr(record_field(Record,Id),IdType,[],TheField),
887 create_texpr(member(TheField,Powerset),pred,[],Constraint).
888 rewrite_struct_ids(Record,field(Id,Powerset),Constraint) :-
889 get_texpr_type(Powerset,set(IdType)),
890 create_texpr(record_field(Record,Id),IdType,[],TheField),
891 create_texpr(member(TheField,Powerset),pred,[],Constraint).
892
893 % relations
894 rewrite_member_of_function(ID,Function,TypeConstraintOut) :-
895 get_texpr_expr(Function,relations(Dom,Ran)),
896 get_texpr_type(Function,set(set(couple(DomT,RanT)))),
897 % relations: only typing constraint !(x,y).((x,y) : ID => x : Dom & y : Ran)
898 unique_typed_id("_smt_tmp",DomT,UIdDom),
899 unique_typed_id("_smt_tmp",RanT,UIdRan),
900 create_texpr(couple(UIdDom,UIdRan),couple(DomT,RanT),[],UIdCouple),
901 create_texpr(member(UIdCouple,ID),pred,[],LHS),
902 create_texpr(member(UIdDom,Dom),pred,[],RHS1),
903 create_texpr(member(UIdRan,Ran),pred,[],RHS2),
904 conjunct_predicates([RHS1,RHS2],RHS),
905 create_implication(LHS,RHS,TypeConsInner),
906
907 create_forall([UIdDom,UIdRan],TypeConsInner,TypeConstraint),
908 get_texpr_expr(TypeConstraint,TypeConstraintOut).
909 rewrite_member_of_function(ID,Function,ConstraintOut) :-
910 get_texpr_expr(Function,total_relation(Dom,Ran)),
911 get_texpr_type(Function,set(set(couple(DomT,RanT)))),
912 % total_relation: relation & !(x).(x : Dom => #(y).(y : Ran & (x,y):Id))
913 unique_typed_id("_smt_tmp",DomT,UIdDom),
914 unique_typed_id("_smt_tmp",RanT,UIdRan),
915 create_texpr(couple(UIdDom,UIdRan),couple(DomT,RanT),[],UIdCouple),
916 create_texpr(member(UIdCouple,ID),pred,[],CoupleInID),
917 create_exists([UIdRan],CoupleInID,RHS),
918 create_texpr(member(UIdDom,Dom),pred,[],LHS),
919 create_implication(LHS,RHS,FunConsInner),
920 create_forall([UIdDom],FunConsInner,FunConstraint),
921 create_texpr(relations(Dom,Ran),set(set(couple(DomT,RanT))),[],Relations),
922 create_texpr(member(ID,Relations),pred,[],IsRelation),
923 ConstraintOut = conjunct(IsRelation,FunConstraint).
924 rewrite_member_of_function(ID,Function,ConstraintOut) :-
925 get_texpr_expr(Function,surjection_relation(Dom,Ran)),
926 get_texpr_type(Function,set(set(couple(DomT,RanT)))),
927 % surjection_relation: relation & ran = T
928 create_texpr(range(ID),set(RanT),[],Range),
929 create_texpr(equal(Range,Ran),pred,[],FunConstraint),
930 create_texpr(relations(Dom,Ran),set(set(couple(DomT,RanT))),[],Relations),
931 create_texpr(member(ID,Relations),pred,[],IsRelation),
932 ConstraintOut = conjunct(IsRelation,FunConstraint).
933 rewrite_member_of_function(ID,Function,ConstraintOut) :-
934 get_texpr_expr(Function,total_surjection_relation(Dom,Ran)),
935 get_texpr_type(Function,set(set(couple(DomT,RanT)))),
936 % total_surjection_relation: total_relation & surjection_relation
937 create_texpr(total_relation(Dom,Ran),set(set(couple(DomT,RanT))),[],TotalRelations),
938 create_texpr(member(ID,TotalRelations),pred,[],IsTotalRelation),
939 create_texpr(surjection_relation(Dom,Ran),set(set(couple(DomT,RanT))),[],SurjectionRelations),
940 create_texpr(member(ID,SurjectionRelations),pred,[],IsSurjectionRelation),
941 ConstraintOut = conjunct(IsTotalRelation,IsSurjectionRelation).
942 % functions
943 rewrite_member_of_function(ID,Function,ConstraintOut) :-
944 get_texpr_expr(Function,partial_function(Dom,Ran)),
945 get_texpr_type(Function,set(set(couple(DomT,RanT)))),
946 % partial_function: relation & !(x,y,z).((x,y) : ID & (x,z) : ID => y = z)
947 unique_typed_id("_smt_tmp",DomT,UIdDom),
948 unique_typed_id("_smt_tmp",RanT,UIdRan),
949 unique_typed_id("_smt_tmp",RanT,UIdRan2),
950 create_texpr(couple(UIdDom,UIdRan),couple(DomT,RanT),[],UIdCouple),
951 create_texpr(couple(UIdDom,UIdRan2),couple(DomT,RanT),[],UIdCouple2),
952 create_texpr(member(UIdCouple,ID),pred,[],C1InID),
953 create_texpr(member(UIdCouple2,ID),pred,[],C2InID),
954 create_texpr(equal(UIdRan,UIdRan2),pred,[],RHS),
955 conjunct_predicates([C1InID,C2InID],LHS),
956 create_implication(LHS,RHS,FunConsInner),
957
958 create_forall([UIdDom,UIdRan,UIdRan2],FunConsInner,FunConstraint),
959 % add typing: is a relation
960 create_texpr(relations(Dom,Ran),set(set(couple(DomT,RanT))),[],Relations),
961 create_texpr(member(ID,Relations),pred,[],IsRelation),
962 ConstraintOut = conjunct(IsRelation,FunConstraint).
963 rewrite_member_of_function(ID,Function,ConstraintOut) :-
964 get_texpr_expr(Function,total_function(Dom,Ran)),
965 get_texpr_type(Function,set(set(couple(DomT,RanT)))),
966 % total_function: partial_function & !(x).(x : Dom => #(y).(y : Ran & (x,y):Id))
967 unique_typed_id("_smt_tmp",DomT,UIdDom),
968 unique_typed_id("_smt_tmp",RanT,UIdRan),
969 create_texpr(couple(UIdDom,UIdRan),couple(DomT,RanT),[],UIdCouple),
970 create_texpr(member(UIdCouple,ID),pred,[],CoupleInID),
971 create_exists([UIdRan],CoupleInID,RHS),
972 create_texpr(member(UIdDom,Dom),pred,[],LHS),
973 create_implication(LHS,RHS,FunConsInner),
974 create_forall([UIdDom],FunConsInner,FunConstraint),
975 % add typing: is a partial_function
976 create_texpr(partial_function(Dom,Ran),set(set(couple(DomT,RanT))),[],PFunctions),
977 create_texpr(member(ID,PFunctions),pred,[],IsPFunction),
978 ConstraintOut = conjunct(IsPFunction,FunConstraint).
979 % injections
980 rewrite_member_of_function(ID,Function,ConstraintOut) :-
981 get_texpr_expr(Function,partial_injection(Dom,Ran)),
982 get_texpr_type(Function,set(set(couple(DomT,RanT)))),
983 % partial_injection: partial_function & !(x1,x2,y).((x1,y) : ID & (x2,y) : ID => x1 = x2)
984 unique_typed_id("_smt_tmp",DomT,UIdDom1),
985 unique_typed_id("_smt_tmp",DomT,UIdDom2),
986 unique_typed_id("_smt_tmp",RanT,UIdRan),
987 create_texpr(couple(UIdDom1,UIdRan),couple(DomT,RanT),[],UIdCouple),
988 create_texpr(couple(UIdDom2,UIdRan),couple(DomT,RanT),[],UIdCouple2),
989 create_texpr(member(UIdCouple,ID),pred,[],C1InID),
990 create_texpr(member(UIdCouple2,ID),pred,[],C2InID),
991 create_texpr(equal(UIdDom1,UIdDom2),pred,[],RHS),
992 conjunct_predicates([C1InID,C2InID],LHS),
993 create_implication(LHS,RHS,FunConsInner),
994
995 create_forall([UIdDom1,UIdDom2,UIdRan],FunConsInner,FunConstraint),
996 % add typing: is a partial_function
997 create_texpr(partial_function(Dom,Ran),set(set(couple(DomT,RanT))),[],PartialFunctions),
998 create_texpr(member(ID,PartialFunctions),pred,[],IsPartialFunction),
999 ConstraintOut = conjunct(IsPartialFunction,FunConstraint).
1000 rewrite_member_of_function(ID,Function,ConstraintOut) :-
1001 get_texpr_expr(Function,total_injection(Dom,Ran)),
1002 get_texpr_type(Function,set(set(couple(DomT,RanT)))),
1003 % total_injection: total_function & partial_injection
1004 create_texpr(total_function(Dom,Ran),set(set(couple(DomT,RanT))),[],TotalFunctions),
1005 create_texpr(member(ID,TotalFunctions),pred,[],IsTotalFunction),
1006 create_texpr(partial_injection(Dom,Ran),set(set(couple(DomT,RanT))),[],PartialInjections),
1007 create_texpr(member(ID,PartialInjections),pred,[],IsPartialInjection),
1008 ConstraintOut = conjunct(IsTotalFunction,IsPartialInjection).
1009 % surjections
1010 rewrite_member_of_function(ID,Function,ConstraintOut) :-
1011 get_texpr_expr(Function,partial_surjection(Dom,Ran)),
1012 get_texpr_type(Function,set(set(couple(DomT,RanT)))),
1013 % partial_surjection: partial_function & ran = T
1014 create_texpr(range(ID),set(RanT),[],TRange),
1015 % TO DO: there is a bug when translating this range as a lambda function, happens for card, possible bug in Z3
1016 add_texpr_infos(TRange, [no_lambda_translation], Range),
1017 create_texpr(equal(Range,Ran),pred,[],FunConstraint),
1018 % add typing: is a partial_function
1019 create_texpr(partial_function(Dom,Ran),set(set(couple(DomT,RanT))),[],PFunctions),
1020 create_texpr(member(ID,PFunctions),pred,[],IsPFunction),
1021 ConstraintOut = conjunct(IsPFunction,FunConstraint).
1022 rewrite_member_of_function(ID,Function,ConstraintOut) :-
1023 get_texpr_expr(Function,total_surjection(Dom,Ran)),
1024 get_texpr_type(Function,set(set(couple(DomT,RanT)))),
1025 % total_surjection: total_function & partial_surjection
1026 create_texpr(total_function(Dom,Ran),set(set(couple(DomT,RanT))),[],TotalFunctions),
1027 create_texpr(member(ID,TotalFunctions),pred,[],IsTotalFunction),
1028 create_texpr(partial_surjection(Dom,Ran),set(set(couple(DomT,RanT))),[],PartialSurjections),
1029 create_texpr(member(ID,PartialSurjections),pred,[],IsPartialSurjection),
1030 ConstraintOut = conjunct(IsTotalFunction,IsPartialSurjection).
1031 % bijections
1032 rewrite_member_of_function(ID,Function,ConstraintOut) :-
1033 get_texpr_expr(Function,partial_bijection(Dom,Ran)),
1034 get_texpr_type(Function,set(set(couple(DomT,RanT)))),
1035 % partial_bijection: partial_surjection & partial_injection
1036 create_texpr(partial_surjection(Dom,Ran),set(set(couple(DomT,RanT))),[],PartialSurjections),
1037 create_texpr(member(ID,PartialSurjections),pred,[],IsPartialSurjection),
1038 create_texpr(partial_injection(Dom,Ran),set(set(couple(DomT,RanT))),[],PartialInjections),
1039 create_texpr(member(ID,PartialInjections),pred,[],IsPartialInjection),
1040 ConstraintOut = conjunct(IsPartialSurjection,IsPartialInjection).
1041 rewrite_member_of_function(ID,Function,ConstraintOut) :-
1042 get_texpr_expr(Function,total_bijection(Dom,Ran)),
1043 get_texpr_type(Function,set(set(couple(DomT,RanT)))),
1044 % total_bijection: total_surjection & total_injection
1045 create_texpr(total_surjection(Dom,Ran),set(set(couple(DomT,RanT))),[],TotalSurjections),
1046 create_texpr(member(ID,TotalSurjections),pred,[],IsTotalSurjection),
1047 create_texpr(total_injection(Dom,Ran),set(set(couple(DomT,RanT))),[],TotalInjections),
1048 create_texpr(member(ID,TotalInjections),pred,[],IsTotalInjection),
1049 ConstraintOut = conjunct(IsTotalSurjection,IsTotalInjection).
1050
1051 rewrite_equal_to_ge_le(ID,GlobalSet,Constraint) :-
1052 unique_typed_id("_smt_tmp",integer,UId),
1053 create_texpr(member(UId,ID),pred,[],UIdInSet),
1054 rewrite_member_to_ge_le(UId,GlobalSet,GeLeConstraints),
1055 create_texpr(GeLeConstraints,pred,[],GeLeTexpr),
1056 create_implication(UIdInSet,GeLeTexpr,Direction1),
1057 create_implication(GeLeTexpr,UIdInSet,Direction2),
1058
1059 create_forall([UId],Direction1,FA1),
1060 create_forall([UId],Direction2,FA2),
1061 Constraint = conjunct(FA1,FA2).
1062
1063 rewrite_global_set_nat_or_int_value(b(value(global_set('NATURAL')),set(integer),Info), Out) :-
1064 !,
1065 Out = b(integer_set('NATURAL'),set(integer),Info).
1066 rewrite_global_set_nat_or_int_value(b(value(global_set('NATURAL1')),set(integer),Info), Out) :-
1067 !,
1068 Out = b(integer_set('NATURAL1'),set(integer),Info).
1069 rewrite_global_set_nat_or_int_value(b(value(global_set('NAT')),set(integer),Info), Out) :-
1070 !,
1071 Out = b(integer_set('NAT'),set(integer),Info).
1072 rewrite_global_set_nat_or_int_value(b(value(global_set('NAT1')),set(integer),Info), Out) :-
1073 !,
1074 Out = b(integer_set('NAT1'),set(integer),Info).
1075 rewrite_global_set_nat_or_int_value(b(value(global_set('INT')),set(integer),Info), Out) :-
1076 !,
1077 Out = b(integer_set('INT'),set(integer),Info).
1078 rewrite_global_set_nat_or_int_value(In, In).
1079
1080 rewrite_member_to_ge_le(ID,Set,Constraint) :-
1081 get_texpr_expr(Set,interval(Low,High)),
1082 create_texpr(greater_equal(ID,Low),pred,[],Lower),
1083 create_texpr(greater_equal(High,ID),pred,[],Higher),
1084 Constraint = conjunct(Lower,Higher).
1085 rewrite_member_to_ge_le(ID,Set,Constraint) :-
1086 rewrite_global_set_nat_or_int_value(Set, NSet),
1087 get_texpr_expr(NSet,integer_set(Kind)), % no cut here see rule below
1088 bzero(BZero), bone(BOne), bminint(MinInt), bmaxint(MaxInt),
1089 create_texpr(greater_equal(ID,LowerBound),pred,[],Lower),
1090 create_texpr(greater_equal(UpperBound,ID),pred,[],Higher),
1091 Constraint = conjunct(Lower,Higher),
1092 (Kind = 'NAT' -> LowerBound = BZero, UpperBound = MaxInt ;
1093 Kind = 'NAT1' -> LowerBound = BOne, UpperBound = MaxInt ;
1094 Kind = 'INT' -> LowerBound = MinInt, UpperBound = MaxInt).
1095 rewrite_member_to_ge_le(ID,Set,Constraint) :-
1096 rewrite_global_set_nat_or_int_value(Set, NSet),
1097 get_texpr_expr(NSet,integer_set(Kind)), !,
1098 bzero(BZero), bone(BOne),
1099 (Kind = 'NATURAL' -> Constraint = greater_equal(ID,BZero) ;
1100 Kind = 'NATURAL1' -> Constraint = greater_equal(ID,BOne)).
1101
1102 bzero(b(integer(0),integer,[])).
1103 bone(b(integer(1),integer,[])).
1104 bminint(b(min_int,integer,[])).
1105 bmaxint(b(max_int,integer,[])).