def assert_equal_lia_and_bv(bvfml, liafml, m: int, opt, check_sub=True) -> None: import treeutil import smtutil import copy liafml_p = treeutil.process_overflow(copy.deepcopy(liafml), m, opt) liafml1 = treeutil.convert_bv2lia(bvfml, m) iff = ["and", ["=>", liafml, liafml1], ["=>", liafml1, liafml]] vs = treeutil.get_variables(iff) cs = treeutil.get_range_constraints(vs, m) with_c = ["and"] + [iff] + [cs] mo = smtutil.get_model_lia([["and", ["not", iff], cs]], statistics.Statistics()) if mo: liafml_subst = ["and"] + [["=", k, v] for k, v in mo.items()] bv_subst = ["and"] + [["=", k, ["_", f"bv{v}", m]] for k, v in mo.items()] liafml_with_c = ["and"] + [liafml] + [ treeutil.get_range_constraints(treeutil.get_variables(liafml), m) ] liafml_p_with_c = ["and"] + [liafml_p] + [ treeutil.get_range_constraints(treeutil.get_variables(liafml_p), m) ] print("----") print("[liafml]", util.debug_print_list(liafml)) print("[liafml_p]", util.debug_print_list(liafml_p)) print("[bvfml]", util.debug_print_list(bvfml)) print("[liafml2]", util.debug_print_list(liafml1)) print("got model in liaandbv", mo) print( "[res_liafml]", check_sat_lia(["and", liafml_with_c, liafml_subst], statistics.Statistics())) print( "[res_liafml_p]", check_sat_lia(["and", liafml_p_with_c, liafml_subst], statistics.Statistics())) print( "[res_bvfml]", check_sat_bv(["and", bv_subst, bvfml], m, statistics.Statistics())) print("----") if check_sub: evaluate_subformulae_lia(liafml_with_c, liafml_subst, m, opt, True) print("----") evaluate_subformulae_lia(liafml_p_with_c, liafml_subst, m, opt, False) print("----") evaluate_subformulae_bv(bvfml, bv_subst, m) assert False return
def get_interpolants_bv( bvfmls: List[Tree], m: int, opt: SMTUtilOption, stat: statistics.Statistics) -> Tuple[List[str], List[str], List[Any]]: st = time.time() liafmls = [convert_bv2lia(fml, m) for fml in bvfmls] # print("checking") # for b, l in zip(bvfmls, liafmls): # assert_equal_bv(b, m, opt) # print("checked") stat.time_to_lia += time.time() - st withconstraints = [["and", p, get_range_constraints(get_variables(p), m)] for p in liafmls] # withconstraints = liafmls # lia_interpols = get_interpolants_lia(withconstraints) while True: try: lia_interpols = get_interpolants_lia(withconstraints, opt, stat) break except UnexpectedInterpolationError: logging.warning("Failed at interpolation") if not opt.expand_floor_in_inteprolation_error: raise UnexpectedInterpolationError() modsmods = [ find_subtrees_by_tags(["mod"], liafml) for liafml in liafmls ] mods = functools.reduce(list.__add__, modsmods) if not mods: raise UnexpectedInterpolationError() def get_divisor(x): assert x[0][0] == "mod" return int(x[0][2]) maxmod, _ = util.argmax(mods, get_divisor) logging.warning( f"{debug_print_list(maxmod[0])} is being replaced.") maxmod[1][maxmod[2]] = mod_to_floor(maxmod[0]) def fv(t): return {v: (0, m - 1) for v in get_variables(t)} def ft(t): reduced_t, replacing_floor = reduce_float_from_tree( t, fv(t), m, opt, "strategy1") processed_replacing_floor = substitute_tree( reduced_t, replacing_floor) return processed_replacing_floor withconstraints = [ft(t) for t in withconstraints] print("hoge") stat.num_interp_failure += 1 st = time.time() converteds = [convert_lia2bv(fml, m, opt, stat) for fml in lia_interpols] stat.time_from_lia += time.time() - st assert_valid_interpolant_bv(bvfmls, converteds, lia_interpols, liafmls, m, opt) return converteds, lia_interpols, withconstraints
def check(x_c, b, m): print(x_c, b, m) naive = naive_lia2bv.naive_lia2bv_normalized_ineq(x_c, b, m) boxed = boxing.box_normalized_ineq(x_c, b, m) n2b = ["=>", naive, boxed] b2n = ["=>", boxed, naive] iff = ["and", n2b, b2n] vs = treeutil.get_variables(iff) cs = treeutil.get_range_constraints(vs, m) with_c = ["and"] + [iff] + [cs] # print(cs) # print(naive) # print(boxed) return smtutil.get_model_lia([["and", ["not", iff], cs]], statistics.Statistics())
def reindex_preds(self, preds: List[util.Tree]) -> List[util.Tree]: if len(preds) == 0: return [] res = [] current_indices: Dict[str, int] = {} for pred in preds: res.append( treeutil.shift_index_tree_dict_immutable( pred, current_indices)) vars = treeutil.get_variables(res[-1]) for var in vars: undec, ind = treeutil.undecorate(var) if undec.startswith("*"): current_indices[undec] = current_indices.get(undec, 0) + 1 else: current_indices[undec] = max(current_indices.get(undec, 0), ind) return res
def assert_equal_lia_and_processed_lia(liafml, m: int, opt: SMTUtilOption) -> None: if ENABLE_ASSERTION == False: return import treeutil import smtutil import copy print("hoge") liafml1 = treeutil.process_overflow(copy.deepcopy(liafml), m, opt) iff = ["and", ["=>", liafml, liafml1], ["=>", liafml1, liafml]] vs = treeutil.get_variables(iff) cs = treeutil.get_range_constraints(vs, m) with_c = ["and"] + [iff] + [cs] m = smtutil.get_model_lia([["and", ["not", iff], cs]], statistics.Statistics()) if m: print("[liafml]", util.debug_print_list(liafml)) print("[liafml1]", util.debug_print_list(liafml1)) print("got model in liaprocessing", m) assert False return
def debug_out_interpolation_problem_lia(xs): lines = [] lines.append("(set-option :produce-interpolants true)") lines.append("(set-logic QF_LIA)") vsl = [] for x in xs: vsl += get_variables(x) vs = set(vsl) for v in vs: lines.append(f"(declare-fun {v} () Int)") n = len(xs) for i, x in enumerate(xs): lines.append(f"(define-fun A{i} () Bool {debug_print_smtform(x)})") for i in range(n): lines.append(f"(assert (! A{i} :interpolation-group g{i}))") lines.append("(check-sat)") for i in range(n + 1): gs = " ".join([f"g{j}" for j in range(i)]) lines.append(f"(get-interpolant ({gs}))") with open("iproblem.smt", "w") as f: f.write("\n".join(lines))
def depict_bv(t: util.Tree, m: int) -> Tuple[str, List[str]]: vs = list(set(treeutil.get_variables(t))) vs.sort() if len(vs) == 0: res = treeutil.evaluate_bv(t, m, {}) return f"[Could not draw because of no variable: {res}]\n", vs elif len(vs) > 2: return f"[Could not draw because of too many variables: {vs}\n", vs assert len(vs) <= 2 rows = range(m) txt = "" if len(vs) == 1: vs.append("hoge") cols = [0] else: cols = range(m - 1, -1, -1) txt += f"^{vs[1]}\n" txt += (f">{vs[0]}\n") for col in cols: for row in rows: res = treeutil.evaluate_bv(t, m, {vs[0]: row, vs[1]: col}) txt += "*" if res else "." txt += "\n" return txt, vs
def fv(t): return {v: (0, m - 1) for v in get_variables(t)}
def get_interpolants_lia(fmls: List[Tree], opt: SMTUtilOption, stat: statistics.Statistics) -> List[Any]: st = time.time() cfg = make_cfg(opt) msat_set_option(cfg, "interpolation", "true") env = msat_create_env(cfg) assert (not MSAT_ERROR_ENV(env)) try: msat_destroy_config(cfg) liafmls_and_vars = [ convert_tree_to_capi_lia_formula(fml, env) for fml in fmls ] liafmls = [i[0] for i in liafmls_and_vars] vars = set() for _, i, _ in liafmls_and_vars: vars = vars.union(set(i)) int_tp = msat_get_integer_type(env) # declare variables/functions for i in vars: d = msat_declare_function(env, i, int_tp) assert (not MSAT_ERROR_DECL(d)) groups: List[Any] = [] for formula in liafmls: # now create the interpolation groups representing the two formulas A and B group = msat_create_itp_group(env) assert group != -1 assert not MSAT_ERROR_TERM(formula) # tell MathSAT that all subsequent formulas belonging to group A res = msat_set_itp_group(env, group) assert res == 0 res = msat_assert_formula(env, formula) assert res == 0 s = msat_term_repr(formula) assert s logging.info(f"Asserted formula (in group {group}: {s}") groups.append(group) if msat_solve(env) == MSAT_UNSAT: interpolants = [] for fmlid in range(len(fmls) + 1): st2 = time.time() interpolant = msat_get_interpolant(env, groups[:fmlid]) stat.time_interp_pure += time.time() - st2 stat.time_smt_pure += time.time() - st2 if MSAT_ERROR_TERM(interpolant): raise UnexpectedInterpolationError() s = msat_term_repr(interpolant) assert s logging.info(f"\nOK, the interpolant is {s}") conv = convert_capi_formula_to_tree(interpolant, env) interpolants.append(conv) # msat_destroy_env(env) res_interp = interpolants else: # msat_destroy_env(env) res_interp = [] finally: msat_destroy_env(env) # reduce floor untranslateds = res_interp translateds = [] st2 = time.time() for i, t in enumerate(res_interp): if opt.theory == "lia": translateds.append(rewrite_float_to_mod(t)) assert_no_float(translateds[-1]) elif opt.theory == "liabv": # res = rewrite_float_to_mod(t) # assert_no_float(res) # translateds.append(res) try: res = rewrite_float_to_mod(t) assert_no_float(res) translateds.append(res) except: print("Fallen to strategical") m = 2**opt.bitwidth d = {v: (0, m - 1) for v in get_variables(t)} t1, rep = reduce_float_from_tree(t, d, m, opt) t2 = substitute_tree(t1, rep) translateds.append(t2) assert_no_float(translateds[-1]) pass else: assert False print("converted") stat.time_process_lia += time.time() - st2 res_interp = translateds # calc time res_time = time.time() - st stat.time_smt += res_time stat.time_interp += res_time stat.num_smt += 1 stat.num_interp += 1 assert_valid_interpolant_lia(fmls, res_interp, untranslateds, opt) return res_interp
def refine(self, v: UNode) -> bool: # False means unsafe logging.debug("Refining") if self.config.theory == "liabv": sat_result = smtutil.check_sat_bv(v.label, 2**self.config.bitwidth, self.stat) elif self.config.theory == "lia": sat_result = smtutil.check_sat_lia(v.label, self.stat) else: assert False if v.cfg_node == self.cfg.final and sat_result: # here vars can be undecorated pi = self.get_path(v) parents = self.get_parents(v) # pi_pred = [smtutil.sexp_and(pi1.pred, pi1.src.label) for i, pi1 in enumerate(pi)] # TODO: add variable constraint here! pi_pred = [pi1.pred for i, pi1 in enumerate(pi)] pi_pred = self.reindex_preds(pi_pred) # TODO: koko ni nondetint no are wo irru pi_pred = self.replace_nondet(pi_pred) # shifted_vars: Dict[str, str] = {} # for pi_pred_i in pi_pred: # for v1 in treeutil.get_variables(pi_pred_i): # shifted_vars[v1] = self.vars_dict[treeutil.set_index(v1, 0)] if self.config.theory == "liabv": interp, interp_lia, prob_lia = smtutil.get_interpolants_bv( pi_pred, 2**self.config.bitwidth, self.config.smtutilopt, self.stat) debug_write_interpolants(interp, interp_lia, prob_lia, f"Path {[x.id for x in pi]}") for b, l in zip(interp, interp_lia): pass # smtutil.assert_lia_processing_ok(l, 2**self.config.bitwidth, self.config.smtutilopt) # smtutil.assert_equal_lia_and_processed_lia(l, 2**self.config.bitwidth, self.config.smtutilopt) # smtutil.assert_equal_lia_and_bv(b, l, 2**self.config.bitwidth, self.config.smtutilopt) elif self.config.theory == "lia": interp = smtutil.get_interpolants_lia(pi_pred, self.config.smtutilopt, self.stat) debug_write_interpolants(interp, pi_pred, [], f"Path {[x.id for x in pi]}") else: assert False self.stat.sizes_interpol.append( [util.count_terms(i) for i in interp]) # logging.debug("Raw Interpolants:" + str("\n".join(interp))) # interp = [smtutil.list2sexp(smtutil.convert_lia2_liabv(sexpdata.loads(i), 2**self.bitwidth)) for i in interp] # logging.debug("Interpolants:" + str("\n".join(interp))) logging.debug(f"Path {[x.id for x in pi]}") self.print(debug=True) pass if interp == []: # Feasible self.stat.counter_path_id = [x.cfg_edge.id for x in pi] self.stat.counter_path_pred = pi_pred if self.config.theory == "liabv": # print("original LIA interp", interp_lia) print("problem LIA interp\n", util.debug_print_preds(prob_lia)) self.stat.counter_model = smtutil.get_model_bv( pi_pred, 2**self.config.bitwidth, self.stat) # DEBUG print("model in LIA", smtutil.get_model_lia(prob_lia, self.stat)) # print("model", smtutil.get_model_bv(pi_pred, list(shifted_vars.items()), 2**self.config.bitwidth)) elif self.config.theory == "lia": self.stat.counter_model = smtutil.get_model_lia( pi_pred, self.stat) # print(util.debug_print_preds (pi_pred)) # print("model", ) else: assert False # self.stat.error_trace = pi print("Feasible!", self.stat.counter_model) return False else: for i, ahat in enumerate(interp): phi = treeutil.set_index_tree_immutable(ahat, 0) assert len(treeutil.get_variables(phi)) == 0 or any([ treeutil.undecorate(i)[1] == 0 for i in treeutil.get_variables(phi) ]) vi = parents[i] s = ["=>", vi.label, phi] vars_with_types = { var: self.vars_dict[treeutil.set_index(var, 0)] for var in treeutil.get_variables(s) } logging.debug( f"{i}th phi: {phi}, ahat: {ahat}, vilabel: {vi.label}") if self.config.theory == "liabv": validity_res = smtutil.check_valid_bv( s, 2**self.config.bitwidth, self.stat) elif self.config.theory == "lia": validity_res = smtutil.check_valid_lia(s, self.stat) else: assert False if not validity_res: self.coverings = {(x, y) for x, y in self.coverings if not (y == vi)} self._maintain_covereds() s = ["=>", phi, vi.label] if self.config.theory == "liabv": validity_res = smtutil.check_valid_bv( s, 2**self.config.bitwidth, self.stat) elif self.config.theory == "lia": validity_res = smtutil.check_valid_lia( s, self.stat) else: assert False if validity_res: vi.label = phi else: vi.label = ["and", vi.label, phi] self.strengthened.add(vi) nonsimplified = vi.label if self.config.simplification: vi.label = simplifier.simplify_tree( vi.label, 2**self.config.bitwidth, self.config.theory) # vi.label = simplifier.simplify_sexp(vi.label, 2**self.config.bitwidth, "liabv") logging.debug(f"Refined, {vi.label}") return True