def GenerateConstraintForExample(spec, specConn, circuits, psiConn, newExample, iteration): substList = [] for circuit in circuits: substList.append((circuit.outputPort.var, circuit.outputPort.GenVarCopyForIteration(iteration))) substList.extend([(circuitInputPort.var, circuitInputPort.GenVarCopyForIteration(iteration)) for circuitInputPort in circuit.inputPorts]) for comp in circuit.components: substList.append((comp.outputPort.var, comp.outputPort.GenVarCopyForIteration(iteration))) substList.extend([(inputPort.var, inputPort.GenVarCopyForIteration(iteration)) for inputPort in comp.inputPorts]) substList.extend((port.var, val) for (port, val) in newExample.iteritems()) constraints = [Bool(True)] constraints.append(substitute(psiConn, substList)) constraints.append(substitute(specConn, substList)) constraints.append(substitute(spec, substList)) return And(constraints)
def subst(self,tab,subst): subs = [(term_to_z3(Constant(x)),term_to_z3(y)) for x,y in subst.iteritems()] # print subs # print all([isinstance(p, tuple) and z3.is_expr(p[0]) and z3.is_expr(p[1]) and p[0].sort().eq(p[1].sort()) for p in subs]) res = [z3.substitute(x,*subs) for x in tab] # print "subst: %s -> %s" % (tab,res) return res
def substitute (t, *m): """ Re-implementation of z3.substitute """ #return z3.substitute (t, *m) r = Substitute (*m) res = r.apply (t) # sanity check assert res.eq (z3.substitute (t, *m)) return res
def GenerateVerificationConstraint(spec, specConn, circuits, psiConn, circuitModel): constraints = [Bool(True)] substList = [] for circuit in circuits: substList.extend([(Int(labelName), circuitModel.eval(Int(labelName), True)) for (_, labelName) in circuit.labels.iteritems()]) constraints.append(substitute(psiConn, substList)) constraints.append(specConn) constraints.append(Not(spec)) return And(constraints)
def fp_add_cover (fp, pred, lemma, level=-1): # no trivial lemmas if z3.is_true (lemma): return assert (z3.is_app (pred)) sub = [] for i in range (0, pred.num_args ()): arg = pred.arg (i) sub.append ((arg, z3.Var (i, arg.decl ().range ()))) tlemma = z3.substitute (lemma, sub) if verbose: print "Lemma for ", pred.decl (), ": ", tlemma fp.add_cover (level, pred.decl (), tlemma)
def to_origin(self, formula) : """Convert all primed state variables into original state variables.""" return z3.substitute(formula, self.boolp_pairs)
def select(self, idx): expr = z3.Select(self._mem, idx) if self._idx is not None: expr = z3.substitute(expr, (self._idx, idx)) return expr
# just used as "true" s.add(get_lit('-1')) # add property to initial states # IC3ref omits this for some reason init = And(init, prop) print("init -> inv...", end='') query = And(init, Not(inv)) s.push() s.add(query) print('OK' if s.check() == unsat else 'FAIL') s.pop() s.push() print('inv /\ T |= inv...', end='') s.add(And(inv, trans, Not(substitute(inv, prime_mapping)))) print('OK' if s.check() == unsat else 'FAIL') s.pop() s.push() print('inv -> prop...', end='') s.add(Not(Implies(inv, prop))) print('OK' if s.check() == unsat else 'FAIL') s.pop() free_vars = get_free_vars(inv) prime_mapping_ids = set(v0.get_id() for v0, v1 in prime_mapping) assert all(fv.get_id() in prime_mapping_ids for fv in free_vars), "expecting all current state variables"
def wp(self, Q): return z3.simplify(z3.substitute(Q, (self.lhs, self.rhs)))
def relationalInduction(): M = TransitionSystem() Msc = SelfComposedTransitionSystem(M) xs = Msc.variables xsp = Msc.addSuffix('prime') # print(xs) # print(xsp) bad = z3.simplify(z3.And(Msc.bad)) init = z3.simplify(z3.And(Msc.init)) check = z3.simplify(z3.And(init, bad)) S = z3.Solver() S.push() S.add(check) rInit = (S.check()) S.pop() assert (rInit == z3.unsat) S.push() bad_assume = bad #Shouldn't bad be a function defined over xs? bad_proofob = z3.simplify(z3.And(Msc.bad_sc(xsp))) trx = z3.simplify(z3.And([xsp[i]==Msc.tr[i] for i in range(len(xs))])) S.add(bad_assume) # print(bad_assume) # print(bad_proofob) S.add(bad_proofob) S.add(trx) n = len(xsp) // 2 while S.check() == z3.sat: #print "Msc CounterExample Found" m = S.model() xm1 = [m.eval(xsi) for xsi in xs[:n]] xm2 = [m.eval(xsi) for xsi in xs[n:]] bad1 = lambda xs: [z3.And(*[xi == xmi for (xi, xmi) in itertools.izip(xm1, xs)])] bad2 = lambda xs: [z3.And(*[xi == xmi for (xi, xmi) in itertools.izip(xm2, xs)])] #r1, count1 = getLength(M, bad1) #no1 = bad1(M.variables) r1, arg1, expr1 = getLength1(M, bad1) print "ARG1: ", arg1 print "xs[:n]: ", xs[:n] if r1 == z3.unsat: #sub1 = zip(M.variables, xs[:n]) #sub2 = zip(M.variables, xs[n:]) sub1 = zip(arg1, xs[:n]) sub2 = zip(arg1, xs[n:]) #p1 = z3.substitute(*(no1 + sub1)) #p2 = z3.substitute(*(no1 + sub2)) p1 = z3.substitute(expr1, *sub1) p2 = z3.substitute(expr1, *sub2) #S.add(z3.Not(p1)) #S.add(z3.Not(p2)) S.add(p1) S.add(p2) continue #r2, count2 = checkLength(M, bad2, arg1) # arg1 stores the value of length when r1 is sat no2 = bad2(M.variables) #r2, arg2, expr2 = checkLength1(M, bad2, arg1) r2, arg2, expr2 = checkLengthBMC(M, bad2, arg1) if r2 == z3.unsat: #sub1 = zip(M.variables, xs[:n]) #sub2 = zip(M.variables, xs[n:]) sub1 = zip(arg2[:n], xs[:n]) sub2 = zip(arg2[n:], xs[n:]) #p1 = z3.substitute(*(no2 + sub1)) #p2 = z3.substitute(*(no2 + sub2)) p1 = z3.substitute(expr2, sub1) p2 = z3.substitute(expr2, sub2) #S.add(z3.Not(p1)) #S.add(z3.Not(p2)) S.add(p1) S.add(p2) continue print("UNSAFE") return print("SAFE") S.pop()
def solve_exists_forall(exp, given_insts=None, model=False): print 'Exists Forall exp:', exp assert z3.is_quantifier(exp) and not exp.is_forall() (exist_consts, e) = strip_qblock(exp) if not z3.is_quantifier(e): # just an smt problem m = check_sat(e) if m is None: return (None, None, None) else: if model: return (m, None, None) sub = mk_subst_from_model(m, exist_consts, model_completion=True) return (sub, None, None) else: assert e.is_forall() (univ_consts, matrix) = strip_qblock(e) print 'Exist consts:', exist_consts print 'Univ consts:', univ_consts print 'Matrix:', matrix w_cons = [] # constraints for witness # initialize w with given_insts if given_insts is not None: for inst in given_insts: sub = mk_subst_from_model(inst, univ_consts, model_completion=True) w_cons.append(z3.substitute(matrix, *sub)) new_insts = list() witnesses = list() while True: print 'Solver for witness:' for cons in w_cons: print cons.sexpr() w = z3.Solver(ctx=exp.ctx) for cons in w_cons: w.add(cons) # obtain witness for instances res = w.check() if res == z3.unsat: print 'FALSE\n', new_insts return (None, new_insts, witnesses) m = w.model() witnesses.append(m) print 'Model for new witness:\n', m sub = mk_subst_from_model(m, exist_consts, model_completion=True) print 'New witness:', sub # check if the witness is sufficient s = z3.Solver(ctx=exp.ctx) print 'checking validity of ', z3.substitute(matrix, *sub) s.add(z3.Not(z3.substitute(matrix, *sub))) print 'Solver for validity:', z3.Not(z3.substitute(matrix, *sub)).sexpr() res = s.check() if res == z3.unsat: print 'TRUE\n', sub if model: return (m, None, None) return (sub, None, None) inst = s.model() new_insts.append(inst) print 'New instance:\n', inst sub = mk_subst_from_model(inst, univ_consts, model_completion=True) w_cons.append(z3.substitute(matrix, *sub))
def visit_FunctionDef(self, node): annotation = NodeVerifier.parse_docstring(ast.get_docstring(node)) if annotation is not None: forall_vars, precondition, self._type_map = annotation # set the distance vars for the corresponding normal vars from collections import OrderedDict for name, var_type in OrderedDict(self._type_map).items(): constraint = None if isinstance(var_type, NumType): self._type_map['^' + name] = NumType(0) if var_type.value != '*': # TODO: distance variables should be simpler distance_vars = re.findall( r"""\^([_a-zA-Z][0-9a-zA-Z_]*)""", var_type.value) constraint = self._symbol('^' + name) == \ self.visit(self.parse_expr(var_type.value.replace('^', '')))[0] for distance_var in distance_vars: constraint = z3.substitute( constraint, (self._symbol(distance_var), self._symbol('^' + distance_var))) elif isinstance(var_type, BoolType): self._type_map['^' + name] = NumType(0) constraint = self._symbol('^' + name) == \ self.visit(self.parse_expr('0'))[0] elif isinstance(var_type, FunctionType): # TODO: consider FunctionType pass elif isinstance(var_type, ListType): # TODO: consider list inside list self._type_map['^' + name] = ListType(NumType(0)) symbol_i = self._symbol('i') if isinstance(var_type.elem_type, NumType) and var_type.elem_type.value != '*': constraint = self._symbol('^' + name)[symbol_i] == \ self.visit(self.parse_expr(var_type.elem_type.value))[0] elif isinstance(var_type.elem_type, BoolType): constraint = self._symbol('^' + name)[symbol_i] == \ self.visit(self.parse_expr('0'))[0] if constraint is not None: self._declarations.append(constraint) # parse the precondition to constraint distance_vars = re.findall(r"""\^([_a-zA-Z][0-9a-zA-Z_]*)""", precondition) pre_constraint = self.visit( self.parse_expr(precondition.replace('^', '')))[0] for distance_var in distance_vars: pre_constraint = z3.substitute( pre_constraint, (self._symbol(distance_var), self._symbol('^' + distance_var))) if forall_vars is not None: pre_constraint = z3.ForAll( [self._symbol(var) for var in forall_vars], pre_constraint) del self._precondition[:] self._precondition.append(pre_constraint) # empty the check list del self._if_checks[:] del self._assign_checks[:] self.generic_visit(node)
def F(*args): replacements = zip([v1, v2, vout], [create_z3_var(s, vtype) for s in args]) return z3.substitute(expr == vout, *replacements)
def _substitute_inner(self, prev_vec, substitute_with, vec_num): substitutions = zip(prev_vec[vec_num], substitute_with) new_prop_formula = simplify(substitute(self._qbf.get_prop(), *substitutions)) new_qbf = QBF(new_prop_formula, self._qbf.get_q_list()) return new_qbf
def check_substitution(wstate_a, wstate_b): logging.info('Checking if %s subsumes %s', wstate_a.trace, wstate_b.trace) if len( set(wstate_b.address_to_account) - set(wstate_a.address_to_account)): logging.debug('check_substitution: Different gstate number') return False constraints_a = wstate_a.constraints constraints_b = wstate_b.constraints sum_vars = [] focus_a = [] focus_b = [] mapping_ids = set() x_index = 0 y_index = 1 x_var = z3.BitVec('X_var', 256) # y_var = z3.BitVec('Y_var', 256) focus_constraints_a = [] focus_constraints_b = [] for address in wstate_b.address_to_account: gstate_a = wstate_a.address_to_account[address] gstate_b = wstate_b.address_to_account[address] focus_constraints_a.append( x_var == z3.simplify(gstate_a.storage.load(x_index))) # focus_constraints_a.append(y_var == gstate_a.storage.load(y_index)) focus_constraints_b.append( x_var == z3.simplify(gstate_b.storage.load(x_index))) # focus_constraints_b.append(y_var == gstate_b.storage.load(y_index)) focus_constraints_a = z3.And(focus_constraints_a) focus_constraints_b = z3.And(focus_constraints_b) constraints_a = z3.And(constraints_a) constraints_b = z3.And(constraints_b) vars_a = get_wstate_z3vars(wstate_a) vars_b = get_wstate_z3vars(wstate_b) vars_a = set([v.n for v in vars_a]) vars_b = set([v.n for v in vars_b]) substitution_dict_a = substitute_bvset(vars_a, 'A') substitution_dict_b = substitute_bvset(vars_b, 'B') # hash_constraints_a = z3.substitute(hash_constraints, [(bv, bv_s) for bv, bv_s in substitution_dict_a.items()]) # hash_constraints_b = z3.substitute(hash_constraints, [(bv, bv_s) for bv, bv_s in substitution_dict_b.items()]) sub_pairs_a = [(bv, bv_s) for bv, bv_s in substitution_dict_a.items()] sub_pairs_b = [(bv, bv_s) for bv, bv_s in substitution_dict_b.items()] focus_a = z3.substitute(focus_constraints_a, sub_pairs_a) focus_b = z3.substitute(focus_constraints_b, sub_pairs_b) constraints_a_s = z3.substitute(constraints_a, sub_pairs_a) constraints_b_s = z3.substitute(constraints_b, sub_pairs_b) B = z3.And(focus_b, constraints_b_s) nA1 = z3.Not(focus_a) nA2 = z3.Not(constraints_a_s) abstraction_not_implies = z3.Or(z3.And(B, nA1), z3.And(B, nA2)) bv_solver = z3.Solver() bv_solver.set('timeout', 10000) a_vars = list(substitution_dict_a.values()) b_vars = list(substitution_dict_b.values()) q_vars = [x_var] q_vars.extend(b_vars) bv_solver.add( z3.simplify( z3.ForAll( q_vars, z3.Exists(a_vars, z3.Implies(z3.And(focus_b), z3.And(focus_a)))))) res = bv_solver.check() print(res) assert res == z3.sat or res == z3.unsat return res == z3.sat
def solve_exists_forall_incremental(exp, model=False): print 'Exists Forall exp:', exp assert z3.is_quantifier(exp) and not exp.is_forall() (exist_consts, e) = strip_qblock(exp) if not z3.is_quantifier(e): # just an smt problem m = check_sat(e) if m is None: return (None, None, None) else: if model: return (m, None, None) sub = mk_subst_from_model(m, exist_consts, model_completion=True) return (sub, None, None) else: assert e.is_forall() (univ_consts, matrix) = strip_qblock(e) print 'Exist consts:', exist_consts print 'Univ consts:', univ_consts print 'Matrix:', matrix print 'Solving by negating the problem' cex_size = 0 curr_exist_consts = [] curr_matrix_disjs = [] for i in range(cex_size): sub = [] for c in univ_consts: name = '{}_{}'.format(c.decl().name(), str(i)) const = z3.Const(name, c.sort()) curr_exist_consts.append(const) sub.append((c, const)) new_disj = z3.substitute(z3.Not(matrix), *sub) curr_matrix_disjs.append(new_disj) while True: print 'CURRENT SIZE:', cex_size + 1 # look for a cex of size 'cex_size' # Exists U1,U2,..U_cex_size. Forall E. Not (matrix), # where U and E are univ_consts and exist_consts # add a new set of exist consts sub = [] for c in univ_consts: name = '{}_{}'.format(c.decl().name(), str(cex_size)) const = z3.Const(name, c.sort()) curr_exist_consts.append(const) sub.append((c, const)) new_disj = z3.substitute(z3.Not(matrix), *sub) curr_matrix_disjs.append(new_disj) curr_exp = z3.Exists( curr_exist_consts, z3.ForAll(exist_consts, z3.Or(*curr_matrix_disjs))) (cex_model, witnesses, _unused_insts) = solve_exists_forall(curr_exp, model=True) if cex_model is not None: print 'FALSE\n', cex_model print 'Size:', cex_size + 1 # TODO: split cex_model into list of models for the original set of # universal variables return (None, cex_model, witnesses) else: # no cex of current size # check if any of the witnesses already works for m in witnesses: w = z3.Solver(ctx=exp.ctx) sub = mk_subst_from_model(m, exist_consts, model_completion=True) w.add(z3.substitute(z3.Not(matrix), *sub)) if w.check() == z3.unsat: print 'TRUE\n', sub if model: return (m, None, None) return (sub, None, None) # increment size cex_size += 1
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