1 % (c) 2019-2022 Lehrstuhl fuer Softwaretechnik und Programmiersprachen.
2 % Heinrich Heine Universitaet Duesseldorf
3 % This software is licenced under EPL 1.0 (http://www.eclipse.org/org/documents/epl-v10.html)
4
5 :- module(cdclt_pred_to_sat, [predicate_to_sat/9,
6 predicate_to_sat/6,
7 sat_to_predicate_from_solution/3,
8 get_amount_of_sat_variables/1,
9 next_sat_var_name/1,
10 reset_sat_var_id/0]).
11
12 :- use_module(library(sets), [subtract/3]).
13 :- use_module(library(avl)).
14 :- use_module(library(lists)).
15 :- use_module(wdsrc(well_def_hyps), [empty_hyps/1,push_hyps/4]).
16 :- use_module(wdsrc(well_def_analyser), [compute_wd/4]).
17 :- use_module(probsrc(debug)).
18 :- use_module(probsrc(translate), [print_bexpr/1]).
19 :- use_module(probsrc(preferences), [get_preference/2]).
20 :- use_module(probsrc(b_ast_cleanup), [clean_up_pred/3]).
21 :- use_module(probsrc(module_information), [module_info/2]).
22 :- use_module(probsrc(error_manager),[add_internal_error/2,add_error_fail/3]).
23 :- use_module(probsrc(b_interpreter_check),[norm_pred_check/2]).
24 :- use_module(probsrc(bsyntaxtree), [add_texpr_infos/3,
25 find_identifier_uses/3,
26 safe_create_texpr/4,
27 conjunct_predicates/2,
28 conjunction_to_list/2,
29 disjunct_predicates/2,
30 disjunction_to_list/2]).
31 :- use_module(cdclt_solver('cdclt_preprocessing')).
32 :- use_module(cdclt_solver('cdclt_settings')).
33 :- use_module(extension('banditfuzz/welldef'), [ensure_wd/2]).
34
35 :- module_info(group, cdclt).
36 :- module_info(description, 'This module provides the conversion from B predicates to SAT formulae and vice-versa to be used for CDCL(T).').
37
38 :- dynamic sat_var_id/1.
39
40 sat_var_id(0).
41
42 %% get_amount_of_sat_variables(-AmountOfVars).
43 get_amount_of_sat_variables(AmountOfVars) :-
44 sat_var_id(AmountOfVars).
45
46 %% reset_sat_var_id.
47 reset_sat_var_id :-
48 retractall(sat_var_id(_)),
49 asserta(sat_var_id(0)).
50
51 debug_format_pred(_, _, _) :-
52 print_logs(false),
53 !.
54 debug_format_pred(Msg, Vars, Pred) :-
55 format(Msg, Vars),
56 print_bexpr(Pred), nl, !.
57
58 %% predicate_to_sat(+Type, +Pred, -NewEnv, -WDPOs, -BoolFormula, -NVarAcc).
59 % Same as predicate_to_sat/9 but initializing an empty environment and accumulator for variables.
60 predicate_to_sat(Type, Pred, NewEnv, WDPOs, BoolFormula, VarAcc) :-
61 empty_predicate_env(Env),
62 ? predicate_to_sat(Type, [], [], Env, Pred, NewEnv, WDPOs, BoolFormula, VarAcc).
63
64 %% predicate_to_sat(+ReuseType, +WDAcc, +Type, +VarAcc, +Env, +Pred, -NewEnv, -BoolFormula, -NVarAcc).
65 % Create a boolean formula from a B predicate, e.g., return 'A=TRUE & B=TRUE' for 'x:INT & x>1'.
66 % Introduces fresh unique identifiers if ReuseType is not equal to 'only_reuse'.
67 % If ReuseType is 'only_reuse': do not introduce new SAT variables but skip parts that need a new SAT variable
68 % (some unsat core computations might deduce new constraints and we do not want to introduce new SAT variables during CDCL).
69 % Env stores pairs of B ASTs (without info field) and its assigned SAT variables.
70 % Add corresponding SAT variable names to AST's info fields (returned in NewPred).
71 % Each SAT variable contains a term smt_formula/1 in its info field providing the corresponding SMT formula.
72 % Note: SMT formula is split on the level of conjunction, disjunction, implication and equivalence.
73 predicate_to_sat(ReuseType, WDAcc, Acc, Env, Pred, NewEnv, WDPOs, BoolFormula, VarAcc) :-
74 Pred = b(Expr, Type, Info),
75 ? predicate_to_sat_e(Expr, Type, Info, ReuseType, WDAcc, Acc, Env, NewEnv, WDPOs, BoolFormula, VarAcc).
76
77 %predicate_to_sat_e(E, _, _, _, WDAcc, Acc, Env, EnvOut, NWDAcc, Falsity, VarAccOut) :- functor(E,F,N),print(F/N),nl,nl,fail.
78 predicate_to_sat_e(negation(Expr), _, _, ReuseType, WDAcc, Acc, Env, NewEnv, WDPOs, BoolFormula, VarAcc) :-
79 predicate_to_sat_neg(Expr, ReuseType, WDAcc, Acc, Env, NewEnv, WDPOs, BoolFormula, VarAcc).
80 predicate_to_sat_e(truth, pred, Info, _, WDAcc, Acc, Env, EnvOut, NWDAcc, Truth, VarAccOut) :-
81 !,
82 EnvOut = Env,
83 VarAccOut = Acc,
84 NWDAcc = WDAcc,
85 Truth = b(truth,pred,Info).
86 predicate_to_sat_e(falsity, pred, Info, _, WDAcc, Acc, Env, EnvOut, NWDAcc, Falsity, VarAccOut) :-
87 !,
88 EnvOut = Env,
89 VarAccOut = Acc,
90 NWDAcc = WDAcc,
91 Falsity = b(falsity,pred,Info).
92
93 predicate_to_sat_e(conjunct(A,B), _, _, ReuseType, WDAcc, VarAcc, Env, NewEnv, WDPOs, BoolFormula, NVarAcc) :-
94 conjunction_to_list(b(conjunct(A,B),pred,[]), PList),
95 !,
96 ? map_predicate_to_sat(ReuseType, WDAcc, VarAcc, Env, PList, NewEnv, WDPOs, SatList, NVarAcc),
97 conjunct_predicates(SatList, BoolFormula).
98 /*predicate_to_sat(_, VarAcc, Env, Pred, NewEnv, BoolFormula, NVarAcc) :-
99 Pred = b(disjunct(_,_),_,_),
100 fetch_predicate(Pred,Env,_,SatVar),
101 % equality from symmetry breaking is a disjunction
102 !,
103 NewEnv = Env,
104 safe_create_texpr(equal(SatVar,b(boolean_true,boolean,[])), pred, [], BoolFormula),
105 NVarAcc = VarAcc.*/
106 predicate_to_sat_e(disjunct(A,B), _, _, ReuseType, WDAcc, VarAcc, Env, NewEnv, WDPOs, BoolFormula, NVarAcc) :-
107 disjunction_to_list(b(disjunct(A,B),pred,[]), PList),
108 !,
109 ? map_predicate_to_sat(ReuseType, WDAcc, VarAcc, Env, PList, NewEnv, WDPOs, SatList, NVarAcc),
110 disjunct_predicates(SatList, BoolFormula).
111 /*predicate_to_sat(ReuseType, VarAcc, Env, b(negation(Pred),pred,_), NewEnv, NewPred, BoolFormula, NVarAcc) :-
112 predicate_to_sat(ReuseType, VarAcc, Env, Pred, NewEnv, TNewPred, BoolFormula, NVarAcc),
113 ( TNewPred \== b(truth,pred,_)
114 -> safe_create_texpr(negation(TNewPred),pred,[], NewPred)
115 ; safe_create_texpr(truth,pred,[], NewPred)
116 ).*/
117 predicate_to_sat_e(Expr, _, _, _, WDAcc, VarAcc, Env, NewEnv, WDPOs, BoolFormula, VarAccOut) :-
118 ( Expr == value(pred_true)
119 ; Expr == value(pred_false)
120 ),
121 !,
122 WDPOs = WDAcc,
123 VarAccOut = VarAcc,
124 safe_create_texpr(Expr, pred, [], BoolFormula),
125 NewEnv = Env.
126 predicate_to_sat_e(implication(Lhs,Rhs), pred, Info, ReuseType, WDAcc, VarAcc, Env, NewEnv, WDPOs, BoolFormula, NVarAcc) :-
127 !,
128 map_predicate_to_sat(ReuseType, WDAcc, VarAcc, Env, [Lhs,Rhs], NewEnv, WDPOs, NSatArgs, NVarAcc),
129 NSatArgs = [NSatLhs,NSatRhs],
130 safe_create_texpr(implication(NSatLhs,NSatRhs), pred, [smt_formula(b(implication(Lhs,Rhs),pred,Info))], BoolFormula).
131 predicate_to_sat_e(equivalence(Lhs,Rhs), pred, Info, ReuseType, WDAcc, VarAcc, Env, NewEnv, WDPOs, BoolFormula, NVarAcc) :-
132 !,
133 map_predicate_to_sat(ReuseType, WDAcc, VarAcc, Env, [Lhs,Rhs], NewEnv, WDPOs, NSatArgs, NVarAcc),
134 NSatArgs = [NSatLhs,NSatRhs],
135 safe_create_texpr(equivalence(NSatLhs,NSatRhs), pred, [smt_formula(b(equivalence(Lhs,Rhs),pred,Info))], BoolFormula).
136 predicate_to_sat_e(Expr, Type, Info, ReuseType, WDAcc, VarAcc, Env, NewEnv, WDPOs, BoolFormula, NVarAcc) :-
137 functor(Expr, _, Arity),
138 ( Arity == 2
139 ; Arity == 3
140 ),
141 !,
142 ? reuse_or_introduce_bool_var(ReuseType, WDAcc, VarAcc, Env, b(Expr,Type,Info), boolean_true, NewEnv, WDPOs, BoolFormula, NVarAcc).
143 predicate_to_sat_e(Expr, Type, Info, ReuseType, WDAcc, VarAcc, Env, NewEnv, WDPOs, BoolFormula, NVarAcc) :-
144 % formula is a singleton pred which is not splitted such as a subset
145 reuse_or_introduce_bool_var(ReuseType, WDAcc, VarAcc, Env, b(Expr,Type,Info), boolean_true, NewEnv, WDPOs, BoolFormula, NVarAcc).
146 % TO DO: if going into quantifications, we have to watch out for local identifier scopes
147 % (i.e., x<7 might not be the same x<7 within a quantification if x is a local id)
148 % Note that we currently do not go into quantifications so this is not an issue.
149
150 predicate_to_sat_neg(Ast, ReuseType, WDAcc, Acc, Env, EnvOut, NWDAcc, NAst, VarAccOut) :-
151 Ast = b(Expr,Type,Info),
152 predicate_to_sat_neg_e(Expr, Type, Info, ReuseType, WDAcc, Acc, Env, EnvOut, NWDAcc, NAst, VarAccOut).
153
154 predicate_to_sat_neg_e(truth, pred, Info, _, WDAcc, Acc, Env, EnvOut, NWDAcc, Falsity, VarAccOut) :-
155 !,
156 EnvOut = Env, VarAccOut = Acc,
157 NWDAcc = WDAcc,
158 Falsity = b(falsity,pred,Info).
159 predicate_to_sat_neg_e(falsity, pred, Info, _, WDAcc, Acc, Env, EnvOut, NWDAcc, Truth, VarAccOut) :-
160 !,
161 EnvOut = Env, VarAccOut = Acc,
162 NWDAcc = WDAcc,
163 Truth = b(truth,pred,Info).
164 predicate_to_sat_neg_e(negation(Pred), pred, _, ReuseType, WDAcc, VarAcc, Env, NewEnv, WDPOs, BoolFormula, NVarAcc) :-
165 !,
166 predicate_to_sat(ReuseType, WDAcc, VarAcc, Env, Pred, NewEnv, WDPOs, BoolFormula, NVarAcc).
167 predicate_to_sat_neg_e(Expr, Type, Info, ReuseType, WDAcc, VarAcc, Env, NewEnv, WDPOs, BoolFormula, NVarAcc) :-
168 ? reuse_or_introduce_bool_var(ReuseType, WDAcc, VarAcc, Env, b(Expr,Type,Info), boolean_false, TNewEnv, TWDPOs, TBoolFormula, TNVarAcc),
169 !,
170 NewEnv = TNewEnv,
171 WDPOs = TWDPOs,
172 BoolFormula = TBoolFormula,
173 NVarAcc = TNVarAcc.
174 predicate_to_sat_neg_e(disjunct(A,B), pred, _, ReuseType, WDAcc, VarAcc, Env, NewEnv, WDPOs, BoolFormula, NVarAcc) :-
175 !,
176 predicate_to_sat(ReuseType, WDAcc, VarAcc, Env, b(negation(A),pred,[]), NewEnv1, WDAcc1, ABoolFormula, NVarAcc1),
177 predicate_to_sat(ReuseType, WDAcc1, NVarAcc1, NewEnv1, b(negation(B),pred,[]), NewEnv, WDPOs, BBoolFormula, NVarAcc),
178 % conjunct_predicate/ ensures that truth and falsity are simplified (1)
179 conjunct_predicates([ABoolFormula,BBoolFormula], BoolFormula).
180 predicate_to_sat_neg_e(conjunct(A,B), pred, _, ReuseType, WDAcc, VarAcc, Env, NewEnv, WDPOs, BoolFormula, NVarAcc) :-
181 !,
182 predicate_to_sat(ReuseType, WDAcc, VarAcc, Env, b(negation(A),pred,[]), NewEnv1, WDAcc1, ABoolFormula, NVarAcc1),
183 predicate_to_sat(ReuseType, WDAcc1, NVarAcc1, NewEnv1, b(negation(B),pred,[]), NewEnv, WDPOs, BBoolFormula, NVarAcc),
184 % see above comment (1) for conjunct_predicates/2
185 disjunct_predicates([ABoolFormula,BBoolFormula], BoolFormula).
186 predicate_to_sat_neg_e(implication(A,B), pred, _, ReuseType, WDAcc, VarAcc, Env, NewEnv, WDPOs, BoolFormula, NVarAcc) :-
187 !,
188 predicate_to_sat(ReuseType, WDAcc, VarAcc, Env, A, NewEnv1, WDAcc1, ABoolFormula, NVarAcc1),
189 predicate_to_sat(ReuseType, WDAcc1, NVarAcc1, NewEnv1, b(negation(B),pred,[]), NewEnv, WDPOs, BBoolFormula, NVarAcc),
190 % see (1)
191 conjunct_predicates([ABoolFormula,BBoolFormula], BoolFormula).
192 predicate_to_sat_neg_e(equivalence(A,B), pred, _, ReuseType, WDAcc, VarAcc, Env, NewEnv, WDPOs, BoolFormula, NVarAcc) :-
193 !,
194 predicate_to_sat(ReuseType, WDAcc, VarAcc, Env, b(negation(b(implication(A,B),pred,[])),pred,[]), NewEnv1, WDAcc1, ABoolFormula, NVarAcc1),
195 predicate_to_sat(ReuseType, WDAcc1, NVarAcc1, NewEnv1, b(negation(b(implication(B,A),pred,[])),pred,[]), NewEnv, WDPOs, BBoolFormula, NVarAcc),
196 % see (1)
197 disjunct_predicates([ABoolFormula,BBoolFormula], BoolFormula).
198
199 map_predicate_to_sat(_, WDAcc, VarAcc, Env, [], Env, WDAcc, BoolFormulas, VarAcc) :- !, BoolFormulas=[].
200 map_predicate_to_sat(ReuseType, WDAcc, VarAcc, Env, [Pred|T], NewEnv, WDPOs, [BoolFormula|NT], NVarAcc) :-
201 ? predicate_to_sat(ReuseType, WDAcc, VarAcc, Env, Pred, TempEnv, TWDAcc, BoolFormula, TVarAcc),
202 ? map_predicate_to_sat(ReuseType, TWDAcc, TVarAcc, TempEnv, T, NewEnv, WDPOs, NT, NVarAcc).
203
204 negate_pred(greater_equal(A,B), less(A,B)).
205 negate_pred(greater(A,B), less_equal(A,B)).
206 negate_pred(less_equal(A,B), less(B,A)).
207 negate_pred(less(A,B), less_equal(B,A)).
208
209 negate_bool_atom(boolean_true, boolean_false).
210 negate_bool_atom(boolean_false, boolean_true).
211
212 % Note: BoolFormula is 'a = TRUE' or 'a = FALSE' for (negated) literal a.
213 /*reuse_or_introduce_bool_var(_, VarAcc, Env, Pred, boolean_true, NewEnv, BoolFormula, NVarAcc) :-
214 % ensure that the same SAT variable is used for boolean equalities such as x=TRUE & x=FALSE
215 % we would usually introduce two different SAT variables for both equalities but don't want to do so for
216 % boolean equalities
217 Pred = b(equal(Bool,BoolId),pred,_),
218 BoolId = b(identifier(BoolIdName),boolean,_),
219 (Bool = b(boolean_true,boolean,[]); Bool = b(boolean_false,boolean,[])),
220 fetch_predicate(b(equal(BoolPred,b(identifier(BoolIdName),boolean,[])),pred,[]),Env,_,SatVar),
221 ( (Bool = b(boolean_true,boolean,_), BoolPred = b(boolean_true,boolean,_))
222 -> BoolAtom = boolean_true
223 ; (Bool = b(boolean_true,boolean,_), BoolPred = b(boolean_false,boolean,_))
224 -> BoolAtom = boolean_false
225 ; (Bool = b(boolean_false,boolean,_), BoolPred = b(boolean_false,boolean,_))
226 -> BoolAtom = boolean_true
227 ; BoolAtom = boolean_false
228 ),
229 !,
230 safe_create_texpr(equal(SatVar,b(BoolAtom,boolean,[])), pred, [], BoolFormula),
231 NewEnv = Env,
232 NVarAcc = VarAcc.*/
233 reuse_or_introduce_bool_var(_, WDAcc, VarAcc, Env, Pred, BoolAtom, NewEnv, NWDAcc, BoolFormula, NVarAcc) :-
234 fetch_predicate(Pred, Env, _, SatVar),
235 !,
236 safe_create_texpr(equal(SatVar,b(BoolAtom,boolean,[])), pred, [], BoolFormula),
237 NewEnv = Env,
238 NWDAcc = WDAcc,
239 NVarAcc = VarAcc.
240 reuse_or_introduce_bool_var(_, WDAcc, VarAcc, Env, Pred, BoolAtom, NewEnv, NWDAcc, BoolFormula, NVarAcc) :-
241 Pred = b(Expr,Type,Info),
242 negate_pred(Expr, NExpr),
243 fetch_predicate(b(NExpr,Type,Info), Env, _, SatVar),
244 !,
245 negate_bool_atom(BoolAtom, NBoolAtom),
246 safe_create_texpr(equal(SatVar,b(NBoolAtom,boolean,[])), pred, [], BoolFormula),
247 NewEnv = Env,
248 NWDAcc = WDAcc,
249 NVarAcc = VarAcc.
250 reuse_or_introduce_bool_var(Type, WDAcc, VarAcc, Env, Pred, BoolAtom, NewEnv, NWDAcc, BoolFormula, NVarAcc) :-
251 Type == normal,
252 !,
253 next_sat_var_name(SatVarName),
254 debug_format_pred("Introduce sat var ~w for pred~n", [SatVarName], Pred),
255 safe_create_texpr(identifier(SatVarName), boolean, [], TUniqueId),
256 add_texpr_infos(TUniqueId, [smt_formula(Pred)], UniqueId),
257 register_predicate(Pred,Pred,Env,UniqueId,NewEnv),
258 safe_create_texpr(equal(UniqueId,b(BoolAtom,boolean,[])), pred, [], BoolFormula),
259 NWDAcc = WDAcc,
260 NVarAcc = [UniqueId|VarAcc].
261 reuse_or_introduce_bool_var(Type, WDAcc, VarAcc, Env, Pred, BoolAtom, NewEnv, NWDAcc, BoolFormula, NVarAcc) :-
262 Type == normal_make_wd,
263 !,
264 next_sat_var_name(SatVarName),
265 ensure_wd(Pred, WDPred),
266 ? collect_toplevel_wd_preds(WDPred, TopLevelWdPred, WDAcc, NWDAcc),
267 debug_format_pred("Introduce sat var ~w for pred~n", [SatVarName], WDPred),
268 safe_create_texpr(identifier(SatVarName), boolean, [], TUniqueId),
269 %find_identifier_uses(Pred, [], UsedIds),
270 ( TopLevelWdPred \= b(truth,_,_)
271 -> add_texpr_infos(TUniqueId, [smt_formula(WDPred),contains_top_level_wd_condition(TopLevelWdPred,Pred)], UniqueId)
272 ; add_texpr_infos(TUniqueId, [smt_formula(WDPred)], UniqueId)
273 ),
274 register_predicate(Pred,WDPred,Env,UniqueId,NewEnv),
275 safe_create_texpr(equal(UniqueId,b(BoolAtom,boolean,[])), pred, [], BoolFormula),
276 NVarAcc = [UniqueId|VarAcc].
277 reuse_or_introduce_bool_var(Type, _, _, _, Pred, _, _, _, _, _) :-
278 Type == only_reuse,
279 add_error_fail(reuse_or_introduce_bool_var, 'Missing SAT variable for SMT constraint. b_interpreter_check:norm_pred_check/2 might be inconsistent.', [Pred]).
280
281 collect_toplevel_wd_preds(b(Node,Type,Info), TopLevelWdPred, WDAcc, NWDAcc) :-
282 ? collect_toplevel_wd_preds_e(Node, Type, Info, TopLevelWdPred, WDAcc, NWDAcc).
283
284 collect_toplevel_wd_preds_e(conjunct(A,B), _, Info, A, WDAcc, NWDAcc) :-
285 member(fuzzed_with_wd_po_included, Info),
286 conjunction_to_list(A, WDPOs),
287 create_wd_impls(WDPOs, B, [], WDImpls),
288 add_wd_impls_to_acc(WDImpls, WDAcc, NWDAcc).
289 collect_toplevel_wd_preds_e(Node, _, _, TopLevelWdPred, WDAcc, NWDAcc) :-
290 Node =.. [_,A,B],
291 collect_toplevel_wd_preds(A, TopLevelWdPred1, WDAcc, NWDAcc1),
292 ? collect_toplevel_wd_preds(B, TopLevelWdPred2, NWDAcc1, NWDAcc),
293 safe_create_texpr(conjunct(TopLevelWdPred1,TopLevelWdPred2), pred, [], TopLevelWdPred).
294 collect_toplevel_wd_preds_e(_, _, _, b(truth,pred,[]), WDAcc, WDAcc).
295
296 next_sat_var_name(SatVarName) :-
297 retract(sat_var_id(Old)),
298 New is Old + 1,
299 asserta(sat_var_id(New)),
300 number_codes(New, NC),
301 atom_codes(Index, NC),
302 atom_concat('sat', Index, SatVarName).
303
304 % Let A be a predicate with a set of WD conditions C. We create an implication A => c & not(c) => not(A) for each c in C.
305 % We don't use a single implication A => (c1 & c2 & .. & cn) since we have to create a CNF anyway.
306 create_wd_impls([], _, Acc, Acc).
307 create_wd_impls([WDPo|T], Pred, Acc, WDImpls) :-
308 % don't use added info is_wd_po_for_cdclt here
309 NegP = b(negation(Pred),pred,[]),
310 safe_create_texpr(disjunct(NegP,WDPo), pred, [], WDImpl1),
311 safe_create_texpr(disjunct(WDPo,NegP), pred, [], WDImpl2),
312 create_wd_impls(T, Pred, [WDImpl1,WDImpl2|Acc], WDImpls).
313
314 add_wd_impls_to_acc([], WDAcc, WDAcc).
315 add_wd_impls_to_acc([WDImpl|T], WDAcc, NWDAcc) :-
316 member(WDImpl, WDAcc),
317 !,
318 add_wd_impls_to_acc(T, WDAcc, NWDAcc).
319 add_wd_impls_to_acc([WDImpl|T], WDAcc, NWDAcc) :-
320 add_wd_impls_to_acc(T, [WDImpl|WDAcc], NWDAcc).
321
322 % managing link from predicates to SAT variables
323
324 empty_predicate_env(E) :- empty_avl(E).
325
326 % TO DO: maybe we should also store SatVarName?
327 register_predicate(Pred,WDPred,Env,UniqueId,NewEnv) :-
328 ( var(Env)
329 ; \+ is_avl(Env)
330 ),
331 !,
332 add_internal_error('Illegal env:', register_predicate(Pred,WDPred,Env,UniqueId,NewEnv)),
333 NewEnv = Env.
334 register_predicate(Pred,WDPred,Env,UniqueId,NewEnv) :- %print('storing: '), writeq(WDPred),nl,
335 norm_pred_check(Pred, NPred),
336 avl_store(NPred,Env,pred2satvar(WDPred,UniqueId),NewEnv).
337
338 fetch_predicate(Pred,Env,StoredPred,SatVar) :- (var(Env) ; \+ is_avl(Env)),!,
339 add_internal_error('Illegal env:',fetch_predicate(Pred,Env,StoredPred,SatVar)), fail.
340 fetch_predicate(Pred,Env,StoredPred,SatVar) :-
341 norm_pred_check(Pred, NPred),
342 avl_fetch(NPred,Env,pred2satvar(StoredPred,SatVar)), !.
343 %fetch_predicate(Pred,_,_,_SatVar) :- print('not found: '), print_bexpr(Pred),nl,fail.
344
345 % ---------------
346
347
348 %% sat_to_predicate_from_solution(+SatBindings, +SatVars, -Conjunction).
349 % Create conjunction of SAT bindings using their corresponding SMT formulae
350 % which are stored in the bool variables' information fields.
351 sat_to_predicate_from_solution([], _, b(truth,pred,[])).
352 sat_to_predicate_from_solution([Binding|T], SatVars, Conjunction) :-
353 get_smt_formula_from_binding(Binding, SatVars, SMT, RestSatVars),
354 !,
355 sat_to_predicate_from_solution(T, SMT, RestSatVars, Conjunction).
356 sat_to_predicate_from_solution([_|T], SatVars, Conjunction) :-
357 % skip: binding might be a variable if instantiation is not required
358 sat_to_predicate_from_solution(T, SatVars, Conjunction).
359
360 sat_to_predicate_from_solution([], SmtAcc, _, SmtAcc).
361 sat_to_predicate_from_solution([Binding|T], SmtAcc, SatVars, Conjunction) :-
362 get_smt_formula_from_binding(Binding, SatVars, SMT, RestSatVars),
363 !,
364 safe_create_texpr(conjunct(SMT,SmtAcc), pred, [], NewSmtAcc),
365 sat_to_predicate_from_solution(T, NewSmtAcc, RestSatVars, Conjunction).
366 sat_to_predicate_from_solution([_|T], SmtAcc, SatVars, Conjunction) :-
367 sat_to_predicate_from_solution(T, SmtAcc, SatVars, Conjunction).
368
369 get_var_and_value_from_binding(bind(SatVarName,Value), SatVarName, Value).
370 get_var_and_value_from_binding(binding(SatVarName,Value,_), SatVarName, Value).
371
372 get_smt_formula_from_binding(Binding, SatVars, SMT, RestSatVars) :-
373 ground(Binding),
374 get_var_and_value_from_binding(Binding, SatVarName, Value),
375 !,
376 ? select(b(identifier(SatVarName),_,Info), SatVars, RestSatVars),
377 ? member(smt_formula(TSMT), Info),!,
378 ( Value == pred_true
379 -> SMT = TSMT
380 ; Value == pred_false,
381 TSMT = b(_,_,TSMTInfo),
382 safe_create_texpr(negation(TSMT), pred, TSMTInfo, SMT)
383 ).
384 /*get_smt_formula_from_binding(Binding, _, _, _) :-
385 add_error(get_smt_formula_from_binding, 'SAT binding not ground:', [Binding]),
386 fail.*/