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 | ||
6 | :- module(kodkod,[apply_kodkod/3, apply_kodkod/4, | |
7 | replace_by_kodkod/3, | |
8 | current_solver_is_not_incremental/0, | |
9 | kodkod_request/5, | |
10 | apply_kodkod_to_counterexample_search/5, | |
11 | kodkod_reset/0]). | |
12 | ||
13 | :- use_module(library(lists)). | |
14 | :- use_module(library(avl)). | |
15 | ||
16 | :- use_module(probsrc(tools)). | |
17 | :- use_module(probsrc(bmachine)). | |
18 | :- use_module(probsrc(self_check)). | |
19 | :- use_module(probsrc(bsyntaxtree)). | |
20 | :- use_module(probsrc(translate)). | |
21 | :- use_module(probsrc(predicate_analysis)). | |
22 | :- use_module(probsrc(btypechecker)). | |
23 | :- use_module(probsrc(b_global_sets),[b_global_set/1,lookup_global_constant/2]). | |
24 | :- use_module(probsrc(preferences),[get_preference/2]). | |
25 | ||
26 | :- use_module(kodkod_translate). | |
27 | :- use_module(kodkod_tools). | |
28 | :- use_module(kodkod_rewrite). | |
29 | :- use_module(kodkod2). | |
30 | :- use_module(kodkod_typing). | |
31 | :- use_module(kodkod_process). | |
32 | ||
33 | :- use_module(probsrc(module_information),[module_info/2]). | |
34 | :- module_info(group,kodkod). | |
35 | :- module_info(description,'This is the central module of the B to Kodkod translation (still experimental).'). | |
36 | ||
37 | %:- dynamic kodkod_error/1. | |
38 | ||
39 | kodkod_reset :- | |
40 | ( stop_kodkod -> true; true). | |
41 | ||
42 | % Signum is either pos (when we want the predicate to succeed) or neg (when we want the predicate to be false) | |
43 | kodkod_request(Id,Signum,LocalState,State,LWF) :- | |
44 | % MaxNrOfSols is the maximum number of solutions found in one go by Kodkod | |
45 | get_max_nr_of_solutions(MaxNrOfSols), | |
46 | kodkod_request(Id,Signum,MaxNrOfSols,LocalState,State,LWF). | |
47 | ||
48 | get_max_nr_of_solutions(MaxNrOfSols) :- | |
49 | current_solver_is_not_incremental,!, | |
50 | MaxNrOfSols = 1. | |
51 | get_max_nr_of_solutions(MaxNrOfSols) :- | |
52 | get_preference(kodkod_max_nr_solutions,MaxNrOfSols). % TO DO: we could look at kodkod_for_components and maxNrOfInitialisations preference | |
53 | ||
54 | current_solver_is_not_incremental :- | |
55 | get_preference(kodkod_sat_solver,Solver), | |
56 | not_incremental(Solver). | |
57 | not_incremental(lingeling). | |
58 | ||
59 | :- use_module(probsrc(error_manager)). | |
60 | ||
61 | :- block kodkod_request(?,?,?,?,?,-). | |
62 | kodkod_request(Id,Signum,MaxNrOfSols,LocalState,State,_LWF) :- | |
63 | on_exception(error(system_error,system_error(E)), % often SPIO_E_NET_CONNRESET | |
64 | kodkod_request_intern(Id,Signum,MaxNrOfSols,LocalState,State), | |
65 | (add_internal_error('System Error while processing Kodkod request: ',E), | |
66 | fail | |
67 | )). | |
68 | ||
69 | ||
70 | ||
71 | apply_kodkod(Identifier,Predicate,NewPredicate) :- | |
72 | get_preference(try_kodkod_on_load,true), | |
73 | replace_by_kodkod(Identifier,Predicate,NewPredicate),!. | |
74 | apply_kodkod(_Identifier,Predicate,Predicate). | |
75 | ||
76 | create_id(Id,Type,b(identifier(Id),Type,[])). | |
77 | ||
78 | % a version which takes ids and types list: | |
79 | apply_kodkod(Ids,Types,Predicate,NewPredicate) :- | |
80 | get_preference(try_kodkod_on_load,true), | |
81 | maplist(create_id,Ids,Types,Identifiers), | |
82 | replace_by_kodkod(Identifiers,Predicate,NewPredicate),!. | |
83 | apply_kodkod(_Identifier,_Types,Predicate,Predicate). | |
84 | ||
85 | % | |
86 | :- use_module(probsrc(b_expression_sharing),[expand_cse_lazy_lets_if_cse_enabled/2]). | |
87 | replace_by_kodkod(Constants,Predicate,NewPredicate) :- | |
88 | % Remove any CSE lazy_lets as Kodkod translation cannot deal with them yet | |
89 | expand_cse_lazy_lets_if_cse_enabled(Predicate,Predicate0), | |
90 | % The Predicate may already contain Kodkod calls, replace | |
91 | % them by their original B predicate | |
92 | undo_kodkod_replacements(Predicate0,Predicate1), | |
93 | % first we do a predicate analysis to determine ranges for integers | |
94 | try_predicate_analysis_with_global_sets(Predicate1,Constants,TaggedConstants,TaggedPredicate), | |
95 | replace_by_kodkod2(TaggedConstants,TaggedPredicate,NewPredicate). | |
96 | ||
97 | :- use_module(probsrc(preferences),[temporary_set_preference/3,reset_temporary_preference/2]). | |
98 | replace_by_kodkod2(Constants,_Predicate,NewPredicate) :- | |
99 | % If the static analysis states that there is no possible solution for one | |
100 | % of the identifiers, we just say "false" | |
101 | somechk(is_inconsistent_expression,Constants),!, | |
102 | write('kodkod: Static analysis detected inconsistencies, new predicate is "false"'),nl, | |
103 | create_texpr(falsity,pred,[],NewPredicate). | |
104 | replace_by_kodkod2(Constants,Predicate,NewPredicate) :- | |
105 | temporary_set_preference(partition_predicates_inline_equalities,false,CHNG), | |
106 | split_predicates(Predicate,PList), % will split into components if KODKOD_ONLY_FULL = FALSE | |
107 | reset_temporary_preference(partition_predicates_inline_equalities,CHNG), | |
108 | % we try to translate each predicate alone | |
109 | try_apply_transformation_l(PList,Constants,1,Result), | |
110 | print_results(Result), | |
111 | % split the result into two lists: the successfull translatable predicates (ToKodkod) | |
112 | % and those which were not translatable (StayProb) | |
113 | filter_translatable(Result,ToKodkod,StayProb), | |
114 | %%print('Stay ProB: '), conjunct_predicates(StayProb,StayPred), translate:print_bexpr(StayPred),nl, | |
115 | % fail if there are no translatable predicates | |
116 | ToKodkod = [_|_], | |
117 | % now, translate all translatable predicates in one run | |
118 | apply_transformation(Constants,ToKodkod,KPred), | |
119 | % the new | |
120 | %%print('For Kodkod: '), translate:print_bexpr(KPred),nl, | |
121 | conjunct_predicates([KPred|StayProb],NewPredicate). | |
122 | ||
123 | apply_kodkod_to_counterexample_search(Variables,Assumption,Assertion,KPred,Rest) :- | |
124 | get_preference(try_kodkod_on_load,true), | |
125 | % The predicates may already contain Kodkod calls, replace | |
126 | % them by their original B predicate | |
127 | undo_kodkod_replacements(Assumption,Assumption1), | |
128 | undo_kodkod_replacements(Assertion,Assertion1), | |
129 | % first we do a predicate analysis to determine ranges for integers | |
130 | analysis_for_counterexample(Variables,Assumption1,Assertion1, | |
131 | TaggedVariables,TaggedAssumption,TaggedAssertions), | |
132 | ||
133 | % analyse assumptions | |
134 | split_assumptions(TaggedAssumption,TaggedVariables, | |
135 | TAssumptions,NTAssumptions,AssumptionsComponents), | |
136 | ||
137 | % analyse assertions | |
138 | translate_assertions(TaggedAssertions,TaggedVariables,TAssumptions,NTAssumptions, | |
139 | UsedAssumptionNumbers,TAssertions,NTAssertions,UsedVariables), | |
140 | ||
141 | % if we do not find a translatalbe assertion, fail and do not apply Kodkod at all | |
142 | TAssertions = [_|_], | |
143 | ||
144 | findall( UP, | |
145 | (member(N,UsedAssumptionNumbers),nth1(N,AssumptionsComponents,component(UP,_))), | |
146 | UsedAssumptions), | |
147 | findall( UP, | |
148 | (nth1(N,AssumptionsComponents,component(UP,_)),nonmember(N,UsedAssumptionNumbers)), | |
149 | UnusedAssumptions), | |
150 | ||
151 | conjunct_predicates(TAssertions,TAssertion), | |
152 | create_texpr(negation(TAssertion),pred,[],Negation), | |
153 | append(UsedAssumptions,[Negation],ToTranslate), | |
154 | apply_transformation(UsedVariables,ToTranslate,KPred), | |
155 | ||
156 | ( NTAssertions = [] -> | |
157 | conjunct_predicates(UnusedAssumptions,Rest) | |
158 | ; otherwise -> | |
159 | conjunct_predicates(NTAssertions,RestAssertion), | |
160 | create_texpr(negate(RestAssertion),pred,[],RestNegated), | |
161 | conjunct_predicates([Assumption,RestNegated],Rest)). | |
162 | ||
163 | split_assumptions(Assumption,Variables,Translatable,NotTranslated,AssumptionsComponents) :- | |
164 | predicate_components(Assumption,AssumptionsComponents), | |
165 | try_apply_transformation_to_components(AssumptionsComponents,Variables,1,AssumptionResults), | |
166 | map_ids_to_assumption(AssumptionResults,Translatable,NotTranslated). | |
167 | ||
168 | translate_assertions(Assertion,Variables,TAssumptions,NTAssumptions,UsedAssumptions, | |
169 | Translatable,NotTranslated,UsedVariables) :- | |
170 | conjunction_to_list(Assertion,Assertions), | |
171 | translate_assertions2(Assertions,Variables,TAssumptions,NTAssumptions,Unsorted, | |
172 | Translatable,NotTranslated,UIds), | |
173 | sort(Unsorted,UsedAssumptions), | |
174 | sort(UIds,Ids), | |
175 | findall(V,(member(V,Variables),get_texpr_id(V,I),memberchk(I,Ids)),UsedVariables). | |
176 | translate_assertions2([],_Variables,_TAssumptions,_NTAssumptions,[],[],[],[]). | |
177 | translate_assertions2([Assertion|Arest],Variables,TAssumptions,NTAssumptions, | |
178 | UsedAssumptions,Translatable,NotTranslated,Ids) :- | |
179 | ( translate_assertion(Assertion,Variables,TAssumptions,NTAssumptions,LUsedAssumptions,LUsedIds) -> | |
180 | append(LUsedAssumptions,Urest,UsedAssumptions), | |
181 | append(LUsedIds,Irest,Ids), | |
182 | Translatable = [Assertion|Trest], NotTranslated = NTrest | |
183 | ; otherwise -> | |
184 | UsedAssumptions = Urest, | |
185 | Ids = Irest, | |
186 | Translatable = Trest, NotTranslated = [Assertion|NTrest]), | |
187 | translate_assertions2(Arest,Variables,TAssumptions,NTAssumptions,Urest,Trest,NTrest,Irest). | |
188 | translate_assertion(Assertion,Variables,TAssumptions,NTAssumptions,UsedAssumptions,Ids) :- | |
189 | find_identifier_uses(Assertion,[],Ids), | |
190 | find_used_predicates(Ids,TAssumptions,NTAssumptions,UsedAssumptions), | |
191 | try_apply_transformation(Assertion,Variables,1,R), | |
192 | functor(R,ok,_). | |
193 | find_used_predicates(Ids,TAssumptions,NTAssumptions,UsedAssumptions) :- | |
194 | maplist(find_predicate(TAssumptions,NTAssumptions),Ids,AssumptionsL), | |
195 | append(AssumptionsL,Assumptions), | |
196 | sort(Assumptions,UsedAssumptions). | |
197 | ||
198 | find_predicate(_TAssumptions,NTAssumptions,Id,_UsedAssumption) :- | |
199 | % if the assertion uses an ID that is also used by a non-translatable | |
200 | % assumption, we do not translate the assumption | |
201 | avl_fetch(Id,NTAssumptions),!,fail. | |
202 | find_predicate(TAssumptions,_NTAssumptions,Id,UsedAssumptions) :- | |
203 | ( avl_fetch(Id,TAssumptions,UsedAssumption) -> | |
204 | UsedAssumptions = [UsedAssumption] | |
205 | ; otherwise -> | |
206 | UsedAssumptions = []). | |
207 | ||
208 | map_ids_to_assumption(AssumptionResults,AssumptionIds,NotTranslated) :- | |
209 | findall( Id-N, | |
210 | ( nth1(N,AssumptionResults,ok(Ids,_,_,_)), | |
211 | member(Id,Ids)), | |
212 | Ids1), | |
213 | list_to_avl(Ids1,AssumptionIds), | |
214 | findall( N, | |
215 | ( nth1(N,AssumptionResults,failure(Ids,_,_,_,_)), | |
216 | member(Id,Ids)), | |
217 | Ids2), | |
218 | list_to_avl(Ids2,NotTranslated). | |
219 | ||
220 | analysis_for_counterexample(Variables,Assumption,Assertion, | |
221 | TaggedVariables,TaggedAssumption,TaggedAssertion) :- | |
222 | create_texpr(negation(Assertion),pred,[],NAssertion), | |
223 | create_texpr(conjunct(Assumption,NAssertion),pred,[],Conj), | |
224 | try_predicate_analysis_with_global_sets(Conj,Variables,TaggedVariables,TaggedConj), | |
225 | create_texpr(conjunct(TaggedAssumption,TaggedNAssertion),pred,_,TaggedConj), | |
226 | create_texpr(negation(TaggedAssertion),pred,_,TaggedNAssertion). | |
227 | ||
228 | split_predicates(Predicate,Parts) :- | |
229 | get_preference(kodkod_for_components,true),!, | |
230 | predicate_components(Predicate,Components), | |
231 | findall(P,member(component(P,_),Components),Parts). | |
232 | split_predicates(Predicate,Parts) :- | |
233 | conjunction_to_list(Predicate,Parts). | |
234 | ||
235 | split_simple_equalities(InPredicate,Equalities,Rest) :- | |
236 | conjunction_to_list(InPredicate,InPredicates), | |
237 | split_list(is_simple_equality,InPredicates,EqualitiesL,RestL), | |
238 | conjunct_predicates(EqualitiesL,Equalities), | |
239 | conjunct_predicates(RestL,Rest). | |
240 | ||
241 | is_simple_equality(TExpr) :- | |
242 | get_texpr_expr(TExpr,equal(A,B)), | |
243 | ( get_texpr_id(A,_),is_base_expression(B) | |
244 | ; get_texpr_id(B,_),is_base_expression(A)),!. | |
245 | ||
246 | is_base_expression(TExpr) :- | |
247 | get_texpr_expr(TExpr,Expr), | |
248 | is_base_expression2(Expr). | |
249 | is_base_expression2(identifier(Id)) :- b_global_set(Id),!. % a deferred set | |
250 | is_base_expression2(identifier(Id)) :- lookup_global_constant(Id,_). % an enumerated set element | |
251 | is_base_expression2(integer(_)). | |
252 | is_base_expression2(couple(A,B)) :- is_base_expression(A),is_base_expression(B). | |
253 | is_base_expression2(set_extension(L)) :- maplist(is_base_expression,L). | |
254 | is_base_expression2(value(_)). | |
255 | is_base_expression2(boolean_true). | |
256 | is_base_expression2(boolean_false). | |
257 | is_base_expression2(empty_set). | |
258 | is_base_expression2(bool_set). | |
259 | is_base_expression2(add(A,B)) :- is_base_expression(A),is_base_expression(B). | |
260 | is_base_expression2(minus(A,B)) :- is_base_expression(A),is_base_expression(B). | |
261 | is_base_expression2(unary_minus(A)) :- is_base_expression(A). | |
262 | is_base_expression2(multiplication(A,B)) :- is_base_expression(A),is_base_expression(B). | |
263 | is_base_expression2(div(A,B)) :- is_base_expression(A),is_base_expression(B). | |
264 | is_base_expression2(floored_div(A,B)) :- is_base_expression(A),is_base_expression(B). | |
265 | is_base_expression2(modulo(A,B)) :- is_base_expression(A),is_base_expression(B). | |
266 | is_base_expression2(power_of(A,B)) :- is_base_expression(A),is_base_expression(B). | |
267 | ||
268 | ||
269 | undo_kodkod_replacements(Old,New) :- | |
270 | contains_kodkod_call(Old),!, | |
271 | undo_kodkod_replacements2(Old,New). | |
272 | undo_kodkod_replacements(Old,Old). | |
273 | undo_kodkod_replacements2(TOld,TNew) :- | |
274 | get_texpr_expr(TOld,Old), | |
275 | undo_kodkod_replacements3(Old,TOld,TNew). | |
276 | undo_kodkod_replacements3(conjunct(A,B),_TOld,TNew) :- | |
277 | !,create_texpr(conjunct(NewA,NewB),pred,[],TNew), | |
278 | undo_kodkod_replacements2(A,NewA), | |
279 | undo_kodkod_replacements2(B,NewB). | |
280 | undo_kodkod_replacements3(kodkod(Id,_),_TOld,Orig) :- | |
281 | !,get_original_problem(Id,Orig). | |
282 | undo_kodkod_replacements3(_Old,TOld,TOld). | |
283 | ||
284 | contains_kodkod_call(TExpr) :- | |
285 | get_texpr_expr(TExpr,Expr), | |
286 | contains_kodkod_call2(Expr),!. | |
287 | contains_kodkod_call2(kodkod(_,_)). | |
288 | contains_kodkod_call2(conjunct(A,_)) :- contains_kodkod_call(A). | |
289 | contains_kodkod_call2(conjunct(_,B)) :- contains_kodkod_call(B). | |
290 | ||
291 | ||
292 | try_predicate_analysis_with_global_sets(Predicate,Constants,TaggedConstants,TaggedPredicate) :- | |
293 | catch(predicate_analysis_with_global_sets(Predicate,[],Constants,TaggedConstants,TaggedPredicate), | |
294 | failed_analysis(Expr), | |
295 | ( write('kodkod fail: predicate analysis failed on expression '), | |
296 | translate_bexpression_with_limit(Expr,80,Msg), | |
297 | write(Msg),nl,fail)), | |
298 | !. | |
299 | try_predicate_analysis_with_global_sets(_Predicate,_Constants,_TaggedConstants,_TaggedPredicate) :- | |
300 | write('kodkod fail: predicate analysis failed.\n'), | |
301 | fail. | |
302 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | |
303 | ||
304 | :- meta_predicate try_call(-,-,0). | |
305 | ||
306 | try_apply_transformation(Predicate,Constants,Index,Result) :- | |
307 | %%print('TRY KODKOD ON: '), translate:print_bexpr(Predicate),nl, | |
308 | Log = log(Predicate,Result,Index,Ints,Bits), | |
309 | try_call( 'applying rewriting rules', Log, | |
310 | apply_rewriting_rules(Predicate,Rewritten)), | |
311 | %%print('REWRITTEN: '), translate:print_bexpr(Rewritten),nl, | |
312 | try_call( 'extracting used types', Log, | |
313 | extract_used_types(Rewritten,Types,Ints,Bits)), | |
314 | try_call( 'creating Kodkod atoms for types', Log, | |
315 | create_atoms_for_types(Types,Ints,Bits,Typemap,Idmap1,_Valuemap)), | |
316 | try_call( 'translate and type Kodkod formula', Log, | |
317 | typed_translation(Constants,Predicate,Bits,Typemap,Idmap1,_Idmap,Rewritten,_KExpr)), | |
318 | finalize_result(Log). | |
319 | try_call(_Msg,log(_Predicate,Result,_Index,_,_),_Call) :- | |
320 | nonvar(Result),!. | |
321 | try_call(Msg,log(Predicate,Result,Index,_,_),Call) :- | |
322 | %%format('Try ~w ~n',[Msg]), | |
323 | ( catch(Call, | |
324 | kodkod(T), | |
325 | ( %%format('Exception: ~w~n',[T]), | |
326 | Result = failure(Index,Predicate,Msg,kodkod_exception(T))) | |
327 | ) -> true | |
328 | ; otherwise -> | |
329 | %%format('Failure for: ~w~n',[Msg]), | |
330 | Result = failure(Index,Predicate,Msg,failed) | |
331 | ). | |
332 | finalize_result(log(Predicate,Result,Index,Ints,Bits)) :- | |
333 | var(Result),!,Result=ok(Index,Predicate,Ints,Bits). | |
334 | finalize_result(_). | |
335 | ||
336 | ||
337 | typed_translation(Constants,Predicate,Bits,Typemap,Idmap1,Idmap,Rewritten,KExpr) :- | |
338 | % Create the relations for the constants that are actually used | |
339 | restrict_to_used_constants(Constants,Predicate,UsedConstants), | |
340 | create_identifier_relations(UsedConstants,Typemap,Bits,Idmap1,Idmap), | |
341 | % translate the formula in two steps: | |
342 | kodkod_translate(Rewritten,Typemap,Idmap,Formula), | |
343 | kodkod_insert_casts(Formula,Typemap,Idmap,KExpr), | |
344 | !. | |
345 | ||
346 | restrict_to_used_constants(Constants,Predicate,UsedConstants) :- | |
347 | find_identifier_uses(Predicate,['$examine_value_was_identifier_info'],UsedIds), % flag says: also get value(_) with was_identifier(_) field | |
348 | include(constant_is_used(UsedIds),Constants,UsedConstants). | |
349 | constant_is_used(UsedIds,C) :- | |
350 | get_texpr_id(C,Id),memberchk(Id,UsedIds). | |
351 | ||
352 | try_apply_transformation_l([],_Constants,_,[]). | |
353 | try_apply_transformation_l([Predicate|Prest],Constants,I,[Result|Rrest]) :- | |
354 | try_apply_transformation(Predicate,Constants,I,Result), | |
355 | I2 is I+1, | |
356 | try_apply_transformation_l(Prest,Constants,I2,Rrest). | |
357 | ||
358 | try_apply_transformation_to_components([],_Vars,_,[]). | |
359 | try_apply_transformation_to_components([component(Predicate,Ids)|Crest],Vars,I,[Result|Rrest]) :- | |
360 | try_apply_transformation(Predicate,Vars,I,Result1), | |
361 | Result1 =.. [Functor|Args], | |
362 | Result =.. [Functor,Ids|Args], | |
363 | I2 is I+1, | |
364 | try_apply_transformation_to_components(Crest,Vars,I2,Rrest). | |
365 | ||
366 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | |
367 | ||
368 | filter_translatable([],[],[]). | |
369 | filter_translatable([Res|Rrest],ToKodkod,StayProb) :- | |
370 | ( Res = ok(_,P,_,_) -> ToKodkod=[P|Krest], StayProb=Prest | |
371 | ; Res = failure(_,P,_,_) -> ToKodkod=Krest, StayProb=[P|Prest]), | |
372 | filter_translatable(Rrest,Krest,Prest). | |
373 | ||
374 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | |
375 | :- use_module(probsrc(error_manager),[add_warning/3,add_warning/4]). | |
376 | :- use_module(probsrc(debug),[debug_mode/1,silent_mode/1,nls/0]). | |
377 | ||
378 | apply_transformation(AllConstants,PredicateList,Result) :- | |
379 | conjunct_predicates(PredicateList,Predicate1), | |
380 | (debug_mode(on) -> print('TRANSLATING FOR KODKOD: '),nl,translate:print_bexpr(Predicate1),nl ; true), | |
381 | apply_transformation2(AllConstants,Predicate1,Result). | |
382 | ||
383 | apply_transformation2(AllConstants,Predicate1,Result) :- | |
384 | split_simple_equalities(Predicate1,Equalities,Predicate), | |
385 | (debug_mode(on) -> print('Equalities: '), translate:print_bexpr(Equalities),nl ; true), | |
386 | (is_truth(Predicate) -> debug:debug_println('Only equalities'),fail | |
387 | ; apply_transformation3(AllConstants,Predicate,Equalities,Result) | |
388 | -> (debug_mode(on) -> print('RESULT: '),nl,translate:print_bexpr(Result),nl ; true) | |
389 | ; add_warning(kodkod,'Kodkod Transformation Failed: ',AllConstants), | |
390 | %trace, apply_transformation3(AllConstants,Predicate,Equalities,Result), | |
391 | fail). | |
392 | ||
393 | apply_transformation3(AllConstants,Predicate,Equalities,Result) :- | |
394 | restrict_to_used_constants(AllConstants,Predicate,Constants), | |
395 | apply_rewriting_rules(Predicate,Rewritten), | |
396 | extract_used_types(Rewritten,Types,Ints,Bits), | |
397 | create_atoms_for_types(Types,Ints,Bits,Typemap,Idmap1,Valuemap), | |
398 | % check if any types are used, if not Kodkod would exit with an | |
399 | % empty universe exception (or something similar) | |
400 | \+ empty_avl(Typemap), | |
401 | typed_translation(Constants,Predicate,Bits,Typemap,Idmap1,Idmap,Rewritten,KExpr), | |
402 | ||
403 | register_problem(Constants,KExpr,Idmap,Typemap,Valuemap,Predicate,ProblemNr), | |
404 | create_texpr(kodkod(ProblemNr,Constants),pred,[],KPred), | |
405 | conjunct_predicates([Equalities,KPred],Result). | |
406 | ||
407 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | |
408 | ||
409 | print_results([]). | |
410 | print_results([R|Rrest]) :- | |
411 | print_result(R),nls, | |
412 | print_results(Rrest). | |
413 | print_result(ok(_Ids,Index,P,Ints,Bits)) :- | |
414 | print_result(ok(Index,P,Ints,Bits)). | |
415 | print_result(ok(_Index,P,Ints,Bits)) :- | |
416 | (silent_mode(on) -> true | |
417 | ; write('kodkod ok: '),print_bexpr_with_limit(P,50), | |
418 | write(' ints: '),write(Ints),write(', intatoms: '),write(Bits) | |
419 | ). | |
420 | print_result(failure(_Ids,Index,P,Msg,Reason)) :- | |
421 | print_result(failure(Index,P,Msg,Reason)). | |
422 | print_result(failure(_Index,P,Msg,Reason)) :- | |
423 | write('kodkod fail: '), | |
424 | translate_bexpression_with_limit(P,50,PS), write(PS), | |
425 | write(' , reason: '),write_reason(Reason),write(' while '),write(Msg), | |
426 | (get_preference(kodkod_raise_warnings,true) | |
427 | -> add_warning(kodkod,'Cannot translate predicate for Kodkod: ',PS,P) | |
428 | ; true). | |
429 | write_reason(kodkod_exception(KE)) :- | |
430 | write_reason2(KE),!. | |
431 | write_reason(E) :- write(E). | |
432 | ||
433 | write_reason2(unsupported_type(T)) :- | |
434 | pretty_type(T,PT), | |
435 | write('unsupported type '),write(PT). | |
436 | write_reason2(unsupported_expression(TE)) :- | |
437 | get_texpr_expr(TE,T), | |
438 | functor(T,Functor,Arity), | |
439 | translate_bexpression(TE,PE), | |
440 | format('unsupported expression ~w/~w: ~w',[Functor,Arity,PE]). | |
441 | write_reason2(unsupported_int(Msg)) :- | |
442 | write(Msg). | |
443 | write_reason2(side_condition(Msg,PPExpr)) :- | |
444 | format('~w: ~w',[Msg,PPExpr]). | |
445 | ||
446 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | |
447 | ||
448 | :- public pdebug/0. | |
449 | pdebug :- | |
450 | install_b_portray_hook, | |
451 | assert(( user:portray(X) :- is_avl(X),!,portray_avl(X) )). |