Beispiel #1
0
def convert_to_dimacs(goal, project_onto):
    '''
    Convert a Z3 goal into DIMACS so that ApproxMC can understand it.
    '''
    # Based on https://stackoverflow.com/a/33860849
    bits = set()
    for var in project_onto:
        nbits = var.sort().size()
        # Give a name to each bit of each bitvector
        for bit_index in range(nbits):
            name = '%s_%d' % (var, bit_index)
            bits.add(name)
            bit = z3.Bool(name)
            mask = z3.BitVecVal(1 << bit_index, nbits)
            goal.add(bit == ((var & mask) == mask))
    # z3.With(..., args) provides arguments to the "..." tactic.
    tactic = z3.Then(
        'simplify',
        z3.With(
            z3.Tactic('bit-blast'),
            blast_full=True,
            blast_quant=True,
        ),
        'blast-term-ite',
        z3.With(
            z3.Tactic('propagate-values'),
            blast_eq_value=True,
            blast_distinct=True,
        ),
        z3.With(
            z3.Tactic('simplify'),
            blast_eq_value=True,
        ),
        'blast-term-ite',
        'tseitin-cnf',
        'blast-term-ite',
    )
    expr = tactic(goal)
    assert len(expr) == 1
    expr = expr[0]
    dimacs = expr.dimacs()
    # ind is the Independent Set
    ind = set()
    # Parse the dimacs to determine how Z3 maps the boolean variables to the
    # dimacs variable number
    lines = dimacs.split('\n')
    for line in lines:
        if not line.startswith('c '):
            # It's not a comment.
            continue
        # Otherwise assume that this line maps variables to names
        parts = line.split()
        _, number, var = parts
        if var in bits:
            bits.remove(var)
            ind.add(number)
    # TODO: will this always be true?
    assert len(bits) == 0, repr(bits)
    return 'c ind %s 0\n%s\n' % (' '.join(ind), dimacs)
Beispiel #2
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())
Beispiel #3
0
def count(smt_file):
    formula = z3.parse_smt2_file(smt_file)
    tactic_simp = z3.With(z3.Tactic('simplify'), 'elim_and', True)
    tactic_total = z3.Then(tactic_simp, z3.Tactic('elim-term-ite'))
    tactic_total = z3.Then(tactic_total, z3.Tactic('tseitin-cnf'))
    goals = tactic_total(formula)
    if len(goals) == 1:
        goal = goals[0]
        return len(goal)
    else:
        return -1
Beispiel #4
0
def calculate(input_smt):
    formula = z3.parse_smt2_file(input_smt)
    tactic_simp = z3.With(z3.Tactic('simplify'), 'elim_and', True)
    tactic_total = z3.Then(tactic_simp, z3.Tactic('elim-term-ite'))
    tactic_total = z3.Then(tactic_total, z3.Tactic('tseitin-cnf'))
    goals = tactic_total.apply(formula)
    if len(goals) == 1:
        goal = goals[0]
        # the goal is the list of constraints, and conjunction of which is equivalent to the original problem
        manager = compute(goal)
        # compute sparseness
        num_visible = manager.get_visible_size()
        num_var = manager.get_var_size()
        num_total = manager.get_total_size()
        num_min = manager.get_maximum_clause_size()
        sparse = (num_visible - num_min) / (num_total - num_min)
        factor_min = math.ceil((1 + math.sqrt(1 + 8 * num_visible)) / 2)
        factor_max = 2 * num_total
        factor = (num_var - factor_min) / (factor_max - factor_min)
        return sparse, factor
    else:
        return '*', '*'
Beispiel #5
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
Beispiel #6
0
    def __init__(self, s, params):
        assert isinstance(s, str)

        self.s = s
        self.params = params
        self.tactic = z3.With(s, **params)
Beispiel #7
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))