| 1 | :- module(z3interface, [init_z3interface/0, | |
| 2 | reset_z3interface/0, % TODO: make more lightweight once cvc 1.5 is out | |
| 3 | z3interface_init_error/1, | |
| 4 | pretty_print_smt/0, % pretty print Z3's internal status and constraints | |
| 5 | pretty_print_smt_for_id/2, % pretty print store + constraint pointed to by ID (previously created by z3_interface_call(s)) | |
| 6 | z3_interface_call/1]). | |
| 7 | ||
| 8 | :- use_module(probsrc(module_information)). | |
| 9 | :- module_info(group, smt_solvers). | |
| 10 | :- module_info(description, 'This is the interface between ProB and the Z3 SMT solver'). | |
| 11 | ||
| 12 | ||
| 13 | foreign_resource(z3interface, [init, | |
| 14 | pretty_print_smt, pretty_print_smt_for_id, | |
| 15 | mk_var, | |
| 16 | mk_bounded_var, | |
| 17 | mk_string_const, | |
| 18 | mk_int_const, | |
| 19 | mk_real_const, | |
| 20 | mk_bool_const, | |
| 21 | mk_empty_set, | |
| 22 | mk_full_set, | |
| 23 | mk_record_const, | |
| 24 | mk_record_field, | |
| 25 | mk_set, | |
| 26 | mk_sort, | |
| 27 | mk_sort_with_cardinality, | |
| 28 | pop_frame, push_frame, | |
| 29 | mk_op, | |
| 30 | mk_op_arglist, | |
| 31 | mk_op_reverse, | |
| 32 | mk_op_domain, | |
| 33 | mk_op_range, | |
| 34 | mk_op_image, | |
| 35 | mk_op_cartesian, | |
| 36 | mk_op_identity, | |
| 37 | mk_op_interval, | |
| 38 | mk_op_pow_subset, | |
| 39 | mk_op_pow1_subset, | |
| 40 | mk_op_composition, | |
| 41 | mk_op_direct_product, | |
| 42 | mk_op_parallel_product, | |
| 43 | mk_op_iteration, | |
| 44 | mk_op_closure, | |
| 45 | mk_op_dom_res, | |
| 46 | mk_op_couple_prj, | |
| 47 | mk_op_dom_sub, | |
| 48 | mk_op_ran_res, | |
| 49 | mk_op_ran_sub, | |
| 50 | mk_op_general_union, | |
| 51 | mk_op_general_intersection, | |
| 52 | mk_op_lambda, | |
| 53 | mk_op_comprehension_set_multi, | |
| 54 | mk_op_comprehension_set_singleton, | |
| 55 | mk_op_floor, | |
| 56 | mk_op_ceiling, | |
| 57 | smt_solve_query, | |
| 58 | reset, | |
| 59 | get_model_string, | |
| 60 | get_full_model_string, | |
| 61 | mk_quantifier, | |
| 62 | conjoin_negated_state, | |
| 63 | add_interpreter_constraint, | |
| 64 | mk_couple, | |
| 65 | get_header_version, | |
| 66 | get_full_version]). | |
| 67 | % will be called by solver_interface: | |
| 68 | :- public mk_var/4, mk_bounded_var/4, mk_empty_set/3, mk_int_const/3, mk_real_const/3, mk_bool_const/2, mk_string_const/3. | |
| 69 | :- public mk_set/3, mk_sort/2, mk_sort_with_cardinality/5, mk_record_const/4, mk_record_field/4. | |
| 70 | :- public mk_op/5, mk_quantifier/5, mk_op_arglist/4, get_model_string/2, conjoin_negated_state/4. | |
| 71 | :- public pop_frame/0, push_frame/0, add_interpreter_constraint/4, mk_couple/5, mk_op_image/7, mk_op_reverse/4, mk_op_domain/6, mk_op_range/6. | |
| 72 | :- public mk_op_comprehension_set_multi/5, mk_op_comprehension_set_singleton/4, mk_op_general_union/5, mk_op_general_intersection/6. | |
| 73 | :- public mk_op_interval/4, mk_op_pow_subset/4, mk_op_pow1_subset/5, mk_op_identity/5, mk_op_couple_prj/5, mk_op_composition/8, mk_op_direct_product/8, mk_op_parallel_product/9. | |
| 74 | :- public mk_op_dom_res/5, mk_op_dom_sub/5, mk_op_ran_res/5, mk_op_ran_sub/5, mk_op_lambda/6, mk_op_iteration/7, mk_op_closure/7, mk_op_cartesian/5, mk_op_floor/5, mk_op_ceiling/5. | |
| 75 | ||
| 76 | :- public mk_full_set/3, get_full_model_string/1, reset/0, smt_solve_query/6. % Z3 only | |
| 77 | ||
| 78 | % function declarations | |
| 79 | foreign(init, c, init). | |
| 80 | foreign(pretty_print_smt, c, pretty_print_smt). | |
| 81 | foreign(pretty_print_smt_for_id, c, pretty_print_smt_for_id(+atom, +integer)). | |
| 82 | foreign(mk_var, c, mk_var(+atom, +term, +string, [-integer])). % creates a variable; second argument is an atom of the type, | |
| 83 | % third argument is the identifier | |
| 84 | foreign(mk_bounded_var, c, mk_bounded_var(+atom, +term, +string, [-integer])). | |
| 85 | foreign(mk_empty_set, c, mk_empty_set(+atom, +term, [-integer])). | |
| 86 | foreign(mk_full_set, c, mk_full_set(+atom, +term, [-integer])). | |
| 87 | foreign(mk_int_const, c, mk_int_const(+atom, +integer, [-integer])). % creates an int constant | |
| 88 | foreign(mk_real_const, c, mk_real_const(+atom, +string, [-integer])). % creates a real constant | |
| 89 | foreign(mk_bool_const, c, mk_bool_const(+string, [-integer])). % creates a bool constant | |
| 90 | foreign(mk_string_const, c, mk_string_const(+atom, +string, [-integer])). | |
| 91 | foreign(mk_set, c, mk_set(+atom, +term, [-integer])). | |
| 92 | foreign(mk_sort, c, mk_sort(+atom, +atom)). | |
| 93 | foreign(mk_sort_with_cardinality, c, mk_sort_with_cardinality(+atom, +atom, +integer, +term, [-term])). | |
| 94 | foreign(mk_record_const, c, mk_record_const(+atom, +term, +term, [-integer])). | |
| 95 | foreign(mk_record_field, c, mk_record_field(+atom, +integer, +integer, [-integer])). | |
| 96 | foreign(mk_op, c, mk_op(+atom, +string, +integer, +integer, [-integer])). | |
| 97 | foreign(mk_quantifier, c, mk_quantifier(+atom, +string, +term, +integer, [-integer])). | |
| 98 | foreign(mk_op_arglist, c, mk_op_arglist(+atom, +string, +term, [-integer])). | |
| 99 | foreign(mk_op_identity, c, mk_op_identity(+atom, +integer, +term, +term, [-integer])). | |
| 100 | foreign(mk_op_interval, c, mk_op_interval(+atom, +integer, +integer, [-integer])). | |
| 101 | foreign(mk_op_pow_subset, c, mk_op_pow_subset(+atom, +integer, +term, [-integer])). | |
| 102 | foreign(mk_op_pow1_subset, c, mk_op_pow1_subset(+atom, +integer, +term, +term, [-integer])). | |
| 103 | foreign(mk_op_composition, c, mk_op_composition(+atom, +integer, +integer, +term, +term, +term, +term, [-integer])). | |
| 104 | foreign(mk_op_direct_product, c, mk_op_direct_product(+atom, +integer, +integer, +term, +term, +term, +term, [-integer])). | |
| 105 | foreign(mk_op_parallel_product, c, mk_op_parallel_product(+atom, +integer, +integer, +term, +term, +term, +term, +term, [-integer])). | |
| 106 | foreign(mk_op_iteration, c, mk_op_iteration(+atom, +integer, +integer, +term, +term, +term, [-integer])). | |
| 107 | foreign(mk_op_closure, c, mk_op_closure(+atom, +integer, +integer, +term, +term, +term, [-integer])). | |
| 108 | foreign(mk_op_cartesian, c, mk_op_cartesian(+atom, +integer, +integer, +term, [-integer])). | |
| 109 | foreign(mk_op_dom_res, c, mk_op_dom_res(+atom, +integer, +integer, +term, [-integer])). | |
| 110 | foreign(mk_op_dom_sub, c, mk_op_dom_sub(+atom, +integer, +integer, +term, [-integer])). | |
| 111 | foreign(mk_op_ran_res, c, mk_op_ran_res(+atom, +integer, +integer, +term, [-integer])). | |
| 112 | foreign(mk_op_ran_sub, c, mk_op_ran_sub(+atom, +integer, +integer, +term, [-integer])). | |
| 113 | foreign(mk_op_reverse, c, mk_op_reverse(+atom, +integer, +term, [-integer])). | |
| 114 | foreign(mk_op_domain, c, mk_op_domain(+atom, +integer, +term, +term, +term, [-integer])). | |
| 115 | foreign(mk_op_range, c, mk_op_range(+atom, +integer, +term, +term, +term, [-integer])). | |
| 116 | foreign(mk_op_image, c, mk_op_image(+atom, +integer, +integer, +term, +term, +term, [-integer])). | |
| 117 | foreign(mk_op_general_union, c, mk_op_general_union(+atom, +integer, +term, +term, [-integer])). | |
| 118 | foreign(mk_op_general_intersection, c, mk_op_general_intersection(+atom, +atom, +integer, +term, +term, [-integer])). | |
| 119 | foreign(mk_op_lambda, c, mk_op_lambda(+atom, +integer, +integer, +integer, +term, [-integer])). | |
| 120 | foreign(mk_op_comprehension_set_singleton, c, mk_op_comprehension_set_singleton(+atom, +integer, +integer, [-integer])). | |
| 121 | foreign(mk_op_comprehension_set_multi, c, mk_op_comprehension_set_multi(+atom, +term, +term, +integer, [-integer])). | |
| 122 | foreign(mk_op_couple_prj, c, mk_op_couple_prj(+atom, +atom, +integer, +term, [-integer])). | |
| 123 | foreign(mk_op_floor, c, mk_op_floor(+atom, +integer, +atom, +integer, [-integer])). | |
| 124 | foreign(mk_op_ceiling, c, mk_op_ceiling(+atom, +integer, +atom, +integer, [-integer])). | |
| 125 | foreign(smt_solve_query, c, smt_solve_query(+term, +integer, +integer, +integer, +integer, [-term])). | |
| 126 | foreign(get_model_string, c, get_model_string(+integer, [-atom])). | |
| 127 | foreign(get_full_model_string, c, get_full_model_string([-atom])). | |
| 128 | foreign(conjoin_negated_state, c, conjoin_negated_state(+atom, +term, +integer, [-integer])). | |
| 129 | foreign(pop_frame, c, pop_frame). | |
| 130 | foreign(push_frame, c, push_frame). | |
| 131 | foreign(reset, c, reset). | |
| 132 | foreign(add_interpreter_constraint, c, add_interpreter_constraint(+integer, +atom, +integer, [-term])). | |
| 133 | foreign(mk_couple, c, mk_couple(+atom, +term, +integer, +integer, [-integer])). | |
| 134 | foreign(get_header_version, c, get_header_version([-atom])). | |
| 135 | foreign(get_full_version, c, get_full_version([-atom])). | |
| 136 | ||
| 137 | :- dynamic is_initialised/0, z3_init_exception/1. | |
| 138 | ||
| 139 | z3interface_init_error(E) :- z3_init_exception(Exc),!, Exc=E. | |
| 140 | z3interface_init_error(unknown) :- \+ is_initialised. | |
| 141 | ||
| 142 | :- use_module(probsrc(pathes_lib), [check_lib_component_available/1]). | |
| 143 | init_z3interface :- is_initialised,!. | |
| 144 | init_z3interface :- | |
| 145 | catch(load_foreign_resource(library(z3interface)),E, | |
| 146 | (format(user_error,'*** LOADING Z3 library failed~n',[]), | |
| 147 | assert(z3_init_exception(E)), % asserted and then added as error by solver_dispatcher | |
| 148 | check_lib_component_available(z3), | |
| 149 | fail) | |
| 150 | ), | |
| 151 | init, | |
| 152 | assertz(is_initialised). | |
| 153 | ||
| 154 | reset_z3interface :- is_initialised, !, | |
| 155 | reset. | |
| 156 | reset_z3interface :- init_z3interface. | |
| 157 | ||
| 158 | :- meta_predicate z3_interface_call(+). | |
| 159 | z3_interface_call(Call) :- | |
| 160 | call(z3interface:Call). |