1 | % (c) 2009-2019 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, [clean_up/2]). | |
6 | ||
7 | :- use_module(probsrc(module_information),[module_info/2]). | |
8 | :- module_info(group,smt_solvers). | |
9 | :- module_info(description,'This module implements transformations needed by the SMT-LIB translation.'). | |
10 | ||
11 | :- use_module(library(lists),[maplist/3, | |
12 | append/2, | |
13 | is_list/1, | |
14 | include/3]). | |
15 | ||
16 | :- use_module(probsrc(bsyntaxtree),[is_texpr/1, | |
17 | remove_bt/4, | |
18 | create_texpr/4, | |
19 | get_texpr_expr/2, | |
20 | get_texpr_type/2, | |
21 | create_negation/2, | |
22 | conjunct_predicates/2, | |
23 | create_forall/3, | |
24 | create_exists/3, | |
25 | create_implication/3, | |
26 | syntaxtransformation/5, | |
27 | unique_typed_id/3, | |
28 | is_just_type/1, | |
29 | find_typed_identifier_uses/2]). | |
30 | :- use_module(probsrc(error_manager), [add_internal_error/2, | |
31 | add_error_fail/3]). | |
32 | ||
33 | :- use_module(probsrc(b_ast_cleanup), [clean_up/3]). | |
34 | ||
35 | :- use_module(smt_common_predicates). | |
36 | :- use_module(seq_rewriter). | |
37 | ||
38 | clean_up(Expr,Out) :- | |
39 | clean_up(Expr,[],CleanExpr), | |
40 | rewrite_seq_to_set(CleanExpr,ExprWithoutSeq), | |
41 | internal_clean_up(ExprWithoutSeq,Out). | |
42 | ||
43 | internal_clean_up(ExprWithoutSeq,Out) :- | |
44 | % translate:translate_bexpression(ExprWithoutSeq,PPExpr), | |
45 | % write(before(PPExpr)),nl, | |
46 | %write(before(Expr)),nl, | |
47 | clean_up(ExprWithoutSeq,CExpr,[],AC,IDs), !, % do not backtrack and compute another "clean" version! | |
48 | %translate:translate_bexpression(CExpr,PPCExpr), | |
49 | %write(after(PPCExpr)),nl, | |
50 | combine_pred_and_ac(CExpr,AC,IDs,Out). | |
51 | %write(after(Out)),nl. | |
52 | ||
53 | clean_up(Expr,CExprOut,Path,ACOut,IDsOut) :- | |
54 | cleanups(pre,Expr,[],TPExpr,Path,ACPre,IDsPre), | |
55 | remove_bt(TPExpr,PExpr,LExpr,TLExpr), | |
56 | syntaxtransformation(PExpr,Subs,_,NewSubs,LExpr), | |
57 | functor(PExpr,F,N), | |
58 | % recursively clean up sub-expressions | |
59 | maplist(internal_clean_up,ACPre,ACPreClean), | |
60 | clean_up_l(Subs,NewSubs,F/N,1,Path,ACL,IDsL), | |
61 | maplist(internal_clean_up,ACL,ACLClean), | |
62 | cleanups(post,TLExpr,[],CExpr,Path,ACPost,IDsPost), | |
63 | maplist(internal_clean_up,ACPost,ACPostClean), | |
64 | append([ACPreClean,ACLClean,ACPostClean],AC), | |
65 | append([IDsPre,IDsL,IDsPost],IDs), | |
66 | (get_texpr_type(CExpr,pred) | |
67 | -> combine_pred_and_ac(CExpr,AC,IDs,CExprOut), IDsOut = [], ACOut = [] | |
68 | ; CExprOut = CExpr, ACOut = AC, IDsOut = IDs). | |
69 | ||
70 | combine_pred_and_ac(Pred,AC,IDs,Out) :- | |
71 | conjunct_predicates(AC,ACPred), | |
72 | conjunct_predicates([Pred,ACPred],OutInnerPred), | |
73 | create_exists(IDs,OutInnerPred,Out). | |
74 | ||
75 | clean_up_l([],[],_Functor,_Nr,_Path,[],[]). | |
76 | clean_up_l([Expr|Rest],[CExpr|CRest],Functor,ArgNr,Path,AC,IDs) :- | |
77 | clean_up(Expr,CExpr,[arg(Functor,ArgNr)|Path],ACC,IDsC), | |
78 | A1 is ArgNr+1, | |
79 | clean_up_l(Rest,CRest,Functor,A1,Path,ACL,IDsL), | |
80 | append(ACC,ACL,AC), | |
81 | append(IDsC,IDsL,IDs). | |
82 | ||
83 | cleanups(Phase,Expr,AppliedRules,Result,Path,ACS,IDs) :- | |
84 | assure_single_rules(AppliedRules,Rule), | |
85 | ( cleanup_phase(Phase,Expr,NExpr,Mode/Rule,Path,ACPhase,IDsPhase) -> % try to apply a rule (matching the current phase) | |
86 | ( Mode==single -> AppRules = [Rule|AppliedRules] % if the rule is marked as "single", we add to the list of already applied rules | |
87 | ; Mode==multi -> AppRules = AppliedRules % if "multi", we do not add it to the list, the rule might be applied more than once | |
88 | ; otherwise -> add_error_fail(ast_cleanup_for_smt,'Unexpected rule mode ',Mode)), | |
89 | cleanups(Phase,NExpr,AppRules,Result,Path,ACRec,IDsRec), % continue recursively with the new expression | |
90 | append(ACPhase,ACRec,ACS), append(IDsPhase,IDsRec,IDs) | |
91 | ; otherwise -> % if no rule matches anymore, | |
92 | Result = Expr, % we leave the expression unmodified | |
93 | ACS = [], IDs = [], | |
94 | Rule = none). % and unblock the co-routine (see assure_single_rules/2) | |
95 | ||
96 | assure_single_rules([],_Rule) :- !. | |
97 | assure_single_rules(AppliedRules,Rule) :- | |
98 | assure_single_rules2(AppliedRules,Rule). | |
99 | :- block assure_single_rules2(?,-). | |
100 | assure_single_rules2(_AppliedRules,none) :- !. | |
101 | assure_single_rules2(AppliedRules,Rule) :- | |
102 | \+ member(Rule, AppliedRules). | |
103 | ||
104 | cleanup_phase(Phase,OTExpr,NTExpr,Mode/Rule,Path,AC,IDs) :- | |
105 | create_texpr(OExpr,OType,OInfo,OTExpr), | |
106 | create_texpr(NExpr,NType,NInfo,NTExpr), | |
107 | cleanup_phase2(Phase,OExpr,OType,OInfo,NExpr,NType,NInfo,Mode/Rule,Path,AC,IDs). | |
108 | cleanup_phase2(pre,OExpr,OType,OInfo,NExpr,NType,NInfo,Mode/Rule,_Path,AC,IDs) :- | |
109 | cleanup_pre(OExpr,OType,OInfo,NExpr,NType,NInfo,Mode_Rule,AC,IDs), | |
110 | (functor(Mode_Rule,'/',2) -> Mode_Rule = Mode/Rule | |
111 | ; add_internal_error('Illegal cleanup_pre rule, missing mode: ',Mode_Rule),fail). | |
112 | cleanup_phase2(post,OExpr,OType,OInfo,NExpr,NType,NInfo,Mode/Rule,Path,AC,IDs) :- | |
113 | cleanup_post_with_path(OExpr,OType,OInfo,NExpr,NType,NInfo,Mode_Rule,Path,AC,IDs), | |
114 | (functor(Mode_Rule,'/',2) | |
115 | -> Mode_Rule = Mode/Rule %,format(' cleanup_post Rule: ~w/~w~n',[Mode,Rule]) | |
116 | ; add_internal_error('Illegal cleanup_post rule, missing mode: ',Mode_Rule),fail). | |
117 | ||
118 | % enforce well-definedness of division | |
119 | cleanup_pre(div(A,B),integer,I,div(A,B),integer,[smt_wd_added|I],multi/div_wd,[AC],[]) :- | |
120 | \+ member(smt_wd_added,I), !, | |
121 | create_texpr(not_equal(B,b(integer(0),integer,[])),pred,[],AC). | |
122 | % replace not_equal(..) by not(equal(..)) | |
123 | % and not_member(..) by not(member(..)) | |
124 | % and not_subset_strict(..) by not(subset_strict(..)) | |
125 | % and not_subset(..) by subset(..) | |
126 | cleanup_pre(not_equal(A,B),pred,I,negation(Equal),pred,[],multi/replace_not_equal,[],[]) :- | |
127 | create_texpr(equal(A,B),pred,I,Equal). | |
128 | cleanup_pre(not_member(A,B),pred,I,negation(Member),pred,[],multi/replace_not_member,[],[]) :- | |
129 | create_texpr(member(A,B),pred,I,Member). | |
130 | cleanup_pre(not_subset_strict(A,B),pred,I,negation(Subset),pred,[],multi/replace_not_subset_strict,[],[]) :- | |
131 | create_texpr(subset_strict(A,B),pred,I,Subset). | |
132 | cleanup_pre(not_subset(A,B),pred,I,negation(Subset),pred,[],multi/replace_not_subset,[],[]) :- | |
133 | create_texpr(subset(A,B),pred,I,Subset). | |
134 | % replace subset_strict by subset and not_equal | |
135 | cleanup_pre(subset_strict(A,B),pred,I,conjunct(NotEqual,Subset),pred,[],multi/replace_not_member,[],[]) :- | |
136 | create_texpr(subset(A,B),pred,I,Subset), | |
137 | create_texpr(not_equal(A,B),pred,I,NotEqual). | |
138 | % replace membership in struct by equalities to avoid powerset construction | |
139 | cleanup_pre(member(R,S),pred,I,POut,pred,I,multi/replace_struct,[],[]) :- | |
140 | get_texpr_expr(R,identifier(_)), | |
141 | get_texpr_expr(S,struct(Proto)), | |
142 | get_texpr_expr(Proto,rec(Fields)), | |
143 | maplist(rewrite_struct_ids(R),Fields,Constraints), | |
144 | conjunct_predicates(Constraints,Conj), | |
145 | get_texpr_expr(Conj,POut). | |
146 | cleanup_pre(member(E,S),pred,I,disjunct(M1,M2),pred,I,multi/split_union_in_member,[],[]) :- | |
147 | get_texpr_expr(S,union(S1,S2)), | |
148 | create_texpr(member(E,S1),pred,I,M1), | |
149 | create_texpr(member(E,S2),pred,I,M2). | |
150 | cleanup_pre(member(E,S),pred,I,conjunct(M1,M2),pred,I,multi/split_intersection_in_member,[],[]) :- | |
151 | get_texpr_expr(S,intersection(S1,S2)), | |
152 | create_texpr(member(E,S1),pred,I,M1), | |
153 | create_texpr(member(E,S2),pred,I,M2). | |
154 | cleanup_pre(member(E,S),pred,I,conjunct(M1,NotM2),pred,I,multi/split_set_subtraction_in_member,[],[]) :- | |
155 | get_texpr_expr(S,set_subtraction(S1,S2)), | |
156 | create_texpr(member(E,S1),pred,I,M1), | |
157 | create_texpr(member(E,S2),pred,I,M2), | |
158 | create_negation(M2,NotM2). | |
159 | cleanup_pre(member(E,F),pred,I,C,pred,I,multi/rewrite_member_of_function,[],[]) :- | |
160 | rewrite_member_of_function(E,F,C). | |
161 | cleanup_pre(member(E,S),pred,I,C,pred,I,multi/rewrite_member_to_disequalities,[],[]) :- | |
162 | get_texpr_type(E,integer), | |
163 | get_texpr_type(S,set(integer)), | |
164 | rewrite_member_to_ge_le(E,S,C). | |
165 | cleanup_pre(equal(S,GlobalIntSet),pred,I,C,pred,I,multi/rewrite_equal_to_disequalities,[],[]) :- | |
166 | get_texpr_type(S,set(integer)), | |
167 | get_texpr_expr(GlobalIntSet,integer_set(_)), | |
168 | rewrite_equal_to_ge_le(S,GlobalIntSet,C). | |
169 | cleanup_pre(subset(Sub,Super),pred,I,C,pred,I,multi/rewrite_subset_of_integer_set_or_interval,[],[]) :- | |
170 | get_texpr_type(Sub,set(integer)), | |
171 | (get_texpr_expr(Super,integer_set(_)) ; get_texpr_expr(Super,interval(_,_))), | |
172 | rewrite_subset_of_integer_set(Sub,Super,C). | |
173 | % if there are still interval nodes after the former rule, try to replace them by constants | |
174 | cleanup_pre(interval(From,To),set(integer),I,set_extension(L),set(integer),I,multi/rewrite_constant_interval,[],[]) :- | |
175 | get_texpr_expr(From,integer(FI)), | |
176 | get_texpr_expr(To,integer(TI)), !, | |
177 | constant_interval_as_list(FI,TI,L). | |
178 | % remaining intervals have to be rewritten to set comprehensions (introduced forall) | |
179 | cleanup_pre(interval(From,To),set(integer),I,comprehension_set([UIdD],Pred),set(integer),I,multi/rewrite_interval_to_set_comprehension,[],[]) :- | |
180 | unique_typed_id("_smt_tmp",integer,UIdD), | |
181 | create_texpr(greater_equal(UIdD,From),pred,[],Pred1), | |
182 | create_texpr(less_equal(UIdD,To),pred,[],Pred2), | |
183 | conjunct_predicates([Pred1,Pred2],Pred). | |
184 | % rewrite some operators to set comprehensions | |
185 | % later rules will rewrite them again and introduce foralls | |
186 | cleanup_pre(pow_subset(Set),set(set(T)),I,comprehension_set([UIdD],Pred),set(set(T)),I,multi/rewrite_pow_subset,[],[]) :- | |
187 | unique_typed_id("_smt_tmp",set(T),UIdD), | |
188 | create_texpr(subset(UIdD,Set),pred,[],Pred). | |
189 | cleanup_pre(pow1_subset(Set),set(set(T)),I,comprehension_set([UIdD],Pred),set(set(T)),I,multi/rewrite_pow1_subset,[],[]) :- | |
190 | unique_typed_id("_smt_tmp",set(T),UIdD), | |
191 | create_texpr(subset(UIdD,Set),pred,[],PredSubset), | |
192 | create_texpr(empty_set,set(T),[],EmptySet), | |
193 | create_texpr(not_equal(UIdD,EmptySet),pred,[],PredNotEqual), | |
194 | conjunct_predicates([PredSubset,PredNotEqual],Pred). | |
195 | cleanup_pre(fin_subset(Set),set(set(T)),I,comprehension_set([UIdD],Pred),set(set(T)),I,multi/rewrite_fin_subset,[],[]) :- | |
196 | unique_typed_id("_smt_tmp",set(T),UIdD), | |
197 | create_texpr(subset(UIdD,Set),pred,[],Pred1), | |
198 | create_texpr(finite(Set),pred,[],Pred2), | |
199 | conjunct_predicates([Pred1,Pred2],Pred). | |
200 | cleanup_pre(fin1_subset(Set),set(set(T)),I,comprehension_set([UIdD],Pred),set(set(T)),I,multi/rewrite_fin1_subset,[],[]) :- | |
201 | unique_typed_id("_smt_tmp",set(T),UIdD), | |
202 | create_texpr(subset(UIdD,Set),pred,[],PredSubset), | |
203 | create_texpr(empty_set,set(T),[],EmptySet), | |
204 | create_texpr(not_equal(UIdD,EmptySet),pred,[],PredNotEqual), | |
205 | create_texpr(finite(Set),pred,[],PredIsFinite), | |
206 | conjunct_predicates([PredSubset,PredNotEqual,PredIsFinite],Pred). | |
207 | cleanup_pre(direct_product(SetA,SetB),Type,I,comprehension_set([UIdE,UIdF,UIdG],Pred),Type,I,multi/rewrite_direct_product,[],[]) :- | |
208 | Type = set(couple(E,couple(F,G))), | |
209 | unique_typed_id("_smt_tmp",E,UIdE), | |
210 | unique_typed_id("_smt_tmp",F,UIdF), | |
211 | unique_typed_id("_smt_tmp",G,UIdG), | |
212 | create_texpr(couple(UIdE,UIdF),couple(E,F),[],CEF), | |
213 | create_texpr(couple(UIdE,UIdG),couple(E,G),[],CEG), | |
214 | create_texpr(member(CEF,SetA),pred,[],M1), | |
215 | create_texpr(member(CEG,SetB),pred,[],M2), | |
216 | conjunct_predicates([M1,M2],Pred). | |
217 | cleanup_pre(parallel_product(SetA,SetB),Type,I,comprehension_set([UIdE,UIdG,UIdF,UIdH],Pred),Type,I,multi/rewrite_parallel_product,[],[]) :- | |
218 | Type = set(couple(couple(E,G),couple(F,H))), | |
219 | unique_typed_id("_smt_tmp",E,UIdE), | |
220 | unique_typed_id("_smt_tmp",F,UIdF), | |
221 | unique_typed_id("_smt_tmp",G,UIdG), | |
222 | unique_typed_id("_smt_tmp",H,UIdH), | |
223 | create_texpr(couple(UIdE,UIdF),couple(E,F),[],CEF), | |
224 | create_texpr(couple(UIdG,UIdH),couple(G,H),[],CGH), | |
225 | create_texpr(member(CEF,SetA),pred,[],M1), | |
226 | create_texpr(member(CGH,SetB),pred,[],M2), | |
227 | conjunct_predicates([M1,M2],Pred). | |
228 | cleanup_pre(composition(Rel1,Rel2),set(couple(TD,TR)),I,comprehension_set([UIdD,UIdR],Pred),set(couple(TD,TR)),I,multi/rewrite_composition,[],[]) :- | |
229 | get_texpr_type(Rel1,set(couple(TD,TI))), | |
230 | unique_typed_id("_smt_tmp",TD,UIdD), | |
231 | unique_typed_id("_smt_tmp",TR,UIdR), | |
232 | unique_typed_id("_smt_tmp",TI,UIdI), | |
233 | create_texpr(couple(UIdD,UIdI),couple(TD,TI),[],CoupleDomToI), | |
234 | create_texpr(couple(UIdI,UIdR),couple(TI,TR),[],CoupleIToRan), | |
235 | create_texpr(member(CoupleDomToI,Rel1),pred,[],Member1), | |
236 | create_texpr(member(CoupleIToRan,Rel2),pred,[],Member2), | |
237 | conjunct_predicates([Member1,Member2],Inner), | |
238 | create_exists([UIdI],Inner,Pred). | |
239 | 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,[],[]) :- | |
240 | unique_typed_id("_smt_tmp",TD,UIdD), | |
241 | unique_typed_id("_smt_tmp",TR,UIdR), | |
242 | create_texpr(couple(UIdD,UIdR),couple(TD,TR),[],Couple), | |
243 | create_texpr(member(Couple,Rel),pred,[],MemberOfRel), | |
244 | create_texpr(member(UIdD,Set),pred,[],MemberOfSet), | |
245 | conjunct_predicates([MemberOfRel,MemberOfSet],Pred). | |
246 | 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,[],[]) :- | |
247 | unique_typed_id("_smt_tmp",TD,UIdD), | |
248 | unique_typed_id("_smt_tmp",TR,UIdR), | |
249 | create_texpr(couple(UIdD,UIdR),couple(TD,TR),[],Couple), | |
250 | create_texpr(member(Couple,Rel),pred,[],MemberOfRel), | |
251 | create_texpr(member(UIdD,Set),pred,[],MemberOfSet), | |
252 | create_negation(MemberOfSet,NotMemberOfSet), | |
253 | conjunct_predicates([MemberOfRel,NotMemberOfSet],Pred). | |
254 | 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,[],[]) :- | |
255 | unique_typed_id("_smt_tmp",TD,UIdD), | |
256 | unique_typed_id("_smt_tmp",TR,UIdR), | |
257 | create_texpr(couple(UIdD,UIdR),couple(TD,TR),[],Couple), | |
258 | create_texpr(member(Couple,Rel),pred,[],MemberOfRel), | |
259 | create_texpr(member(UIdR,Set),pred,[],MemberOfSet), | |
260 | conjunct_predicates([MemberOfRel,MemberOfSet],Pred). | |
261 | 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,[],[]) :- | |
262 | unique_typed_id("_smt_tmp",TD,UIdD), | |
263 | unique_typed_id("_smt_tmp",TR,UIdR), | |
264 | create_texpr(couple(UIdD,UIdR),couple(TD,TR),[],Couple), | |
265 | create_texpr(member(Couple,Rel),pred,[],MemberOfRel), | |
266 | create_texpr(member(UIdR,Set),pred,[],MemberOfSet), | |
267 | create_negation(MemberOfSet,NotMemberOfSet), | |
268 | conjunct_predicates([MemberOfRel,NotMemberOfSet],Pred). | |
269 | cleanup_pre(overwrite(Set1,Set2),set(couple(TD,TR)),I,union(Set2,DomSub),set(couple(TD,TR)),I,multi/rewrite_overwrite,[],[]) :- | |
270 | create_texpr(domain(Set2),set(TD),[],DomainSet2), | |
271 | create_texpr(domain_subtraction(DomainSet2,Set1),set(couple(TD,TR)),[],DomSub). | |
272 | 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,[],[]) :- | |
273 | unique_typed_id("_smt_tmp",TD,UIdD), | |
274 | unique_typed_id("_smt_tmp",TR,UIdR), | |
275 | create_texpr(member(UIdR,SetA),pred,[],MemberOf1), | |
276 | create_texpr(member(UIdD,SetB),pred,[],MemberOf2), | |
277 | conjunct_predicates([MemberOf1,MemberOf2],Pred). | |
278 | cleanup_pre(Input,pred,I,C,pred,I2,multi/function_application_in_predicate_position_1,[],[]) :- | |
279 | Input =.. [Pred,E,Arg], | |
280 | \+ is_list(E), % avoids quantifiers | |
281 | is_texpr(E), is_texpr(Fun), | |
282 | get_texpr_expr(E,function(Fun,Elem)), | |
283 | get_texpr_type(Fun,set(couple(RanT,DomT))), | |
284 | unique_typed_id("_smt_tmp",DomT,UId), | |
285 | create_texpr(couple(Elem,UId),couple(RanT,DomT),[],Couple), | |
286 | create_texpr(member(Couple,Fun),pred,[],CoupleInFun), | |
287 | Output =.. [Pred,UId,Arg], | |
288 | create_texpr(Output,pred,I,UIdInS), | |
289 | conjunct_predicates([CoupleInFun,UIdInS],Inner), | |
290 | create_exists([UId],Inner,b(C,pred,I2)). | |
291 | cleanup_pre(Input,pred,I,C,pred,I2,multi/function_application_in_predicate_position_2,[],[]) :- | |
292 | Input =.. [Pred,E,Arg], | |
293 | \+ is_list(Arg), % avoids quantifiers | |
294 | is_texpr(Arg), is_texpr(Fun), | |
295 | get_texpr_expr(Arg,function(Fun,Elem)), | |
296 | get_texpr_type(Fun,set(couple(RanT,DomT))), | |
297 | unique_typed_id("_smt_tmp",DomT,UId), | |
298 | create_texpr(couple(Elem,UId),couple(RanT,DomT),[],Couple), | |
299 | create_texpr(member(Couple,Fun),pred,[],CoupleInFun), | |
300 | Output =.. [Pred,E,UId], | |
301 | create_texpr(Output,pred,I,UIdInS), | |
302 | conjunct_predicates([CoupleInFun,UIdInS],Inner), | |
303 | create_exists([UId],Inner,b(C,pred,I2)). | |
304 | % in case the former two rules have not removed a function/2 | |
305 | cleanup_pre(function(F,X),Type,I,UnwrappedId,Type,I,multi/function_application_to_membership,[AC],[UId]) :- | |
306 | unique_typed_id("_smt_tmp",Type,UId), | |
307 | get_texpr_expr(UId,UnwrappedId), | |
308 | get_texpr_type(F,set(FunType)), | |
309 | create_texpr(couple(X,UId),FunType,[],CoupleInFunction), | |
310 | create_texpr(member(CoupleInFunction,F),pred,[],AC). | |
311 | ||
312 | % ---------------------------------------------------------------------------- | |
313 | % the following rules introduce new identifiers and quantifiers to define them | |
314 | % thus, they should be the last rules executed and be avoided if possible | |
315 | % some of the expressions that are rewritten here can be removed if they | |
316 | % occur in another context, i.e. f(x) in the predicate f(x) : S | |
317 | % see rules above | |
318 | % ---------------------------------------------------------------------------- | |
319 | cleanup_pre(integer_set('INTEGER'),set(integer),I,UnwrappedId,set(integer),I,multi/rewrite_integer_set_if_above_fails,[AC],[UId]) :- | |
320 | % the integer set is replaced by an identifier (uid) | |
321 | unique_typed_id("_smt_tmp",set(integer),UId), | |
322 | get_texpr_expr(UId,UnwrappedId), | |
323 | ||
324 | % the identifer carries an additional constraint: | |
325 | % !(id).(id : uid) | |
326 | unique_typed_id("_smt_tmp",integer,IdToQuantify), | |
327 | ||
328 | create_texpr(member(IdToQuantify,UId),pred,[],MemberIn), | |
329 | ||
330 | create_forall([IdToQuantify],MemberIn,AC). | |
331 | cleanup_pre(min(Set),integer,I,UnwrappedId,integer,I,multi/min_to_definition,[AC1,AC2],[UId]) :- | |
332 | unique_typed_id("_smt_tmp",integer,UId), | |
333 | get_texpr_expr(UId,UnwrappedId), | |
334 | % two axioms: | |
335 | % !(x).(x : Set => uid <= x) | |
336 | % #(x).(x : Set & uid = x) | |
337 | ||
338 | unique_typed_id("_smt_tmp",integer,QuantifiedVar), | |
339 | ||
340 | create_texpr(less_equal(UId,QuantifiedVar),pred,[],LessEqual), | |
341 | create_texpr(equal(UId,QuantifiedVar),pred,[],Equal), | |
342 | create_texpr(member(QuantifiedVar,Set),pred,[],QuantifiedInSet), | |
343 | ||
344 | conjunct_predicates([QuantifiedInSet,Equal],ExistsInner), | |
345 | create_implication(QuantifiedInSet,LessEqual,ForallInner), | |
346 | ||
347 | create_exists([QuantifiedVar],ExistsInner,AC1), | |
348 | create_forall([QuantifiedVar],ForallInner,AC2). | |
349 | cleanup_pre(max(Set),integer,I,UnwrappedId,integer,I,multi/max_to_definition,[AC1,AC2],[UId]) :- | |
350 | unique_typed_id("_smt_tmp",integer,UId), | |
351 | get_texpr_expr(UId,UnwrappedId), | |
352 | % two axioms: | |
353 | % !(x).(x : Set => uid >= x) | |
354 | % #(x).(x : Set & uid = x) | |
355 | ||
356 | unique_typed_id("_smt_tmp",integer,QuantifiedVar), | |
357 | ||
358 | create_texpr(greater_equal(UId,QuantifiedVar),pred,[],GreaterEqual), | |
359 | create_texpr(equal(UId,QuantifiedVar),pred,[],Equal), | |
360 | create_texpr(member(QuantifiedVar,Set),pred,[],QuantifiedInSet), | |
361 | ||
362 | conjunct_predicates([QuantifiedInSet,Equal],ExistsInner), | |
363 | create_implication(QuantifiedInSet,GreaterEqual,ForallInner), | |
364 | ||
365 | create_exists([QuantifiedVar],ExistsInner,AC1), | |
366 | create_forall([QuantifiedVar],ForallInner,AC2). | |
367 | cleanup_pre(card(Set),integer,I,UnwrappedId,integer,I,multi/card_to_exists,[AC1,AC2],[UId]) :- | |
368 | unique_typed_id("_smt_tmp",integer,UId), | |
369 | get_texpr_expr(UId,UnwrappedId), | |
370 | get_texpr_type(Set,set(SetT)), | |
371 | unique_typed_id("_smt_tmp",set(couple(integer,SetT)),ForExists), | |
372 | create_texpr(interval(b(integer(1),integer,[]),UId),set(integer),[],Interval), | |
373 | create_texpr(total_bijection(Interval,Set),set(set(couple(integer,SetT))),[],Bijection), | |
374 | create_texpr(member(ForExists,Bijection),pred,[],MemberOf), | |
375 | create_exists([ForExists],MemberOf,AC1), | |
376 | % without the following constraint, the empty set could have any (negative) cardinality | |
377 | create_texpr(greater_equal(UId,b(integer(0),integer,[])),pred,[],AC2). | |
378 | cleanup_pre(finite(Set),pred,I,ForallExpr,pred,I,multi/finite_to_forall,[],[]) :- | |
379 | get_texpr_type(Set,set(ST)), | |
380 | unique_typed_id("_smt_tmp",integer,IDA), | |
381 | unique_typed_id("_smt_tmp",integer,IDB), | |
382 | create_texpr(interval(IDA,IDB),set(integer),[],IntervalAToB), | |
383 | unique_typed_id("_smt_tmp",set(couple(ST,integer)),IDFun), | |
384 | create_texpr(total_injection(Set,IntervalAToB),set(set(couple(ST,integer))),[],Functions), | |
385 | create_texpr(member(IDFun,Functions),pred,[],Member), | |
386 | create_exists([IDB,IDFun],Member,Exists), | |
387 | create_forall([IDA],Exists,ForallTExpr), | |
388 | get_texpr_expr(ForallTExpr,ForallExpr). | |
389 | cleanup_pre(comprehension_set(Identifiers,Pred),set(X),I,UnwrappedId,set(X),I,multi/comprehension_set_to_forall,[AC],[UId]) :- | |
390 | expr_list_to_couple_expr(Identifiers,X,IDCouple), | |
391 | % the set comprehension is replaced by an identifier (uid) | |
392 | unique_typed_id("_smt_tmp",set(X),UId), | |
393 | get_texpr_expr(UId,UnwrappedId), | |
394 | % the identifer carries an additional constraint: | |
395 | % !(id).(Pred(id) <-> id : uid) | |
396 | create_texpr(member(IDCouple,UId),pred,[],MemberInComprehension), | |
397 | create_implication(Pred,MemberInComprehension,Direction1), | |
398 | create_implication(MemberInComprehension,Pred,Direction2), | |
399 | % use two foralls instead of equivalence! | |
400 | create_forall(Identifiers,Direction1,AC1), | |
401 | create_forall(Identifiers,Direction2,AC2), | |
402 | conjunct_predicates([AC1,AC2],AC). | |
403 | cleanup_pre(identity(Set),set(couple(SetT,SetT)),I,UnwrappedId,set(couple(SetT,SetT)),I,multi/identity_to_forall,[AC],[UId]) :- | |
404 | % the identity is replaced by an identifier (uid) | |
405 | unique_typed_id("_smt_tmp",set(couple(SetT,SetT)),UId), | |
406 | get_texpr_expr(UId,UnwrappedId), | |
407 | % the identifer carries an additional constraint: | |
408 | % !(id).(id : set <-> (id,id) : uid) | |
409 | unique_typed_id("_smt_tmp",SetT,UIdInSet), | |
410 | create_texpr(couple(UIdInSet,UIdInSet),couple(SetT,SetT),[],IdCouple), | |
411 | create_texpr(member(UIdInSet,Set),pred,[],MemberInSet), | |
412 | create_texpr(member(IdCouple,UId),pred,[],MemberInIdentity), | |
413 | create_implication(MemberInIdentity,MemberInSet,Direction1), | |
414 | create_implication(MemberInSet,MemberInIdentity,Direction2), | |
415 | % use two foralls instead of equivalence! | |
416 | create_forall([UIdInSet],Direction1,AC1), | |
417 | create_forall([UIdInSet],Direction2,AC2), | |
418 | conjunct_predicates([AC1,AC2],AC). | |
419 | cleanup_pre(reverse(Set),set(couple(TA,TB)),I,UnwrappedId,set(couple(TA,TB)),I,multi/reverse_to_forall,[AC],[UId]) :- | |
420 | % the reverse is replaced by an identifier (uid) | |
421 | unique_typed_id("_smt_tmp",set(couple(TA,TB)),UId), | |
422 | get_texpr_expr(UId,UnwrappedId), | |
423 | % the identifer carries an additional constraint: | |
424 | % !(ida,idb).((ida,idb) : set <-> (idb,ida) : uid) | |
425 | unique_typed_id("_smt_tmp",TA,UIdA), | |
426 | unique_typed_id("_smt_tmp",TB,UIdB), | |
427 | create_texpr(couple(UIdA,UIdB),couple(TA,TB),[],CoupleAB), | |
428 | create_texpr(couple(UIdB,UIdA),couple(TB,TA),[],CoupleBA), | |
429 | ||
430 | create_texpr(member(CoupleAB,UId),pred,[],MemberA), | |
431 | create_texpr(member(CoupleBA,Set),pred,[],MemberB), | |
432 | create_implication(MemberA,MemberB,Direction1), | |
433 | create_implication(MemberB,MemberA,Direction2), | |
434 | % use two foralls instead of equivalence! | |
435 | create_forall([UIdA,UIdB],Direction1,AC1), | |
436 | create_forall([UIdA,UIdB],Direction2,AC2), | |
437 | conjunct_predicates([AC1,AC2],AC). | |
438 | cleanup_pre(domain(Set),set(TD),I,UnwrappedId,set(TD),I,multi/domain_to_forall,[AC],[UId]) :- | |
439 | % the domain is replaced by an identifier (uid) | |
440 | get_texpr_type(Set,set(couple(TD,TR))), | |
441 | unique_typed_id("_smt_tmp",set(TD),UId), | |
442 | get_texpr_expr(UId,UnwrappedId), | |
443 | % the identifer carries an additional constraint: | |
444 | % !(id).(id : uid <-> #(idr) : (id,idr) : set) | |
445 | unique_typed_id("_smt_tmp",TD,UIdInDomain), | |
446 | unique_typed_id("_smt_tmp",TR,UIdInRange), | |
447 | ||
448 | create_texpr(couple(UIdInDomain,UIdInRange),couple(TD,TR),[],CoupleDR), | |
449 | create_texpr(member(CoupleDR,Set),pred,[],CoupleInSet), | |
450 | create_exists([UIdInRange],CoupleInSet,ExistsRanElement), | |
451 | ||
452 | create_texpr(member(UIdInDomain,UId),pred,[],MemberInDomain), | |
453 | ||
454 | create_implication(ExistsRanElement,MemberInDomain,Direction1), | |
455 | create_implication(MemberInDomain,ExistsRanElement,Direction2), | |
456 | % use two foralls instead of equivalence! | |
457 | create_forall([UIdInDomain],Direction1,AC1), | |
458 | create_forall([UIdInDomain],Direction2,AC2), | |
459 | conjunct_predicates([AC1,AC2],AC). | |
460 | cleanup_pre(range(Set),set(TR),I,UnwrappedId,set(TR),I,multi/range_to_forall,[AC],[UId]) :- | |
461 | % the range is replaced by an identifier (uid) | |
462 | get_texpr_type(Set,set(couple(TD,TR))), | |
463 | unique_typed_id("_smt_tmp",set(TR),UId), | |
464 | get_texpr_expr(UId,UnwrappedId), | |
465 | % the identifer carries an additional constraint: | |
466 | % !(id).(id : uid <-> #(idd) : (idd,id) : set) | |
467 | unique_typed_id("_smt_tmp",TD,UIdInDomain), | |
468 | unique_typed_id("_smt_tmp",TR,UIdInRange), | |
469 | ||
470 | create_texpr(couple(UIdInDomain,UIdInRange),couple(TD,TR),[],CoupleDR), | |
471 | create_texpr(member(CoupleDR,Set),pred,[],CoupleInSet), | |
472 | create_exists([UIdInDomain],CoupleInSet,ExistsDomElement), | |
473 | ||
474 | create_texpr(member(UIdInRange,UId),pred,[],MemberInRange), | |
475 | create_implication(ExistsDomElement,MemberInRange,Direction1), | |
476 | create_implication(MemberInRange,ExistsDomElement,Direction2), | |
477 | % use two foralls instead of equivalence! | |
478 | create_forall([UIdInRange],Direction1,AC1), | |
479 | create_forall([UIdInRange],Direction2,AC2), | |
480 | conjunct_predicates([AC1,AC2],AC). | |
481 | cleanup_pre(image(Function,Set),set(TR),I,UnwrappedId,set(TR),I,multi/image_to_forall,[AC],[UId]) :- | |
482 | % the image is replaced by an identifier (uid) | |
483 | get_texpr_type(Function,set(couple(TD,TR))), | |
484 | unique_typed_id("_smt_tmp",set(TR),UId), | |
485 | get_texpr_expr(UId,UnwrappedId), | |
486 | % the identifer carries an additional constraint: | |
487 | % !(idr).(idr : uid <-> #(idd) : idd:set & (idd,idr) : function) | |
488 | unique_typed_id("_smt_tmp",TD,UIdInDomain), | |
489 | unique_typed_id("_smt_tmp",TR,UIdInRange), | |
490 | ||
491 | create_texpr(couple(UIdInDomain,UIdInRange),couple(TD,TR),[],CoupleDR), | |
492 | create_texpr(member(CoupleDR,Function),pred,[],CoupleInFunction), | |
493 | create_texpr(member(UIdInDomain,Set),pred,[],DomElementInSet), | |
494 | conjunct_predicates([CoupleInFunction,DomElementInSet],ExistsInner), | |
495 | create_exists([UIdInDomain],ExistsInner,RHS), | |
496 | ||
497 | create_texpr(member(UIdInRange,UId),pred,[],LHS), | |
498 | ||
499 | create_implication(LHS,RHS,Direction1), | |
500 | create_implication(RHS,LHS,Direction2), | |
501 | % use two foralls instead of equivalence! | |
502 | create_forall([UIdInRange],Direction1,AC1), | |
503 | create_forall([UIdInRange],Direction2,AC2), | |
504 | conjunct_predicates([AC1,AC2],AC). | |
505 | ||
506 | cleanup_post_with_path(OExpr,OType,OInfo,NExpr,NType,NInfo,Mode/Rule,_Path,[],[]) :- | |
507 | cleanup_post(OExpr,OType,OInfo,NExpr,NType,NInfo,Mode/Rule). | |
508 | % remove membership / subset if only used for typing | |
509 | cleanup_post(subset(A,B),pred,I,truth,pred,[was(subset(A,B))|I],multi/remove_type_subset) :- | |
510 | is_just_type(B), !. | |
511 | cleanup_post(member(X,B),pred,I,truth,pred,[was(member(X,B))|I],multi/remove_type_member) :- | |
512 | is_just_type(B), !. | |
513 | cleanup_post(not_member(X,B),pred,I,falsity,pred,[was(not_member(X,B))|I],multi/remove_type_not_member) :- | |
514 | is_just_type(B), !. | |
515 | ||
516 | expr_list_to_couple_expr(Exprs,TypeOfCoupleExpr,Result) :- | |
517 | expr_list_to_couple_expr(Exprs,TypeOfCoupleExpr,[],Result). | |
518 | expr_list_to_couple_expr([T],_Type,[],R) :- !, T=R. | |
519 | expr_list_to_couple_expr([E|Es],couple(TA,TR),Rest,R) :- | |
520 | TA \= couple(_,_), !, | |
521 | expr_list_to_couple_expr(Es,TR,Rest,RHS), | |
522 | get_texpr_type(RHS,RHST), get_texpr_type(E,ET), | |
523 | create_texpr(couple(E,RHS),couple(ET,RHST),[],R). | |
524 | expr_list_to_couple_expr(Es,couple(TA,TR),Rest,R) :- !, | |
525 | TA = couple(SA,SB), | |
526 | expr_list_to_couple_expr(Es,SA,TRest,LHS), | |
527 | expr_list_to_couple_expr(TRest,SB,TRest2,RHS), | |
528 | get_texpr_type(RHS,RHST), get_texpr_type(LHS,LHST), | |
529 | create_texpr(couple(LHS,RHS),couple(LHST,RHST),[],R1), | |
530 | expr_list_to_couple_expr(TRest2,TR,Rest,R2), | |
531 | get_texpr_type(R1,R1T), get_texpr_type(R2,R2T), | |
532 | create_texpr(couple(R1,R2),couple(R1T,R2T),[],R). | |
533 | expr_list_to_couple_expr([T|Ts],_Type,Ts,R) :- !, T=R. | |
534 | ||
535 | rewrite_subset_of_integer_set(Sub,Super,COut) :- | |
536 | unique_typed_id("_smt_tmp",integer,ForAllVar), | |
537 | create_texpr(member(ForAllVar,Sub),pred,[],LHS), | |
538 | create_texpr(member(ForAllVar,Super),pred,[],RHS), % will be replaced by another rule | |
539 | create_implication(LHS,RHS,Inner), | |
540 | create_forall([ForAllVar],Inner,C), | |
541 | get_texpr_expr(C,COut). | |
542 | ||
543 | rewrite_struct_ids(Record,field(Id,Powerset),Constraint) :- | |
544 | get_texpr_type(Powerset,set(IdType)), | |
545 | create_texpr(record_field(Record,Id),IdType,[],TheField), | |
546 | create_texpr(member(TheField,Powerset),pred,[],Constraint). | |
547 | ||
548 | % relations | |
549 | rewrite_member_of_function(ID,Function,TypeConstraintOut) :- | |
550 | get_texpr_expr(Function,relations(Dom,Ran)), | |
551 | get_texpr_type(Function,set(set(couple(DomT,RanT)))), | |
552 | % relations: only typing constraint !(x,y).((x,y) : ID => x : Dom & y : Ran) | |
553 | unique_typed_id("_smt_tmp",DomT,UIdDom), | |
554 | unique_typed_id("_smt_tmp",RanT,UIdRan), | |
555 | create_texpr(couple(UIdDom,UIdRan),couple(DomT,RanT),[],UIdCouple), | |
556 | create_texpr(member(UIdCouple,ID),pred,[],LHS), | |
557 | create_texpr(member(UIdDom,Dom),pred,[],RHS1), | |
558 | create_texpr(member(UIdRan,Ran),pred,[],RHS2), | |
559 | conjunct_predicates([RHS1,RHS2],RHS), | |
560 | create_implication(LHS,RHS,TypeConsInner), | |
561 | create_forall([UIdDom,UIdRan],TypeConsInner,TypeConstraint), | |
562 | get_texpr_expr(TypeConstraint,TypeConstraintOut). | |
563 | rewrite_member_of_function(ID,Function,ConstraintOut) :- | |
564 | get_texpr_expr(Function,total_relation(Dom,Ran)), | |
565 | get_texpr_type(Function,set(set(couple(DomT,RanT)))), | |
566 | % total_relation: relation & !(x).(x : Dom => #(y).(y : Ran & (x,y):Id)) | |
567 | unique_typed_id("_smt_tmp",DomT,UIdDom), | |
568 | unique_typed_id("_smt_tmp",RanT,UIdRan), | |
569 | create_texpr(couple(UIdDom,UIdRan),couple(DomT,RanT),[],UIdCouple), | |
570 | create_texpr(member(UIdCouple,ID),pred,[],CoupleInID), | |
571 | create_exists([UIdRan],CoupleInID,RHS), | |
572 | create_texpr(member(UIdDom,Dom),pred,[],LHS), | |
573 | create_implication(LHS,RHS,FunConsInner), | |
574 | create_forall([UIdDom],FunConsInner,FunConstraint), | |
575 | create_texpr(relations(Dom,Ran),set(set(couple(DomT,RanT))),[],Relations), | |
576 | create_texpr(member(ID,Relations),pred,[],IsRelation), | |
577 | ConstraintOut = conjunct(IsRelation,FunConstraint). | |
578 | rewrite_member_of_function(ID,Function,ConstraintOut) :- | |
579 | get_texpr_expr(Function,surjection_relation(Dom,Ran)), | |
580 | get_texpr_type(Function,set(set(couple(DomT,RanT)))), | |
581 | % surjection_relation: relation & ran = T | |
582 | create_texpr(range(ID),set(RanT),[],Range), | |
583 | create_texpr(equal(Range,Ran),pred,[],FunConstraint), | |
584 | create_texpr(relations(Dom,Ran),set(set(couple(DomT,RanT))),[],Relations), | |
585 | create_texpr(member(ID,Relations),pred,[],IsRelation), | |
586 | ConstraintOut = conjunct(IsRelation,FunConstraint). | |
587 | rewrite_member_of_function(ID,Function,ConstraintOut) :- | |
588 | get_texpr_expr(Function,total_surjection_relation(Dom,Ran)), | |
589 | get_texpr_type(Function,set(set(couple(DomT,RanT)))), | |
590 | % total_surjection_relation: total_relation & surjection_relation | |
591 | create_texpr(total_relation(Dom,Ran),set(set(couple(DomT,RanT))),[],TotalRelations), | |
592 | create_texpr(member(ID,TotalRelations),pred,[],IsTotalRelation), | |
593 | create_texpr(surjection_relation(Dom,Ran),set(set(couple(DomT,RanT))),[],SurjectionRelations), | |
594 | create_texpr(member(ID,SurjectionRelations),pred,[],IsSurjectionRelation), | |
595 | ConstraintOut = conjunct(IsTotalRelation,IsSurjectionRelation). | |
596 | % functions | |
597 | rewrite_member_of_function(ID,Function,ConstraintOut) :- | |
598 | get_texpr_expr(Function,partial_function(Dom,Ran)), | |
599 | get_texpr_type(Function,set(set(couple(DomT,RanT)))), | |
600 | % partial_function: relation & !(x,y,z).((x,y) : ID & (x,z) : ID => y = z) | |
601 | unique_typed_id("_smt_tmp",DomT,UIdDom), | |
602 | unique_typed_id("_smt_tmp",RanT,UIdRan), | |
603 | unique_typed_id("_smt_tmp",RanT,UIdRan2), | |
604 | create_texpr(couple(UIdDom,UIdRan),couple(DomT,RanT),[],UIdCouple), | |
605 | create_texpr(couple(UIdDom,UIdRan2),couple(DomT,RanT),[],UIdCouple2), | |
606 | create_texpr(member(UIdCouple,ID),pred,[],C1InID), | |
607 | create_texpr(member(UIdCouple2,ID),pred,[],C2InID), | |
608 | create_texpr(equal(UIdRan,UIdRan2),pred,[],RHS), | |
609 | conjunct_predicates([C1InID,C2InID],LHS), | |
610 | create_implication(LHS,RHS,FunConsInner), | |
611 | create_forall([UIdDom,UIdRan,UIdRan2],FunConsInner,FunConstraint), | |
612 | % add typing: is a relation | |
613 | create_texpr(relations(Dom,Ran),set(set(couple(DomT,RanT))),[],Relations), | |
614 | create_texpr(member(ID,Relations),pred,[],IsRelation), | |
615 | ConstraintOut = conjunct(IsRelation,FunConstraint). | |
616 | rewrite_member_of_function(ID,Function,ConstraintOut) :- | |
617 | get_texpr_expr(Function,total_function(Dom,Ran)), | |
618 | get_texpr_type(Function,set(set(couple(DomT,RanT)))), | |
619 | % total_function: partial_function & !(x).(x : Dom => #(y).(y : Ran & (x,y):Id)) | |
620 | unique_typed_id("_smt_tmp",DomT,UIdDom), | |
621 | unique_typed_id("_smt_tmp",RanT,UIdRan), | |
622 | create_texpr(couple(UIdDom,UIdRan),couple(DomT,RanT),[],UIdCouple), | |
623 | create_texpr(member(UIdCouple,ID),pred,[],CoupleInID), | |
624 | create_exists([UIdRan],CoupleInID,RHS), | |
625 | create_texpr(member(UIdDom,Dom),pred,[],LHS), | |
626 | create_implication(LHS,RHS,FunConsInner), | |
627 | create_forall([UIdDom],FunConsInner,FunConstraint), | |
628 | % add typing: is a partial_function | |
629 | create_texpr(partial_function(Dom,Ran),set(set(couple(DomT,RanT))),[],PFunctions), | |
630 | create_texpr(member(ID,PFunctions),pred,[],IsPFunction), | |
631 | ConstraintOut = conjunct(IsPFunction,FunConstraint). | |
632 | % injections | |
633 | rewrite_member_of_function(ID,Function,ConstraintOut) :- | |
634 | get_texpr_expr(Function,partial_injection(Dom,Ran)), | |
635 | get_texpr_type(Function,set(set(couple(DomT,RanT)))), | |
636 | % partial_injection: partial_function & !(x1,x2,y).((x1,y) : ID & (x2,y) : ID => x1 = x2) | |
637 | unique_typed_id("_smt_tmp",DomT,UIdDom1), | |
638 | unique_typed_id("_smt_tmp",DomT,UIdDom2), | |
639 | unique_typed_id("_smt_tmp",RanT,UIdRan), | |
640 | create_texpr(couple(UIdDom1,UIdRan),couple(DomT,RanT),[],UIdCouple), | |
641 | create_texpr(couple(UIdDom2,UIdRan),couple(DomT,RanT),[],UIdCouple2), | |
642 | create_texpr(member(UIdCouple,ID),pred,[],C1InID), | |
643 | create_texpr(member(UIdCouple2,ID),pred,[],C2InID), | |
644 | create_texpr(equal(UIdDom1,UIdDom2),pred,[],RHS), | |
645 | conjunct_predicates([C1InID,C2InID],LHS), | |
646 | create_implication(LHS,RHS,FunConsInner), | |
647 | create_forall([UIdDom1,UIdDom2,UIdRan],FunConsInner,FunConstraint), | |
648 | % add typing: is a partial_function | |
649 | create_texpr(partial_function(Dom,Ran),set(set(couple(DomT,RanT))),[],PartialFunctions), | |
650 | create_texpr(member(ID,PartialFunctions),pred,[],IsPartialFunction), | |
651 | ConstraintOut = conjunct(IsPartialFunction,FunConstraint). | |
652 | rewrite_member_of_function(ID,Function,ConstraintOut) :- | |
653 | get_texpr_expr(Function,total_injection(Dom,Ran)), | |
654 | get_texpr_type(Function,set(set(couple(DomT,RanT)))), | |
655 | % total_injection: total_function & partial_injection | |
656 | create_texpr(total_function(Dom,Ran),set(set(couple(DomT,RanT))),[],TotalFunctions), | |
657 | create_texpr(member(ID,TotalFunctions),pred,[],IsTotalFunction), | |
658 | create_texpr(partial_injection(Dom,Ran),set(set(couple(DomT,RanT))),[],PartialInjections), | |
659 | create_texpr(member(ID,PartialInjections),pred,[],IsPartialInjection), | |
660 | ConstraintOut = conjunct(IsTotalFunction,IsPartialInjection). | |
661 | % surjections | |
662 | rewrite_member_of_function(ID,Function,ConstraintOut) :- | |
663 | get_texpr_expr(Function,partial_surjection(Dom,Ran)), | |
664 | get_texpr_type(Function,set(set(couple(DomT,RanT)))), | |
665 | % partial_surjection: partial_function & ran = T | |
666 | create_texpr(range(ID),set(RanT),[],Range), | |
667 | create_texpr(equal(Range,Ran),pred,[],FunConstraint), | |
668 | % add typing: is a partial_function | |
669 | create_texpr(partial_function(Dom,Ran),set(set(couple(DomT,RanT))),[],PFunctions), | |
670 | create_texpr(member(ID,PFunctions),pred,[],IsPFunction), | |
671 | ConstraintOut = conjunct(IsPFunction,FunConstraint). | |
672 | rewrite_member_of_function(ID,Function,ConstraintOut) :- | |
673 | get_texpr_expr(Function,total_surjection(Dom,Ran)), | |
674 | get_texpr_type(Function,set(set(couple(DomT,RanT)))), | |
675 | % total_surjection: total_function & partial_surjection | |
676 | create_texpr(total_function(Dom,Ran),set(set(couple(DomT,RanT))),[],TotalFunctions), | |
677 | create_texpr(member(ID,TotalFunctions),pred,[],IsTotalFunction), | |
678 | create_texpr(partial_surjection(Dom,Ran),set(set(couple(DomT,RanT))),[],PartialSurjections), | |
679 | create_texpr(member(ID,PartialSurjections),pred,[],IsPartialSurjection), | |
680 | ConstraintOut = conjunct(IsTotalFunction,IsPartialSurjection). | |
681 | % bijections | |
682 | rewrite_member_of_function(ID,Function,ConstraintOut) :- | |
683 | get_texpr_expr(Function,partial_bijection(Dom,Ran)), | |
684 | get_texpr_type(Function,set(set(couple(DomT,RanT)))), | |
685 | % partial_bijection: partial_surjection & partial_injection | |
686 | create_texpr(partial_surjection(Dom,Ran),set(set(couple(DomT,RanT))),[],PartialSurjections), | |
687 | create_texpr(member(ID,PartialSurjections),pred,[],IsPartialSurjection), | |
688 | create_texpr(partial_injection(Dom,Ran),set(set(couple(DomT,RanT))),[],PartialInjections), | |
689 | create_texpr(member(ID,PartialInjections),pred,[],IsPartialInjection), | |
690 | ConstraintOut = conjunct(IsPartialSurjection,IsPartialInjection). | |
691 | rewrite_member_of_function(ID,Function,ConstraintOut) :- | |
692 | get_texpr_expr(Function,total_bijection(Dom,Ran)), | |
693 | get_texpr_type(Function,set(set(couple(DomT,RanT)))), | |
694 | % total_bijection: total_surjection & total_injection | |
695 | create_texpr(total_surjection(Dom,Ran),set(set(couple(DomT,RanT))),[],TotalSurjections), | |
696 | create_texpr(member(ID,TotalSurjections),pred,[],IsTotalSurjection), | |
697 | create_texpr(total_injection(Dom,Ran),set(set(couple(DomT,RanT))),[],TotalInjections), | |
698 | create_texpr(member(ID,TotalInjections),pred,[],IsTotalInjection), | |
699 | ConstraintOut = conjunct(IsTotalSurjection,IsTotalInjection). | |
700 | ||
701 | rewrite_equal_to_ge_le(ID,GlobalSet,Constraint) :- | |
702 | unique_typed_id("_smt_tmp",integer,UId), | |
703 | create_texpr(member(UId,ID),pred,[],UIdInSet), | |
704 | rewrite_member_to_ge_le(UId,GlobalSet,GeLeConstraints), | |
705 | create_texpr(GeLeConstraints,pred,[],GeLeTexpr), | |
706 | create_implication(UIdInSet,GeLeTexpr,Direction1), | |
707 | create_implication(GeLeTexpr,UIdInSet,Direction2), | |
708 | create_forall([UId],Direction1,FA1), | |
709 | create_forall([UId],Direction2,FA2), | |
710 | Constraint = conjunct(FA1,FA2). | |
711 | ||
712 | rewrite_member_to_ge_le(ID,Set,Constraint) :- | |
713 | get_texpr_expr(Set,interval(Low,High)), | |
714 | create_texpr(greater_equal(ID,Low),pred,[],Lower), | |
715 | create_texpr(greater_equal(High,ID),pred,[],Higher), | |
716 | Constraint = conjunct(Lower,Higher). | |
717 | rewrite_member_to_ge_le(ID,Set,Constraint) :- | |
718 | get_texpr_expr(Set,integer_set(Kind)), % no cut here see rule below | |
719 | bzero(BZero), bone(BOne), bminint(MinInt), bmaxint(MaxInt), | |
720 | create_texpr(greater_equal(ID,LowerBound),pred,[],Lower), | |
721 | create_texpr(greater_equal(UpperBound,ID),pred,[],Higher), | |
722 | Constraint = conjunct(Lower,Higher), | |
723 | (Kind = 'NAT' -> LowerBound = BZero, UpperBound = MaxInt ; | |
724 | Kind = 'NAT1' -> LowerBound = BOne, UpperBound = MaxInt ; | |
725 | Kind = 'INT' -> LowerBound = MinInt, UpperBound = MaxInt). | |
726 | rewrite_member_to_ge_le(ID,Set,Constraint) :- | |
727 | get_texpr_expr(Set,integer_set(Kind)), !, | |
728 | bzero(BZero), bone(BOne), | |
729 | (Kind = 'NATURAL' -> Constraint = greater_equal(ID,BZero) ; | |
730 | Kind = 'NATURAL1' -> Constraint = greater_equal(ID,BOne)). | |
731 | ||
732 | bzero(b(integer(0),integer,[])). | |
733 | bone(b(integer(1),integer,[])). | |
734 | bminint(b(min_int,integer,[])). | |
735 | bmaxint(b(max_int,integer,[])). | |
736 | ||
737 | constant_interval_as_list(FI,TI,[]) :- | |
738 | FI > TI. | |
739 | constant_interval_as_list(FI,FI,[BI]) :- | |
740 | !, create_texpr(integer(FI), integer, [], BI). | |
741 | constant_interval_as_list(FI,TI,[BI|BIs]) :- | |
742 | create_texpr(integer(FI), integer, [], BI), | |
743 | NFI is FI + 1, | |
744 | constant_interval_as_list(NFI,TI,BIs). |