1 | % (c) 2014-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(smtlib2_translation,[smt_type_to_prob_type/3, | |
6 | smt_term_to_prob_term/3, | |
7 | smt_type_to_prob_type_maplist/3, | |
8 | smt_term_to_prob_term_maplist/3, | |
9 | bool_to_pred/2, | |
10 | typing_constraint/2, | |
11 | is_function_constraint/3]). | |
12 | ||
13 | :- use_module(probsrc(module_information),[module_info/2]). | |
14 | :- module_info(group,smtlib). | |
15 | :- module_info(description,'The SMT-LIB 2 Interpreter - Translation from SMT-LIB 2 to B'). | |
16 | ||
17 | :- use_module(library(lists)). | |
18 | ||
19 | :- use_module(probsrc(bsyntaxtree),[get_texpr_type/2, | |
20 | get_texpr_expr/2, | |
21 | safe_create_texpr/3, | |
22 | create_forall/3, | |
23 | create_exists/3, | |
24 | create_couple/2, | |
25 | create_implication/3, | |
26 | conjunct_predicates/2, | |
27 | replace_id_by_expr/4]). | |
28 | ||
29 | :- use_module(smtlib_solver(smtlib2_environment)). | |
30 | ||
31 | chain(Op,[A,B],BPred) :- !, | |
32 | Pred =.. [Op,A,B], | |
33 | BPred = b(Pred,pred,[]). | |
34 | chain(Op,[First,Second|Further],TermOut) :- | |
35 | chain(Op,[First,Second],Pred), | |
36 | chain(Op,[Second|Further],FurtherPred), | |
37 | conjunct_predicates([Pred,FurtherPred],TermOut). | |
38 | ||
39 | interleave(_Op,[A],TermOut) :- !, TermOut=A. | |
40 | interleave(Op,[First|Further],TermOut) :- | |
41 | interleave(Op,Further,FurtherPred), | |
42 | get_texpr_type(FurtherPred,FurtherType), | |
43 | Pred =.. [Op,First,FurtherPred], | |
44 | safe_create_texpr(Pred,FurtherType,TermOut). | |
45 | ||
46 | :- use_module(probsrc(preferences), [get_preference/2]). | |
47 | :- use_module(probsrc(error_manager),[add_error/3]). | |
48 | smt_type_to_prob_type(sort('Int'),_,integer) :- !. | |
49 | smt_type_to_prob_type(sort('Bool'),_,boolean) :- !. | |
50 | smt_type_to_prob_type(sort('Array',[From,sort('Bool')]),E,Out) :- | |
51 | get_preference(smtlib2b_arrays_as_sets,true), | |
52 | !, % we could translate arrays to Bool as sets | |
53 | smt_type_to_prob_type(From,E,FromType), | |
54 | Out = set(FromType). | |
55 | smt_type_to_prob_type(sort('Array',[From,To]),E,Out) :- !, | |
56 | %format('Sort Array ~w to ~w~n',[From,To]),nl, | |
57 | smt_type_to_prob_type(From,E,FromType), | |
58 | smt_type_to_prob_type(To,E,ToType), | |
59 | Out = set(couple(FromType,ToType)). | |
60 | smt_type_to_prob_type(sort('BitVec',[_Length]),_E,Out) :- !, | |
61 | Out = set(couple(integer,integer)). | |
62 | smt_type_to_prob_type(sort('Set',[Sub]),E,Out) :- !, | |
63 | smt_type_to_prob_type(Sub,E,SubType), | |
64 | Out = set(SubType). | |
65 | smt_type_to_prob_type(sort(X),E,global(X)) :- | |
66 | is_custom_type(E,X), !. | |
67 | smt_type_to_prob_type(X,_,_) :- !, | |
68 | add_error(smtlib2_translation,'Unsupported sort in smt_type_to_prob_type:',X), fail. | |
69 | ||
70 | % special versions for maplist that keeps first argument indexing | |
71 | smt_term_to_prob_term_maplist(E,I,O) :- | |
72 | smt_term_to_prob_term(I,E,O). | |
73 | smt_type_to_prob_type_maplist(E,I,O) :- | |
74 | smt_type_to_prob_type(I,E,O). | |
75 | ||
76 | smt_term_to_prob_term(attributed_term(Term,_Attr),Env,Out) :- !, | |
77 | smt_term_to_prob_term(Term,Env,Out). | |
78 | smt_term_to_prob_term(id_term(id('not'),[Arg]),Env,Out) :- !, | |
79 | smt_term_to_prob_term(Arg,Env,BArg), | |
80 | get_texpr_type(BArg,Type), | |
81 | (Type = pred | |
82 | -> Out = b(negation(BArg),pred,[]) | |
83 | ; Out = b(equal(BArg,b(boolean_false,boolean,[])),pred,[])). | |
84 | smt_term_to_prob_term(id_term(id('-'),[SingleArg]),Env,Out) :- !, | |
85 | % special case for unary minus: can not be interleaved | |
86 | smt_term_to_prob_term(SingleArg,Env,BArg), | |
87 | Out = b(unary_minus(BArg),integer,[]). | |
88 | smt_term_to_prob_term(id_term(id('='),Args),Env,Out) :- !, | |
89 | maplist(smt_term_to_prob_term_maplist(Env),Args,BArgs), | |
90 | maplist(get_texpr_type,BArgs,Types), | |
91 | (member(pred,Types) | |
92 | -> maplist(bool_to_pred,BArgs,BArgsPreds), | |
93 | chain(equivalence,BArgsPreds,Out) | |
94 | ; chain(equal,BArgs,Out)). | |
95 | smt_term_to_prob_term(id_term(id('ite'),[Test,If,Then]),Env,Out) :- !, | |
96 | smt_term_to_prob_term(Test,Env,BTestT), | |
97 | smt_term_to_prob_term(If,Env,BIfT), | |
98 | smt_term_to_prob_term(Then,Env,BThenT), | |
99 | bool_to_pred(BTestT,BTest), | |
100 | to_bool_if_necessary(BIfT,BIf), | |
101 | to_bool_if_necessary(BThenT,BThen), | |
102 | get_texpr_type(BIf,Type), | |
103 | Out = b(if_then_else(BTest,BIf,BThen),Type,[]). | |
104 | % set logic | |
105 | smt_term_to_prob_term(id_term(id(member),[Element,Set]),Env,Out) :- !, | |
106 | smt_term_to_prob_term(Set,Env,BSet), | |
107 | smt_term_to_prob_term(Element,Env,BElement), | |
108 | Out = b(member(BElement,BSet),pred,[]). | |
109 | smt_term_to_prob_term(id_term(id(card),[Set]),Env,Out) :- !, | |
110 | smt_term_to_prob_term(Set,Env,BSet), | |
111 | Out = b(card(BSet),integer,[]). | |
112 | smt_term_to_prob_term(id_term(id(singleton),[Element]),Env,Out) :- !, | |
113 | smt_term_to_prob_term(Element,Env,BElement), | |
114 | get_texpr_type(BElement,ElementType), | |
115 | Out = b(set_extension([BElement]),set(ElementType),[]). | |
116 | smt_term_to_prob_term(id_term(id(union),[SetA,SetB]),Env,Out) :- !, | |
117 | smt_term_to_prob_term(SetA,Env,BSetA), | |
118 | smt_term_to_prob_term(SetB,Env,BSetB), | |
119 | get_texpr_type(BSetB,Type), | |
120 | Out = b(union(BSetA,BSetB),Type,[]). | |
121 | smt_term_to_prob_term(id_term(id(intersection),[SetA,SetB]),Env,Out) :- !, | |
122 | smt_term_to_prob_term(SetA,Env,BSetA), | |
123 | smt_term_to_prob_term(SetB,Env,BSetB), | |
124 | get_texpr_type(BSetB,Type), | |
125 | Out = b(intersection(BSetA,BSetB),Type,[]). | |
126 | smt_term_to_prob_term(id_term(id(subset),[SetA,SetB]),Env,Out) :- !, | |
127 | smt_term_to_prob_term(SetA,Env,BSetA), | |
128 | smt_term_to_prob_term(SetB,Env,BSetB), | |
129 | Out = b(subset(BSetA,BSetB),pred,[]). | |
130 | % array logics | |
131 | smt_term_to_prob_term(id_term(id('store'),[Array,Index,Element]),Env,Out) :- !, | |
132 | smt_term_to_prob_term(Array,Env,BArray), | |
133 | get_texpr_type(BArray,ArrayType), | |
134 | ArrayType = set(CoupleType), | |
135 | smt_term_to_prob_term(Index,Env,BIndex), | |
136 | smt_term_to_prob_term(Element,Env,BElement), | |
137 | % TO DO: generate union or set_difference depending on Element=true or false when smtlib2b_arrays_as_sets | |
138 | % store(X,Index,El) = IF El=TRUE THEN X \/ {Index} ELSE X \ {Index} END | |
139 | SetEx = b(set_extension([b(couple(BIndex,BElement),CoupleType,[])]),ArrayType,[]), | |
140 | Out = b(overwrite(BArray,SetEx),ArrayType,[]). | |
141 | smt_term_to_prob_term(id_term(id('select'),[Array,Index]),Env,Out) :- !, | |
142 | smt_term_to_prob_term(Array,Env,BArray), | |
143 | smt_term_to_prob_term(Index,Env,BIndex), | |
144 | get_texpr_type(BArray,ArrayType), | |
145 | %format('select of array ~w (type: ~w) at index ~w~n',[Array,ArrayType,Index]), | |
146 | (ArrayType = set(couple(_From,To)) % Array was translated as total function From --> To | |
147 | -> Out = b(function(BArray,BIndex),To,[]) | |
148 | ; ArrayType = set(_From), % Array was translated as set (smtlib2b_arrays_as_sets=true) | |
149 | MEM = b(member(BIndex,BArray),pred,[]), | |
150 | Out = b(convert_bool(MEM),boolean,[]) | |
151 | ). | |
152 | % bitvector logics | |
153 | smt_term_to_prob_term(id_term(id('concat'),[A,B]),Env,Out) :- !, | |
154 | smt_term_to_prob_term(A,Env,BA), | |
155 | smt_term_to_prob_term(B,Env,BB), | |
156 | bvwidth(BA,WidthA), | |
157 | bvwidth(BB,WidthB), | |
158 | WidthBP1 = b(add(WidthB,Int1),integer,[]), | |
159 | Int0 = b(integer(0),integer,[]), | |
160 | Int1 = b(integer(1),integer,[]), | |
161 | IdX1 = b(identifier('\\tmp1'),integer,[]), | |
162 | IdX2 = b(identifier('\\tmp2'),integer,[]), | |
163 | FullWidth = b(add(b(add(WidthA,WidthB),integer,[]),Int1),integer,[]), | |
164 | TypeOfX1 = b(member(IdX1,b(interval(Int0,FullWidth),set(integer),[])),pred,[]), | |
165 | TypeOfX2 = b(member(IdX2,b(interval(Int0,Int1),set(integer),[])),pred,[]), | |
166 | ValOfX2 = b(if_then_else(b(less_equal(IdX1,WidthB),pred,[]), | |
167 | b(function(BB,IdX1),integer,[]), | |
168 | b(function(BA,b(minus(IdX1,WidthBP1),integer,[])),integer,[])),integer,[]), | |
169 | conjunct_predicates([TypeOfX1,TypeOfX2,b(equal(IdX2,ValOfX2),pred,[])],Pred), | |
170 | Out = b(comprehension_set([IdX1,IdX2],Pred),set(couple(integer,integer)),[]). | |
171 | smt_term_to_prob_term(id_term(id(zero_extend(NewLength)),[A]),Env,Out) :- !, | |
172 | smt_term_to_prob_term(A,Env,BA), | |
173 | bvwidth(BA,WidthA), | |
174 | WidthAP1 = b(add(WidthA,Int1),integer,[]), | |
175 | Int0 = b(integer(0),integer,[]), | |
176 | Int1 = b(integer(1),integer,[]), | |
177 | IdX1 = b(identifier('\\tmp1'),integer,[]), | |
178 | IdX2 = b(identifier('\\tmp2'),integer,[]), | |
179 | FullWidth = b(add(WidthA,b(integer(NewLength),integer,[])),integer,[]), | |
180 | TypeOfX1 = b(member(IdX1,b(interval(Int0,FullWidth),set(integer),[])),pred,[]), | |
181 | TypeOfX2 = b(member(IdX2,b(interval(Int0,Int1),set(integer),[])),pred,[]), | |
182 | ValOfX2 = b(if_then_else(b(less_equal(IdX1,WidthA),pred,[]), | |
183 | b(integer(0),integer,[]), | |
184 | b(function(BA,b(minus(IdX1,WidthAP1),integer,[])),integer,[])),integer,[]), | |
185 | conjunct_predicates([TypeOfX1,TypeOfX2,b(equal(IdX2,ValOfX2),pred,[])],Pred), | |
186 | Out = b(comprehension_set([IdX1,IdX2],Pred),set(couple(integer,integer)),[]). | |
187 | smt_term_to_prob_term(id_term(id(sign_extend(NewLength)),[A]),Env,Out) :- !, | |
188 | smt_term_to_prob_term(A,Env,BA), | |
189 | bvwidth(BA,WidthA), | |
190 | Int0 = b(integer(0),integer,[]), | |
191 | Int1 = b(integer(1),integer,[]), | |
192 | IdX1 = b(identifier('\\tmp1'),integer,[]), | |
193 | IdX2 = b(identifier('\\tmp2'),integer,[]), | |
194 | WidthAP1 = b(add(WidthA,Int1),integer,[]), | |
195 | FullWidth = b(add(WidthA,b(integer(NewLength),integer,[])),integer,[]), | |
196 | TypeOfX1 = b(member(IdX1,b(interval(Int0,FullWidth),set(integer),[])),pred,[]), | |
197 | TypeOfX2 = b(member(IdX2,b(interval(Int0,Int1),set(integer),[])),pred,[]), | |
198 | ValOfX2 = b(if_then_else(b(less_equal(IdX1,WidthA),pred,[]), | |
199 | b(function(BA,IdX1),integer,[]), | |
200 | b(function(BA,b(minus(IdX1,WidthAP1),integer,[])),integer,[])),integer,[]), | |
201 | conjunct_predicates([TypeOfX1,TypeOfX2,b(equal(IdX2,ValOfX2),pred,[])],Pred), | |
202 | Out = b(comprehension_set([IdX1,IdX2],Pred),set(couple(integer,integer)),[]). | |
203 | smt_term_to_prob_term(id_term(id(extract(I,J)),[S]),Env,Out) :- !, | |
204 | BI = b(integer(I),integer,[]), | |
205 | BJ = b(integer(J),integer,[]), | |
206 | smt_term_to_prob_term(S,Env,BS), | |
207 | Int0 = b(integer(0),integer,[]), | |
208 | Int1 = b(integer(1),integer,[]), | |
209 | DomX1 = b(add(b(minus(BI,BJ),integer,[]),Int1),integer,[]), | |
210 | IdX1 = b(identifier('\\tmp1'),integer,[]), | |
211 | IdX2 = b(identifier('\\tmp2'),integer,[]), | |
212 | TypeOfX1 = b(member(IdX1,b(interval(Int0,DomX1),set(integer),[])),pred,[]), | |
213 | TypeOfX2 = b(member(IdX2,b(interval(Int0,Int1),set(integer),[])),pred,[]), | |
214 | ValOfX2 = b(function(BS,IdX1),integer,[]), | |
215 | conjunct_predicates([TypeOfX1,TypeOfX2,b(equal(IdX2,ValOfX2),pred,[])],Pred), | |
216 | Out = b(comprehension_set([IdX1,IdX2],Pred),set(couple(integer,integer)),[]). | |
217 | smt_term_to_prob_term(id_term(id('bvnot'),[A]),Env,Out) :- !, | |
218 | smt_term_to_prob_term(A,Env,BA), | |
219 | bvwidth(BA,Width), | |
220 | Int0 = b(integer(0),integer,[]), | |
221 | Int1 = b(integer(1),integer,[]), | |
222 | IdX1 = b(identifier('\\tmp1'),integer,[]), | |
223 | IdX2 = b(identifier('\\tmp2'),integer,[]), | |
224 | TypeOfX1 = b(member(IdX1,b(interval(Int0,Width),set(integer),[])),pred,[]), | |
225 | TypeOfX2 = b(member(IdX2,b(interval(Int0,Int1),set(integer),[])),pred,[]), | |
226 | ValOfX2 = b(if_then_else(b(equal(b(function(BA,IdX1),integer,[]),Int0),pred,[]),Int1,Int0),integer,[]), | |
227 | conjunct_predicates([TypeOfX1,TypeOfX2,b(equal(IdX2,ValOfX2),pred,[])],Pred), | |
228 | Out = b(comprehension_set([IdX1,IdX2],Pred),set(couple(integer,integer)),[]). | |
229 | smt_term_to_prob_term(id_term(id('bvand'),[A,B]),Env,Out) :- !, | |
230 | smt_term_to_prob_term(A,Env,BA), | |
231 | smt_term_to_prob_term(B,Env,BB), | |
232 | bvwidth(BA,Width), | |
233 | Int0 = b(integer(0),integer,[]), | |
234 | Int1 = b(integer(1),integer,[]), | |
235 | IdX1 = b(identifier('\\tmp1'),integer,[]), | |
236 | IdX2 = b(identifier('\\tmp2'),integer,[]), | |
237 | TypeOfX1 = b(member(IdX1,b(interval(Int0,Width),set(integer),[])),pred,[]), | |
238 | TypeOfX2 = b(member(IdX2,b(interval(Int0,Int1),set(integer),[])),pred,[]), | |
239 | ValOfX2 = b(if_then_else(b(equal(b(function(BA,IdX1),integer,[]),Int0),pred,[]),Int0,b(function(BB,IdX1),integer,[])),integer,[]), | |
240 | conjunct_predicates([TypeOfX1,TypeOfX2,b(equal(IdX2,ValOfX2),pred,[])],Pred), | |
241 | Out = b(comprehension_set([IdX1,IdX2],Pred),set(couple(integer,integer)),[]). | |
242 | smt_term_to_prob_term(id_term(id('bvor'),[A,B]),Env,Out) :- !, | |
243 | smt_term_to_prob_term(A,Env,BA), | |
244 | smt_term_to_prob_term(B,Env,BB), | |
245 | bvwidth(BA,Width), | |
246 | Int0 = b(integer(0),integer,[]), | |
247 | Int1 = b(integer(1),integer,[]), | |
248 | IdX1 = b(identifier('\\tmp1'),integer,[]), | |
249 | IdX2 = b(identifier('\\tmp2'),integer,[]), | |
250 | TypeOfX1 = b(member(IdX1,b(interval(Int0,Width),set(integer),[])),pred,[]), | |
251 | TypeOfX2 = b(member(IdX2,b(interval(Int0,Int1),set(integer),[])),pred,[]), | |
252 | ValOfX2 = b(if_then_else(b(equal(b(function(BA,IdX1),integer,[]),Int1),pred,[]),Int1,b(function(BB,IdX1),integer,[])),integer,[]), | |
253 | conjunct_predicates([TypeOfX1,TypeOfX2,b(equal(IdX2,ValOfX2),pred,[])],Pred), | |
254 | Out = b(comprehension_set([IdX1,IdX2],Pred),set(couple(integer,integer)),[]). | |
255 | smt_term_to_prob_term(id_term(id('bvxor'),[A,B]),Env,Out) :- !, | |
256 | smt_term_to_prob_term(A,Env,BA), | |
257 | smt_term_to_prob_term(B,Env,BB), | |
258 | bvwidth(BA,Width), | |
259 | Int0 = b(integer(0),integer,[]), | |
260 | Int1 = b(integer(1),integer,[]), | |
261 | IdX1 = b(identifier('\\tmp1'),integer,[]), | |
262 | IdX2 = b(identifier('\\tmp2'),integer,[]), | |
263 | TypeOfX1 = b(member(IdX1,b(interval(Int0,Width),set(integer),[])),pred,[]), | |
264 | TypeOfX2 = b(member(IdX2,b(interval(Int0,Int1),set(integer),[])),pred,[]), | |
265 | ValOfX2 = b(if_then_else(b(equal(b(function(BA,IdX1),integer,[]),b(function(BB,IdX1),integer,[])),pred,[]),Int0,Int1),integer,[]), | |
266 | conjunct_predicates([TypeOfX1,TypeOfX2,b(equal(IdX2,ValOfX2),pred,[])],Pred), | |
267 | Out = b(comprehension_set([IdX1,IdX2],Pred),set(couple(integer,integer)),[]). | |
268 | smt_term_to_prob_term(id_term(id('bvult'),[A,B]),Env,Out) :- !, | |
269 | bv_to_nat_and_compare(A,B,less,Env,Out). | |
270 | smt_term_to_prob_term(id_term(id('bvule'),[A,B]),Env,Out) :- !, | |
271 | bv_to_nat_and_compare(A,B,less_equal,Env,Out). | |
272 | smt_term_to_prob_term(id_term(id('bvuge'),[A,B]),Env,Out) :- !, | |
273 | bv_to_nat_and_compare(A,B,greater_equal,Env,Out). | |
274 | smt_term_to_prob_term(id_term(id('bvugt'),[A,B]),Env,Out) :- !, | |
275 | bv_to_nat_and_compare(A,B,greater,Env,Out). | |
276 | smt_term_to_prob_term(id_term(id('bvslt'),[A,B]),Env,Out) :- !, | |
277 | signed_bv_to_nat_and_compare(A,B,less,Env,Out). | |
278 | smt_term_to_prob_term(id_term(id('bvsle'),[A,B]),Env,Out) :- !, | |
279 | signed_bv_to_nat_and_compare(A,B,less_equal,Env,Out). | |
280 | smt_term_to_prob_term(id_term(id('bvsge'),[A,B]),Env,Out) :- !, | |
281 | signed_bv_to_nat_and_compare(A,B,greater_equal,Env,Out). | |
282 | smt_term_to_prob_term(id_term(id('bvsgt'),[A,B]),Env,Out) :- !, | |
283 | signed_bv_to_nat_and_compare(A,B,greater,Env,Out). | |
284 | smt_term_to_prob_term(id_term(id('bvneg'),[A]),Env,Out) :- !, | |
285 | smt_term_to_prob_term(A,Env,BA), | |
286 | bvwidth(BA,Width), | |
287 | WidthP1 = b(add(Width,b(integer(1),integer,[])),integer,[]), | |
288 | bv2nat(BA,BANat), | |
289 | Int2 = b(integer(2),integer,[]), | |
290 | Pow = b(power_of(Int2,WidthP1),integer,[]), | |
291 | Differenz = b(minus(Pow,BANat),integer,[]), | |
292 | nat2bv(Differenz,Width,Out). | |
293 | smt_term_to_prob_term(id_term(id('bvadd'),[A,B]),Env,Out) :- !, | |
294 | smt_term_to_prob_term(A,Env,BA), | |
295 | smt_term_to_prob_term(B,Env,BB), | |
296 | bvwidth(BA,Width), | |
297 | bv2nat(BA,BANat), | |
298 | bv2nat(BB,BBNat), | |
299 | Sum = b(add(BANat,BBNat),integer,[]), | |
300 | nat2bv(Sum,Width,Out). | |
301 | smt_term_to_prob_term(id_term(id('bvsub'),[A,B]),Env,Out) :- !, | |
302 | smt_term_to_prob_term(A,Env,BA), | |
303 | smt_term_to_prob_term(B,Env,BB), | |
304 | bvwidth(BA,Width), | |
305 | bv2nat(BA,BANat), | |
306 | bv2nat(BB,BBNat), | |
307 | Sum = b(minus(BANat,BBNat),integer,[]), | |
308 | nat2bv(Sum,Width,Out). | |
309 | smt_term_to_prob_term(id_term(id('bvmul'),[A,B]),Env,Out) :- !, | |
310 | smt_term_to_prob_term(A,Env,BA), | |
311 | smt_term_to_prob_term(B,Env,BB), | |
312 | bvwidth(BA,Width), | |
313 | bv2nat(BA,BANat), | |
314 | bv2nat(BB,BBNat), | |
315 | Prod = b(multiplication(BANat,BBNat),integer,[]), | |
316 | nat2bv(Prod,Width,Out). | |
317 | smt_term_to_prob_term(id_term(id('bvudiv'),[A,B]),Env,Out) :- !, | |
318 | smt_term_to_prob_term(A,Env,BA), | |
319 | smt_term_to_prob_term(B,Env,BB), | |
320 | bvwidth(BA,Width), | |
321 | bv2nat(BA,BANat), | |
322 | bv2nat(BB,BBNat), | |
323 | Div = b(div(BANat,BBNat),integer,[]), | |
324 | nat2bv(Div,Width,Out). | |
325 | smt_term_to_prob_term(id_term(id('bvurem'),[A,B]),Env,Out) :- !, | |
326 | smt_term_to_prob_term(A,Env,BA), | |
327 | smt_term_to_prob_term(B,Env,BB), | |
328 | bvwidth(BA,Width), | |
329 | bv2nat(BA,BANat), | |
330 | bv2nat(BB,BBNat), | |
331 | Rem = b(modulo(BANat,BBNat),integer,[]), | |
332 | nat2bv(Rem,Width,Out). | |
333 | smt_term_to_prob_term(id_term(id('bvshl'),[A,B]),Env,Out) :- !, | |
334 | smt_term_to_prob_term(A,Env,BA), | |
335 | smt_term_to_prob_term(B,Env,BB), | |
336 | bvwidth(BA,Width), | |
337 | bv2nat(BA,BANat), | |
338 | bv2nat(BB,BBNat), | |
339 | Int2 = b(integer(2),integer,[]), | |
340 | Exp = b(power_of(Int2,BBNat),integer,[]), | |
341 | Res = b(multiplication(BANat,Exp),integer,[]), | |
342 | nat2bv(Res,Width,Out). | |
343 | smt_term_to_prob_term(id_term(id('bvlshr'),[A,B]),Env,Out) :- !, | |
344 | smt_term_to_prob_term(A,Env,BA), | |
345 | smt_term_to_prob_term(B,Env,BB), | |
346 | bvwidth(BA,Width), | |
347 | bv2nat(BA,BANat), | |
348 | bv2nat(BB,BBNat), | |
349 | Int2 = b(integer(2),integer,[]), | |
350 | Exp = b(power_of(Int2,BBNat),integer,[]), | |
351 | Res = b(div(BANat,Exp),integer,[]), | |
352 | nat2bv(Res,Width,Out). | |
353 | % division is a special case, because it has a different | |
354 | % semantic in B and SMT-LIB | |
355 | smt_term_to_prob_term(id_term(id(div),[Dividend|Divisors]),Env,Out) :- !, | |
356 | smt_term_to_prob_term(id_term(id('*'),Divisors),Env,BDivisor), | |
357 | smt_term_to_prob_term(Dividend,Env,BDividend), | |
358 | Zero = b(integer(0),integer,[]), | |
359 | DividendLessZero = b(less(BDividend,Zero),pred,[]), | |
360 | DivisorLessZero = b(less(BDivisor,Zero),pred,[]), | |
361 | DivisorGreaterZero = b(greater(BDivisor,Zero),pred,[]), | |
362 | DivisorMinusOne = b(minus(BDivisor,b(integer(1),integer,[])),integer,[]), | |
363 | DivisorPlusOne = b(add(BDivisor,b(integer(1),integer,[])),integer,[]), | |
364 | MinusDivisorPlusOne = b(unary_minus(DivisorPlusOne),integer,[]), | |
365 | ||
366 | conjunct_predicates([DividendLessZero,DivisorGreaterZero],If1), | |
367 | conjunct_predicates([DividendLessZero,DivisorLessZero],If2), | |
368 | ||
369 | FixInner = b(if_then_else(If2,MinusDivisorPlusOne,Zero),integer,[]), | |
370 | Fix = b(if_then_else(If1,DivisorMinusOne,FixInner),integer,[]), | |
371 | NewBDividend = b(minus(BDividend,Fix),integer,[]), | |
372 | Out = b(div(NewBDividend,BDivisor),integer,[]). | |
373 | % general cases | |
374 | smt_term_to_prob_term(id_term(id(Id),Args),Env,Out) :- | |
375 | smt_id_to_prob_id_preds(Id,BId), !, | |
376 | maplist(smt_term_to_prob_term_maplist(Env),Args,BArgs), | |
377 | maplist(bool_to_pred,BArgs,PredBArgs), | |
378 | interleave(BId,PredBArgs,Out). | |
379 | smt_term_to_prob_term(id_term(id(Id),Args),Env,Out) :- | |
380 | smt_id_to_prob_id(Id,BId,ConnectingPred), !, | |
381 | maplist(smt_term_to_prob_term_maplist(Env),Args,BArgs), | |
382 | call(ConnectingPred,BId,BArgs,Out). | |
383 | smt_term_to_prob_term(id_term(id(Id),Args),Env,Out) :- | |
384 | get_function(Id,Env,Params,_Results,Definition), !, | |
385 | replace_identifiers(Params,Args,Definition,Out,Env). | |
386 | smt_term_to_prob_term(id_term(id(Id),Args),Env,Out) :- | |
387 | get_type(Id,Env,set(couple(_X,Y))), !, | |
388 | smt_term_to_prob_term(id(Id),Env,BId), | |
389 | maplist(smt_term_to_prob_term_maplist(Env),Args,BArgs), | |
390 | create_couple(BArgs,BArg), | |
391 | Out = b(function(BId,BArg),Y,[]). | |
392 | smt_term_to_prob_term(id(true),_,b(boolean_true,boolean,[])) :- !. | |
393 | smt_term_to_prob_term(id(false),_,b(boolean_false,boolean,[])) :- !. | |
394 | smt_term_to_prob_term(id(Id),Env,OutId) :- !, | |
395 | get_type(Id,Env,Type), | |
396 | OutId = b(identifier(Id),Type,[]).%, | |
397 | %(Type = boolean | |
398 | % -> bool_to_pred(OutId,Out) | |
399 | % ; Out = OutId). | |
400 | smt_term_to_prob_term(id(Id,Sort),Env,OutId) :- !, | |
401 | smt_type_to_prob_type(Sort,Env,Type), | |
402 | OutId = b(identifier(Id),Type,[]). | |
403 | smt_term_to_prob_term(svar(Id,Sort),Env,Out) :- !, | |
404 | smt_type_to_prob_type(Sort,Env,Type), | |
405 | Out = b(identifier(Id),Type,[]). | |
406 | smt_term_to_prob_term(integer(I),_,b(integer(I),integer,[])) :- !. | |
407 | smt_term_to_prob_term(let(Bindings,Term),Env,BTerm) :- !, | |
408 | let_equalities_and_bids(Bindings,BIDs,Assignments,Env), | |
409 | create_local_env(Env,BIDs,LocalEnv), | |
410 | smt_term_to_prob_term(Term,LocalEnv,InnerBTerm), | |
411 | get_texpr_type(InnerBTerm,InnerType), | |
412 | (InnerType = pred | |
413 | -> safe_create_texpr(let_predicate(BIDs,Assignments,InnerBTerm),pred,BTerm) | |
414 | ; safe_create_texpr(let_expression(BIDs,Assignments,InnerBTerm),InnerType,BTerm)). | |
415 | smt_term_to_prob_term(forall(IDs,Term),Env,Forall) :- !, | |
416 | maplist(smt_term_to_prob_term_maplist(Env),IDs,Identifiers), | |
417 | create_local_env(Env,Identifiers,LocalEnv), | |
418 | smt_term_to_prob_term(Term,LocalEnv,InnerTerm), | |
419 | convlist(typing_constraint,IDs,InnerConstraints), | |
420 | bool_to_pred(InnerTerm,InnerTermAsPred), % necessary ?? | |
421 | conjunct_predicates(InnerConstraints,LHS), | |
422 | create_implication(LHS,InnerTermAsPred,Body), | |
423 | create_forall(Identifiers,Body,Forall). | |
424 | smt_term_to_prob_term(exists(IDs,Term),Env,Forall) :- !, | |
425 | maplist(smt_term_to_prob_term_maplist(Env),IDs,Identifiers), | |
426 | create_local_env(Env,Identifiers,LocalEnv), | |
427 | smt_term_to_prob_term(Term,LocalEnv,InnerTerm), | |
428 | convlist(typing_constraint,IDs,InnerConstraints), | |
429 | append(InnerConstraints,[InnerTerm],IList), | |
430 | conjunct_predicates(IList,Inner), | |
431 | bool_to_pred(Inner,InnerAsPred), | |
432 | create_exists(Identifiers,InnerAsPred,Forall). | |
433 | smt_term_to_prob_term(bitvector(Value,Length),_Env,Out) :- !, | |
434 | integer_to_binary_couples(Value,Length,Couples), | |
435 | Out = b(set_extension(Couples),set(couple(integer,integer)),[]). | |
436 | smt_term_to_prob_term(bitvector(Bits),_Env,Out) :- !, | |
437 | binary_to_binary_couples(Bits,Couples), | |
438 | Out = b(set_extension(Couples),set(couple(integer,integer)),[]). | |
439 | smt_term_to_prob_term(X,_,_) :- | |
440 | add_error(smtlib2_translation,'Unsupported term in smt_term_to_prob_term:',X), fail. | |
441 | ||
442 | ||
443 | bool_to_pred(Bool,Pred) :- | |
444 | get_texpr_expr(Bool,convert_bool(Pred)), !. | |
445 | bool_to_pred(Bool,Pred) :- | |
446 | get_texpr_type(Bool,boolean), !, | |
447 | safe_create_texpr(equal(Bool,b(boolean_true,boolean,[])),pred,Pred). | |
448 | bool_to_pred(Bool,Bool) :- | |
449 | get_texpr_type(Bool,pred), !. | |
450 | ||
451 | to_bool_if_necessary(PossiblePred,Bool) :- | |
452 | get_texpr_type(PossiblePred,pred), !, | |
453 | safe_create_texpr(convert_bool(PossiblePred),boolean,Bool). | |
454 | to_bool_if_necessary(NonPred,NonPred). | |
455 | ||
456 | let_equalities_and_bids([bind(ID,Term)],[IDTerm],[AssOut],Env) :- !, | |
457 | smt_term_to_prob_term(Term,Env,Ass), | |
458 | get_texpr_type(Ass,IdentifierType), | |
459 | (IdentifierType == pred | |
460 | -> IDTerm = b(identifier(ID),boolean,[]), | |
461 | safe_create_texpr(convert_bool(Ass),boolean,AssOut) | |
462 | ; IDTerm = b(identifier(ID),IdentifierType,[]), | |
463 | AssOut = Ass). | |
464 | let_equalities_and_bids([bind(ID,Term)|Further],[IDTerm|FurtherIdentifiers],Assignments,Env) :- | |
465 | let_equalities_and_bids([bind(ID,Term)],[IDTerm],FirstAssignment,Env), | |
466 | let_equalities_and_bids(Further,FurtherIdentifiers,FurtherAssignments,Env), | |
467 | append(FirstAssignment,FurtherAssignments,Assignments). | |
468 | ||
469 | replace_identifiers([],[],D,D,_Env). | |
470 | replace_identifiers([b(identifier(I),_,_)|T1],[Term|Terms],In,Out,Env) :- | |
471 | smt_term_to_prob_term(Term,Env,BTerm), | |
472 | replace_id_by_expr(In,I,BTerm,TOut), | |
473 | replace_identifiers(T1,Terms,TOut,Out,Env). | |
474 | ||
475 | % certain sorts enforce an inner constrait to strengthen their type | |
476 | typing_constraint(svar(Name,sort('Array',[Index,Element])),Constraint) :- | |
477 | smt_type_to_prob_type(Index,EIn,BIndex), | |
478 | smt_type_to_prob_type(Element,EIn,BElement), | |
479 | Identifier = b(identifier(Name),FullType,[]), | |
480 | Constraint = b(member(Identifier,b(EXPR,set(FullType),[])),pred,[]), | |
481 | type_to_expr(BIndex,From), | |
482 | (BElement=boolean,get_preference(smtlib2b_arrays_as_sets,true) % we translate boolean Array as Set | |
483 | -> EXPR = pow_subset(From), | |
484 | FullType = set(BIndex) | |
485 | ; type_to_expr(BElement,To), | |
486 | EXPR=total_function(From,To), | |
487 | FullType = set(couple(BIndex,BElement)) | |
488 | ). | |
489 | typing_constraint(svar(Name,sort('BitVec',[Length])),Constraint) :- | |
490 | Zero = b(integer(0),integer,[]), | |
491 | One = b(integer(1),integer,[]), | |
492 | L2 is Length - 1, | |
493 | LengthMinusOne = b(integer(L2),integer,[]), | |
494 | FullType = set(couple(integer,integer)), | |
495 | Identifier = b(identifier(Name),FullType,[]), | |
496 | From = b(interval(Zero,LengthMinusOne),set(integer),[]), | |
497 | To = b(interval(Zero,One),set(integer),[]), | |
498 | Constraint = b(member(Identifier,b(total_function(From,To),set(FullType),[])),pred,[]). | |
499 | ||
500 | is_function_constraint(Id,FullType,Constraint) :- | |
501 | FullType = set(couple(From,To)), | |
502 | Identifier = b(identifier(Id),FullType,[]), | |
503 | type_to_expr(From,FromExpr), | |
504 | type_to_expr(To,ToExpr), | |
505 | Constraint = b(member(Identifier,b(partial_function(FromExpr,ToExpr),set(FullType),[])),pred,[]). | |
506 | ||
507 | integer_to_binary_couples(Value,Length,Couples) :- | |
508 | PLength is Length - 1, | |
509 | integer_to_binary_couples(Value,0,PLength,Couples). | |
510 | integer_to_binary_couples(Value,Current,Current,[b(couple(A,B),couple(integer,integer),[])]) :- !, | |
511 | A = b(integer(Current),integer,[]), | |
512 | BVal is mod(Value,2), | |
513 | B = b(integer(BVal),integer,[]). | |
514 | integer_to_binary_couples(Value,Current,PLength,[b(couple(A,B),couple(integer,integer),[])|Cs]) :- | |
515 | A = b(integer(Current),integer,[]), | |
516 | BVal is mod(Value,2), | |
517 | B = b(integer(BVal),integer,[]), | |
518 | NValue is Value // 2, | |
519 | NCurrent is Current + 1, | |
520 | integer_to_binary_couples(NValue,NCurrent,PLength,Cs). | |
521 | ||
522 | binary_to_binary_couples(Bits,Couples) :- | |
523 | length(Bits,L), FirstL is L - 1, | |
524 | binary_to_binary_couples(FirstL,Bits,Couples). | |
525 | binary_to_binary_couples(-1,[],[]). | |
526 | binary_to_binary_couples(L,[Bit|Bits],[Couple|Couples]) :- | |
527 | A = b(integer(L),integer,[]), | |
528 | B = b(integer(Bit),integer,[]), | |
529 | Couple = b(couple(A,B),couple(integer,integer),[]), | |
530 | L2 is L - 1, | |
531 | binary_to_binary_couples(L2,Bits,Couples). | |
532 | ||
533 | smt_id_to_prob_id('<=',less_equal,chain). | |
534 | smt_id_to_prob_id('>=',greater_equal,chain). | |
535 | smt_id_to_prob_id('<',less,chain). | |
536 | smt_id_to_prob_id('>',greater,chain). | |
537 | smt_id_to_prob_id('distinct',not_equal,chain). | |
538 | smt_id_to_prob_id('*',multiplication,interleave). | |
539 | smt_id_to_prob_id('+',add,interleave). | |
540 | smt_id_to_prob_id('-',minus,interleave). | |
541 | ||
542 | smt_id_to_prob_id_preds('or',disjunct). | |
543 | smt_id_to_prob_id_preds('and',conjunct). | |
544 | smt_id_to_prob_id_preds('=>',implication). | |
545 | ||
546 | bvwidth(BV,Width) :- | |
547 | Width = b(max(b(domain(BV),set(integer),[])),integer,[]). | |
548 | ||
549 | bv2nat(BV,Nat) :- | |
550 | IntOne = b(integer(1),integer,[]), | |
551 | IntTwo = b(integer(2),integer,[]), | |
552 | IdX1 = b(identifier('\\tmp1'),integer,[]), | |
553 | IdX2 = b(identifier('\\tmp2'),integer,[]), | |
554 | PowerOf = b(power_of(IntTwo,b(minus(IdX1,IntOne),integer,[])),integer,[]), | |
555 | Nat = b(general_sum([IdX1,IdX2],b(member(b(couple(IdX1,IdX2),couple(integer,integer),[]),BV),pred,[]),b(multiplication(IdX2,PowerOf),integer,[])),integer,[]). | |
556 | signed_bv2nat(BV,Nat) :- | |
557 | IntOne = b(integer(1),integer,[]), | |
558 | IntTwo = b(integer(2),integer,[]), | |
559 | IntMinusOne = b(integer(-1),integer,[]), | |
560 | % todo: make sure identifiers do not collide | |
561 | IdX1 = b(identifier('\\tmp1'),integer,[]), | |
562 | IdX2 = b(identifier('\\tmp2'),integer,[]), | |
563 | NotZeroIndex = b(not_equal(IdX1,b(integer(0),integer,[])),pred,[]), | |
564 | MemberConstraint = b(member(b(couple(IdX1,IdX2),couple(integer,integer),[]),BV),pred,[]), | |
565 | conjunct_predicates([NotZeroIndex,MemberConstraint],Const), | |
566 | PowerOf = b(power_of(IntTwo,b(minus(IdX1,IntOne),integer,[])),integer,[]), | |
567 | Sum = b(general_sum([IdX1,IdX2],Const,b(multiplication(IdX2,PowerOf),integer,[])),integer,[]), | |
568 | ZeroIndex = b(function(BV,b(integer(0),integer,[])),integer,[]), | |
569 | Sign = b(power_of(IntMinusOne,ZeroIndex),integer,[]), | |
570 | Nat = b(multiplication(Sign,Sum),integer,[]). | |
571 | ||
572 | nat2bv(Nat,Width,BV) :- | |
573 | IntOne = b(integer(1),integer,[]), | |
574 | IntTwo = b(integer(2),integer,[]), | |
575 | % todo: make sure identifiers do not collide | |
576 | IdX1 = b(identifier('\\tmp1'),integer,[]), | |
577 | IdX2 = b(identifier('\\tmp2'),integer,[]), | |
578 | TypeId1 = b(member(IdX1,b(interval(b(integer(1),integer,[]),Width),set(integer),[])),pred,[]), | |
579 | TypeId2 = b(member(IdX2,b(interval(b(integer(0),integer,[]),b(integer(1),integer,[])),set(integer),[])),pred,[]), | |
580 | PowerOf = b(power_of(IntTwo,b(minus(IdX1,IntOne),integer,[])),integer,[]), | |
581 | ValueOfId2 = b(equal(IdX2,b(modulo(b(div(Nat,PowerOf),integer,[]),IntTwo),integer,[])),pred,[]), | |
582 | conjunct_predicates([TypeId1,TypeId2,ValueOfId2],InnerPred), | |
583 | BV = b(comprehension_set([IdX1,IdX2],InnerPred),set(couple(integer,integer)),[]). | |
584 | ||
585 | type_to_expr(set(A),Res) :- !, Res = b(pow_subset(AE),set(set(A)),[]), | |
586 | type_to_expr(A,AE). | |
587 | type_to_expr(couple(A,B),b(cartesian_product(AE,BE),set(couple(AET,BET)),[])) :- !, | |
588 | type_to_expr(A,AE), type_to_expr(B,BE), | |
589 | get_texpr_type(AE,AET), get_texpr_type(BE,BET). | |
590 | type_to_expr(integer,b(integer_set('INTEGER'),set(integer),[])) :- !. | |
591 | type_to_expr(boolean,b(bool_set,set(boolean),[])) :- !. | |
592 | type_to_expr(global(E),b(identifier(E),set(global(E)),[])) :- !. | |
593 | type_to_expr(T,_) :- | |
594 | add_error(smtlib2_translation,'Unsupported type in type_to_expr:',T), fail. | |
595 | ||
596 | signed_bv_to_nat_and_compare(A,B,Op,Env,Out) :- | |
597 | smt_term_to_prob_term(A,Env,BA), | |
598 | smt_term_to_prob_term(B,Env,BB), | |
599 | signed_bv2nat(BA,BANat), | |
600 | signed_bv2nat(BB,BBNat), | |
601 | Operation =.. [Op,BANat,BBNat], | |
602 | Out = b(Operation,pred,[]). | |
603 | ||
604 | bv_to_nat_and_compare(A,B,Op,Env,Out) :- | |
605 | smt_term_to_prob_term(A,Env,BA), | |
606 | smt_term_to_prob_term(B,Env,BB), | |
607 | bv2nat(BA,BANat), | |
608 | bv2nat(BB,BBNat), | |
609 | Operation =.. [Op,BANat,BBNat], | |
610 | Out = b(Operation,pred,[]). |