示例#1
0
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
示例#2
0
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())
示例#4
0
 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
示例#5
0
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
示例#6
0
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))
示例#7
0
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
示例#8
0
 def fv(t):
     return {v: (0, m - 1) for v in get_variables(t)}
示例#9
0
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
示例#10
0
    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