1 % (c) 2015-2023 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(smt_solvers_interface, [smt_solve_predicate/4,
6 smt_solve_predicate/5,
7 smt_solve_predicate_free/3,
8 smt_add_predicate/5,
9 smt_solve_predicate_in_state/5,
10 reset_smt_supported_interpreter/0,
11 smt_add_cnf/3, smt_add_extra_clause_cnf/2, smt_solve_cnf/2, smt_reset_cnf/1]).
12
13 :- use_module(library(terms), [term_size/2]).
14 :- use_module(library(sets), [list_to_set/2]).
15 :- use_module(library(lists), [same_length/2,maplist/2, maplist/3, maplist/4,
16 append/2, exclude/3, include/3, select/3,
17 nth0/3, some/2, is_list/1]).
18 :- use_module(probsrc(tools_timeout),[get_time_out_with_factor/2]).
19 :- use_module(probsrc(specfile),[get_state_for_b_formula/3]).
20 :- use_module(probsrc(debug), [debug_mode/1, debug_level_active_for/1,debug_format/3]).
21 :- use_module(probsrc(bmachine), [b_get_machine_set/1]).
22 :- use_module(probsrc(kernel_objects), [infer_value_type/2,
23 equal_object/2]).
24 :- use_module(probsrc(bsyntaxtree), [map_over_typed_bexpr/3,
25 safe_create_texpr/4,
26 find_typed_identifier_uses/2,
27 find_typed_identifier_uses/3,
28 get_texpr_type/2,
29 get_texpr_expr/2,
30 get_texpr_id/2,
31 predicate_components_in_scope/3,
32 conjunction_to_list/2,
33 conjunct_predicates/2,
34 disjunction_to_list/2,
35 syntaxtraversion/6]).
36 :- use_module(probsrc(error_manager), [add_error_fail/3, add_message/2, add_message/3, add_message/4,
37 add_error/3, add_internal_error/2, add_warning/3]).
38 :- use_module(probsrc(tools), [start_ms_timer/1,stop_ms_timer_with_debug_msg/2,split_atom/3]).
39 :- use_module(probsrc(tools_strings), [atom_prefix/2]).
40 :- use_module(probsrc(translate), [translate_bexpression/2]).
41 :- use_module(probsrc(preferences), [get_preference/2]).
42 :- use_module(probsrc(b_interpreter), [b_test_boolean_expression_cs/5]).
43 :- use_module(probsrc(tools_meta),[safe_time_out/3]).
44 :- use_module(probsrc(b_global_sets), [b_global_deferred_set/1,
45 unfixed_deferred_set/1,
46 b_get_global_enumerated_sets/1,
47 is_b_global_constant/3,
48 get_user_defined_scope/4,
49 list_contains_unfixed_deferred_set_id/1]).
50 :- use_module(probsrc(custom_explicit_sets), [expand_custom_set_to_list_now/2]).
51 :- use_module(probsrc(eventhandling),[register_event_listener/3]).
52 :- use_module(probsrc(external_functions), [is_external_function_name/1]).
53 :- use_module(cdclt_solver('cdclt_preprocessing'), [preprocess_predicate/6]).
54 :- use_module(cdclt_solver('cdclt_pred_to_sat'), [predicate_to_sat/6]).
55 :- use_module(smt_solvers_interface(model_translation), [translate_smt_model_to_b_values/4,
56 consistent_deferred_set_sizes/0,
57 store_explicit_set_unique_id/2,
58 assert_virtual_deferred_set_id/2]).
59 :- use_module(smt_solvers_interface(ast_cleanup_for_smt)).
60 :- use_module(smt_solvers_interface(prob_state_predicates), [create_state_pred/4, create_state_pred/5]).
61 :- use_module(smt_solvers_interface(solver_dispatcher)).
62 :- use_module(smt_solvers_interface(smt_common_predicates)).
63
64 :- use_module(probsrc(module_information),[module_info/2]).
65 :- module_info(group,smt_solvers).
66 :- module_info(description,'This module provides an interface to SMT-solvers like CVC4 or Z3.').
67
68 :- dynamic backjumping_symbols/1, solve_in_state/0.
69
70 clear_state :-
71 reset_interface(z3),
72 garbage_collect,
73 trimcore,
74 retractall(solve_in_state),
75 model_translation:clear_translation_state.
76
77 init_smt_supported_interpreter :-
78 retractall(backjumping_symbols(_)), %clean smt backjumping information
79 (get_preference(smt_supported_interpreter,true) -> init_interface(z3) ; true).
80 reset_smt_supported_interpreter :-
81 (get_preference(smt_supported_interpreter,true) -> clear_state
82 ; true).
83
84 :- register_event_listener(start_solving,init_smt_supported_interpreter,'Init Z3 for new solving, clean backjumping'),
85 register_event_listener(end_solving,reset_smt_supported_interpreter,'Reset Z3 after solving').
86
87
88 :- block smt_add_predicate(-,?,?,?,?).
89 smt_add_predicate(_EnumWf, Pred, ProBLocalState, ProBState, Symbol) :-
90 backjump_on_symbol(Symbol),
91 smt_add_predicate_to_solver(z3, Pred, ProBLocalState, ProBState, Symbol).
92
93 smt_add_predicate_to_solver(Solver, Pred, ProBLocalState, ProBState, Symbol) :-
94 init_interface(Solver),
95 smt_clean_up_opts(axiomatic, Pred, [instantiate_quantifier_limit(20)], AxmCPred), % constructive translation isn't fully supported by the incremental solver
96 find_typed_identifier_uses(AxmCPred, [], Identifiers),
97 ( contains_introduced_identifiers(Identifiers, AxmCPred)
98 -> debug_format(9, 'z3: skip: ~w~n because there were introduced identifiers', [Symbol])
99 ; smt_solver_interface_call(Solver, push_frame),
100 create_state_pred(Identifiers, ProBLocalState, ProBState, StatePred),
101 conjunction_to_list(StatePred, StatePredConjuncts),
102 exclude(contains_unsupported_type_or_expression(axiomatic, Solver), StatePredConjuncts, FilteredStatePredConjuncts),
103 conjunct_predicates(FilteredStatePredConjuncts, FilteredStatePred),
104 conjunct_predicates([FilteredStatePred, AxmCPred], FullPred),
105 setup_sets(axiomatic, Solver, GlobalIdentifiers),
106 create_smt_state(axiomatic, Solver, Identifiers, IdentifierState, _),
107 append(IdentifierState, GlobalIdentifiers, GlobalState),
108 mk_expr_skip(axiomatic, Solver, FullPred, [], GlobalState, Expr),
109 translate_bexpression(FullPred, PPExpr),
110 debug_format(9, 'z3: add expr: ~w using symbol: ~w~n', [PPExpr, Symbol]),
111 !,
112 smt_add_predicate_aux(Solver, Expr, Symbol)
113 ).
114 smt_add_predicate_to_solver(Solver, _, _, _, _) :- % in case the predicate contains unsupported types, etc.
115 smt_solver_interface_call(Solver, pop_frame).
116
117 contains_introduced_identifiers(FreeIDs,TExpr) :-
118 syntaxtraversion(TExpr,_,Type,Infos,Subs,_),
119 (member(introduced_by(_),Infos) % identifier that has been introduced
120 -> % check if it is not bound by some quantifiers
121 get_texpr_id(TExpr,Identifier),
122 member(b(identifier(Identifier),Type,_),FreeIDs)
123 ; some(contains_introduced_identifiers(FreeIDs),Subs)).
124
125 smt_add_predicate_aux(Solver,Expr,Symbol) :-
126 get_preference(time_out,TO),
127 QuickTO is TO // 100,
128 % smt solver is called multiple times anyway
129 % and keeps its state inbetween
130 % thus we can use only a fraction of the time_out
131 % after e.g. 100 predicates, the whole timeout will be spent.
132 smt_solver_interface_call(Solver,add_interpreter_constraint(Expr,Symbol,QuickTO,SMTResult)),
133 ( SMTResult = unsat(Core)
134 -> % inconsistency detected
135 debug_format(9,'z3: false with core: ~w~n',[Core]),
136 store_core_for_backjumping(Core),
137 fail
138 ; true
139 ).
140 smt_add_predicate_aux(Solver,_,_) :-
141 % remove frame upon backtracking
142 smt_solver_interface_call(Solver,pop_frame), fail.
143
144 store_core_for_backjumping(Core) :-
145 retractall(backjumping_symbols(_)),
146 cleanup_core_for_backjumping(Core,CleanCore),
147 assertz(backjumping_symbols(CleanCore)).
148 cleanup_core_for_backjumping([],[]).
149 cleanup_core_for_backjumping([E|Es],[CE|CEs]) :-
150 split_atom(E,['|'],[CE]),
151 cleanup_core_for_backjumping(Es,CEs).
152
153 backjump_on_symbol(Symbol) :-
154 backjumping_symbols(Symbols),
155 member(Symbol,Symbols),
156 debug_format(9,'smt check for backjump:~ncurrent symbol: ~w~nbackjumping symbols: ~w~n',[Symbol,Symbols]),
157 !, debug_format(9,'backjumping!',[]), fail.
158 backjump_on_symbol(_) :-
159 retractall(backjumping_symbols(_)).
160
161 % solve a predicate freely (without any given state or values)
162 smt_solve_predicate_free(SolverName,Pred,Store) :-
163 write(solving_with(SolverName)),nl,
164 smt_solve_predicate(SolverName, Pred, _, Result),
165 write(result(Result)),nl,
166 % TODO: provide enumeration warnings / timeouts in other cases
167 Result = solution(Bindings),
168 maplist(translate_binding,Bindings,Store).
169
170 % translate solver binding to ProB interpreter store
171 translate_binding(binding(ID,Val,_),bind(ID,Val)).
172
173 % solve in a state stored in the state space
174 smt_solve_predicate_in_state(StateID, Solver, Pred, SolutionState, Result) :-
175 get_state_for_b_formula(StateID, Pred, FullStore),
176 !,
177 asserta(solve_in_state),
178 debug_format(19, 'Solving predicate with ~w in state ~w~n', [Solver,StateID]),
179 append(FullStore, SolutionState, SMTState),
180 smt_solve_predicate(Solver, Pred, SMTState, Result).
181 smt_solve_predicate_in_state(StateID, Solver, _, _, _) :-
182 debug_format(19, 'Cannot solve predicate with ~w in state ~w~n', [Solver,StateID]),
183 fail.
184
185 %% smt_solve_predicate(+SolverName, +Pred, +State, -Result).
186 smt_solve_predicate(SolverName, Pred, State, Result) :-
187 smt_solve_predicate(SolverName, [check_sat_skeleton(250),instantiate_quantifier_limit(50)], Pred, State, Result).
188
189 %% smt_solve_predicate(+Solver, +OptionList, +Pred, +State, -Result).
190 % valid options: decompose_into_components, check_sat_skeleton(+TimeOut)
191 smt_solve_predicate(SolverName, Options, Pred, State, Result) :-
192 translate_solver_name(SolverName,Solver,SelectedTranslations),!,
193 get_preference(time_out, TO),
194 safe_time_out(smt_solve_predicate6(SelectedTranslations, Solver, Options, Pred, State, TResult), TO, TORes),
195 ( TORes == time_out
196 -> Result = time_out,
197 clear_state
198 ; Result = TResult
199 ).
200
201 translate_solver_name(z3sat,z3,[sat,sat_cdcl]). % specialized SAT solver for QF_FD; runs two SAT solvers in parallel using local search and CDCL
202 translate_solver_name(z3axm,z3,[axm_ninc]). % axiomatic translation
203 translate_solver_name(z3cns,z3,[cns_ninc]). % constructive translation
204 translate_solver_name(z3,z3,T) :- T=[axm_ninc,cns_ninc]. % multithreading of the above
205 translate_solver_name(cvc4,cvc4,[axm_inc]).
206 translate_solver_name(S,_,_) :- add_internal_error('Unknown solver name: ', S), fail.
207
208 %% smt_solve_predicate6(+SelectedSolvers, +Solver, +Options, +Pred, +State, -Result).
209 % +Solver is either cvc4 or z3.
210 % We provide different translations and solver configurations for Z3, e.g., (non-)incremental.
211 % For z3, SelectedSolvers is a list of atoms representing the names of specific solvers
212 % defined in the Z3 C++ interface.
213 smt_solve_predicate6(SelectedSolvers, Solver, Options, Pred, State, Result) :-
214 model_translation:clear_translation_state,
215 is_list(SelectedSolvers),
216 get_texpr_type(Pred, pred),
217 !,
218 start_ms_timer(T0),
219 smt_clean_up_pre(Pred, State, Options, CPred),
220 stop_ms_timer_with_debug_msg(T0,smt_clean_up_pre(Solver,Options)),
221 ( CPred = b(truth,pred,_)
222 -> Result = solution([])
223 ; CPred = b(falsity,pred,_)
224 -> Result = contradiction_found
225 ; catch(smt_solve_predicate_aux(SelectedSolvers, Solver, Options, CPred, State, Result),
226 SolverException, % exception most likely happened in the setup phase; in check_sat the exceptions are caught
227 treat_exception(Solver, SolverException, Result))
228 ).
229 % not a predicate or cleanup failed
230 smt_solve_predicate6(SelectedSolvers, _, _, _, _, error) :-
231 add_internal_error('Unknown solver config: ', SelectedSolvers).
232
233 % remove bindings from environment which are not relevant
234 % (otherwise we get errors like z3exception in get_model_string: invalid usage)
235 remove_useless_bindings(X,_,Res) :- var(X),!,Res=X.
236 remove_useless_bindings([],_,[]).
237 remove_useless_bindings([bind(Var,Val)|T],Ids,Res) :-
238 ( (get_texpr_id(TVar,Var), member(TVar,Ids))
239 -> Res = [bind(Var,Val)|RT]
240 ; Res=RT
241 ),
242 remove_useless_bindings(T,Ids,RT).
243
244 filter_unsupported_types_or_expressions(_, _, [], [], []).
245 filter_unsupported_types_or_expressions(TranslationType, Solver, [LP|T], FilteredLPs, UnsupportedLPs) :-
246 contains_unsupported_type_or_expression(TranslationType, Solver, LP),
247 !,
248 UnsupportedLPs = [LP|TUnsupportedLPs],
249 filter_unsupported_types_or_expressions(TranslationType, Solver, T, FilteredLPs, TUnsupportedLPs).
250 filter_unsupported_types_or_expressions(TranslationType, Solver, [LP|T], [LP|TFilteredLPs], UnsupportedLPs) :-
251 filter_unsupported_types_or_expressions(TranslationType, Solver, T, TFilteredLPs, UnsupportedLPs).
252
253 %% get_full_pred(+TranslationType, +Solver, +Pred, +ProBState, -FullPred, -FullProBState, -Filtered, -SkippedVars, -UnsupportedLPs).
254 get_full_pred(TranslationType, Solver, Pred, ProBState, FullPred, FullProBState, Filtered, SkippedVars, UnsupportedLPs) :-
255 find_typed_identifier_uses(Pred, Identifiers),
256 remove_useless_bindings(ProBState, Identifiers, FullProBState),
257 create_state_pred(Identifiers, [], FullProBState, StatePred, [skipped_variables(SkippedVars)]),
258 % print(state),nl,translate:nested_print_bexpr(StatePred),nl,
259 safe_create_texpr(conjunct(StatePred,Pred), pred, [], FullConj),
260 conjunction_to_list(FullConj, LPs),
261 filter_unsupported_types_or_expressions(TranslationType, Solver, LPs, FilteredLPs, UnsupportedLPs),
262 ( same_length(LPs, FilteredLPs)
263 -> Filtered = false
264 ; Filtered = true,
265 ( debug_mode(off)
266 -> true
267 ; include(contains_unsupported_type_or_expression(TranslationType, Solver), LPs, Unsupported),
268 conjunct_predicates(Unsupported,US),
269 add_message(Solver, 'Unsupported constraints were discarded for SMT solver: ', US, US)
270 )
271 ),
272 conjunct_predicates(FilteredLPs, FullPred).
273
274 validate_selected_solvers(cvc4, SelectedSolvers) :-
275 SelectedSolvers == [axm_inc],
276 !.
277 validate_selected_solvers(cvc4, _) :-
278 add_error_fail(validate_selected_solvers, 'Only axiomatic translation with incremental solver (axm_inc) available for cvc4.', []).
279 validate_selected_solvers(z3, SelectedSolvers) :-
280 validate_selected_z3_solvers(SelectedSolvers).
281
282 validate_selected_z3_solvers(SelectedSolvers) :-
283 AvailableSolvers = [axm_inc,axm_ninc,sat,sat_cdcl,cns_ninc], % see z3interface/main.cpp:available_solvers
284 findall(Solver, (member(Solver, SelectedSolvers), \+ member(Solver, AvailableSolvers)), UnavailableSolvers),
285 UnavailableSolvers == [],
286 !.
287 validate_selected_z3_solvers(_) :-
288 add_error_fail(validate_selected_z3_solvers, 'At least one selected Z3 solver is not available.', []).
289
290 add_translation_for_solver(TranslationType, Solver, ProBState, Pred, Options, TranslationsAcc, NewAcc, IsUnfilteredTruth, Result) :-
291 start_ms_timer(T0),
292 smt_clean_up_post(TranslationType, Pred, Options, CPred),
293 ( CPred = b(truth,pred,_)
294 -> Result = solution([])
295 ; CPred = b(falsity,pred,_)
296 -> Result = contradiction_found
297 ; get_full_pred(TranslationType, Solver, CPred, ProBState, FullPred, FullProBState, Filtered, SkippedVars, UnsupportedLPs),
298 stop_ms_timer_with_debug_msg(T0,add_translation_for_solver_preprocessing(TranslationType,Solver)),
299 start_ms_timer(T1),
300 ( nonvar(FullPred), FullPred = b(truth,pred,_)
301 -> % fail if all operators are unsupported
302 ( Filtered == false
303 -> IsUnfilteredTruth = true,
304 NewAcc = TranslationsAcc
305 ; add_message(smt_solvers_interface, 'Could not translate predicate for solver: ', Solver:TranslationType),
306 add_message(smt_solvers_interface, 'Unsupported predicates: ', UnsupportedLPs),
307 fail
308 )
309 ; IsUnfilteredTruth = false,
310 setup_sets(TranslationType, Solver, GlobalIdentifiers),
311 find_typed_identifier_uses(FullPred, Ids),
312 create_smt_state(TranslationType, Solver, Ids, IdState, _),
313 append(IdState, GlobalIdentifiers, GlobalState),
314 mk_expr(FullPred, TranslationType, Solver, [], GlobalState, PExpr),
315 %format("~w:~n", [TranslationType]), translate:nested_print_bexpr_as_classicalb(FullAxmPred),nl,
316 ( debug:debug_mode(on)
317 -> translate_bexpression(FullPred, PPPred),
318 format('Sending to ~w translation to ~w: ~w~n', [TranslationType,Solver,PPPred])
319 ; true
320 ),
321 flush_output,
322 % comment next line in if you want to directly test ProB on the translated constraint:
323 %write(solving_with_prob(TranslationType)),nl,(solver_interface:solve_predicate(FullPred,_,3,[],CBCResult) -> write(CBCResult) ; write(fail)),nl,
324 Translation = (TranslationType,PExpr,ProBState,FullProBState,Ids,GlobalState,Filtered,SkippedVars,UnsupportedLPs),
325 NewAcc = [Translation|TranslationsAcc]
326 ),
327 stop_ms_timer_with_debug_msg(T1,add_translation_for_solver_core(TranslationType,Solver))
328 ).
329
330 contains_solver_name_with_prefix(Prefix, SelectedSolvers) :-
331 member(Name, SelectedSolvers),
332 atom_prefix(Prefix, Name),
333 !.
334
335 %% remove_solvers_with_prefix(+Prefix, +SelectedSolvers, -NewSelectedSolvers).
336 % Remove solvers for specific translation, e.g., if all operators are unsupported.
337 remove_solvers_with_prefix(_, [], []).
338 remove_solvers_with_prefix(Prefix, [SelectedSolver|T], NT) :-
339 atom_prefix(Prefix, SelectedSolver),
340 !,
341 remove_solvers_with_prefix(Prefix, T, NT).
342 remove_solvers_with_prefix(Prefix, [SelectedSolver|T], [SelectedSolver|NT]) :-
343 remove_solvers_with_prefix(Prefix, T, NT).
344
345 combine_satisfiable_component_results([], SatComponentResult, NResultAcc) :-
346 !,
347 NResultAcc = SatComponentResult.
348 combine_satisfiable_component_results(solution(AccBindings), solution(ComponentBindings), NResultAcc) :-
349 append(AccBindings, ComponentBindings, NAccBindings),
350 NResultAcc = solution(NAccBindings).
351
352 create_term_size_pairs([], []).
353 create_term_size_pairs([component(C,_)|T], [NTS-C|NT]) :-
354 term_size(C, TS),
355 NTS is TS * -1, % so that we can use keysort which sorts in ascending order
356 create_term_size_pairs(T, NT).
357
358 sort_components_descending_term_size(Components, SortedComponents) :-
359 % term sizes are negative so that we can use keysort to derive a descending order
360 % but we don't need the actual term sizes anyway
361 create_term_size_pairs(Components, TermSizePairs),
362 keysort(TermSizePairs, SortedComponents).
363
364 %% solve_components_with_z3(+Components, +AvailableSolvers, +Options, +State, +ResultAcc, +UnknownOccurred, -Result).
365 % Log unknown in +UnknownOccurred so that a contradiction can possibly be found in a specific component
366 % although a prior component's satisfiability couldn't be decided.
367 solve_components_with_z3([], _, _, _, _, true, no_solution_found(solver_answered_unknown)).
368 solve_components_with_z3([], _, _, _, ResultAcc, false, ResultAcc).
369 solve_components_with_z3([ComponentTerm|T], AvailableSolvers, Options, State, ResultAcc, UnknownOccurred, Result) :-
370 ( ComponentTerm = component(Component,_)
371 ; ComponentTerm = _TermSize-Component
372 ), !,
373 smt_solve_pre_cleaned_predicate(AvailableSolvers, z3, Options, Component, State, ComponentResult),
374 constraint_uses_unfixed_deferred_set(Component, UsesDefSet),
375 ( ( ComponentResult == contradiction_found,
376 ( UsesDefSet == false
377 ; get_preference(z3_solve_for_animation, false) % this is a genuine contradiction without considering DEFAULT_SETSIZE
378 )
379 )
380 -> Result = contradiction_found
381 ; ( ComponentResult = solution(_)
382 -> combine_satisfiable_component_results(ResultAcc, ComponentResult, NResultAcc),
383 solve_components_with_z3(T, AvailableSolvers, Options, State, NResultAcc, UnknownOccurred, Result)
384 ; % unknown, unfixed deferred sets or translation failed
385 solve_components_with_z3(T, AvailableSolvers, Options, State, ResultAcc, true, Result)
386 )
387 ).
388
389 %% sat_skeleton_is_contradictory(+Pred, +Solver).
390 % Is true if a contradiction has been found for the predicate's SAT skeleton. Otherwise, the call fails.
391 sat_skeleton_is_contradictory(Pred, Solver) :-
392 start_ms_timer(T0),
393 preprocess_predicate(false, false, Pred, LiftedPred, _, _),
394 % abstract formula to SAT as is done by lazy SMT solvers
395 predicate_to_sat(normal, LiftedPred, _, _TopLevelWDPOs, SmtBoolFormula, SatVars),
396 findall(bind(IdName,_), member(b(identifier(IdName),_,_), SatVars), Bindings),
397 stop_ms_timer_with_debug_msg(T0, preprocess_predicate_to_sat_predicate_to_find_contradiction(Solver)),
398 start_ms_timer(T1),
399 ( b_test_boolean_expression_cs(SmtBoolFormula, [], Bindings, 'SMT Boolean abstraction', Solver)
400 -> stop_ms_timer_with_debug_msg(T1, no_contradiction_found),
401 fail
402 ; stop_ms_timer_with_debug_msg(T1, contradiction_found)
403 ).
404
405 %% smt_solve_predicate_aux(+SelectedSolvers, +Solver, +OptionsList, +CPred, +ProBState, -Result).
406 % smt_clean_up_pre/4 has been called on +CPred.
407 smt_solve_predicate_aux(_, Solver, Options, CPred, _, Result) :-
408 member(check_sat_skeleton(TimeOut), Options),
409 TimeOut > 0,
410 % don't translate to SMT-LIB if formula has static contradiction, e.g., a:INT & a/:INT
411 safe_time_out(sat_skeleton_is_contradictory(CPred, Solver), TimeOut, TimeOutRes),
412 TimeOutRes \== time_out,
413 !,
414 Result = contradiction_found,
415 clear_state.
416 smt_solve_predicate_aux(SelectedSolvers, Solver, Options, CPred, ProBState, Result) :-
417 member(decompose_into_components, Options),!,
418 % decompose predicate into components to be solved independently
419 % important to not split among deferred sets since we need to know the cardinality if is set
420 start_ms_timer(T0),
421 findall(DeferredSetId, b_get_machine_set(DeferredSetId), DeferredSetIds),
422 predicate_components_in_scope(CPred, DeferredSetIds, Components),
423 stop_ms_timer_with_debug_msg(T0,predicate_components_in_scope(SelectedSolvers)),
424 ( Components = [component(SingleComponent,_)]
425 -> smt_solve_pre_cleaned_predicate(SelectedSolvers, Solver, Options, SingleComponent, ProBState, FreshResult)
426 ; ( member(sort_components,Options)
427 -> sort_components_descending_term_size(Components, SortedComponents)
428 ; SortedComponents = Components
429 ),
430 solve_components_with_z3(SortedComponents, SelectedSolvers, Options, ProBState, solution([]), false, FreshResult)
431 ),
432 Result = FreshResult,
433 clear_state.
434 smt_solve_predicate_aux(SelectedSolvers, Solver, Options, CPred, ProBState, Result) :-
435 smt_solve_pre_cleaned_predicate(SelectedSolvers, Solver, Options, CPred, ProBState, Result).
436
437 %% smt_solve_pre_cleaned_predicate(+SelectedSolvers, +Solver, +CPred, +ProBState, -Result).
438 % smt_clean_up_pre/4 has been called on +CPred.
439 smt_solve_pre_cleaned_predicate(SelectedSolvers, Solver, Options, CPred, ProBState, Result) :-
440 validate_selected_solvers(Solver, SelectedSolvers),
441 ( init_interface(Solver)
442 -> % one translation for each type, contexts are copied in the C++ interface
443 % if more than one solver uses a specific translation
444 ( (contains_solver_name_with_prefix(axm, SelectedSolvers),
445 add_translation_for_solver(axiomatic, Solver, ProBState, CPred, Options, [], TranslationsAcc1, AxmIsUnfilteredTruth, AxmResult))
446 -> SelectedSolvers2 = SelectedSolvers
447 ; TranslationsAcc1 = [],
448 AxmIsUnfilteredTruth = false,
449 remove_solvers_with_prefix(axm, SelectedSolvers, SelectedSolvers2)
450 ),
451 ( ground(AxmResult)
452 -> Result = AxmResult
453 ; ( (contains_solver_name_with_prefix(cns, SelectedSolvers),
454 add_translation_for_solver(constructive, Solver, ProBState, CPred, Options, TranslationsAcc1, TranslationsAcc2, CnsIsUnfilteredTruth, CnsResult))
455 -> RestSelectedSolvers = SelectedSolvers2
456 ; TranslationsAcc2 = TranslationsAcc1,
457 CnsIsUnfilteredTruth = false,
458 remove_solvers_with_prefix(cns, SelectedSolvers2, RestSelectedSolvers)
459 ),
460 ( ground(CnsResult)
461 -> Result = CnsResult
462 ; ( (contains_solver_name_with_prefix(sat, SelectedSolvers),
463 add_translation_for_solver(sat, Solver, ProBState, CPred, Options, TranslationsAcc2, Translations, SatIsUnfilteredTruth, SatResult))
464 -> RestSelectedSolvers2 = RestSelectedSolvers
465 ; Translations = TranslationsAcc2,
466 SatIsUnfilteredTruth = false,
467 remove_solvers_with_prefix(sat, RestSelectedSolvers, RestSelectedSolvers2)
468 ),
469 ( ground(SatResult)
470 -> Result = SatResult
471 ; Translations \== [],
472 RestSelectedSolvers2 \== [],
473 constraint_uses_unfixed_deferred_set(CPred, UsesDefSet),
474 !,
475 ( (AxmIsUnfilteredTruth; CnsIsUnfilteredTruth; SatIsUnfilteredTruth)
476 -> Result = solution([])
477 ; catch(check_sat(RestSelectedSolvers2, Solver, UsesDefSet, Translations, Options, SolverResult, SolvedTranslation),
478 model_translation_failed, Result = no_solution_found(model_translation_failed)),
479 member((SolvedTranslation,_,_,_,_,_,Filtered,SkippedVars), Translations),
480 ( (SolverResult=solution(_), nonvar(SkippedVars), is_list(SkippedVars)) % is_list grounds list
481 -> Result = no_solution_found(complex_state_values(SkippedVars)),
482 add_message(smt_solve_predicate,'Some variable values were discarded as they are not supported: ',SkippedVars)
483 ; SolverResult = solution(_), Filtered == true
484 -> Result = no_solution_found(unsupported_predicates)
485 ; Result = SolverResult
486 )
487 )
488 )
489 ),
490 !, % not backtrackable
491 clear_state
492 )
493 ; Result = no_solution_found(solver_not_available)
494 ).
495 smt_solve_pre_cleaned_predicate(_,_,_,_Pred,_,no_solution_found(translation_or_setup_failed)) :-
496 clear_state.
497
498 mk_expr_skip(TranslationType, Solver, Pred, [], GlobalState, Expr) :-
499 smt_clean_up(TranslationType, Pred, AxmCPred),
500 !,
501 conjunction_to_list(AxmCPred, List),
502 exclude(contains_unsupported_type_or_expression(TranslationType, Solver), List, NList),
503 conjunct_predicates(NList, NewCPred),
504 mk_expr(NewCPred, TranslationType, Solver, [], GlobalState, Expr).
505 mk_expr_skip(_, _, Pred, _, _, _) :- !,
506 add_error_fail(smt_solvers_interface, 'mk_expr_skip failed', Pred).
507
508 %% check_sat(+SelectedSolvers, +Solver, +UsesDefSet, +Translations, -Result, -SolvedTranslation).
509 % SolvedTranslation is either axiomatic or constructive.
510 check_sat(SelectedSolvers, Solver, UsesDefSet, Translations, Options, Result, SolvedTranslation) :-
511 start_ms_timer(T1),
512 catch(check_sat_aux(SelectedSolvers, Solver, UsesDefSet, Translations, Options, Result, SolvedTranslation),
513 SolverException,
514 treat_exception(Solver, SolverException, Result)),
515 stop_ms_timer_with_debug_msg(T1,check_sat(SelectedSolvers,Solver, Options)).
516
517 treat_exception(Solver, Exc, Result) :-
518 known_solver_exception(Exc, Reason),
519 add_internal_error('Exception occurred during SMT solving: ', Reason),
520 !,
521 reset_interface(Solver),
522 Result = no_solution_found(solver_answered_unknown).
523 treat_exception(Solver, Exc, _) :-
524 format('Unknown exception in solver ~w: ~w~n', [Solver, Exc]),
525 throw(Exc).
526
527 known_solver_exception(model_translation_failed, model_translation_failed).
528 known_solver_exception(z3_exception(Reason), Reason).
529 known_solver_exception(logic_exception(Reason), Reason).
530 known_solver_exception(error(representation_error(nofit(integer)),representation_error(_,_,nofit(integer))), integer_overflow).
531
532 constraint_uses_unfixed_deferred_set(Constraint, UsesDefSet) :-
533 find_typed_identifier_uses(Constraint, [], UsedIds),
534 ( list_contains_unfixed_deferred_set_id(UsedIds)
535 -> UsesDefSet = true
536 ; UsesDefSet = false
537 ).
538
539 check_sat_aux(_, cvc4, UsesDefSet, Translations, Options, Result, SolvedTranslation) :-
540 memberchk((axiomatic,AxmPExpr,_,_,_,_,_,_,_), Translations),
541 get_smt_time_out(Options,TO),
542 smt_solver_interface_call(cvc4, cvc4interface:smt_solve_query(AxmPExpr, TO, SMTResult)),
543 get_model_or_return_result(SMTResult, UsesDefSet, TO, axiomatic, Translations, cvc4, Result, SolvedTranslation),
544 SolvedTranslation == axiomatic.
545 check_sat_aux(SelectedSolvers, z3, UsesDefSet, Translations, Options, Result, SolvedTranslation) :-
546 ( memberchk((axiomatic,AxmPExpr,_,_,_,_,_,_,_), Translations),
547 !
548 ; AxmPExpr = -1 % do not solve any Z3 formula with axiomatic solver
549 ),
550 ( memberchk((constructive,CnsPExpr,_,_,_,_,_,_,_), Translations),
551 !
552 ; CnsPExpr = -1 % do not solve any Z3 formula with constructive solver
553 ),
554 ( memberchk((sat,SatPExpr,_,_,_,_,_,_,_), Translations),
555 !
556 ; SatPExpr = -1
557 ),
558 get_smt_time_out(Options,TO),
559 % format('Calling Z3 with time-out ~w, solvers:~w (~w:~w)~n',[TO,SelectedSolvers,AxmPExpr,CnsPExpr]),
560 % Selected Solvers can be axm_inc, axm_ninc, sat or cns_ninc
561 smt_solver_interface_call(z3, z3interface:smt_solve_query(SelectedSolvers, AxmPExpr, CnsPExpr, SatPExpr, TO, SMTResultData)),
562 ( debug_level_active_for(9)
563 -> write('; SMT TRANSLATION: '), nl, pretty_print_smt(z3), nl
564 ; true
565 ),
566 SMTResultData = result_tuple(TempSolvedTranslation,SMTResult),
567 %format('Calling get_model_or_return_result ~w~n',[SMTResult]),
568 get_model_or_return_result(SMTResult, UsesDefSet, TO, TempSolvedTranslation, Translations, z3, Result, SolvedTranslation).
569
570 get_smt_time_out(Options,TO) :-
571 member(smt_time_out_factor(TOFactor),Options),!,
572 get_time_out_with_factor(TOFactor,TO).
573 get_smt_time_out(_,TO) :- get_preference(time_out, TO).
574
575 add_state_to_bindings([], FullBindings, FullBindings).
576 add_state_to_bindings([bind(IdName,Value)|T], Bindings, FullBindings) :-
577 ( member(binding(IdName,ModelValue,_), Bindings)
578 -> equal_object(Value, ModelValue),
579 NewAcc = Bindings
580 ; infer_value_type(Value, Type),
581 translate_bexpression(b(value(Value),Type,[]), PrettyValue),
582 NewAcc = [binding(IdName,Value,PrettyValue)|Bindings]
583 ),
584 !,
585 add_state_to_bindings(T, NewAcc, FullBindings).
586 add_state_to_bindings([bind(IdName,_)|_], _, _) :-
587 add_error_fail(add_state_to_bindings, 'The synchronisation of the model found by Z3 with the global state bindings failed.', [IdName]).
588
589 get_model_or_return_result(unsat, UsesDefSet, _, SolvedTranslation, _, _, Solution, SolvedTranslationOut) :-
590 get_preference(z3_solve_for_animation, true), % behave such as ProB by considering DEFAULT_SETSIZE
591 !,
592 SolvedTranslation = SolvedTranslationOut,
593 ( (UsesDefSet == true, \+ solve_in_state)
594 -> Solution = no_solution_found(unfixed_deferred_sets)
595 ; Solution = contradiction_found
596 ).
597 get_model_or_return_result(unsat, _, _, SolvedTranslation, _, _, contradiction_found, SolvedTranslation).
598 get_model_or_return_result(unknown, _, _, SolvedTranslation, _, _, no_solution_found(solver_answered_unknown), SolvedTranslation).
599 get_model_or_return_result(time_out, _, _, SolvedTranslation, _, _, time_out, SolvedTranslation).
600 get_model_or_return_result(sat, _, TO, SolvedTranslation, Translations, Solver, Solution, SolvedTranslation) :-
601 memberchk((SolvedTranslation,_,ProBState,_,Ids,GlobalState,_,_,UnsupportedLPs), Translations),
602 ( UnsupportedLPs \== []
603 -> add_message(get_model_or_return_result, 'A solution has been found but some predicates are not supported and were not considered: ', UnsupportedLPs),
604 Solution = no_solution_found(solver_answered_unknown)
605 ; exclude(is_smt_temp_var, Ids, FilteredIDs),
606 % we replaced ProBState ids with values in ast_cleanup_for_smt so we add them to the solution here
607 ( catch(
608 translate_smt_model_to_b_values_with_timeout(TO,Solver, GlobalState, FilteredIDs, Bindings),
609 E,
610 (add_error(smt_solvers_interface,'Exception in model translation: ',E),
611 throw(model_translation_failed)))
612 -> ( (
613 get_preference(z3_solve_for_animation, true),
614 % Z3 behaves as ProB by considering its deferred set size preference
615 \+ consistent_deferred_set_sizes
616 )
617 -> Solution = no_solution_found(unfixed_deferred_sets)
618 ; add_state_to_bindings(ProBState, Bindings, FullBindings),
619 maplist(bind_in_prob_state(FullBindings), ProBState)
620 -> % for this solution, Z3 possibly considered a smaller deferred set size than ProB
621 % if Z3 considered a larger deferred set size, an error would have been thrown by model_translation:handle_globalsets_fdrange_contradiction/2
622 ( \+ consistent_deferred_set_sizes
623 -> add_message(get_model_or_return_result, 'Deferred set size considered by Z3 is smaller than the one of ProB (DEFAULT_SETSIZE)')
624 ; true
625 ),
626 Solution = solution(FullBindings)
627 ; throw(model_solution_extraction_failed)
628 )
629 ; add_warning(smt_solvers_interface,'Failure in model translation: ',Solver),
630 throw(model_translation_failed)
631 )
632 ).
633 %get_model_or_return_result(sat, _, TO, PreSolvedTranslation, Translations, Solver, Result, SolvedTranslation) :-
634 % memberchk((PreSolvedTranslation,_,_,Ids,_,_,_), Translations),
635 % next_result(Solver, PreSolvedTranslation, Translations, Ids, Result, SolvedTranslation).
636
637 translate_smt_model_to_b_values_with_timeout(TO,Solver, GlobalState, FilteredIDs, Bindings) :-
638 safe_time_out(translate_smt_model_to_b_values(Solver, GlobalState, FilteredIDs, Bindings),TO,TORes),
639 ( TORes = time_out
640 -> add_warning(smt_solvers_interface,'Time-out in model translation: ',Solver),
641 throw(model_translation_failed)
642 ; true
643 ).
644
645 bind_in_prob_state(Bindings,bind(Id,Val)) :-
646 member(binding(Id,Z3Val,_),Bindings), %format('~w: ~w = ~w~n',[Id,Z3Val,Val]),nl,
647 % Z3 may return solution in list form, ProB had it in AVL form: hence use equal_object
648 equal_object(Z3Val,Val).
649
650 /*next_result(_,PreSolvedTranslation,_,[],Result,SolvedTranslation) :- !,
651 % no global identifiers -> no other solution
652 Result = contradiction_found,
653 SolvedTranslation = PreSolvedTranslation.
654 next_result(Solver,_,Translations,_,Result,SolvedTranslation) :-
655 memberchk((axiomatic,AxmPExpr,AxmProBState,AxmIds,AxmGlobalState,AxmFiltered,AxmSkippedVars), Translations),
656 memberchk((constructive,CnsPExpr,CnsProBState,CnsIds,CnsGlobalState,CnsFiltered,CnsSkippedVars), Translations),
657 findall(Id,member(id(_,Id),AxmGlobalState),AxmExprIds),
658 findall(Id,member(id(_,Id),CnsGlobalState),CnsExprIds),
659 smt_solver_interface_call(Solver,conjoin_negated_state(axiomatic,AxmExprIds,AxmPExpr,NewAxmPExpr)),
660 smt_solver_interface_call(Solver,conjoin_negated_state(constructive,CnsExprIds,CnsPExpr,NewCnsPExpr)),
661 NewTranslations = [
662 (axiomatic,NewAxmPExpr,AxmProBState,AxmIds,AxmGlobalState,AxmFiltered,AxmSkippedVars),
663 (constructive,NewCnsPExpr,CnsProBState,CnsIds,CnsGlobalState,CnsFiltered,CnsSkippedVars)],
664 check_sat(Solver,NewTranslations,Result,SolvedTranslation).
665 */
666
667 % Unary and binary operators that have a direct counterpart in SMT-LIB.
668 unary_operator(negation).
669 unary_operator(unary_minus).
670 unary_operator(unary_minus_real).
671 unary_operator(convert_real).
672 binary_operator(floored_div).
673 binary_operator(equivalence).
674 binary_operator(implication).
675 binary_operator(less).
676 binary_operator(less_equal).
677 binary_operator(less_real).
678 binary_operator(less_equal_real).
679 binary_operator(greater).
680 binary_operator(greater_equal).
681 binary_operator(add).
682 binary_operator(modulo).
683 binary_operator(minus).
684 binary_operator(multiplication).
685 binary_operator(div).
686 binary_operator(power_of).
687 binary_operator(member).
688 binary_operator(subset).
689 binary_operator(union).
690 binary_operator(intersection).
691 binary_operator(set_subtraction).
692 binary_operator(add_real).
693 binary_operator(minus_real).
694 binary_operator(multiplication_real).
695 binary_operator(div_real).
696
697 % Collect couple types from a list of identifiers to reduce the list to a single couple afterwards (left-associative).
698 % We need the couple types for the constructors in SMT-Lib.
699 get_couple_types_comp_args([Arg1,Arg2|T], CoupleTypes) :-
700 Arg1 = b(identifier(_),Type1,_),
701 Arg2 = b(identifier(_),Type2,_),
702 get_couple_types_comp_args(T, couple(Type1,Type2), [couple(Type1,Type2)|D]-D, CoupleTypes).
703
704 get_couple_types_comp_args([], _, CoupleTypes-D, CoupleTypes) :-
705 D = [].
706 get_couple_types_comp_args([Arg|T], LastCoupleType, Acc-D, CoupleTypes) :-
707 Arg = b(identifier(_),Type,_),
708 D = [couple(LastCoupleType,Type)|ND],
709 get_couple_types_comp_args(T, couple(LastCoupleType,Type), Acc-ND, CoupleTypes).
710
711 mk_expr_maplist(TranslationType,Solver,LS,GS,Op,Expr) :-
712 mk_expr(Op,TranslationType,Solver,LS,GS,Expr).
713
714 mk_expr(b(Op,Type,_Infos),TranslationType,Solver,LS,GS,Expr) :-
715 mk_expr_aux(Op,Type,TranslationType,Solver,LS,GS,Expr).
716
717 % unary operators
718 mk_expr_aux(first_of_pair(Couple), _, TranslationType, Solver, LS, GS, Expr) :-
719 get_texpr_type(Couple, CoupleType),
720 mk_expr(Couple, TranslationType, Solver, LS, GS, AE),
721 smt_solver_interface_call(Solver, mk_op_couple_prj(TranslationType, first, AE, CoupleType, Expr)).
722 mk_expr_aux(second_of_pair(Couple), _, TranslationType, Solver, LS, GS, Expr) :-
723 get_texpr_type(Couple, CoupleType),
724 mk_expr(Couple, TranslationType, Solver, LS, GS, AE),
725 smt_solver_interface_call(Solver, mk_op_couple_prj(TranslationType, second, AE, CoupleType, Expr)).
726 /*
727 % change in Z3: lambda inside recursive functions was declared unsupported until proper support is provided (see https://github.com/Z3Prover/z3/issues/5813)
728 % see mk_op_iteration_func_decl in /extensions/z3interface/src/cpp/main.cpp
729 mk_expr_aux(Op, Type, TranslationType, Solver, LS, GS, Expr) :-
730 functor(Op, Functor, 1),
731 ( (Functor == closure, IsReflexive = 0)
732 ; (Functor == reflexive_closure, IsReflexive = 1)
733 ),
734 !,
735 arg(1, Op, A),
736 Type = set(CoupleType),
737 CoupleType = couple(_,ExistsVarType),
738 mk_expr(A, TranslationType, Solver, LS, GS, AE),
739 smt_solver_interface_call(Solver, mk_op_closure(TranslationType, IsReflexive, AE, Type, CoupleType, ExistsVarType, Expr)).
740 mk_expr_aux(iteration(A1,A2), Type, TranslationType, Solver, LS, GS, Expr) :-
741 !,
742 Type = set(CoupleType),
743 CoupleType = couple(_,ExistsVarType),
744 mk_expr(A1, TranslationType, Solver, LS, GS, AE1),
745 mk_expr(A2, TranslationType, Solver, LS, GS, AE2),
746 smt_solver_interface_call(Solver, mk_op_iteration(TranslationType, AE1, AE2, Type, CoupleType, ExistsVarType, Expr)).*/
747 mk_expr_aux(interval(A1,A2), _, TranslationType, Solver, LS, GS, Expr) :-
748 !,
749 mk_expr(A1, TranslationType, Solver, LS, GS, AE1),
750 mk_expr(A2, TranslationType, Solver, LS, GS, AE2),
751 smt_solver_interface_call(Solver, mk_op_interval(TranslationType, AE1, AE2, Expr)).
752 mk_expr_aux(direct_product(Arg1,Arg2), Type, TranslationType, Solver, LS, GS, Expr) :-
753 !,
754 Type = set(CoupleOutType),
755 CoupleOutType = couple(_,Couple2Type),
756 mk_expr(Arg1, TranslationType, Solver, LS, GS, Arg1E),
757 mk_expr(Arg2, TranslationType, Solver, LS, GS, Arg2E),
758 Arg1 = b(_,set(CoupleType1),_),
759 Arg2 = b(_,set(CoupleType2),_),
760 smt_solver_interface_call(Solver, mk_op_direct_product(TranslationType, Arg1E, Arg2E, Couple2Type, CoupleType1, CoupleType2, CoupleOutType, Expr)).
761 mk_expr_aux(parallel_product(Arg1,Arg2), Type, TranslationType, Solver, LS, GS, Expr) :-
762 !,
763 Type = set(CoupleOutType),
764 mk_expr(Arg1, TranslationType, Solver, LS, GS, Arg1E),
765 mk_expr(Arg2, TranslationType, Solver, LS, GS, Arg2E),
766 Arg1 = b(_,set(CoupleType1),_),
767 Arg2 = b(_,set(CoupleType2),_),
768 CoupleOutType = couple(ExistsCoupleType1,ExistsCoupleType2),
769 smt_solver_interface_call(Solver, mk_op_parallel_product(TranslationType, Arg1E, Arg2E, CoupleType1, CoupleType2, ExistsCoupleType1, ExistsCoupleType2, CoupleOutType, Expr)).
770 mk_expr_aux(composition(Arg1,Arg2), Type, TranslationType, Solver, LS, GS, Expr) :-
771 !,
772 Type = set(CoupleOutType),
773 Arg1 = b(_,set(CoupleType1),_),
774 CoupleType1 = couple(A,B),
775 Arg2 = b(_,set(CoupleType2),_),
776 CoupleType2 = couple(B,C),
777 CoupleOutType = couple(A,C),
778 mk_expr(Arg1, TranslationType, Solver, LS, GS, Arg1E),
779 mk_expr(Arg2, TranslationType, Solver, LS, GS, Arg2E),
780 smt_solver_interface_call(Solver, mk_op_composition(TranslationType, Arg1E, Arg2E, B, CoupleType1, CoupleType2, CoupleOutType, Expr)).
781 mk_expr_aux(cartesian_product(A1,A2), Type, TranslationType, Solver, LS, GS, Expr) :-
782 !,
783 Type = set(CoupleType),
784 mk_expr(A1, TranslationType, Solver, LS, GS, AE1),
785 mk_expr(A2, TranslationType, Solver, LS, GS, AE2),
786 smt_solver_interface_call(Solver, mk_op_cartesian(TranslationType, AE1, AE2, CoupleType, Expr)).
787 mk_expr_aux(identity(A), Type, TranslationType, Solver, LS, GS, Expr) :-
788 !,
789 Type = set(CoupleType),
790 CoupleType = couple(InnerSetType,_),
791 mk_expr(A, TranslationType, Solver, LS, GS, AE),
792 smt_solver_interface_call(Solver, mk_op_identity(TranslationType, AE, InnerSetType, CoupleType, Expr)).
793 mk_expr_aux(reverse(A), Type, TranslationType, Solver, LS, GS, Expr) :-
794 !,
795 Type = set(CoupleType),
796 mk_expr(A, TranslationType, Solver, LS, GS, AE),
797 smt_solver_interface_call(Solver, mk_op_reverse(TranslationType, AE, CoupleType, Expr)).
798 % binary operators
799 mk_expr_aux(comprehension_set(Args,Body), Type, TranslationType, Solver, LS, GS, Expr) :-
800 LambdaId = b(identifier('_lambda_result_'),_,_),
801 select(LambdaId, Args, LambdaArgs),
802 create_bounded_smt_state(TranslationType, Solver, LambdaArgs, State, ArgsE),
803 ArgsE = [Arg],
804 append(State, LS, NLS),
805 conjunction_to_list(Body, ConjList),
806 select(b(equal(LambdaId,BodyExpr),pred,Info), ConjList, RestConjList),
807 member(prob_annotation('LAMBDA-EQUALITY'), Info),
808 conjunct_predicates(RestConjList, BodyPred),
809 Type = set(CoupleType),
810 !,
811 mk_expr(BodyExpr, TranslationType, Solver, NLS, GS, BodyE),
812 mk_expr(BodyPred, TranslationType, Solver, NLS, GS, BodyP),
813 smt_solver_interface_call(Solver, mk_op_lambda(TranslationType, Arg, BodyP, BodyE, CoupleType, Expr)).
814 mk_expr_aux(comprehension_set(Args,Body), _, TranslationType, Solver, LS, GS, Expr) :-
815 !,
816 create_bounded_smt_state(TranslationType, Solver, Args, State, ArgsE),
817 append(State, LS, NLS),
818 mk_expr(Body, TranslationType, Solver, NLS, GS, BodyE),
819 length(ArgsE, ArgAmount),
820 ( ArgAmount == 1
821 -> ArgsE = [Arg],
822 smt_solver_interface_call(Solver, mk_op_comprehension_set_singleton(TranslationType, Arg, BodyE, Expr))
823 ; get_couple_types_comp_args(Args, CoupleTypes),
824 smt_solver_interface_call(Solver, mk_op_comprehension_set_multi(TranslationType, ArgsE, CoupleTypes, BodyE, Expr))
825 ).
826 mk_expr_aux(image(A,B), _, TranslationType, Solver, LS, GS, Expr) :-
827 !,
828 A = b(_,set(couple(Prj1Type,Prj2Type)),_),
829 mk_expr(A, TranslationType, Solver, LS, GS, AE),
830 mk_expr(B, TranslationType, Solver, LS, GS, BE),
831 smt_solver_interface_call(Solver, mk_op_image(TranslationType, AE,BE,couple(Prj1Type,Prj2Type),Prj1Type,Prj2Type,Expr)).
832 % conjunct and disjunct are deconstructed to lists
833 mk_expr_aux(conjunct(A,B),pred,TranslationType, Solver,LS,GS,Expr) :-
834 !,
835 conjunction_to_list(b(conjunct(A,B),pred,[]),List),
836 maplist(mk_expr_maplist(TranslationType, Solver,LS,GS),List,ExprList), % apply mk_expr on List
837 % truth/0 are removed from the conjunction during list / from list
838 % the list might be empty now!
839 ( ExprList = []
840 -> smt_solver_interface_call(Solver,mk_bool_const(boolean_true,Expr))
841 ; ( ExprList = [X]
842 -> Expr = X
843 ; smt_solver_interface_call(Solver,mk_op_arglist(TranslationType, conjunct,ExprList,Expr))
844 )
845 ).
846 mk_expr_aux(disjunct(A,B),pred,TranslationType, Solver,LS,GS,Expr) :-
847 !,
848 disjunction_to_list(b(disjunct(A,B),pred,[]),List),
849 maplist(mk_expr_maplist(TranslationType, Solver,LS,GS),List,ExprList),
850 smt_solver_interface_call(Solver,mk_op_arglist(TranslationType, disjunct,ExprList,Expr)).
851 % special case for if then else
852 mk_expr_aux(if_then_else(Pred,A,B),_,TranslationType, Solver,LS,GS,Expr) :-
853 !,
854 maplist(mk_expr_maplist(TranslationType, Solver,LS,GS),[Pred,A,B],ArgList),
855 smt_solver_interface_call(Solver,mk_op_arglist(TranslationType, if_then_else,ArgList,Expr)).
856 % special case for partition
857 mk_expr_aux(partition(S,Sets),pred,TranslationType, Solver,LS,GS,Expr) :-
858 !,
859 % definition: sets are disjoint and S is the union
860 maplist(mk_expr_maplist(TranslationType, Solver,LS,GS),Sets,SetExprs),
861 pairwise_union(TranslationType,SetExprs,Solver,UnionOfSets),
862 mk_expr(S,TranslationType, Solver,LS,GS,SExpr),
863 smt_solver_interface_call(Solver,mk_op(TranslationType, equal,SExpr,UnionOfSets,EqualToUnion)), % S = Union(Sets)
864 % enforce sets pairwise disjoint (= intersection is empty)
865 get_texpr_type(S,Type),
866 smt_solver_interface_call(Solver,mk_empty_set(TranslationType, Type,EmptySet)),
867 pairwise_disjoint(TranslationType,SetExprs,Solver,EmptySet,PWConstraint),
868 smt_solver_interface_call(Solver,mk_op_arglist(TranslationType, conjunct,[EqualToUnion,PWConstraint],Expr)).
869 % quantifiers
870 mk_expr_aux(forall(IDs,b(truth,pred,_),B),pred,TranslationType, Solver,LS,GS,Expr) :-
871 !,
872 create_bounded_smt_state(TranslationType, Solver,IDs,State,SMTExprs),
873 append(State,LS,NLS),
874 mk_expr(B,TranslationType, Solver,NLS,GS,BE),
875 smt_solver_interface_call(Solver,mk_quantifier(TranslationType, forall,SMTExprs,BE,Expr)).
876 mk_expr_aux(forall(IDs,A,B),pred,TranslationType, Solver,LS,GS,Expr) :-
877 !,
878 create_bounded_smt_state(TranslationType, Solver,IDs,State,SMTExprs),
879 append(State,LS,NLS),
880 mk_expr(A,TranslationType, Solver,NLS,GS,AE), mk_expr(B,TranslationType, Solver,NLS,GS,BE),
881 smt_solver_interface_call(Solver,mk_op(TranslationType, implication,AE,BE,InnerExpr)),
882 smt_solver_interface_call(Solver,mk_quantifier(TranslationType, forall,SMTExprs,InnerExpr,Expr)).
883 mk_expr_aux(exists(IDs,B),pred,TranslationType, Solver,LS,GS,Expr) :-
884 !,
885 create_bounded_smt_state(TranslationType, Solver,IDs,State,SMTExprs),
886 append(State,LS,NLS),
887 mk_expr(B,TranslationType, Solver,NLS,GS,InnerExpr),
888 smt_solver_interface_call(Solver,mk_quantifier(TranslationType, exists,SMTExprs,InnerExpr,Expr)).
889 % equality is a special case as it needs to distinguish between booleans and other types
890 mk_expr_aux(equal(A,B),pred,TranslationType, Solver,LS,GS,Expr) :-
891 !,
892 mk_expr(A,TranslationType, Solver,LS,GS,AE),
893 mk_expr(B,TranslationType, Solver,LS,GS,BE),
894 get_texpr_type(A,Type),
895 ( Type = boolean
896 -> smt_solver_interface_call(Solver, mk_op(TranslationType, equivalence, AE, BE, Expr))
897 ; smt_solver_interface_call(Solver, mk_op(TranslationType, equal, AE, BE, Expr))
898 ).
899 mk_expr_aux(convert_int_floor(Real),integer,TranslationType, Solver,LS,GS,Expr) :-
900 mk_expr(Real, TranslationType, Solver, LS, GS, RealExpr),
901 !,
902 number_codes(RealExpr, ECodes),
903 append([102,108,111,111,114], ECodes, EECodes),
904 atom_codes(EAtom, EECodes),
905 ( is_ground_real(Real)
906 -> IsGroundArg = 1
907 ; IsGroundArg = 0
908 ),
909 smt_solver_interface_call(Solver,mk_op_floor(TranslationType,IsGroundArg,EAtom,RealExpr,Expr)).
910 mk_expr_aux(convert_int_ceiling(Real),integer,TranslationType, Solver,LS,GS,Expr) :-
911 mk_expr(Real, TranslationType, Solver, LS, GS, RealExpr),
912 !,
913 number_codes(RealExpr, ECodes),
914 append([99,101,105,108,105,110,103], ECodes, EECodes),
915 atom_codes(EAtom, EECodes),
916 ( is_ground_real(Real)
917 -> IsGroundArg = 1
918 ; IsGroundArg = 0
919 ),
920 smt_solver_interface_call(Solver,mk_op_ceiling(TranslationType,IsGroundArg,EAtom,RealExpr,Expr)).
921 % records
922 mk_expr_aux(rec(ListOfFields),Type,TranslationType, Solver,LS,GS,Expr) :-
923 !,
924 findall(FieldExpr, member(field(_,FieldExpr),ListOfFields), FieldExprs),
925 maplist(mk_expr_maplist(TranslationType, Solver,LS,GS),FieldExprs,SMTFieldExprs),
926 smt_solver_interface_call(Solver,mk_record_const(TranslationType, Type,SMTFieldExprs,Expr)).
927 mk_expr_aux(record_field(Record,FieldName),Type,TranslationType, Solver,LS,GS,Expr) :-
928 !,
929 get_texpr_type(Record,record(RFields)),
930 nth0(FieldNr,RFields,field(FieldName,Type)),
931 % debug_format(9,'Field: ~w Type: ~w~n-> FieldNr: ~w~n',[FieldName,RFields,FieldNr]),
932 mk_expr(Record,TranslationType, Solver,LS,GS,SMTRecordExpr),
933 smt_solver_interface_call(Solver,mk_record_field(TranslationType, SMTRecordExpr,FieldNr,Expr)).
934 % couple construction
935 mk_expr_aux(couple(A,B),Type,TranslationType, Solver,LS,GS,Expr) :-
936 !,
937 mk_expr(A,TranslationType, Solver,LS,GS,AE),
938 mk_expr(B,TranslationType, Solver,LS,GS,BE),
939 smt_solver_interface_call(Solver,mk_couple(TranslationType, Type,AE,BE,Expr)).
940 % constants and identifiers
941 mk_expr_aux(identifier(Id),_,_,_Solver,LS,GS,Expr) :-
942 !,
943 lookup(Id,LS,GS,Expr).
944 mk_expr_aux(real(RealAtom),real,TranslationType, Solver,_LS,_GS,Expr) :-
945 !,
946 smt_solver_interface_call(Solver,mk_real_const(TranslationType, RealAtom,Expr)).
947 mk_expr_aux(integer(Int),integer,TranslationType, Solver,_LS,_GS,Expr) :-
948 !,
949 smt_solver_interface_call(Solver,mk_int_const(TranslationType, Int,Expr)).
950 mk_expr_aux(min_int,integer,TranslationType, Solver,_LS,_GS,Expr) :-
951 !,
952 get_preference(minint,MinInt),
953 smt_solver_interface_call(Solver,mk_int_const(TranslationType, MinInt,Expr)).
954 mk_expr_aux(max_int,integer,TranslationType, Solver,_LS,_GS,Expr) :-
955 !,
956 get_preference(maxint,MaxInt),
957 smt_solver_interface_call(Solver,mk_int_const(TranslationType, MaxInt,Expr)).
958 mk_expr_aux(boolean_true,boolean,_,Solver,_LS,_GS,Expr) :-
959 !,
960 smt_solver_interface_call(Solver,mk_bool_const(boolean_true,Expr)).
961 mk_expr_aux(boolean_false,boolean,_,Solver,_LS,_GS,Expr) :-
962 !,
963 smt_solver_interface_call(Solver,mk_bool_const(boolean_false,Expr)).
964 mk_expr_aux(string(S),string,TranslationType,Solver,_LS,_GS,Expr) :-
965 !,
966 smt_solver_interface_call(Solver,mk_string_const(TranslationType, S,Expr)).
967 mk_expr_aux(truth,pred,_,Solver,_LS,_GS,Expr) :-
968 !,
969 smt_solver_interface_call(Solver,mk_bool_const(boolean_true,Expr)).
970 mk_expr_aux(falsity,pred,_,Solver,_LS,_GS,Expr) :-
971 !,
972 smt_solver_interface_call(Solver,mk_bool_const(boolean_false,Expr)).
973 mk_expr_aux(bool_set,set(boolean),TranslationType, Solver,_LS,_GS,Expr) :-
974 !,
975 smt_solver_interface_call(Solver,mk_bool_const(boolean_true,True)),
976 smt_solver_interface_call(Solver,mk_bool_const(boolean_false,False)),
977 smt_solver_interface_call(Solver,mk_set(TranslationType, [True,False],Expr)).
978 mk_expr_aux(set_extension(List),set(T),TranslationType, Solver,LS,GS,Expr) :-
979 !,
980 maplist(mk_expr_maplist(TranslationType, Solver,LS,GS),List,SubExprs),
981 ( SubExprs = []
982 -> smt_solver_interface_call(Solver,mk_empty_set(TranslationType, set(T),Expr))
983 ; smt_solver_interface_call(Solver,mk_set(TranslationType, SubExprs,Expr))
984 ).
985 mk_expr_aux(empty_set,Type,TranslationType, Solver,_LS,_GS,Expr) :-
986 !,
987 smt_solver_interface_call(Solver,mk_empty_set(TranslationType, Type,Expr)).
988 % given values
989 mk_expr_aux(value(V),Type,TranslationType, Solver,LS,GS,Expr) :-
990 !,
991 mk_value(Type,V,TranslationType, Solver,LS,GS,Expr).
992 % ast nodes that can be ignored
993 mk_expr_aux(convert_bool(P),boolean,TranslationType, Solver,LS,GS,Expr) :-
994 !,
995 mk_expr(P,TranslationType, Solver,LS,GS,Expr).
996 % lets
997 mk_expr_aux(let_expression(ListOfIDs,ListOfDefinitions,LetExpression),_Type,TranslationType, Solver,LS,GS,Expr) :-
998 create_let_state(ListOfIDs,ListOfDefinitions,TranslationType, Solver,LS,GS,NewLS),
999 !,
1000 mk_expr(LetExpression,TranslationType, Solver,NewLS,GS,Expr).
1001 mk_expr_aux(let_predicate(ListOfIDs,ListOfDefinitions,LetExpression),pred,TranslationType, Solver,LS,GS,Expr) :-
1002 create_let_state(ListOfIDs,ListOfDefinitions,TranslationType, Solver,LS,GS,NewLS),
1003 !,
1004 mk_expr(LetExpression,TranslationType, Solver,NewLS,GS,Expr).
1005 % -- cases with functor:
1006 mk_expr_aux(Op, Type, TranslationType, Solver, LS, GS, Expr) :-
1007 functor(Op, Functor, 1),
1008 (Functor == pow_subset; Functor == pow1_subset; Functor == fin_subset; Functor == fin1_subset),
1009 !,
1010 arg(1, Op, A),
1011 Type = set(set(InnerSetType)),
1012 mk_expr(A, TranslationType, Solver, LS, GS, AE),
1013 ( Functor == pow_subset
1014 -> smt_solver_interface_call(Solver, mk_op_pow_subset(TranslationType, AE, set(InnerSetType), Expr))
1015 ; Functor == pow1_subset
1016 -> smt_solver_interface_call(Solver, mk_op_pow1_subset(TranslationType, AE, set(InnerSetType), InnerSetType, Expr))
1017 ; Functor == fin_subset
1018 -> smt_solver_interface_call(Solver, mk_op_fin_subset(TranslationType, AE, set(InnerSetType), Expr))
1019 ; smt_solver_interface_call(Solver, mk_op_fin1_subset(TranslationType, AE, set(InnerSetType), InnerSetType, Expr))
1020 ).
1021 mk_expr_aux(Op, _, TranslationType, Solver, LS, GS, Expr) :-
1022 functor(Op, Functor, 1),
1023 (Functor == domain; Functor == range),
1024 !,
1025 arg(1, Op, A),
1026 mk_expr(A, TranslationType, Solver, LS, GS, AE),
1027 A = b(_,set(CoupleType),_),
1028 CoupleType = couple(Prj1Type,Prj2Type),
1029 ( Functor == domain
1030 -> smt_solver_interface_call(Solver, mk_op_domain(TranslationType, AE, CoupleType, Prj1Type, Prj2Type, Expr))
1031 ; smt_solver_interface_call(Solver, mk_op_range(TranslationType, AE, CoupleType, Prj1Type, Prj2Type, Expr))
1032 ).
1033 mk_expr_aux(Op, Type, TranslationType, Solver, LS, GS, Expr) :-
1034 functor(Op, Functor, 2),
1035 (Functor == domain_restriction; Functor == domain_subtraction; Functor == range_restriction; Functor == range_subtraction),
1036 !,
1037 Type = set(CoupleType),
1038 arg(1, Op, A1),
1039 arg(2, Op, A2),
1040 mk_expr(A1, TranslationType, Solver, LS, GS, AE1),
1041 mk_expr(A2, TranslationType, Solver, LS, GS, AE2),
1042 ( Functor == domain_restriction
1043 -> smt_solver_interface_call(Solver, mk_op_dom_res(TranslationType, AE1, AE2, CoupleType, Expr))
1044 ; Functor == domain_subtraction
1045 -> smt_solver_interface_call(Solver, mk_op_dom_sub(TranslationType, AE1, AE2, CoupleType, Expr))
1046 ; Functor == range_restriction
1047 -> smt_solver_interface_call(Solver, mk_op_ran_res(TranslationType, AE1, AE2, CoupleType, Expr))
1048 ; smt_solver_interface_call(Solver, mk_op_ran_sub(TranslationType, AE1, AE2, CoupleType, Expr))
1049 ).
1050 mk_expr_aux(Op,_,TranslationType, Solver,LS,GS,Expr) :-
1051 functor(Op,Functor,1),
1052 unary_operator(Functor),
1053 !,
1054 arg(1,Op,A),
1055 mk_expr(A,TranslationType, Solver,LS,GS,AE),
1056 smt_solver_interface_call(Solver,mk_op_arglist(TranslationType, Functor, [AE], Expr)).
1057 mk_expr_aux(Op, _, TranslationType, Solver, LS, GS, Expr) :-
1058 functor(Op, Functor, 1),
1059 ( Functor == general_union; Functor == general_intersection),
1060 !,
1061 arg(1, Op, A),
1062 A = b(_,set(set(InnerType)),_),
1063 mk_expr(A, TranslationType, Solver, LS, GS, AE),
1064 ( Functor == general_union
1065 -> smt_solver_interface_call(Solver, mk_op_general_union(TranslationType, AE, set(InnerType), InnerType, Expr))
1066 ; store_explicit_set_unique_id(A, UniqueIdName),
1067 smt_solver_interface_call(Solver, mk_op_general_intersection(TranslationType, UniqueIdName, AE, set(InnerType), InnerType, Expr))
1068 ).
1069 mk_expr_aux(Op,_,TranslationType, Solver,LS,GS,Expr) :-
1070 functor(Op,Functor,2),
1071 binary_operator(Functor),
1072 !,
1073 arg(1,Op,A),
1074 mk_expr(A,TranslationType, Solver,LS,GS,AE),
1075 arg(2,Op,B),
1076 mk_expr(B,TranslationType, Solver,LS,GS,BE),
1077 smt_solver_interface_call(Solver,mk_op(TranslationType, Functor,AE,BE,Expr)).
1078 % error case
1079 mk_expr_aux(Expr,_,_,_,_,_,_) :- !,
1080 add_error_fail(smt_solvers_interface,'mk_expr failed',Expr).
1081
1082 create_let_state([],[],_,_,S,_,S).
1083 create_let_state([ID|IDs],[Def|Defs],TranslationType, Solver,StateSoFar,GS,State) :-
1084 get_texpr_id(ID,UnwrappedId),
1085 mk_expr(Def,TranslationType, Solver,StateSoFar,GS,Expr),
1086 create_let_state(IDs,Defs,TranslationType, Solver,[id(UnwrappedId,Expr)|StateSoFar],GS,State).
1087
1088 mk_value_maplist(Type,TranslationType, Solver,LS,GS,Val,Expr) :-
1089 mk_value(Type,Val,TranslationType, Solver,LS,GS,Expr).
1090
1091 mk_value(Type,Val,TranslationType, Solver,LS,GS,Expr) :-
1092 (mk_value_aux(Type,Val,TranslationType, Solver,LS,GS,Expr) -> true). % avoid spurious error messages upon backtrack
1093
1094 mk_value_aux(real,RealTerm,TranslationType, Solver,_LS,_GS,Expr) :-
1095 ( RealTerm = term(floating(Real))
1096 ; RealTerm = real(Real)
1097 ),
1098 float(Real),
1099 !,
1100 number_codes(Real, RealCodes),
1101 atom_codes(RealAtom, RealCodes),
1102 smt_solver_interface_call(Solver,mk_real_const(TranslationType,RealAtom,Expr)).
1103 mk_value_aux(real,real(RealAtom),TranslationType, Solver,_LS,_GS,Expr) :-
1104 !,
1105 smt_solver_interface_call(Solver,mk_real_const(TranslationType,RealAtom,Expr)).
1106 mk_value_aux(string,string(Atom),TranslationType, Solver,_LS,_GS,Expr) :-
1107 !,
1108 smt_solver_interface_call(Solver,mk_string_const(TranslationType,Atom,Expr)).
1109 mk_value_aux(integer,int(Int),TranslationType, Solver,_LS,_GS,Expr) :-
1110 !,
1111 smt_solver_interface_call(Solver,mk_int_const(TranslationType,Int,Expr)).
1112 mk_value_aux(boolean,pred_false,_,Solver,_LS,_GS,Expr) :-
1113 !,
1114 smt_solver_interface_call(Solver,mk_bool_const(boolean_false,Expr)).
1115 mk_value_aux(boolean,pred_true,_,Solver,_LS,_GS,Expr) :-
1116 !,
1117 smt_solver_interface_call(Solver,mk_bool_const(boolean_true,Expr)).
1118 % only supported thanks to z3 full sets
1119 mk_value_aux(set(integer),global_set('INTEGER'),TranslationType, z3,_LS,_GS,Expr) :-
1120 !,
1121 smt_solver_interface_call(z3,mk_full_set(TranslationType,set(integer),Expr)).
1122 mk_value_aux(set(string),global_set('STRING'),TranslationType, z3,_LS,_GS,Expr) :-
1123 !,
1124 smt_solver_interface_call(z3,mk_full_set(TranslationType,set(string),Expr)).
1125 mk_value_aux(set(global(X)),global_set(X),_,_Solver,LS,GS,Expr) :-
1126 lookup(X,LS,GS,Expr).
1127 mk_value_aux(set(X),avl_set(Val),TranslationType, Solver,LS,GS,Expr) :-
1128 expand_custom_set_to_list_now(avl_set(Val),Values),
1129 !,
1130 mk_value(set(X),Values,TranslationType, Solver,LS,GS,Expr).
1131 mk_value_aux(set(X),List,TranslationType, Solver,LS,GS,Expr) :-
1132 maplist(mk_value_maplist(X,TranslationType, Solver,LS,GS),List,SubExprs),
1133 !,
1134 ( SubExprs = []
1135 -> smt_solver_interface_call(Solver,mk_empty_set(TranslationType,set(X),Expr))
1136 ; smt_solver_interface_call(Solver,mk_set(TranslationType,SubExprs,Expr))
1137 ).
1138 mk_value_aux(couple(AT,BT),(A,B), TranslationType, Solver,LS,GS,Expr) :-
1139 mk_value(AT,A,TranslationType, Solver,LS,GS,AE),!,
1140 mk_value(BT,B,TranslationType, Solver,LS,GS,BE),
1141 !,
1142 smt_solver_interface_call(Solver,mk_couple(TranslationType, couple(AT,BT),AE,BE,Expr)).
1143 mk_value_aux(record(FieldTypes), rec(Fields), TranslationType, Solver, LS, GS, Expr) :-
1144 create_exprs_for_rec_value_fields(FieldTypes, Fields, TranslationType, Solver, LS, GS, SMTFieldExprs),
1145 !,
1146 smt_solver_interface_call(Solver, mk_record_const(TranslationType,record(FieldTypes),SMTFieldExprs,Expr)).
1147 mk_value_aux(global(Name),fd(Num,Name),_,_Solver,LS,GS,Expr) :-
1148 is_b_global_constant(Name,Num,Constant),
1149 !,
1150 lookup(Constant,LS,GS,Expr).
1151 % error case
1152 mk_value_aux(Type,Value,_,_,_,_,_) :- !,
1153 add_error_fail(smt_solvers_interface,'mk_value failed',[Type,Value]).
1154
1155 is_ground_real(b(unary_minus_real(Real),real,_)) :-
1156 is_ground_real(Real).
1157 is_ground_real(b(real(_),real,_)).
1158 is_ground_real(b(value(_),real,_)).
1159
1160 %% create_exprs_for_rec_value_fields(+FieldTypes, +Fields, +TranslationType, +Solver, +LS, +GS, -FieldExprs).
1161 create_exprs_for_rec_value_fields([], [], _, _, _, _, []).
1162 create_exprs_for_rec_value_fields([field(Name,Type)|TT], [field(Name,Value)|FT], TranslationType, Solver, LS, GS, [Expr|NT]) :-
1163 mk_value(Type, Value, TranslationType, Solver, LS, GS, Expr),
1164 create_exprs_for_rec_value_fields(TT, FT, TranslationType, Solver, LS, GS, NT).
1165
1166 pairwise_union(_, [S],_Solver,Out) :-
1167 !,
1168 Out = S.
1169 pairwise_union(TranslationType, [S|Sets],Solver,Expr) :-
1170 pairwise_union(TranslationType, Sets,Solver,SS),
1171 smt_solver_interface_call(Solver,mk_op(TranslationType,union,S,SS,Expr)).
1172
1173 pairwise_disjoint(TranslationType, [H,T],Solver,EmptySet,Constraint) :- !,
1174 pairwise_disjoint_mk_expr(TranslationType, Solver,H,T,EmptySet,Constraint).
1175 pairwise_disjoint(TranslationType, [H|T],Solver,EmptySet,Constraint) :-
1176 pairwise_disjoint(TranslationType, H,T,Solver,EmptySet,SubConstraints),
1177 pairwise_disjoint(TranslationType, T,Solver,EmptySet,SubConstraint),
1178 smt_solver_interface_call(Solver,mk_op_arglist(TranslationType,conjunct,[SubConstraint|SubConstraints],Constraint)).
1179
1180 pairwise_disjoint(TranslationType, E,[Last],Solver,EmptySet,[C]) :- !,
1181 pairwise_disjoint_mk_expr(TranslationType, Solver,E,Last,EmptySet,C).
1182 pairwise_disjoint(TranslationType, E,[H|T],Solver,EmptySet,[C|Cs]) :-
1183 pairwise_disjoint_mk_expr(TranslationType, Solver,E,H,EmptySet,C),
1184 pairwise_disjoint(TranslationType, E,T,Solver,EmptySet,Cs).
1185
1186 pairwise_disjoint_mk_expr(TranslationType, Solver,A,B,EmptySet,PWConstraint) :-
1187 smt_solver_interface_call(Solver,mk_op(TranslationType,intersection,A,B,Inter)),
1188 smt_solver_interface_call(Solver,mk_op(TranslationType,equal,Inter,EmptySet,PWConstraint)).
1189
1190 mk_sort(TranslationType,Solver,Set) :-
1191 smt_solver_interface_call(Solver,mk_sort(TranslationType,Set)).
1192
1193 setup_deferred_sets(_, _, [], DefSetIdentifiers) :-
1194 !,
1195 DefSetIdentifiers = [].
1196 setup_deferred_sets(TranslationType, Solver, DeferredSets, DefSetIdentifiers) :-
1197 % deferred sets and which are either not unfixed or ProB's default set size preference is not considered -> only create a sort
1198 maplist(mk_sort(TranslationType, Solver), DeferredSets),
1199 mk_deferred_set_identifiers(TranslationType, Solver, DeferredSets, DefSetIdentifiers).
1200
1201 %% create_virtual_enum_elms(+DefaultSetSize, +DefSet, -DefElms).
1202 % For a deferred set D and preference DEFAULT_SETSIZE of 3 we create 'D1', 'D2', and 'D3'.
1203 create_virtual_enum_elms(DefaultSetSize, DefSet, DefElms) :-
1204 create_virtual_enum_elms(1, DefaultSetSize, DefSet, DefElms).
1205
1206 create_virtual_enum_elms(Counter, DefaultSetSize, _, Out) :-
1207 Counter > DefaultSetSize,
1208 !,
1209 Out = [].
1210 create_virtual_enum_elms(Counter, DefaultSetSize, DefSet, [EnumElm|NT]) :-
1211 number_codes(Counter, NC),
1212 atom_codes(AC, NC),
1213 atom_concat(DefSet, AC, EnumElm),
1214 Counter1 is Counter + 1,
1215 assert_virtual_deferred_set_id(EnumElm, fd(Counter,DefSet)),
1216 create_virtual_enum_elms(Counter1, DefaultSetSize, DefSet, NT).
1217
1218 prepare_unfixed_deferred_sets_with_virtual_elms(_, [], []).
1219 prepare_unfixed_deferred_sets_with_virtual_elms(DefaultSetSize, [DefSet|T], [(DefSet,DefElms)|NT]) :-
1220 ( get_user_defined_scope(DefSet,Low,Up,_Span)
1221 -> % a specific deferred set's size might be user defined in the definitions
1222 DeferredSetSize is 1+Up-Low
1223 ; DeferredSetSize = DefaultSetSize
1224 ),
1225 create_virtual_enum_elms(DeferredSetSize, DefSet, DefElms),
1226 prepare_unfixed_deferred_sets_with_virtual_elms(DefaultSetSize, T, NT).
1227
1228 prepare_enumerated_sets_with_elms([], []).
1229 prepare_enumerated_sets_with_elms([EnumSet|T], [(EnumSet,EnumElms)|NT]) :-
1230 % find all global constants belonging to the given set
1231 findall(Cst, is_b_global_constant(EnumSet, _, Cst), EnumElms),
1232 prepare_enumerated_sets_with_elms(T, NT).
1233
1234 setup_sets(TranslationType, Solver, GlobalIdentifiers) :-
1235 ( get_preference(z3_solve_for_animation, true)
1236 -> % Z3 behaves as ProB by considering DEFAULT_SETSIZE preference
1237 findall(DS, (b_global_deferred_set(DS), unfixed_deferred_set(DS)), UnfixedDefSets),
1238 get_preference(globalsets_fdrange, DefaultSetSize),
1239 prepare_unfixed_deferred_sets_with_virtual_elms(DefaultSetSize, UnfixedDefSets, EnumDefSetPairs),
1240 findall(DS, (b_global_deferred_set(DS), \+ unfixed_deferred_set(DS)), DeferredSets),
1241 setup_deferred_sets(TranslationType, Solver, DeferredSets, DefSetIdentifiers)
1242 ; % Z3 behaves differently compared to ProB if deferred sets are used
1243 findall(X, b_global_deferred_set(X), DeferredSets),
1244 setup_deferred_sets(TranslationType, Solver, DeferredSets, DefSetIdentifiers),
1245 EnumDefSetPairs = []
1246 ),
1247 % enumerated sets -> create a dedicated datatype in SMT-LIB
1248 b_get_global_enumerated_sets(EnumeratedSets),
1249 % can not use setof / bagof for some reason
1250 list_to_set(EnumeratedSets, EnumeratedSetsNoDuplicates),
1251 prepare_enumerated_sets_with_elms(EnumeratedSetsNoDuplicates, EnumSetPairs),
1252 append(EnumSetPairs, EnumDefSetPairs, GlobalSetPairs),
1253 maplist(setup_enumerated_set(TranslationType, Solver), GlobalSetPairs, IdentifierLists),
1254 append([DefSetIdentifiers|IdentifierLists], GlobalIdentifiers).
1255
1256 % currently only functional for z3
1257 mk_deferred_set_identifiers(_, cvc4, _, []).
1258 mk_deferred_set_identifiers(TranslationType, z3, DeferredSets, DefSetIdentifiers) :-
1259 maplist(mk_deferred_set_identifiers2(TranslationType), DeferredSets, DefSetIdentifiers).
1260
1261 mk_deferred_set_identifiers2(TranslationType, SetName, id(SetName, SetExpression)) :-
1262 smt_solver_interface_call(z3, mk_full_set(TranslationType, set(global(SetName)), SetExpression)).
1263
1264 setup_enumerated_set(TranslationType, Solver, (SetName,SetElements), [SetIdentifier|Identifiers]) :-
1265 %b_global_set_cardinality(SetName, Cardinality), % don't use b_global_set_cardinality/2 here since it can be different than the actual cardinality due to the preference globalsets_fdrange
1266 length(SetElements, Cardinality),
1267 % make a new sort and create identifiers
1268 smt_solver_interface_call(Solver, mk_sort_with_cardinality(TranslationType, SetName, Cardinality, SetElements, EnumExprs)),
1269 SetIdentifier = id(SetName, SetExpression),
1270 create_enum_element_smt_state(SetElements, EnumExprs, Identifiers),
1271 smt_solver_interface_call(Solver, mk_set(TranslationType, EnumExprs, SetExpression)).
1272
1273 create_enum_element_smt_state([], [], []).
1274 create_enum_element_smt_state([IdName|TIds], [EnumExpr|TExprs], [id(IdName,EnumExpr)|T]) :-
1275 create_enum_element_smt_state(TIds, TExprs, T).
1276
1277 create_smt_state(TranslationType, Solver,Identifiers,State,Exprs) :-
1278 exclude(is_external_function_identifier,Identifiers,LessIdentifiers),
1279 maplist(create_smt_identifier(TranslationType, Solver),LessIdentifiers,State,Exprs).
1280
1281 create_bounded_smt_state(TranslationType, Solver,Identifiers,State,Exprs) :-
1282 maplist(create_bounded_smt_identifier(TranslationType, Solver),Identifiers,State,Exprs).
1283
1284 create_smt_identifier(TranslationType, Solver,b(identifier(Id),Type,_Infos),id(Id,Expr),Expr) :-
1285 ground(Id),
1286 !,
1287 smt_solver_interface_call(Solver,mk_var(TranslationType, Type,Id,Expr)).
1288 create_smt_identifier(_, _, b(identifier(_),Type,_Infos), _, _) :-
1289 add_error_fail(create_smt_identifier, 'Identifier name is not ground for type ~w~n', [Type]).
1290
1291 create_bounded_smt_identifier(TranslationType, Solver, b(identifier(Id),Type,_Infos), id(Id,Expr), Expr) :-
1292 ground(Id),
1293 !,
1294 smt_solver_interface_call(Solver,mk_bounded_var(TranslationType, Type,Id,Expr)).
1295 create_bounded_smt_identifier(_, _, b(identifier(_),Type,_Infos), _, _) :-
1296 add_error_fail(create_bounded_smt_identifier, 'Identifier name is not ground for type ~w~n', [Type]).
1297
1298 is_external_function_identifier(Id) :-
1299 get_texpr_id(Id,Name),
1300 is_external_function_name(Name).
1301
1302 lookup(Id,LS,GS,Expr) :-
1303 ( member(id(Id,Expr),LS) % id defined in local store
1304 ; member(id(Id,Expr),GS) % id defined in global store
1305 ).
1306
1307 contains_unsupported_type_or_expression(TranslationType, Solver, TExpr) :-
1308 contains_unsupported_type_or_expression(TranslationType, Solver, TExpr, _).
1309 contains_unsupported_type_or_expression(TranslationType, Solver, TExpr, Unsupported) :-
1310 map_over_typed_bexpr(smt_solvers_interface:contains_unsupported_aux(TranslationType, Solver), TExpr, Unsupported).
1311
1312 :- public contains_unsupported_aux/4.
1313 contains_unsupported_aux(TranslationType, Solver, TExpr, Expr) :-
1314 get_texpr_expr(TExpr, Expr),
1315 get_texpr_type(TExpr, Type),
1316 ( unsupported_type(TranslationType, Type, Solver)
1317 -> debug:debug_println(9,unsupported_type(TranslationType,Type,Solver))
1318 ; ( unsupported_expr(TranslationType, Expr, Type, Solver)
1319 -> functor(Expr,F,A),
1320 debug:debug_println(9,unsupported_expr(TranslationType,F/A))
1321 )
1322 ).
1323
1324 % these expressions are not supported by one or more translation types
1325 %% change in Z3: lambda inside recursive functions was declared unsupported until proper support is provided (see https://github.com/Z3Prover/z3/issues/5813)
1326 %% see mk_op_iteration_func_decl in /extensions/z3interface/src/cpp/main.cpp
1327 unsupported_expr(sat, Expr, _, _) :-
1328 !,
1329 \+ (Expr = conjunct(_,_); Expr = disjunct(_,_); Expr = identifier(_); Expr = equal(_,_); Expr = implication(_,_); Expr = equivalence(_,_);
1330 Expr = negation(_); Expr = boolean_true; Expr = boolean_false; Expr = value(pred_true); Expr = value(pred_false)).
1331 unsupported_expr(_, power_of_real(_,_),_,_).
1332 unsupported_expr(_, struct(_),_,_).
1333 unsupported_expr(constructive, closure(_),_,_).
1334 unsupported_expr(constructive, iteration(_,_),_,_).
1335 %%
1336 unsupported_expr(axiomatic, general_union(_),_,_).
1337 unsupported_expr(axiomatic, general_intersection(_),_,_).
1338 unsupported_expr(_,general_product(_,_,_),_,_).
1339 unsupported_expr(_,general_sum(_,_,_),_,_).
1340 unsupported_expr(axiomatic, iteration(_,_),_,_).
1341 unsupported_expr(axiomatic, closure(_),_,_).
1342 unsupported_expr(_,external_pred_call(Pred,_),_,_) :-
1343 Pred \= 'LEQ_SYM'. % introduced by symmetry breaking; we could also try and turn this off in ast_cleanup
1344 unsupported_expr(_,external_function_call(_,_),_,_).
1345 unsupported_expr(_,function(Name,_),_,_) :-
1346 is_external_function_name(Name).
1347 unsupported_expr(_, general_concat(_),_,_).
1348 % the following exprs should have been removed by a rewrite rule
1349 unsupported_expr(axiomatic, pow_subset(_),_,_).
1350 unsupported_expr(axiomatic, pow1_subset(_),_,_).
1351 unsupported_expr(axiomatic, fin_subset(_),_,_).
1352 unsupported_expr(axiomatic, fin1_subset(_),_,_).
1353 unsupported_expr(axiomatic, composition(_,_),_,_).
1354 unsupported_expr(axiomatic, comprehension_set(_,_),_,_).
1355 unsupported_expr(axiomatic, image(_,_),_,_).
1356 unsupported_expr(axiomatic, reverse(_),_,_).
1357 unsupported_expr(axiomatic, range(_),_,_).
1358 unsupported_expr(axiomatic, domain(_),_,_).
1359 unsupported_expr(_,min(_),_,_).
1360 unsupported_expr(_,max(_),_,_).
1361 unsupported_expr(_,card(_),_,_).
1362 unsupported_expr(_,finite(_),_,_).
1363 unsupported_expr(axiomatic, interval(_,_),_,_).
1364 unsupported_expr(_,integer_set(_),_,_).
1365 unsupported_expr(_,real_set(_),_,_).
1366 unsupported_expr(_,float_set(_),_,_).
1367 unsupported_expr(axiomatic,parallel_product(_,_),_,_).
1368 unsupported_expr(axiomatic,direct_product(_,_),_,_).
1369 unsupported_expr(axiomatic, domain_restriction(_,_),_,_).
1370 unsupported_expr(axiomatic, range_restriction(_,_),_,_).
1371 unsupported_expr(axiomatic, domain_subtraction(_,_),_,_).
1372 unsupported_expr(axiomatic, range_subtraction(_,_),_,_).
1373 unsupported_expr(_,overwrite(_,_),_,_).
1374 unsupported_expr(axiomatic, cartesian_product(_,_),_,_).
1375 unsupported_expr(_,function(_,_),_,_).
1376 unsupported_expr(_,not_equal(_,_),_,_).
1377 unsupported_expr(_,not_member(_,_),_,_).
1378 unsupported_expr(_,relations(_,_),_,_).
1379 unsupported_expr(_,partial_function(_,_),_,_).
1380 unsupported_expr(_,total_function(_,_),_,_).
1381 unsupported_expr(_,partial_injection(_,_),_,_).
1382 unsupported_expr(_,total_injection(_,_),_,_).
1383 unsupported_expr(_,partial_surjection(_,_),_,_).
1384 unsupported_expr(_,total_surjection(_,_),_,_).
1385 unsupported_expr(_,total_relation(_,_),_,_).
1386 unsupported_expr(_,surjection_relation(_,_),_,_).
1387 unsupported_expr(_,total_surjection_relation(_,_),_,_).
1388 % certain values are not supported yet
1389 unsupported_expr(_,value(X),_,_) :- \+ ground(X). % can not translate unknown values
1390 unsupported_expr(TranslationType,value(couple(A,B)),couple(AT,BT),Solver) :-
1391 unsupported_expr(TranslationType,value(A),AT,Solver) ;
1392 unsupported_expr(TranslationType,value(B),BT,Solver).
1393 unsupported_expr(_,value(global_set('INTEGER')),_,cvc4).
1394 unsupported_expr(_,value(V),Type,_) :-
1395 V \= [], % empty set can be translated
1396 unsupported_value_type(Type).
1397 unsupported_expr(_,value(fd(Num,SetName)),global(SetName),_) :-
1398 \+ is_b_global_constant(SetName,Num,_). % has been invented by prob but is unnamed
1399 % cvc4 does not support generating a full set of a sort, thus there
1400 % is currently no way of expressing a complete deferred set
1401 unsupported_expr(_,identifier(SetName),set(global(SetName)),cvc4).
1402
1403 % some types are not supported / can not be translated at the moment
1404 unsupported_type(sat,Type,_) :-
1405 !,
1406 \+ (Type == pred; Type == boolean).
1407 unsupported_type(_,freetype,_).
1408 unsupported_type(_,any,_).
1409 unsupported_type(_,seq(_),_). % seq(S) is set(couple(integer,S)) and has been rewritten by seq_rewriter.pl
1410 unsupported_type(TranslationType,set(X),S) :-
1411 unsupported_type(TranslationType,X,S).
1412 unsupported_type(TranslationType,couple(A,B),S) :-
1413 unsupported_type(TranslationType,A,S) ; unsupported_type(TranslationType,B,S).
1414
1415 % currently unsupported values
1416 unsupported_value_type(set(T)) :-
1417 unsupported_value_type(T).
1418 unsupported_value_type(couple(A,B)) :-
1419 unsupported_value_type(A) ; unsupported_value_type(B).
1420 unsupported_value_type(global(S)) :-
1421 unfixed_deferred_set(S).
1422
1423
1424 % --------------------------------
1425
1426 % use_module(smt_solvers_interface(smt_solvers_interface)),smt_solvers_interface:smt_add_cnf([1,2,3],[[1],[2,3]]).
1427
1428 smt_add_cnf(Literals,Clauses) :-
1429 smt_add_cnf(z3sat,Literals,Clauses).
1430
1431 :- dynamic stored_solver_cnf_reference/1, stored_literal_avl_map/1.
1432
1433 :- use_module(library(avl),[list_to_avl/2, avl_fetch/3]).
1434 smt_add_cnf(Solver,Literals,Clauses) :-
1435 retractall(stored_solver_cnf_reference(_)),
1436 retractall(stored_literal_avl_map(_)),
1437 init_interface(Solver),
1438 smt_reset_cnf(Solver),
1439 format('Sending CNF to solver ~w~n',[Solver]),
1440 start_ms_timer(T0),
1441 maplist(add_literal(Solver),Literals,LitMap),
1442 list_to_avl([pred_true-1,pred_false-2|LitMap],LitAvl), % not sure we need pred_true-1 and pred_false-2 map
1443 assert(stored_literal_avl_map(LitAvl)),nl,
1444 debug_format(9,'Registered literals: ~w~n',[LitMap]),
1445 maplist(add_clause(Solver,LitAvl),Clauses,ClauseRefs),
1446 smt_solver_interface_call(Solver,mk_op_arglist(sat,conjunct,ClauseRefs,CNFRef)),
1447 tools:stop_ms_timer_with_msg(T0,sending_cnf_to_smt_solver(Solver)),
1448 assert(stored_solver_cnf_reference(CNFRef)).
1449
1450 add_clause(Solver,LitAvl,Clause,ClauseRef) :-
1451 maplist(translate_literal(Solver,LitAvl),Clause,ExprList),
1452 debug_format(9,'Sending clause to solver ~w~n',[ExprList]),
1453 smt_solver_interface_call(Solver,mk_op_arglist(sat,disjunct,ExprList,ClauseRef)).
1454
1455 smt_add_extra_clause_cnf(Solver,Clause) :-
1456 retract(stored_solver_cnf_reference(CNFRef)),
1457 stored_literal_avl_map(LitAvl),!,
1458 add_clause(Solver,LitAvl,Clause,NewClauseRef),
1459 smt_solver_interface_call(Solver,mk_op_arglist(sat,conjunct,[CNFRef,NewClauseRef],NewCNFRef)),
1460 debug:debug_println(19,stored_new_clause(Clause)),
1461 assert(stored_solver_cnf_reference(NewCNFRef)).
1462 smt_add_extra_clause_cnf(Solver,Clause) :-
1463 add_internal_error('No CNF stored for adding clause:',smt_add_extra_clause_cnf(Solver,Clause)),fail.
1464
1465
1466 smt_solve_cnf(Solver,Model) :-
1467 \+ stored_solver_cnf_reference(_),!,
1468 add_internal_error('No CNF stored for solving:',smt_solve_cnf(Solver,Model)),fail.
1469 smt_solve_cnf(Solver,Model) :-
1470 stored_solver_cnf_reference(CNFRef),
1471 start_ms_timer(T1),
1472 get_preference(time_out, TO),
1473 SelectedSolvers = [sat,sat_cdcl],
1474 AxmRef = -1, % do not solve anything with axiomatic and constructive z3 solver
1475 CnsRef = -1,
1476 smt_solver_interface_call(z3, z3interface:smt_solve_query(SelectedSolvers,AxmRef,CnsRef,CNFRef,TO,SMTResultData)),
1477 tools:stop_ms_timer_with_msg(T1,solving_cnf_with_smt_solver(Solver)),
1478 (debug_mode(off) -> true
1479 ; write('; SMT TRANSLATION: '), nl, pretty_print_smt(z3), nl
1480 ),
1481 write(result_data(SMTResultData)),nl,
1482 SMTResultData = result_tuple(_,SMTResult),
1483 ( SMTResult=sat
1484 -> %smt_solver_interface_call(z3,get_full_model_string(FullModel)),
1485 model_translation:get_full_model_as_avl(Solver,AVL),
1486 %avl:portray_avl(AVL),nl,
1487 avl:avl_to_list(AVL,List),
1488 convert_to_cnf_model(List,1,Model)
1489 ; write('UNSAT'),nl,flush_output,
1490 fail
1491 ).
1492
1493
1494 smt_reset_cnf(_Solver) :- clear_state.
1495
1496 convert_to_cnf_model([],_,R) :- !, R=[].
1497 convert_to_cnf_model([_-X|T],Nr,[Lit|TM]) :-
1498 is_bool(X,Val),!,
1499 (Val=true -> Lit=Nr ; Lit is -Nr),
1500 N1 is Nr+1,
1501 convert_to_cnf_model(T,N1,TM).
1502 convert_to_cnf_model(L,_,R) :- add_error(smt_solvers_interface,'Invalid model value:',L),R=[].
1503
1504 is_bool('z3-define-fun'([],'Bool',Val),Val).
1505
1506
1507 %:- use_module(probsrc(tools_meta), [translate_term_into_atom/2]).
1508 add_literal(Solver,Number,Number-Z3Ref) :-
1509 number_to_atom(Number,Atom),
1510 smt_solver_interface_call(Solver,mk_bounded_var(sat,boolean,Atom,Z3Ref)).
1511
1512 lookup_literal(Literal,LitAvl,Z3Expr) :-
1513 avl_fetch(Literal,LitAvl,Z3Expr).
1514
1515 % we need to ensure that atoms have same order as numbers; otherwise we need to sort model
1516 number_to_atom(Nr,Atom) :- number_codes(Nr,C),
1517 gen_leading_zeros(Nr,9999999,C0s,C),
1518 (10*Nr>=9999999 -> add_warning(smt_solvers_interface,'Too many SAT variables:',Nr) ; true),
1519 atom_codes(Atom,[0'x|C0s]).
1520
1521 gen_leading_zeros(Nr,Lim) --> {Nr>Lim},!.
1522 gen_leading_zeros(Nr,Lim) --> [0'0], {N1 is Nr*10}, gen_leading_zeros(N1,Lim).
1523
1524
1525 translate_literal(Solver,LitAvl,neg(PLiteral),LitRef) :- !,
1526 lookup_literal(PLiteral,LitAvl,Z3Expr) ,
1527 smt_solver_interface_call(Solver,mk_op_arglist(sat,negation,[Z3Expr],LitRef)).
1528 translate_literal(_Solver,LitAvl,Literal,Z3Expr) :-
1529 Literal > 0,
1530 !,
1531 lookup_literal(Literal,LitAvl,Z3Expr).
1532 translate_literal(Solver,LitAvl,Literal,LitRef) :-
1533 Literal < 0,
1534 PLiteral is Literal * -1,
1535 translate_literal(Solver,LitAvl,neg(PLiteral),LitRef).
1536
1537
1538