예제 #1
0
   def convert(self, c):
       """
 Main conversion function
 Parameter:
   c (BoolExp): the boolean expression to translate
 returns a pair of:
   var_id (dict): maps all variables in c into a index into the CNF constraint
   cnf (list of list of int): the CNF constraint, where variables are encoded as positive int, and negation of a variable is encoded as -variable_id
 """
       z3_translator = gzl.toZ3Visitor()
       z3_constraint = z3_translator.visit(c)
       goal = z3.Goal()
       goal.add(z3_constraint)
       tactic = z3.Tactic('tseitin-cnf')
       z3_cnf = tactic(goal)
       self._cnf = []
       self._var_dict = {}
       self._curr_id = 1
       for z3_c in z3_cnf[0]:
           self.visit_or(z3_c)
       self._var_translation = {
           k.decl().name(): v_id
           for k, v_id in self._var_dict.items()
       }
       return self
예제 #2
0
def bitblast(e):
    ctx = e.ctx
    goal = z3.Goal(ctx=ctx)
    goal.add(z3.simplify(e))
    tactic = z3.Tactic('bit-blast', ctx=ctx)
    res = tactic.apply(goal, blast_full=True)
    assert (len(res) == 1)
    return res[0].as_expr()
예제 #3
0
def parse_with_z3(file):
    t = z3.With(z3.Tactic("horn-simplify"), "xform.inline_eager", False)
    assertions = z3.parse_smt2_file(file)
    g = z3.Goal()
    g.add(assertions)
    r = t(g)
    s = z3.Solver()
    s.add(r[0])
    print(s.sexpr())
예제 #4
0
def build_test(config, main_formula, cond_tuple, pkt_range):
    permut_conds, avoid_conds, undefined_conds = cond_tuple

    # now we actually verify that we can find an input
    s = z3.Solver()
    # bind the output constant to the output of the main program
    output_const = z3.Const("output", main_formula.sort())
    s.add(main_formula == output_const)

    undefined_matches = z3.And(*undefined_conds)
    s.add(undefined_matches)

    avoid_matches = z3.Not(z3.Or(*avoid_conds))
    s.add(avoid_matches)
    # we need this tactic to find out which values will be undefined at the end
    # or which headers we expect to be invalid
    # the tactic effectively simplifies the formula to a single expression
    # under the constraints we have defined
    t = z3.Then(z3.Tactic("propagate-values"),
                z3.Tactic("ctx-solver-simplify"), z3.Tactic("elim-and"))
    # this is the test string we assemble
    stf_str = ""
    for permut in permut_conds:
        s.push()
        s.add(permut)
        log.info("Checking for solution...")
        ret = s.check()
        if ret == z3.sat:
            log.info("Found a solution!")
            # get the model
            m = s.model()
            # this does not work well yet... desperate hack
            # FIXME: Figure out a way to solve this, might not be solvable
            g = z3.Goal()
            g.add(main_formula == output_const, avoid_matches,
                  undefined_matches, z3.And(*permut))
            log.debug(z3.tactics())
            log.info("Inferring simplified input and output")
            constrained_output = t.apply(g)
            log.info("Inferring dont-care map...")
            # FIXME: horrible
            output_var = constrained_output[0][0].children()[0]
            dont_care_map = get_dont_care_map(config, output_var, pkt_range)
            input_hdr = m[z3.Const(config["ingress_var"], output_const.sort())]
            output_hdr = m[output_const]
            log.debug("Output header: %s", output_hdr)
            log.debug("Input header: %s", input_hdr)
            flat_input = input_hdr.children()[pkt_range]
            flat_output = output_hdr.children()[pkt_range]
            stf_str += get_stf_str(flat_input, flat_output, dont_care_map)
            stf_str += "\n"
        else:
            # FIXME: This should be an error
            log.warning("No valid input could be found!")
        s.pop()
    # the final stf string lists all the interesting packets to test
    return stf_str
예제 #5
0
 def __init__(self, nbits, key):
     self.nbits = nbits
     self.slvr = z3.Goal()
     self.init = z3.BitVec('init', nbits)
     tmp = z3.BitVec('tmp', nbits)
     # make sure Goal() start with `init` (at step 2)
     for i in range(nbits):
         self.slvr.add(z3.Extract(i, i, tmp) == z3.Extract(i, i, self.init))
     self.state = self.init
     self.poly = z3.BitVecVal(key, nbits)
     self.zero = z3.BitVecVal(0, nbits)
     self.one = z3.BitVecVal(1, nbits)
예제 #6
0
 def programVisit(self, program):
     res = [retvisit(self, i) for i in self.solver.instantiate_graph_constraints]
     for i in program.ast:
         val = retvisit(self, i)
         if val:
             res.append(val)
     expr = z3.And(res)
     goal = z3.Goal()
     goal.add(expr)
     tactic = z3.Tactic("tseitin-cnf")
     prog = tactic(goal)[0]
     return self.parse_Z3_tseitin(prog)
예제 #7
0
def get_features(file_path, feature_setting, logic="", track=""):
    if file_path not in cache:
        cache[file_path] = {}
    if logic not in cache[file_path]:
        cache[file_path][logic] = {}
    if track not in cache[file_path][logic]:
        cache[file_path][logic][track] = {}
    if feature_setting == "bow":
        features = get_syntactic_count_features(file_path)
    elif feature_setting == "probes":
        g = z3.Goal()
        g.add(z3.parse_smt2_file(file_path))
        features = [z3.Probe(x)(g) for x in PROBES]
    else:
        g = z3.Goal()
        g.add(z3.parse_smt2_file(file_path))
        features = get_syntactic_count_features(file_path) + [
            z3.Probe(x)(g) for x in PROBES
        ]

    cache[file_path][logic][track] = features
    return features
예제 #8
0
    def __init__(self):
        """
        Class construction. A formula is meant to be instanciated
        via the static methods from_z3, from_smt2_file, from_dimacs_string
        and from_dimacs_file.
        """
        self.goal = z3.Goal()
        self.tactics = z3.Then('simplify', 'bit-blast', 'tseitin-cnf')
        self.subgoal = None  # keep it in case of
        # Goal is a collection of constraints we want to find a solution or show to be unsatisfiable (infeasible).
        # Goals are processed using Tactics. A Tactic transforms a goal into a set of subgoals.
        # A goal has a solution if one of its subgoals has a solution.
        # A goal is unsatisfiable if all subgoals are unsatisfiable.

        self.variables_num = None
        self.clauses_num = None
        self.clauses = []
예제 #9
0
    def test_example_negate_self(self):
        if not os.path.exists(definitions.EXAMPLE_PATH):
            print('{} does not exist! Exiting...'.format(
                definitions.EXAMPLE_PATH))
            exit(1)

        subprocess.call(
            [definitions.EXAMPLE_PATH,
             os.path.abspath(TEST1_FILE)])

        z3_fml, seen_lits = utils.dimacs2fml(TEST1_FILE)
        # print('[{}] z3 formula: {}'.format(self._testMethodName, z3_fml))
        print('[{}] #vars: {}'.format(self._testMethodName, seen_lits))
        self.assertEqual(len(seen_lits), 17)

        g = z3.Goal()
        neg_z3_fml = z3.Not(z3.And(z3_fml))
        # print('[{}] Negated formula: {}'.format(self._testMethodName, neg_z3_fml))
        g.add(neg_z3_fml)
        t = z3.Then('simplify', 'tseitin-cnf')
        neg_cnf = t(g)[0]
        #print('[{}] Negated CNF: {}'.format(self._testMethodName, neg_cnf))

        utils.translate2dimacs(neg_cnf,
                               len(seen_lits),
                               TEST1_FILE,
                               append_to_file=True)
        num_vars, num_clauses = utils.parse_dimacs_header(TEST1_FILE)

        print('[{}] Formula and not formula num_vars {}, num_clauses \
              {}'.format(self._testMethodName, num_vars, num_clauses))

        fml, seen_lits = utils.dimacs2fml(TEST1_FILE)
        s = z3.Solver()
        s.add(fml)
        sol = s.check()
        self.assertEqual(sol, z3.unsat)
예제 #10
0
파일: simplify.py 프로젝트: XujieSi/PIE
    opAssoc.LEFT,
), (
    aop1,
    2,
    opAssoc.LEFT,
), (
    aop2,
    2,
    opAssoc.LEFT,
)])

pred = Forward()
stmt = Forward()

stmt << (const | Group(expr + rop + expr) | (LPAR + stmt + RPAR))
pred << ((BOps + LPAR + Group(delimitedList(pred)) + RPAR).setParseAction(
    lambda s, l, t: [joinit(t[1], t[0])] if t[0] != '!' else [['!', t[1][0]]])
         | stmt)

if __name__ == '__main__':
    goal = z3.Goal()
    goal.add(
        z3.parse_smt2_string(
            smtlib2_string_from_file(
                'assert', sys.argv[1],
                "1" if len(sys.argv) > 2 and sys.argv[2] == "0" else "0")))
    print(
        flatString(
            pred.parseString(str(z3.simplify(goal.as_expr())),
                             parseAll=True).asList()[0]))
예제 #11
0
파일: format.py 프로젝트: jpgallagher/pecos
def parse_with_z3(file, out_dir, check_only, split_queries, simplify, skip_err,
                  datalog):
    if check_only:
        assertions = z3.parse_smt2_file(file)
        check.check_chcs(assertions.children())
        print("success")
        return
    lst = file.split('/')
    tmp = lst.pop()
    lst = tmp.split('.')
    base_name = lst[0]
    assert len(lst) > 0
    if len(lst) > 1:
        for stuff in lst[1:-1]:
            base_name = base_name + '.' + stuff

    # Check if the file is actually in datalog.
    engine = z3.Fixedpoint()
    engine.set("xform.inline_eager", simplify, "xform.inline_linear", simplify,
               "xform.slice", simplify, "xform.coi", simplify,
               "xform.compress_unbound", simplify, "xform.subsumption_checker",
               simplify, "xform.tail_simplifier_pve", simplify)
    try:
        queries = engine.parse_file(file)
    except z3.Z3Exception as e:
        raise Exc('Parse error on file {}'.format(file))

    assertions = engine.get_assertions()
    for rule in engine.get_rules():
        assertions.push(rule)
    for query in queries:
        assertions.push(z3.Implies(query, False))

    # engine.get_assertions()
    goals = z3.Goal()
    goals.add(assertions)

    #non_lin = z3.Probe('arith-max-deg')
    #if non_lin(goals) > 1:
    #    raise Skip(
    #        'found non-linear expressions'
    #    )

    # if simplify:
    tactic = z3.Tactic("horn-simplify")
    simplified = tactic(goals, "xform.inline_eager", simplify,
                        "xform.inline_linear", simplify, "xform.slice",
                        simplify, "xform.coi", simplify,
                        "xform.compress_unbound", simplify,
                        "xform.subsumption_checker", simplify,
                        "xform.tail_simplifier_pve", simplify)

    # else:
    #     simplified = [goals]
    clauses = []
    queries = []
    if len(simplified) == 0:
        #raise Skip(
        #   'empty benchmark (possibly because of pre-processing)'
        #)
        print('')

    pred_decls = set()

    for index, clause in enumerate(simplified[0]):
        try:
            clause, is_query = fix.fix_clause(clause, pred_decls)
            if is_query:
                queries.append(clause)
            else:
                clauses.append(clause)
        except Exc as e:
            raise Exc('While fixing clause {}:\n{}'.format(index, e.value))

    if len(queries) < 1:
        #    raise Skip('no query clause (possibly because of pre-processing)')
        print('')

    separated_clauses = []

    if split_queries:

        for cnt, query in enumerate(queries):
            these_clauses = []
            for clause in clauses:
                these_clauses.append(clause)
            these_clauses.append(query)

            separated_clauses.append(these_clauses)

    else:

        for query in queries:
            clauses.append(query)

        separated_clauses.append(clauses)

    cnt = 0

    for clauses in separated_clauses:

        if out_dir is not None:
            out_file = "{}/{}_{:0>3}.smt2".format(out_dir, base_name, cnt)
            cnt += 1
            print('Writing to {}'.format(out_file))
            writer = open(out_file, mode='w')
        else:
            writer = sys.stdout

        if split_queries:
            try:
                check.check_chcs(clauses)
            except Exc as e:
                exc = Exc('Result of formatting is ill-formed:\n{}'.format(
                    e.value))
                if skip_err:
                    eprint('Error on file {}'.format(file))
                    eprint(exc.value)
                    continue
                else:
                    raise exc

        if datalog:
            write_clauses_datalog(pred_decls, clauses, writer)
        else:
            write_clauses_smt2(pred_decls, clauses, writer)
예제 #12
0
def walk_block(node, prev_g=None, cond=True):
    g = z3.Goal()
    g.add(cond)
    if prev_g is not None:
        for e in prev_g:
            if isinstance(e, z3.Goal):
                g.add(e.as_expr())
            else:
                g.add(e)

    if isinstance(node, pycp.c_ast.Compound):
        if node.block_items is not None:
            for e in node.block_items:
                g_next = walk_block(e, g)
                g = g_next
    elif isinstance(node, pycp.c_ast.Decl):
        if "int" in node.type.type.names:
            vars[node.name] = z3.Int(node.name)
        if "float" in node.type.type.names:
            vars[node.name] = z3.Real(node.name)
    elif isinstance(node, pycp.c_ast.FuncCall):
        if node.name.name == "__ASSUME":
            for e_exp in node.args.exprs:
                g.add(gen_smt_expr(e_exp))
        elif node.name.name == "__ASSERT":
            assertions = z3.Goal()
            for e_exp in node.args.exprs:
                assertions.add(gen_smt_expr(e_exp))
            print("solving..")
            print("SP:", g.as_expr())
            print("assert:", assertions)

            seen = set()

            def bv_length(e):
                li = [-1]
                if e in seen:
                    return -1
                if (z3.is_bv(e) and
                        z3.is_const(e) and
                        e.decl().kind() == z3.Z3_OP_UNINTERPRETED):
                    li.append(e.size())
                seen.add(e)
                if z3.is_app(e):
                    for ch in e.children():
                        li.append(bv_length(ch))
                elif z3.is_quantifier(e):
                    for ch in e.body().children():
                        li.append(bv_length(ch))
                return max(li)

            t = z3.Tactic('nla2bv')
            s = z3.Then(t, 'default').solver()
            fml = z3.And(g.as_expr(), z3.Not(assertions.as_expr()))
            print("solving using bitvector underapproximation..")
            s.add(fml)
            status = s.check()

            if status == z3.unknown:
                print("returned 'unknown'! trying again with bigger bit length..")
                print("getting highest bit length used in formula..")
                bv_l = bv_length(t(fml).as_expr())
                print("highest bit length used:", bv_l)

                while True:
                    bv_l += 1
                    print("trying with bit length:", bv_l)
                    s = z3.Then(z3.With('nla2bv', nla2bv_bv_size=bv_l),
                                'default').solver()
                    s.add(fml)
                    status = s.check()

                    if status != z3.unknown or bv_l >= 64:
                        break

            if status == z3.sat:
                model = s.model()
                print("program is unsafe.\nlisting an unsafe assignments..")
                for e in vars:
                    print(e, ':', model[vars[e]])
            elif status == z3.unsat:
                print("program is safe.")
            elif status == z3.unknown:
                print("unknown")

            s.reset()
        else:
            print("found a func call")
    elif isinstance(node, pycp.c_ast.Assignment):
        rexp = gen_smt_expr(node.rvalue)
        if z3.is_int(vars[node.lvalue.name]):
            hand_ = z3.Int('__hand__')
        elif z3.is_real(vars[node.lvalue.name]):
            hand_ = z3.Real('__hand__')
        if node.op == "=":
            g.add(hand_ == rexp)
        elif node.op == "+=":
            g.add(hand_ == (vars[node.lvalue.name] + rexp))
        elif node.op == "-=":
            g.add(hand_ == (vars[node.lvalue.name] - rexp))
        elif node.op == "*=":
            g.add(hand_ == (vars[node.lvalue.name] * rexp))
        elif node.op == "%=":
            g.add(hand_ == (vars[node.lvalue.name] % rexp))
        g_ = z3.Goal()
        g_.add(z3.Exists(vars[node.lvalue.name], g.as_expr()))
        g_ = t_qe_(g_)
        g = z3.Goal()
        g.add(z3.substitute(g_.as_expr(), (hand_, vars[node.lvalue.name])))
        # g = g.simplify()
    elif isinstance(node, pycp.c_ast.If):
        cond_exp = gen_smt_expr(node.cond)
        if node.iftrue is not None:
            true_expr = walk_block(node.iftrue, g, cond_exp).as_expr()
        else:
            true_expr = z3.And(cond_exp, g.as_expr())
        if node.iffalse is not None:
            false_expr = walk_block(
                node.iffalse, g, z3.Not(cond_exp)).as_expr()
        else:
            false_expr = z3.And(z3.Not(cond_exp), g.as_expr())
        g = z3.Goal()
        g.add(z3.Or(true_expr, false_expr))
        g = t(g)  # g.simplify()
    else:
        return prev_g
    # print(g.as_expr(), "\n")
    return g
예제 #13
0
def luigi(ctx, priors, mpc, model_counter, verbose_approxmc, dump_circuit):
    # ctx is provided by click
    ctx.ensure_object(dict)
    mc = MODEL_COUNTERS[model_counter](verbose_approxmc)
    ctx.obj['model_counter'] = mc

    _OPERATORS = _operators(mc)

    # STEP ONE: Parse and load the arguments
    reveal, raw_mapping, priors = spdz_ingest(mpc, priors)
    if len(dump_circuit) > 0:
        dump_graphviz(dump_circuit, reveal, raw_mapping)
    # STEP TWO: Convert values to our AST
    goal = z3.Goal()
    exprs = dict()

    def get(x):
        '''
        Turn a handle from the JSON mapping into an Expression.
        If the handle is a constant, make it a constant expression.
        Otherwise, look it up in the map.
        '''
        if isinstance(x, int):
            return Expr(min=x, max=x, value=mc.const(x))
        else:
            return exprs[x]

    ctx.obj['inputs'] = []
    # Rather than recursing using the function call stack, we manually mantain a stack
    stack = [(e, 0) for e in reveal]
    while len(stack) > 0:
        name, partial = stack.pop()
        if isinstance(name, int):
            exprs[name] = get(name)
            continue
        operator, *args = raw_mapping[name]
        if operator == 'INPUT':
            # INPUTs are handled specially from other expressions.
            vmin, vmax = priors[args[0]]
            nbits = num_bits(vmin, vmax)
            var = mc.new_var(name, nbits)
            goal.add(mc.const(vmin, nbits) <= var)
            goal.add(var <= mc.const(vmax, nbits))
            ctx.obj['inputs'].append(name)
            exprs[name] = Expr(min=vmin, max=vmax, value=var)
            continue
        # Partial denotes the number of arguments that have been processed.
        while partial < len(args):
            arg = args[partial]
            # If the argument is either a constant, or has already has a
            # corresponding expression, then we can proceed to the next
            # argument.
            if isinstance(arg, int) or arg in exprs:
                partial += 1
            else:
                # Otherwise, we push ourselves back onto the stack, followed by
                # the argument that we need to evalute.
                stack.append((name, partial))
                stack.append((arg, 0))
                break
        else:
            # The loop has exitied without "break"-ing, so we know that:
            assert partial == len(args)
            # Thus, we can get() each argument to get the corresponding Expr
            operator = _OPERATORS[operator]
            args = [get(arg) for arg in args]
            the_min = operator.min(*args)
            the_max = operator.max(*args)
            args = operator.sext_mode(mc, args)
            value = operator.value(*args)
            new_expr = Expr(min=the_min, max=the_max, value=value)
            assert type(new_expr) is Expr
            exprs[name] = new_expr
    ctx.obj['goal'] = goal
    ctx.obj['exprs'] = exprs
    ctx.obj['reveal'] = reveal
예제 #14
0
def perform_blackbox_test(config):
    out_dir = config["out_dir"]
    p4_input = config["p4_input"]
    if out_dir == OUT_DIR:
        out_dir = out_dir.joinpath(p4_input.stem)
    util.check_dir(out_dir)
    util.copy_file(p4_input, out_dir)
    config["out_dir"] = out_dir
    config["p4_input"] = p4_input

    # get the semantic representation of the original program
    z3_main_prog, result = get_semantics(config)
    if result != util.EXIT_SUCCESS:
        return result
    # now we actually verify that we can find an input
    s = z3.Solver()
    # we currently ignore all other pipelines and focus on the ingress pipeline
    main_formula = z3.simplify(z3_main_prog[config["pipe_name"]])
    # this util might come in handy later.
    # z3.z3util.get_vars(main_formula)
    conditions = get_branch_conditions(main_formula)
    log.info(conditions)
    cond_tuple = dissect_conds(config, conditions)
    permut_conds, avoid_conds, undefined_conds = cond_tuple
    log.info("Computing permutations...")
    # FIXME: This does not scale well...
    # FIXME: This is a complete hack, use a more sophisticated method
    permuts = [[f(var) for var, f in zip(permut_conds, x)]
               for x in itertools.product([z3.Not, lambda x: x],
                                          repeat=len(permut_conds))]
    output_const = z3.Const("output", main_formula.sort())
    # bind the output constant to the output of the main program
    s.add(main_formula == output_const)
    # all keys must be false for now
    # FIXME: Some of them should be usable
    log.info(15 * "#")
    log.info("Undefined conditions:")
    s.add(z3.And(*undefined_conds))
    for cond in undefined_conds:
        log.info(cond)
    log.info("Conditions to avoid:")
    s.add(z3.Not(z3.Or(*avoid_conds)))
    for cond in avoid_conds:
        log.info(cond)
    log.info("Permissible permutations:")
    for cond in permuts:
        log.info(cond)
    log.info(15 * "#")
    for permut in permuts:
        s.push()
        s.add(permut)
        log.info("Checking for solution...")
        ret = s.check()
        if ret == z3.sat:
            log.info("Found a solution!")
            # get the model
            m = s.model()
            # this does not work well yet... desperate hack
            # FIXME: Figure out a way to solve this, might not be solvable
            avoid_matches = z3.Not(z3.Or(*avoid_conds))
            undefined_matches = z3.And(*undefined_conds)
            permut_match = z3.And(*permut)
            g = z3.Goal()
            g.add(main_formula == output_const, avoid_matches,
                  undefined_matches, permut_match)
            log.debug(z3.tactics())
            t = z3.Then(z3.Tactic("propagate-values"),
                        z3.Tactic("ctx-solver-simplify"),
                        z3.Tactic("elim-and"))
            log.info("Inferring simplified input and output")
            constrained_output = t.apply(g)
            log.info("Inferring dont-care map...")
            output_var = constrained_output[0][0]
            dont_care_map = get_dont_care_map(config, output_var)
            result = check_with_stf(config, m, output_const, dont_care_map)
            if result != util.EXIT_SUCCESS:
                return result
        else:
            # FIXME: This should be an error
            log.warning("No valid input could be found!")
        s.pop()
    return result
예제 #15
0
def solve(threshold):

    MAX_TURN = 42

    s = z3.Goal()  # z3.Solver()

    bb_player = [z3.BitVec(f"bb_player_{i}", 64) for i in range(MAX_TURN + 2)]
    bb_opponent = [
        z3.BitVec(f"bb_opponent_{i}", 64) for i in range(MAX_TURN + 2)
    ]
    pop_move = [z3.BitVec(f"pop_move_{i}", 64) for i in range(MAX_TURN + 2)]

    directions1 = [z3.BitVec(f"directions1_{i}", 64) for i in range(4)]
    directions2 = [z3.BitVec(f"directions2_{i}", 64) for i in range(4)]

    flip_const1 = [z3.BitVec(f"flip_const1_{i}", 64) for i in range(4)]
    flip_const2 = [z3.BitVec(f"flip_const2_{i}", 64) for i in range(4)]
    flip_const3 = [z3.BitVec(f"flip_const3_{i}", 64) for i in range(4)]

    num_zero = z3.BitVec("num_zero", 64)
    num_one = z3.BitVec("num_one", 64)

    num_threshold = z3.BitVec("num_threshold", 64)

    s.add(bb_player[0] == 0x0000001008000000,
          bb_opponent[0] == 0x0000000810000000, pop_move[0] == 0,
          directions1[0] == 1, directions1[1] == 7, directions1[2] == 8,
          directions1[3] == 9, directions2[0] == 2, directions2[1] == 14,
          directions2[2] == 16, directions2[3] == 18,
          flip_const1[0] == 0xFFFFFFFFFFFFFFFF,
          flip_const1[1] == 0x7E7E7E7E7E7E7E7E,
          flip_const1[2] == 0x7E7E7E7E7E7E7E7E,
          flip_const1[3] == 0x7E7E7E7E7E7E7E7E,
          flip_const2[0] == 0x0080808080808080,
          flip_const2[1] == 0x7F00000000000000,
          flip_const2[2] == 0x0102040810204000,
          flip_const2[3] == 0x0040201008040201,
          flip_const3[0] == 0x0101010101010100,
          flip_const3[1] == 0x00000000000000FE,
          flip_const3[2] == 0x0002040810204080,
          flip_const3[3] == 0x8040201008040200, num_zero == 0, num_one == 1,
          num_threshold == threshold)

    for turn in range(MAX_TURN + 1):
        bb_occupied = z3.BitVec(f"bb_occupied_{turn}", 64)
        bb_empty = z3.BitVec(f"bb_empty_{turn}", 64)
        masked_bb_opponent = z3.BitVec(f"masked_bb_opponent_{turn}", 64)

        movemask = [z3.BitVec(f"movemask_{turn}_{i}", 64) for i in range(4)]

        flip_l_0 = [z3.BitVec(f"flip_l_0_{turn}_{i}", 64) for i in range(4)]
        flip_r_0 = [z3.BitVec(f"flip_r_0_{turn}_{i}", 64) for i in range(4)]
        flip_l_1 = [z3.BitVec(f"flip_l_1_{turn}_{i}", 64) for i in range(4)]
        flip_r_1 = [z3.BitVec(f"flip_r_1_{turn}_{i}", 64) for i in range(4)]
        flip_l_2 = [z3.BitVec(f"flip_l_2_{turn}_{i}", 64) for i in range(4)]
        flip_r_2 = [z3.BitVec(f"flip_r_2_{turn}_{i}", 64) for i in range(4)]
        flip_l_3 = [z3.BitVec(f"flip_l_3_{turn}_{i}", 64) for i in range(4)]
        flip_r_3 = [z3.BitVec(f"flip_r_3_{turn}_{i}", 64) for i in range(4)]
        mask_l = [z3.BitVec(f"mask_l_{turn}_{i}", 64) for i in range(4)]
        mask_r = [z3.BitVec(f"mask_r_{turn}_{i}", 64) for i in range(4)]

        some_moves = [
            z3.BitVec(f"some_moves_{turn}_{i}", 64) for i in range(4)
        ]
        all_moves = z3.BitVec(f"all_moves_{turn}", 64)
        pop_now = z3.BitVec(f"pop_now_{turn}", 64)

        popcnt_move_tmp1 = z3.BitVec(f"popcnt_move_tmp1_{turn}", 64)
        popcnt_move_tmp2 = z3.BitVec(f"popcnt_move_tmp2_{turn}", 64)

        s.add(bb_occupied == bb_player[turn] | bb_opponent[turn],
              bb_empty == bb_occupied ^ 0xFFFFFFFFFFFFFFFF,
              masked_bb_opponent == bb_opponent[turn] & 0x7E7E7E7E7E7E7E7E,
              movemask[0] == masked_bb_opponent,
              movemask[1] == masked_bb_opponent,
              movemask[2] == bb_opponent[turn],
              movemask[3] == masked_bb_opponent)
        s.add([
            z3.And(flip_l_0[i] == (movemask[i]
                                   & (bb_player[turn] << directions1[i])))
            for i in range(4)
        ])
        s.add([
            z3.And(flip_r_0[i] == (movemask[i]
                                   & z3.LShR(bb_player[turn], directions1[i])))
            for i in range(4)
        ])
        s.add([
            z3.And(flip_l_1[i] == (
                flip_l_0[i] | (movemask[i] & (flip_l_0[i] << directions1[i]))))
            for i in range(4)
        ])
        s.add([
            z3.And(flip_r_1[i] == (
                flip_r_0[i]
                | (movemask[i] & z3.LShR(flip_r_0[i], directions1[i]))))
            for i in range(4)
        ])
        s.add([
            z3.And(mask_l[i] == (movemask[i]
                                 & (movemask[i] << directions1[i])))
            for i in range(4)
        ])
        s.add([
            z3.And(mask_r[i] == (movemask[i]
                                 & z3.LShR(movemask[i], directions1[i])))
            for i in range(4)
        ])
        s.add([
            z3.And(flip_l_2[i] == (
                flip_l_1[i] | (mask_l[i] & (flip_l_1[i] << directions2[i]))))
            for i in range(4)
        ])
        s.add([
            z3.And(flip_r_2[i] == (
                flip_r_1[i]
                | (mask_r[i] & z3.LShR(flip_r_1[i], directions2[i]))))
            for i in range(4)
        ])
        s.add([
            z3.And(flip_l_3[i] == (
                flip_l_2[i] | (mask_l[i] & (flip_l_2[i] << directions2[i]))))
            for i in range(4)
        ])
        s.add([
            z3.And(flip_r_3[i] == (
                flip_r_2[i]
                | (mask_r[i] & z3.LShR(flip_r_2[i], directions2[i]))))
            for i in range(4)
        ])
        s.add([
            z3.And(some_moves[i] == ((flip_l_3[i] << directions1[i])
                                     | z3.LShR(flip_r_3[i], directions1[i])))
            for i in range(4)
        ])
        s.add(
            all_moves == (some_moves[0] | some_moves[1] | some_moves[2]
                          | some_moves[3]) & bb_empty,
            popcnt_move_tmp1 == all_moves -
            (z3.LShR(all_moves, 1) & 0x7777777777777777) -
            (z3.LShR(all_moves, 2) & 0x3333333333333333) -
            (z3.LShR(all_moves, 3) & 0x1111111111111111), popcnt_move_tmp2 == (
                (popcnt_move_tmp1 + z3.LShR(popcnt_move_tmp1, 4))
                & 0x0F0F0F0F0F0F0F0F) * 0x0101010101010101, pop_now == z3.LShR(
                    popcnt_move_tmp2,
                    56), pop_move[turn + 1] == z3.If(pop_now > pop_move[turn],
                                                     pop_now, pop_move[turn]))

        move_onebit = z3.BitVec(f"move_onebit_{turn}", 64)
        move_bsf_tmp = [
            z3.BitVec(f"move_bsf_tmp_{turn}_{i}", 64) for i in range(9)
        ]
        move_pos = z3.BitVec(f"move_pos_{turn}", 64)

        s.add(
            move_onebit & (move_onebit - 1) == 0, move_onebit
            & all_moves == move_onebit, move_bsf_tmp[0] == move_onebit - 1,
            move_bsf_tmp[1] == move_bsf_tmp[0] | z3.LShR(move_bsf_tmp[0], 1),
            move_bsf_tmp[2] == move_bsf_tmp[1] | z3.LShR(move_bsf_tmp[1], 2),
            move_bsf_tmp[3] == move_bsf_tmp[2] | z3.LShR(move_bsf_tmp[2], 4),
            move_bsf_tmp[4] == move_bsf_tmp[3] | z3.LShR(move_bsf_tmp[3], 8),
            move_bsf_tmp[5] == move_bsf_tmp[4] | z3.LShR(move_bsf_tmp[4], 16),
            move_bsf_tmp[6] == move_bsf_tmp[5] | z3.LShR(move_bsf_tmp[5], 32),
            move_bsf_tmp[7] == move_bsf_tmp[6] -
            (z3.LShR(move_bsf_tmp[6], 1) & 0x7777777777777777) -
            (z3.LShR(move_bsf_tmp[6], 2) & 0x3333333333333333) -
            (z3.LShR(move_bsf_tmp[6], 3) & 0x1111111111111111),
            move_bsf_tmp[8] == ((move_bsf_tmp[7] + z3.LShR(move_bsf_tmp[7], 4))
                                & 0x0F0F0F0F0F0F0F0F) * 0x0101010101010101,
            move_pos == z3.LShR(move_bsf_tmp[8], 56))

        OM = [z3.BitVec(f"OM_{turn}_{i}", 64) for i in range(4)]
        mask1 = [z3.BitVec(f"mask1_{turn}_{i}", 64) for i in range(4)]
        upperbit_argument = [
            z3.BitVec(f"upperbit_argument_{turn}_{i}", 64) for i in range(4)
        ]
        upperbit_tmp1 = [
            z3.BitVec(f"upperbit_tmp1_{turn}_{i}", 64) for i in range(4)
        ]
        upperbit_tmp2 = [
            z3.BitVec(f"upperbit_tmp2_{turn}_{i}", 64) for i in range(4)
        ]
        upperbit_tmp3 = [
            z3.BitVec(f"upperbit_tmp3_{turn}_{i}", 64) for i in range(4)
        ]
        upperbit_tmp4 = [
            z3.BitVec(f"upperbit_tmp4_{turn}_{i}", 64) for i in range(4)
        ]
        upperbit_tmp5 = [
            z3.BitVec(f"upperbit_tmp5_{turn}_{i}", 64) for i in range(4)
        ]
        upperbit_tmp6 = [
            z3.BitVec(f"upperbit_tmp6_{turn}_{i}", 64) for i in range(4)
        ]
        upperbit_tmp7 = [
            z3.BitVec(f"upperbit_tmp7_{turn}_{i}", 64) for i in range(4)
        ]
        upperbit_tmp8 = [
            z3.BitVec(f"upperbit_tmp8_{turn}_{i}", 64) for i in range(4)
        ]
        upperbit_tmp9 = [
            z3.BitVec(f"upperbit_tmp9_{turn}_{i}", 64) for i in range(4)
        ]
        upperbit_tmp10 = [
            z3.BitVec(f"upperbit_tmp10_{turn}_{i}", 64) for i in range(4)
        ]
        upperbit_result = [
            z3.BitVec(f"upperbit_result_{turn}_{i}", 64) for i in range(4)
        ]
        outflank1 = [z3.BitVec(f"outflank1_{turn}_{i}", 64) for i in range(4)]
        flipped1 = [z3.BitVec(f"flipped1_{turn}_{i}", 64) for i in range(4)]

        mask2 = [z3.BitVec(f"mask2_{turn}_{i}", 64) for i in range(4)]
        outflank2 = [z3.BitVec(f"outflank2_{turn}_{i}", 64) for i in range(4)]
        nonzero = [z3.BitVec(f"nonzero_{turn}_{i}", 64) for i in range(4)]
        flipped2 = [z3.BitVec(f"flipped2_{turn}_{i}", 64) for i in range(4)]

        bb_flip = z3.BitVec(f"bb_flip_{turn}", 64)
        next_player_tmp = z3.BitVec(f"next_player_tmp_{turn}", 64)
        next_opponent_tmp = z3.BitVec(f"next_opponent_tmp_{turn}", 64)

        s.add([
            z3.And(OM[i] == (bb_opponent[turn] & flip_const1[i]))
            for i in range(4)
        ])
        s.add([
            z3.And(mask1[i] == z3.LShR(flip_const2[i], 63 - move_pos))
            for i in range(4)
        ])

        s.add([
            z3.And(upperbit_argument[i] == (~OM[i]) & mask1[i])
            for i in range(4)
        ])
        s.add([
            z3.And(upperbit_tmp1[i] == upperbit_argument[i]
                   | z3.LShR(upperbit_argument[i], 1)) for i in range(4)
        ])
        s.add([
            z3.And(upperbit_tmp2[i] == upperbit_tmp1[i]
                   | z3.LShR(upperbit_tmp1[i], 2)) for i in range(4)
        ])
        s.add([
            z3.And(upperbit_tmp3[i] == upperbit_tmp2[i]
                   | z3.LShR(upperbit_tmp2[i], 4)) for i in range(4)
        ])
        s.add([
            z3.And(upperbit_tmp4[i] == (~z3.LShR(upperbit_tmp3[i], 1))
                   & upperbit_tmp3[i]) for i in range(4)
        ])
        s.add([
            z3.And(upperbit_tmp5[i] == (upperbit_tmp4[i] << 32)
                   | z3.LShR(upperbit_tmp4[i], 32)) for i in range(4)
        ])
        s.add([
            z3.And(upperbit_tmp6[i] == (
                (upperbit_tmp5[i] & 0x0000FFFF0000FFFF) << 16)
                   | z3.LShR(upperbit_tmp5[i] & 0xFFFF0000FFFF0000, 16))
            for i in range(4)
        ])
        s.add([
            z3.And(upperbit_tmp7[i] == (
                (upperbit_tmp6[i] & 0x00FF00FF00FF00FF) << 8)
                   | z3.LShR(upperbit_tmp6[i] & 0xFF00FF00FF00FF00, 8))
            for i in range(4)
        ])
        s.add([
            z3.And(upperbit_tmp8[i] == upperbit_tmp7[i] & (-upperbit_tmp7[i]))
            for i in range(4)
        ])
        s.add([
            z3.And(upperbit_tmp9[i] == (upperbit_tmp8[i] << 32)
                   | z3.LShR(upperbit_tmp8[i], 32)) for i in range(4)
        ])
        s.add([
            z3.And(upperbit_tmp10[i] == (
                (upperbit_tmp9[i] & 0x0000FFFF0000FFFF) << 16)
                   | z3.LShR(upperbit_tmp9[i] & 0xFFFF0000FFFF0000, 16))
            for i in range(4)
        ])
        s.add([
            z3.And(upperbit_result[i] == (
                (upperbit_tmp10[i] & 0x00FF00FF00FF00FF) << 8)
                   | z3.LShR(upperbit_tmp10[i] & 0xFF00FF00FF00FF00, 8))
            for i in range(4)
        ])

        s.add([
            z3.And(outflank1[i] == upperbit_result[i] & bb_player[turn])
            for i in range(4)
        ])
        s.add([
            z3.And(flipped1[i] == ((-outflank1[i]) << 1) & mask1[i])
            for i in range(4)
        ])

        s.add(
            [z3.And(mask2[i] == flip_const3[i] << move_pos) for i in range(4)])
        s.add([
            z3.And(outflank2[i] == ((OM[i] | (~mask2[i])) + 1) & mask2[i]
                   & bb_player[turn]) for i in range(4)
        ])
        s.add([
            z3.And(nonzero[i] == z3.If(outflank2[i] == 0, num_zero, num_one))
            for i in range(4)
        ])
        s.add([
            z3.And(flipped2[i] == (outflank2[i] - nonzero[i]) & mask2[i])
            for i in range(4)
        ])
        s.add(
            bb_flip == flipped1[0] | flipped1[1] | flipped1[2] | flipped1[3]
            | flipped2[0] | flipped2[1] | flipped2[2] | flipped2[3],
            next_player_tmp == bb_opponent[turn] ^ bb_flip,
            next_opponent_tmp == bb_player[turn] ^ (bb_flip | move_onebit),
            bb_player[turn + 1] == z3.If(move_onebit == 0, bb_opponent[turn],
                                         next_player_tmp),
            bb_opponent[turn + 1] == z3.If(move_onebit == 0, bb_player[turn],
                                           next_opponent_tmp))

    s.add(pop_move[MAX_TURN + 1] >= num_threshold)

    t = z3.Then('simplify', 'bit-blast', 'solve-eqs', 'tseitin-cnf')
    subgoal = t(s)
    assert len(subgoal) == 1

    return subgoal[0]
예제 #16
0
  with open(kclause_file, 'r') as fp:
    # kclause, defined_vars, used_vars = pickle.load(fp)
    kclause = pickle.load(fp)

    kclause_constraints = {}
    for var in kclause.keys():
      kclause_constraints[var] = [ z3.parse_smt2_string(clause) for clause in kclause[var] ]

    constraints = []
    for var in kclause_constraints.keys():
      for z3_clause in kclause_constraints[var]:
        constraints.extend(z3_clause)

    return constraints

constraints = get_kclause_constraints(".kmax/kclause/x86_64/kclause")

solver = z3.Solver()

use_tseitin = True

if use_tseitin:
  g = z3.Goal()
  g.add(constraints)
  t = z3.Tactic('tseitin-cnf')
  solver.add(g)
else:
  solver.add(constraints)

print(solver.dimacs())
예제 #17
0
def walk_block(node, prev_g=None, cond=True):
    g = z3.Goal()
    g.add(cond)
    if prev_g is not None:
        for e in prev_g:
            if isinstance(e, z3.Goal):
                g.add(e.as_expr())
            else:
                g.add(e)

    if isinstance(node, pycp.c_ast.Compound):
        if node.block_items is not None:
            for e in node.block_items:
                g_next = walk_block(e, g)
                g = g_next
    elif isinstance(node, pycp.c_ast.Decl):
        if "int" in node.type.type.names:
            ts[node.name] = 0
            vars[node.name] = z3.BitVec("%s!!%d" % (node.name, ts[node.name]),
                                        32)
    elif isinstance(node, pycp.c_ast.FuncCall):
        if node.name.name == "__ASSUME":
            for e_exp in node.args.exprs:
                g.add(gen_smt_expr(e_exp))
        elif node.name.name == "__ASSERT":
            assertions = z3.Goal()
            for e_exp in node.args.exprs:
                assertions.add(gen_smt_expr(e_exp))
            print("solving..")
            print("SP:", g.as_expr())
            print("assert:", assertions)

            fml = z3.And(g.as_expr(), z3.Not(assertions.as_expr()))

            s = z3.SolverFor('bv')
            s.add(fml)

            under_approx_info = {}
            for e in vars:
                under_approx_info[e] = [1, z3.Bool('%s!!switch' % e)]

            while (1):
                s.push()
                switches = []
                for e in vars:
                    if under_approx_info[e][0] <= 30:
                        s.add(
                            z3.Implies(
                                under_approx_info[e][1],
                                z3.Extract(30, under_approx_info[e][0],
                                           vars[e]) == 0))
                        switches.append(under_approx_info[e][1])

                if len(switches) == 0:
                    status = s.check()
                    s.pop()
                    break

                # print(s)
                status = s.check(switches)
                s.pop()
                if status == z3.unsat:
                    u_core = s.unsat_core()
                    # print(u_core)
                    if len(u_core) == 0:
                        break
                    e_bool = random.choice(u_core)
                    var_st = str(e_bool)[:-8]
                    # print(var_st)
                    under_approx_info[var_st][0] += 1
                elif status == z3.sat:
                    break
                else:
                    break

            if status == z3.sat:
                # print(s)
                model = s.model()
                print("program is unsafe.\nlisting an unsafe assignments..")
                for e in vars:
                    print(e, ':', model[vars[e]].as_signed_long())
            elif status == z3.unsat:
                print("program is safe.")
            elif status == z3.unknown:
                print("unknown")
        else:
            print("found a func call")
    elif isinstance(node, pycp.c_ast.Assignment):
        rexp = gen_smt_expr(node.rvalue)
        ts[node.lvalue.name] += 1
        old_ = vars[node.lvalue.name]
        if z3.is_bv(vars[node.lvalue.name]):
            curr_ = z3.BitVec(
                '%s!!%d' % (node.lvalue.name, ts[node.lvalue.name]), 32)
        vars[node.lvalue.name] = curr_
        if node.op == "=":
            g.add(curr_ == rexp)
        elif node.op == "+=":
            g.add(curr_ == (old_ + rexp))
        elif node.op == "-=":
            g.add(curr_ == (old_ - rexp))
        elif node.op == "*=":
            g.add(curr_ == (old_ * rexp))
        elif node.op == "%=":
            g.add(curr_ == (old_ % rexp))
        g_ = z3.Goal()
        g_.add(z3.Exists(old_, g.as_expr()))
        g_ = t_qe(g_)
        if not z3.is_quantifier(g_.as_expr()):
            print("q eliminated: %s" % old_)
            g = g_
        # g = z3.Goal()
        # g = g.simplify()
    elif isinstance(node, pycp.c_ast.If):
        cond_exp = gen_smt_expr(node.cond)
        vars_ = {}
        for e in vars:
            vars_[e] = vars[e]
        if node.iftrue is not None:
            true_expr = walk_block(node.iftrue, g, cond_exp).as_expr()
        else:
            true_expr = z3.And(cond_exp, g.as_expr())
        vars_t = {}
        for e in vars:
            vars_t[e] = vars[e]
            vars[e] = vars_[e]
        if node.iffalse is not None:
            false_expr = walk_block(node.iffalse, g,
                                    z3.Not(cond_exp)).as_expr()
        else:
            false_expr = z3.And(z3.Not(cond_exp), g.as_expr())
        g_t = z3.Goal()
        g_f = z3.Goal()
        g_t.add(true_expr)
        g_f.add(false_expr)
        for e in vars:
            if not vars[e].eq(vars_t[e]):
                ts[e] += 1
                new_ = z3.BitVec('%s!!%s' % (e, ts[e]), 32)
                g_t.add(new_ == vars_t[e])
                g_f.add(new_ == vars[e])
                vars[e] = new_
        g = z3.Goal()
        g.add(z3.Or(g_t.as_expr(), g_f.as_expr()))
        # print(g)
        g = t(g)  # g.simplify()
    else:
        return prev_g
    # print(g.as_expr(), "\n")
    return g
예제 #18
0
def parse_with_z3(file, out_dir, check_only):
    lst = file.split('/')
    tmp = lst.pop()
    lst = tmp.split('.')
    base_name = lst[0]
    assert len(lst) > 0
    if len(lst) > 1:
        for stuff in lst[1:-1]:
            base_name = base_name + '.' + stuff

    t = z3.With(
        z3.Tactic("horn-simplify"),
        "xform.inline_eager",
        False,
        "xform.inline_linear",
        False,
        "xform.slice",
        False,
        "xform.coi",
        False,
        "xform.compress_unbound",
        False,
    )
    assertions = z3.parse_smt2_file(file)
    goals = z3.Goal()
    goals.add(assertions)

    if check_only:
        check_chcs(goals)
        print "success"
    else:
        simplified = t(goals)
        clauses = []
        queries = []
        for clause, is_query in [
                fix_clause(clause) for clause in simplified[0]
        ]:
            if is_query:
                queries.append(clause)
            else:
                clauses.append(clause)

        for cnt, query in enumerate(queries):
            these_clauses = []
            for clause in clauses:
                these_clauses.append(clause)
            these_clauses.append(query)
            goals = z3.Solver()
            goals.add(these_clauses)
            if out_dir is None:
                print('(set-logic HORN)')
                print goals.sexpr()
                print '(check-sat)'
                print '(exit)'
            else:
                out_file = "{}/{}_{:0>3}.smt2".format(out_dir, base_name, cnt)
                print 'Writing to {}'.format(out_file)
                out_file = open(out_file, mode='w')
                out_file.write('(set-logic HORN)\n\n')
                out_file.write(goals.sexpr())
                out_file.write('\n\n(check-sat)\n')
                out_file.write('(exit)\n')
            try:
                check_chcs(these_clauses)
            except Exception, blah:
                raise Exception(
                    "Result of formatting is ill-formed:\n{}".format(blah))
예제 #19
0
파일: z3_utils.py 프로젝트: jrkoenig/mypyvy
def z3_skolemize(e: z3.ExprRef) -> z3.ExprRef:
    g = z3.Goal()
    g.add(e)
    t = z3.Tactic('snf')
    res = t(g)
    return res.as_expr()
예제 #20
0
def walk_block(node, prev_g=None):
    g = z3.Goal()
    if prev_g is not None:
        for e in prev_g:
            if isinstance(e, z3.Goal):
                g.add(e.as_expr())
            else:
                g.add(e)

    if isinstance(node, pycp.c_ast.Compound):
        if node.block_items is not None:
            for e in node.block_items:
                if isinstance(e, pycp.c_ast.Decl):
                    if "int" in e.type.type.names:
                        vars[e.name] = z3.BitVec(e.name, 32)
            for e in reversed(node.block_items):
                g_next = walk_block(e, g)
                g = g_next
    elif isinstance(node, pycp.c_ast.FuncCall):
        if node.name.name == "__ASSERT":
            li = []
            for e_exp in node.args.exprs:
                li.append(gen_smt_expr(e_exp))
            g.add(z3.Not(z3.And(li)))
        elif node.name.name == "__ASSUME":
            assumptions = z3.Goal()
            for e_exp in node.args.exprs:
                assumptions.add(gen_smt_expr(e_exp))
            print("solving..")
            print("WP:", g.as_expr())
            print("assume:", assumptions)
            s.add(assumptions.as_expr())
            s.add(g.as_expr())
            status = s.check()
            print(s)

            if status == z3.sat:
                model = s.model()
                print("program is unsafe.\nlisting an unsafe assignments..")
                for e in vars:
                    print(e, ':', model[vars[e]].as_signed_long())
            elif status == z3.unsat:
                print("program is safe.")
            elif status == z3.unknown:
                print("unknown")

            s.reset()
        else:
            print("found a func call")
    elif isinstance(node, pycp.c_ast.Assignment):
        rexp = gen_smt_expr(node.rvalue)
        g_ = z3.Goal()
        if node.op == "=":
            g_.add(z3.substitute(g.as_expr(), (vars[node.lvalue.name], rexp)))
        elif node.op == "+=":
            g_.add(
                z3.substitute(
                    g.as_expr(),
                    (vars[node.lvalue.name], vars[node.lvalue.name] + rexp)))
        elif node.op == "-=":
            g_.add(
                z3.substitute(
                    g.as_expr(),
                    (vars[node.lvalue.name], vars[node.lvalue.name] - rexp)))
        elif node.op == "*=":
            g_.add(
                z3.substitute(
                    g.as_expr(),
                    (vars[node.lvalue.name], vars[node.lvalue.name] * rexp)))
        elif node.op == "%=":
            g_.add(
                z3.substitute(
                    g.as_expr(),
                    (vars[node.lvalue.name], vars[node.lvalue.name] % rexp)))
        g = t(g_)
        # g = g.simplify()
    elif isinstance(node, pycp.c_ast.If):
        cond_exp = gen_smt_expr(node.cond)
        true_expr, false_expr = None, None
        if node.iftrue is not None:
            true_ = walk_block(node.iftrue, g)
            true_expr = true_.as_expr()
        else:
            true_expr = g.as_expr()
        if node.iffalse is not None:
            false_ = walk_block(node.iffalse, g)
            false_expr = false_.as_expr()
        else:
            false_expr = g.as_expr()
        true_expr = z3.And(cond_exp, true_expr)
        false_expr = z3.And(z3.Not(cond_exp), false_expr)
        g = z3.Goal()
        g.add(z3.Or(true_expr, false_expr))
        g = t(g)  # g.simplify()
    else:
        g = prev_g
    # print(g.as_expr(), "\n")
    return g