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
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()
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())
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
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)
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)
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
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 = []
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)
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]))
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)
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
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
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
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]
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())
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
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))
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()
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