def visitor_eq(e): if z3.is_eq(e): yield e else: for ch in e.children(): for e0 in visitor_eq(ch): yield e0
def fixedpoint(M, bad): fp = z3.Fixedpoint() options = {'engine':'spacer'} fp.set(**options) xs = M.variables() xsp = M.variables('prime') sorts = M.sorts() + [z3.BoolSort()] inv = z3.Function('inv', *sorts) err = z3.Function('err', z3.BoolSort()) fp.register_relation(inv) fp.register_relation(err) for zi in xs + xsp: fp.declare_var(zi) inv_xs = inv(*xs) inv_xsp = inv(*xsp) fp.rule(inv_xs, M.init(xs)) fp.rule(inv_xsp, M.tr(xs, xsp) + [inv_xs]) fp.rule(err(), bad(xs) + [inv_xs]) if fp.query(err) == z3.unsat: inv = fp.get_answer() assert inv.is_forall() body = inv.body() assert z3.is_eq(body) fapp = body.arg(0) assert (z3.is_app(fapp)) args = [fapp.arg(i) for i in range(body.num_args())] assert len(args) == len(xs) expr = (body.arg(1)) return (z3.unsat, args, expr) else: return (z3.sat, None, None)
def unique_eq_terms_on_const(const, exp, eq_terms=None, done_exp=None): def insert(e): found = False for t in eq_terms: if z3.eq(t, e): found = True break if not found: eq_terms.append(e) return True return False def process_eq(e1, e2): if z3.eq(e1, const): ret_val = z3.simplify(e2) else: assert z3.is_app(e1) if not (z3.is_app_of(e1, z3.Z3_OP_ADD) or z3.is_app_of(e1, z3.Z3_OP_SUB)): return None is_add = z3.is_app_of(e1, z3.Z3_OP_ADD) arg0 = e1.arg(0) arg1 = e1.arg(1) if z3.eq(arg1, const): if is_add: ret_val = z3.simplify(e2 - arg0) else: ret_val = z3.simplify(arg0 - e2) else: if is_add: ret_val = process_eq(arg0, e2 - arg1) else: ret_val = process_eq(arg0, e2 + arg1) return ret_val if eq_terms is None: eq_terms = [] if done_exp is None: done_exp = [] for e in done_exp: if e.eq(exp): return # sub-dag is already processed if z3.is_eq(exp): arg0 = exp.arg(0) arg1 = exp.arg(1) if has_const(arg1, const): arg0, arg1 = arg1, arg0 # swap if has_const(arg0, const): t = process_eq(arg0, arg1) if t is not None: if insert(t): yield (t, exp) else: yield (None, exp) elif z3.is_app(exp): for i in range(exp.num_args()): for (t, eq) in unique_eq_terms_on_const(const, exp.arg(i), eq_terms, done_exp): yield (t, eq) done_exp.append(exp)
def checkLength1(M, bad, count): fp = z3.Fixedpoint() options = {'engine': 'spacer'} fp.set(**options) addCounter(M) xs = M.variables sorts = M.sorts + [z3.BoolSort()] inv = z3.Function('inv', *sorts) err = z3.Bool('err') fp.register_relation(inv) fp.register_relation(err.decl()) fp.declare_var(*xs) bad_state = [z3.And(bad(xs) + [xs[-1] == count])] fp.rule(inv(*xs), M.init) fp.rule(inv(*M.tr), inv(*xs)) fp.rule(err, bad_state + [inv(*xs)]) r = fp.query(err) if r == z3.unsat: inv = fp.get_answer() print("INV:") print(inv) assert inv.is_forall() body = inv.body() assert z3.is_eq(body) print("BODY:", body) fapp = body.arg(0) assert (z3.is_app(fapp)) args = [fapp.arg(i) for i in range(body.num_args())] assert len(args) == len(xs) expr = (body.arg(1)) print(z3.unsat, args, expr) return (z3.unsat, args, expr) else: return (z3.sat, len(inv.children()), None)
def mk_app(self, f, args): if z3.is_eq(f): return args[0] == args[1] elif z3.is_and(f): return And(*args) elif z3.is_or(f): return Or(*args) elif z3.is_not(f): return Not(*args) elif z3.is_add(f): return reduce(operator.add, args[1:], args[0]) elif z3.is_mul(f): return reduce(operator.mul, args[1:], args[0]) elif z3.is_sub(f): return args[0] - args[1] elif z3.is_div(f): return args[0] / args[1] elif z3.is_lt(f): return args[0] < args[1] elif z3.is_le(f): return args[0] <= args[1] elif z3.is_gt(f): return args[0] > args[1] elif z3.is_ge(f): return args[0] >= args[1] elif z3.is_to_real(f): # TODO: ignore coercions? return args[0] elif z3.is_to_int(f): return args[0] elif f.name() == '=>': return implies(args[0], args[1]) else: dom_types = [self.mk_sort(f.domain(i))\ for i in range(0, f.arity())] cod_type = self.mk_sort(f.range()) dom_types.reverse() fun_type = reduce((lambda X, Y: type_arrow(Y, X)), \ dom_types, cod_type) func = self.mk_fun(f) return func(*args)
def _back_single_term(self, expr, args): assert z3.is_expr(expr) if z3.is_quantifier(expr): raise NotImplementedError( "Quantified back conversion is currently not supported") res = None if z3.is_and(expr): res = self.mgr.And(args) elif z3.is_or(expr): res = self.mgr.Or(args) elif z3.is_add(expr): res = self.mgr.Plus(args) elif z3.is_div(expr): res = self.mgr.Div(args[0], args[1]) elif z3.is_eq(expr): if self._get_type(args[0]).is_bool_type(): res = self.mgr.Iff(args[0], args[1]) else: res = self.mgr.Equals(args[0], args[1]) elif z3.is_iff(expr): res = self.mgr.Iff(args[0], args[1]) elif z3.is_xor(expr): res = self.mgr.Xor(args[0], args[1]) elif z3.is_false(expr): res = self.mgr.FALSE() elif z3.is_true(expr): res = self.mgr.TRUE() elif z3.is_gt(expr): res = self.mgr.GT(args[0], args[1]) elif z3.is_ge(expr): res = self.mgr.GE(args[0], args[1]) elif z3.is_lt(expr): res = self.mgr.LT(args[0], args[1]) elif z3.is_le(expr): res = self.mgr.LE(args[0], args[1]) elif z3.is_mul(expr): res = self.mgr.Times(args[0], args[1]) elif z3.is_uminus(expr): tp = self._get_type(args[0]) if tp.is_real_type(): minus_one = self.mgr.Real(-1) else: assert tp.is_int_type() minus_one = self.mgr.Int(-1) res = self.mgr.Times(args[0], minus_one) elif z3.is_sub(expr): res = self.mgr.Minus(args[0], args[1]) elif z3.is_not(expr): res = self.mgr.Not(args[0]) elif z3.is_implies(expr): res = self.mgr.Implies(args[0], args[1]) elif z3.is_quantifier(expr): raise NotImplementedError elif z3.is_const(expr): if z3.is_rational_value(expr): n = expr.numerator_as_long() d = expr.denominator_as_long() f = Fraction(n, d) res = self.mgr.Real(f) elif z3.is_int_value(expr): n = expr.as_long() res = self.mgr.Int(n) elif z3.is_bv_value(expr): n = expr.as_long() w = expr.size() res = self.mgr.BV(n, w) else: # it must be a symbol res = self.mgr.get_symbol(str(expr)) elif z3.is_ite(expr): res = self.mgr.Ite(args[0], args[1], args[2]) elif z3.is_function(expr): res = self.mgr.Function(self.mgr.get_symbol(expr.decl().name()), args) elif z3.is_to_real(expr): res = self.mgr.ToReal(args[0]) elif z3.is_bv_and(expr): res = self.mgr.BVAnd(args[0], args[1]) elif z3.is_bv_or(expr): res = self.mgr.BVOr(args[0], args[1]) elif z3.is_bv_xor(expr): res = self.mgr.BVXor(args[0], args[1]) elif z3.is_bv_not(expr): res = self.mgr.BVNot(args[0]) elif z3.is_bv_neg(expr): res = self.mgr.BVNeg(args[0]) elif z3.is_bv_concat(expr): res = self.mgr.BVConcat(args[0], args[1]) elif z3.is_bv_ult(expr): res = self.mgr.BVULT(args[0], args[1]) elif z3.is_bv_uleq(expr): res = self.mgr.BVULE(args[0], args[1]) elif z3.is_bv_slt(expr): res = self.mgr.BVSLT(args[0], args[1]) elif z3.is_bv_sleq(expr): res = self.mgr.BVSLE(args[0], args[1]) elif z3.is_bv_ugt(expr): res = self.mgr.BVUGT(args[0], args[1]) elif z3.is_bv_ugeq(expr): res = self.mgr.BVUGE(args[0], args[1]) elif z3.is_bv_sgt(expr): res = self.mgr.BVSGT(args[0], args[1]) elif z3.is_bv_sgeq(expr): res = self.mgr.BVSGE(args[0], args[1]) elif z3.is_bv_extract(expr): end = z3.get_payload(expr, 0) start = z3.get_payload(expr, 1) res = self.mgr.BVExtract(args[0], start, end) elif z3.is_bv_add(expr): res = self.mgr.BVAdd(args[0], args[1]) elif z3.is_bv_mul(expr): res = self.mgr.BVMul(args[0], args[1]) elif z3.is_bv_udiv(expr): res = self.mgr.BVUDiv(args[0], args[1]) elif z3.is_bv_sdiv(expr): res = self.mgr.BVSDiv(args[0], args[1]) elif z3.is_bv_urem(expr): res = self.mgr.BVURem(args[0], args[1]) elif z3.is_bv_srem(expr): res = self.mgr.BVSRem(args[0], args[1]) elif z3.is_bv_lshl(expr): res = self.mgr.BVLShl(args[0], args[1]) elif z3.is_bv_lshr(expr): res = self.mgr.BVLShr(args[0], args[1]) elif z3.is_bv_ashr(expr): res = self.mgr.BVAShr(args[0], args[1]) elif z3.is_bv_sub(expr): res = self.mgr.BVSub(args[0], args[1]) elif z3.is_bv_rol(expr): amount = z3.get_payload(expr, 0) res = self.mgr.BVRol(args[0], amount) elif z3.is_bv_ror(expr): amount = z3.get_payload(expr, 0) res = self.mgr.BVRor(args[0], amount) elif z3.is_bv_ext_rol(expr): amount = args[1].bv_unsigned_value() res = self.mgr.BVRol(args[0], amount) elif z3.is_bv_ext_ror(expr): amount = args[1].bv_unsigned_value() res = self.mgr.BVRor(args[0], amount) elif z3.is_bv_sext(expr): amount = z3.get_payload(expr, 0) res = self.mgr.BVSExt(args[0], amount) elif z3.is_bv_zext(expr): amount = z3.get_payload(expr, 0) res = self.mgr.BVZExt(args[0], amount) if res is None: raise ConvertExpressionError(message=("Unsupported expression: %s" % str(expr)), expression=expr) return res
def back(self, expr): assert z3.is_expr(expr) if askey(expr) in self.backconversion: return self.backconversion[askey(expr)] if z3.is_quantifier(expr): raise NotImplementedError( "Quantified back conversion is currently not supported") args = [self.back(x) for x in expr.children()] res = None if z3.is_and(expr): res = self.mgr.And(args) elif z3.is_or(expr): res = self.mgr.Or(args) elif z3.is_add(expr): res = self.mgr.Plus(args) elif z3.is_div(expr): res = self.mgr.Div(args[0], args[1]) elif z3.is_eq(expr): if self._get_type(args[0]) == types.BOOL: res = self.mgr.Iff(args[0], args[1]) else: res = self.mgr.Equals(args[0], args[1]) elif z3.is_false(expr): res = self.mgr.FALSE() elif z3.is_true(expr): res = self.mgr.TRUE() elif z3.is_gt(expr): res = self.mgr.GT(args[0], args[1]) elif z3.is_ge(expr): res = self.mgr.GE(args[0], args[1]) elif z3.is_lt(expr): res = self.mgr.LT(args[0], args[1]) elif z3.is_le(expr): res = self.mgr.LE(args[0], args[1]) elif z3.is_mul(expr): res = self.mgr.Times(args[0], args[1]) elif z3.is_sub(expr): res = self.mgr.Minus(args[0], args[1]) elif z3.is_not(expr): res = self.mgr.Not(args[0]) elif z3.is_quantifier(expr): if expr.is_forall(): pass else: pass raise NotImplementedError elif z3.is_const(expr): if z3.is_rational_value(expr): n = expr.numerator_as_long() d = expr.denominator_as_long() f = Fraction(n, d) res = self.mgr.Real(f) elif z3.is_int_value(expr): n = expr.as_long() res = self.mgr.Int(n) else: # it must be a symbol res = self.mgr.get_symbol(str(expr)) elif z3.is_ite(expr): res = self.mgr.Ite(args[0], args[1], args[2]) else: raise TypeError("Unsupported expression:", expr) if res is None: raise TypeError("Unsupported expression:", expr) self.backconversion[askey(expr)] = res return res
def _back_single_term(self, expr, args, model=None): assert z3.is_expr(expr) if z3.is_quantifier(expr): raise NotImplementedError( "Quantified back conversion is currently not supported") res = None if z3.is_and(expr): res = self.mgr.And(args) elif z3.is_or(expr): res = self.mgr.Or(args) elif z3.is_add(expr): res = self.mgr.Plus(args) elif z3.is_div(expr): res = self.mgr.Div(args[0], args[1]) elif z3.is_eq(expr): if self._get_type(args[0]).is_bool_type(): res = self.mgr.Iff(args[0], args[1]) else: res = self.mgr.Equals(args[0], args[1]) elif z3.is_iff(expr): res = self.mgr.Iff(args[0], args[1]) elif z3.is_xor(expr): res = self.mgr.Xor(args[0], args[1]) elif z3.is_false(expr): res = self.mgr.FALSE() elif z3.is_true(expr): res = self.mgr.TRUE() elif z3.is_gt(expr): res = self.mgr.GT(args[0], args[1]) elif z3.is_ge(expr): res = self.mgr.GE(args[0], args[1]) elif z3.is_lt(expr): res = self.mgr.LT(args[0], args[1]) elif z3.is_le(expr): res = self.mgr.LE(args[0], args[1]) elif z3.is_mul(expr): res = self.mgr.Times(args[0], args[1]) elif z3.is_uminus(expr): tp = self._get_type(args[0]) if tp.is_real_type(): minus_one = self.mgr.Real(-1) else: assert tp.is_int_type() minus_one = self.mgr.Int(-1) res = self.mgr.Times(args[0], minus_one) elif z3.is_sub(expr): res = self.mgr.Minus(args[0], args[1]) elif z3.is_not(expr): res = self.mgr.Not(args[0]) elif z3.is_implies(expr): res = self.mgr.Implies(args[0], args[1]) elif z3.is_quantifier(expr): raise NotImplementedError elif z3.is_const(expr): if z3.is_rational_value(expr): n = expr.numerator_as_long() d = expr.denominator_as_long() f = Fraction(n, d) res = self.mgr.Real(f) elif z3.is_int_value(expr): n = expr.as_long() res = self.mgr.Int(n) elif z3.is_bv_value(expr): n = expr.as_long() w = expr.size() res = self.mgr.BV(n, w) elif z3.is_as_array(expr): if model is None: raise NotImplementedError("As-array expressions cannot be" \ " handled as they are not " \ "self-contained") else: interp_decl = z3.get_as_array_func(expr) interp = model[interp_decl] default = self.back(interp.else_value(), model=model) assign = {} for i in xrange(interp.num_entries()): e = interp.entry(i) assert e.num_args() == 1 idx = self.back(e.arg_value(0), model=model) val = self.back(e.value(), model=model) assign[idx] = val arr_type = self._z3_to_type(expr.sort()) res = self.mgr.Array(arr_type.index_type, default, assign) elif z3.is_algebraic_value(expr): # Algebraic value return self.mgr._Algebraic(Numeral(expr)) else: # it must be a symbol res = self.mgr.get_symbol(str(expr)) elif z3.is_ite(expr): res = self.mgr.Ite(args[0], args[1], args[2]) elif z3.is_function(expr): res = self.mgr.Function(self.mgr.get_symbol(expr.decl().name()), args) elif z3.is_to_real(expr): res = self.mgr.ToReal(args[0]) elif z3.is_bv_and(expr): res = self.mgr.BVAnd(args[0], args[1]) elif z3.is_bv_or(expr): res = self.mgr.BVOr(args[0], args[1]) elif z3.is_bv_xor(expr): res = self.mgr.BVXor(args[0], args[1]) elif z3.is_bv_not(expr): res = self.mgr.BVNot(args[0]) elif z3.is_bv_neg(expr): res = self.mgr.BVNeg(args[0]) elif z3.is_bv_concat(expr): res = self.mgr.BVConcat(args[0], args[1]) elif z3.is_bv_ult(expr): res = self.mgr.BVULT(args[0], args[1]) elif z3.is_bv_uleq(expr): res = self.mgr.BVULE(args[0], args[1]) elif z3.is_bv_slt(expr): res = self.mgr.BVSLT(args[0], args[1]) elif z3.is_bv_sleq(expr): res = self.mgr.BVSLE(args[0], args[1]) elif z3.is_bv_ugt(expr): res = self.mgr.BVUGT(args[0], args[1]) elif z3.is_bv_ugeq(expr): res = self.mgr.BVUGE(args[0], args[1]) elif z3.is_bv_sgt(expr): res = self.mgr.BVSGT(args[0], args[1]) elif z3.is_bv_sgeq(expr): res = self.mgr.BVSGE(args[0], args[1]) elif z3.is_bv_extract(expr): end = z3.get_payload(expr, 0) start = z3.get_payload(expr, 1) res = self.mgr.BVExtract(args[0], start, end) elif z3.is_bv_add(expr): res = self.mgr.BVAdd(args[0], args[1]) elif z3.is_bv_mul(expr): res = self.mgr.BVMul(args[0], args[1]) elif z3.is_bv_udiv(expr): res = self.mgr.BVUDiv(args[0], args[1]) elif z3.is_bv_sdiv(expr): res = self.mgr.BVSDiv(args[0], args[1]) elif z3.is_bv_urem(expr): res = self.mgr.BVURem(args[0], args[1]) elif z3.is_bv_srem(expr): res = self.mgr.BVSRem(args[0], args[1]) elif z3.is_bv_lshl(expr): res = self.mgr.BVLShl(args[0], args[1]) elif z3.is_bv_lshr(expr): res = self.mgr.BVLShr(args[0], args[1]) elif z3.is_bv_ashr(expr): res = self.mgr.BVAShr(args[0], args[1]) elif z3.is_bv_sub(expr): res = self.mgr.BVSub(args[0], args[1]) elif z3.is_bv_rol(expr): amount = z3.get_payload(expr, 0) res = self.mgr.BVRol(args[0], amount) elif z3.is_bv_ror(expr): amount = z3.get_payload(expr, 0) res = self.mgr.BVRor(args[0], amount) elif z3.is_bv_ext_rol(expr): amount = args[1].bv_unsigned_value() res = self.mgr.BVRol(args[0], amount) elif z3.is_bv_ext_ror(expr): amount = args[1].bv_unsigned_value() res = self.mgr.BVRor(args[0], amount) elif z3.is_bv_sext(expr): amount = z3.get_payload(expr, 0) res = self.mgr.BVSExt(args[0], amount) elif z3.is_bv_zext(expr): amount = z3.get_payload(expr, 0) res = self.mgr.BVZExt(args[0], amount) elif z3.is_array_select(expr): res = self.mgr.Select(args[0], args[1]) elif z3.is_array_store(expr): res = self.mgr.Store(args[0], args[1], args[2]) elif z3.is_const_array(expr): arr_ty = self._z3_to_type(expr.sort()) k = args[0] res = self.mgr.Array(arr_ty.index_type, k) elif z3.is_power(expr): res = self.mgr.Pow(args[0], args[1]) if res is None: raise ConvertExpressionError(message=("Unsupported expression: %s" % str(expr)), expression=expr) return res