def _isVar(self, elem): return any([ z3.is_int_value(z3.simplify(elem)), z3.is_rational_value(z3.simplify(elem)), z3.is_algebraic_value(z3.simplify(elem)), is_const(z3.simplify(elem)) ])
def _is_literal(z3ast): if z3.is_int(z3ast): return z3.is_int_value(z3ast) if z3.is_bool(z3ast): return z3.is_true(z3ast) or z3.is_false(z3ast) if z3ast.sort_kind() == z3.Z3_UNINTERPRETED_SORT: return z3.is_const(z3ast) and '!' in str(z3ast) raise NotImplementedError('Don\'t know how to literal-check %s' % z3ast)
def is_bool_or_int_value(value): if z3.is_int_value(value): return True if value.sort() == z3.BoolSort(): if z3.is_true(value) or z3.is_false(value): return True else: return False
def collect_numerals(z3term): if z3.is_int_value(z3term) or z3.is_bv_value(z3term): yield z3term elif z3.is_app_of(z3term, z3.Z3_OP_ITE): for z in collect_numerals(z3term.arg(1)): yield z for z in collect_numerals(z3term.arg(2)): yield z
def pp_app(self, a, d, xs): if z3.is_int_value(a): return self.pp_int(a) elif z3.is_rational_value(a): return self.pp_rational(a) elif z3.is_algebraic_value(a): return self.pp_algebraic(a) elif z3.is_bv_value(a): return self.pp_bv(a) elif z3.is_finite_domain_value(a): return self.pp_fd(a) elif z3.is_fprm_value(a): return self.pp_fprm_value(a) elif z3.is_fp_value(a): return self.pp_fp_value(a) elif z3.is_fp(a): return self.pp_fp(a, d, xs) elif z3.is_string_value(a): return self.pp_string(a) elif z3.is_const(a): return self.pp_const(a) else: f = a.decl() k = f.kind() if k == Z3_OP_POWER: return self.pp_power(a, d, xs) elif k == Z3_OP_DISTINCT: return self.pp_distinct(a, d, xs) elif k == Z3_OP_SELECT: return self.pp_select(a, d, xs) elif k == Z3_OP_SIGN_EXT or k == Z3_OP_ZERO_EXT or k == Z3_OP_REPEAT: return self.pp_unary_param(a, d, xs) elif k == Z3_OP_EXTRACT: return self.pp_extract(a, d, xs) elif k == Z3_OP_RE_LOOP: return self.pp_loop(a, d, xs) elif k == Z3_OP_DT_IS: return self.pp_is(a, d, xs) elif k == Z3_OP_ARRAY_MAP: return self.pp_map(a, d, xs) elif k == Z3_OP_CONST_ARRAY: return self.pp_K(a, d, xs) elif k == Z3_OP_PB_AT_MOST: return self.pp_atmost(a, d, f, xs) elif k == Z3_OP_PB_LE: return self.pp_pbcmp(a, d, f, xs) elif k == Z3_OP_PB_GE: return self.pp_pbcmp(a, d, f, xs) elif k == Z3_OP_PB_EQ: return self.pp_pbcmp(a, d, f, xs) elif z3.is_pattern(a): return self.pp_pattern(a, d, xs) elif self.is_infix(k): return self.pp_infix(a, d, xs) elif self.is_unary(k): return self.pp_unary(a, d, xs) else: return self.pp_prefix(a, d, xs)
def convert(t, values): if z3.is_int_value(t): return t.as_long() if z3.is_app(t): func = globals()[t.decl().name()] return func( *[convert(t.arg(i), values) for i in range(t.num_args())]) elif z3.is_var(t): return values[z3.get_var_index(t)]
def pp_app(self, a, d, xs): if z3.is_int_value(a): return self.pp_int(a) elif z3.is_rational_value(a): return self.pp_rational(a) elif z3.is_algebraic_value(a): return self.pp_algebraic(a) elif z3.is_bv_value(a): return self.pp_bv(a) elif z3.is_finite_domain_value(a): return self.pp_fd(a) elif z3.is_fprm_value(a): return self.pp_fprm_value(a) elif z3.is_fp_value(a): return self.pp_fp_value(a) elif z3.is_fp(a): return self.pp_fp(a, d, xs) elif z3.is_string_value(a): return self.pp_string(a) elif z3.is_const(a): return self.pp_const(a) else: f = a.decl() k = f.kind() if k == Z3_OP_POWER: return self.pp_power(a, d, xs) elif k == Z3_OP_DISTINCT: return self.pp_distinct(a, d, xs) elif k == Z3_OP_SELECT: return self.pp_select(a, d, xs) elif k == Z3_OP_SIGN_EXT or k == Z3_OP_ZERO_EXT or k == Z3_OP_REPEAT: return self.pp_unary_param(a, d, xs) elif k == Z3_OP_EXTRACT: return self.pp_extract(a, d, xs) elif k == Z3_OP_DT_IS: return self.pp_is(a, d, xs) elif k == Z3_OP_ARRAY_MAP: return self.pp_map(a, d, xs) elif k == Z3_OP_CONST_ARRAY: return self.pp_K(a, d, xs) elif k == Z3_OP_PB_AT_MOST: return self.pp_atmost(a, d, f, xs) elif k == Z3_OP_PB_LE: return self.pp_pbcmp(a, d, f, xs) elif k == Z3_OP_PB_GE: return self.pp_pbcmp(a, d, f, xs) elif k == Z3_OP_PB_EQ: return self.pp_pbcmp(a, d, f, xs) elif z3.is_pattern(a): return self.pp_pattern(a, d, xs) elif self.is_infix(k): return self.pp_infix(a, d, xs) elif self.is_unary(k): return self.pp_unary(a, d, xs) else: return self.pp_prefix(a, d, xs)
def model_to_val(m, var): p = m[var] if is_int_value(p): return float(p.as_long()) if is_algebraic_value(p): p = p.approx(5) # Precise to 5 decimals if is_rational_value(p): x = float(p.numerator_as_long()) / \ float(p.denominator_as_long()) return x
def collect_consts(smt_expr): """Returns list of all constants (as ExprRef instances) that appear in the given expression""" assert (isinstance(smt_expr, z3.ExprRef)) non_unique_res = expr_fold(smt_expr, lambda t: [t] if not z3.is_int_value(t) else [], lambda _, cs: utils.flatten(cs)) for c in non_unique_res: assert (z3.is_const(c)) # Leaving the following in, in case conversion breaks again with strange z3 exceptions... #logger.info([c.__class__ for c in non_unique_res]) res = set(non_unique_res) #logger.info("Consts in expr: {}".format(res)) return [c for c in res if str(c) not in keywords]
def rec(e): if isinstance(e, z3.QuantifierRef): for n in range(e.num_vars()): mkvar(e.var_name(n), e.var_sort(n)) elif z3.is_algebraic_value(e) or \ z3.is_bv_value(e) or \ z3.is_int_value(e) or \ z3.is_rational_value(e): pass elif z3.is_const(e): mkvar(str(e), e.sort()) for sub in e.children(): rec(sub)
def to_python(some_number): if isinstance(some_number, numbers.Number): return some_number some_number = z3.simplify(some_number) if z3.is_algebraic_value(some_number): some_number = some_number.approx(config.approx) if z3.is_int_value(some_number): return some_number.as_long() else: try: return float(some_number.numerator_as_long()) / float( some_number.denominator_as_long()) except Exception: return str(some_number) # last resort, return as string
def val(self, exp): '''Evaluate a z3 ref to a python value based on this solution. ''' v = self.model.eval(exp) if z3.is_true(v): return True if z3.is_false(v): return False if z3.is_algebraic_value(v): v = v.approx(20) if z3.is_int_value(v): return v.as_long() if z3.is_rational_value(v): return v.numerator_as_long() / v.denominator_as_long() return z3.is_true(v)
def to_python(some_number): raise DeprecationWarning("use config.to_python instead") if isinstance(some_number, (int, float, str, bool)): return some_number some_number = z3.simplify(some_number) if z3.is_algebraic_value(some_number): some_number = some_number.approx(config.approx) if z3.is_int_value(some_number): return some_number.as_long() else: try: return float(some_number.numerator_as_long()) / float( some_number.denominator_as_long()) except Exception: return str(some_number) # last resort
def get_py_val_from_z3_val(z3_result): if z3_result is not None: if z3.is_int_value(z3_result): return z3_result.as_long() elif z3.is_real(z3_result): return float(z3_result.numerator_as_long()) / float( z3_result.denominator_as_long()) elif z3.is_true(z3_result): return True elif z3.is_false(z3_result): return False elif z3.is_string_value(z3_result): return z3_result.as_string() else: raise NotImplementedError( "Z3 model result other than int, real, bool, string is not supported yet!" )
def z3ToPoint(self, point): res = [] # get the variables corresponding to the axis names for idx, i in enumerate(self.axis_names): locals()[i] = Globals.z3variables[i] if i in Globals.z3types: # non-numeric points -> coord to value value = Globals.z3types[i][point[locals()[i]].as_long()] elif None == point[locals()[i]]: info("no value for %s, take %r (incomplete model)" % (self.axis_names[idx], self.axis_val_ranges[idx][0])) value = self.axis_val_ranges[idx][0] elif z3.is_int_value(point[locals()[i]]): value = point[locals()[i]].as_long() elif z3.is_true(point[locals()[i]]) or z3.is_false( point[locals()[i]]): value = z3.is_true(point[locals()[i]]) res.append(value) return res
def mk_const(self, c): if z3.is_int_value(c): return ii(c.as_long()) if z3.is_rational_value(c): # TODO: what should we convert a rational to? return rr(Fraction(c.numerator_as_long(), \ c.denominator_as_long())) elif z3.is_true(c): return true elif z3.is_false(c): return false else: try: return self.context.decls[str(c)] except KeyError: #Constant is not found in the context typ = self.mk_sort(c.sort()) return const(str(c), typ)
def get_value(r): # https://stackoverflow.com/questions/12598408/z3-python-getting-python-values-from-model/12600208 """ Convert from Z3 to python values. """ if z3.is_true(r): return z3.is_true(r) elif z3.is_false(r): return z3.is_false(r) elif z3.is_int_value(r): return r.as_long() elif z3.is_algebraic_value(r): return round(num(r.approx(15)), 10) elif z3.is_rational_value(r): return r.as_decimal(20) elif r is None: None else: return num(r)
def pp_app(self, a, d, xs): if z3.is_int_value(a): return self.pp_int(a) elif z3.is_rational_value(a): return self.pp_rational(a) elif z3.is_algebraic_value(a): return self.pp_algebraic(a) elif z3.is_bv_value(a): return self.pp_bv(a) elif z3.is_fprm_value(a): return self.pp_fprm_value(a) elif z3.is_fp_value(a): return self.pp_fp_value(a) elif z3.is_fp(a): return self.pp_fp(a, d, xs) elif z3.is_const(a): return self.pp_const(a) else: f = a.decl() k = f.kind() if k == Z3_OP_POWER: return self.pp_power(a, d, xs) elif k == Z3_OP_DISTINCT: return self.pp_distinct(a, d, xs) elif k == Z3_OP_SELECT: return self.pp_select(a, d, xs) elif k == Z3_OP_SIGN_EXT or k == Z3_OP_ZERO_EXT or k == Z3_OP_REPEAT: return self.pp_unary_param(a, d, xs) elif k == Z3_OP_EXTRACT: return self.pp_extract(a, d, xs) elif k == Z3_OP_ARRAY_MAP: return self.pp_map(a, d, xs) elif k == Z3_OP_CONST_ARRAY: return self.pp_K(a, d, xs) elif z3.is_pattern(a): return self.pp_pattern(a, d, xs) elif self.is_infix(k): return self.pp_infix(a, d, xs) elif self.is_unary(k): return self.pp_unary(a, d, xs) else: return self.pp_prefix(a, d, xs)
def coerceTypesIfPossible(var, other_var): if z3.is_or(other_var) and not z3.is_bool(var): other_var = transformNonBooleanLazyEvaluations(other_var) if z3.is_or(var) and not z3.is_bool(other_var): var = transformNonBooleanLazyEvaluations(var) if z3.is_and(other_var) and not z3.is_bool(var): other_var = transformNonBooleanLazyEvaluations(other_var) if z3.is_and(var) and not z3.is_bool(other_var): var = transformNonBooleanLazyEvaluations(var) if var.decl().kind() == z3.Z3_OP_UNINTERPRETED: if z3.is_bool(other_var) and not z3.is_bool(var): infered_types[str(var)] = 'boolean' return z3.Bool(str(var)), other_var if z3.is_string(other_var) and not z3.is_string(var): if other_var.as_string() == '': # we probably dont want to coerce in this specific case as this is merely a non empty check if z3.is_bool(var): return var, z3.BoolVal(False) if z3.is_int(var): return var, z3.IntVal(0) else: infered_types[str(var)] = 'string' return z3.String(str(var)), other_var if z3.is_int(other_var) and not z3.is_int(var): infered_types[str(var)] = 'number' return z3.Int(str(var)), other_var elif var.decl().kind() == z3.Z3_OP_UNINTERPRETED: if z3.is_bool(var): infered_types[str(var)] = 'boolean' if z3.is_string(var): infered_types[str(var)] = 'string' if z3.is_int(var): infered_types[str(var)] = 'number' else: # this means that it is non-interpreted and we need to coerce other var to the type of var if z3.is_string(var) and z3.is_int_value(other_var): other_var = z3.StringVal(str(other_var)) if z3.is_arith(var) and z3.is_string(other_var): other_var = z3.IntVal(int(other_var.as_string())) return var, other_var
def check_value(self, val): assert val is not None, f"Setting a port's value to None is not allowed" # check that we only assign correct values to the ports if isinstance(self.domain, list): return val in self.domain elif self.domain is Types.INTEGER: return isinstance(val, int) or z3.is_int_value(val) or z3.is_int(val) elif self.domain is Types.REAL: # z3 types return (isinstance(val, numbers.Number) and not isinstance(val, bool)) or z3.is_real(val) elif self.domain is Types.INT: # TODO: check also for these types return isinstance(val, int) elif self.domain is Types.FLOAT: # TODO: check also for these types return (isinstance(val, numbers.Number) and not isinstance(val, bool)) elif self.domain is Types.STRING: # TODO: check also for these types return isinstance(val, str) elif self.domain is Types.BOOL: # TODO: check also for these types return isinstance(val, bool) else: return False
def unique_leaves(exp, leaf_keys=None): def insert_and_yield(e): k = exp_key(e) if k not in leaf_keys: leaf_keys.append(k) yield e if leaf_keys is None: leaf_keys = [] if z3.is_const(exp) and not (z3.is_int_value(exp) or z3.is_rational_value(exp)): for leaf in insert_and_yield(exp): yield leaf elif z3.is_app(exp): for i in range(exp.num_args()): for leaf in unique_leaves(exp.arg(i), leaf_keys): yield leaf else: assert z3.is_var(exp) for leaf in insert_and_yield(exp): yield leaf
def z3_to_val(z3_expr): """Send a z3 expression to it's value as a python expression, if it has one, otherwise return the expresson itself. Arguments: - `z3_expr`: a z3 AST """ if z3.is_int_value(z3_expr): return z3_expr.as_long() if z3.is_rational_value(z3_expr): return Fraction(z3_expr.numerator_as_long(), \ z3_expr.denominator_as_long()) elif z3.is_true(z3_expr): return True elif z3.is_false(z3_expr): return False elif isinstance(z3_expr, z3.FuncInterp): return z3_to_fun(z3_expr) else: return z3_expr
def z3_to_val(z3_expr): """Send a z3 expression to its value as a python expression, if it has one, otherwise return the expresson itself. Arguments: - `z3_expr`: a z3 AST """ if z3.is_int_value(z3_expr): return z3_expr.as_long() if z3.is_rational_value(z3_expr): return Fraction(z3_expr.numerator_as_long(), \ z3_expr.denominator_as_long()) elif z3.is_true(z3_expr): return True elif z3.is_false(z3_expr): return False elif isinstance(z3_expr, z3.FuncInterp): return z3_to_fun(z3_expr) else: return z3_expr
def pp_app(self, a, d, xs): if z3.is_int_value(a): return self.pp_int(a) elif z3.is_rational_value(a): rat = self.pp_rational(a) return rat elif z3.is_algebraic_value(a): return self.pp_algebraic(a) elif z3.is_bv_value(a): return self.pp_bv(a) elif z3.is_const(a): return self.pp_const(a) else: f = a.decl() k = f.kind() if k == Z3_OP_POWER: return self.pp_power(a, d, xs) elif k == Z3_OP_DISTINCT: return self.pp_distinct(a, d, xs) elif k == Z3_OP_SELECT: return self.pp_select(a, d, xs) elif k == Z3_OP_SIGN_EXT or k == Z3_OP_ZERO_EXT or k == Z3_OP_REPEAT: return self.pp_unary_param(a, d, xs) elif k == Z3_OP_EXTRACT: return self.pp_extract(a, d, xs) elif k == Z3_OP_ARRAY_MAP: return self.pp_map(a, d, xs) elif k == Z3_OP_CONST_ARRAY: return self.pp_K(a, d, xs) elif z3.is_pattern(a): return self.pp_pattern(a, d, xs) elif self.is_infix(k): return self.pp_infix(a, d, xs) elif self.is_unary(k): return self.pp_unary(a, d, xs) else: return self.pp_prefix(a, d, xs)
def _state_id_to_prism_variable_to_value(self, state_id): """ Returns a dict from prism variables to z3 values representing the valuation of state_id. :param state_id: :return: """ state_valuation = self.state_graph.get_state_valuation(state_id) return {input_variable.get_prism_variable(): z3.is_true(z3_value) for input_variable, z3_value in state_valuation.items() if not (z3.is_int_value(z3_value) or z3.is_rational_value(z3_value))}, {input_variable.get_prism_variable() : z3_value.as_long() for input_variable, z3_value in state_valuation.items() if (z3.is_int_value(z3_value) or z3.is_rational_value(z3_value))}
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") assert not len(args) > 2 or \ (z3.is_and(expr) or z3.is_or(expr) or z3.is_add(expr) or z3.is_mul(expr) or (len(args) == 3 and (z3.is_ite(expr) or z3.is_array_store(expr)))),\ "Unexpected n-ary term: %s" % expr res = None try: decl = z3.Z3_get_app_decl(expr.ctx_ref(), expr.as_ast()) kind = z3.Z3_get_decl_kind(expr.ctx.ref(), decl) # Try to get the back-conversion function for the given Kind fun = self._back_fun[kind] return fun(args, expr) except KeyError as ex: pass if z3.is_const(expr): # Const or Symbol if z3.is_rational_value(expr): n = expr.numerator_as_long() d = expr.denominator_as_long() f = Fraction(n, d) return self.mgr.Real(f) elif z3.is_int_value(expr): n = expr.as_long() return self.mgr.Int(n) elif z3.is_bv_value(expr): n = expr.as_long() w = expr.size() return 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()) return 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 try: return self.mgr.get_symbol(str(expr)) except UndefinedSymbolError: import warnings symb_type = self._z3_to_type(expr.sort()) warnings.warn("Defining new symbol: %s" % str(expr)) return self.mgr.FreshSymbol(symb_type, template="__z3_%d") elif z3.is_function(expr): # This needs to be after we try to convert regular Symbols fsymbol = self.mgr.get_symbol(expr.decl().name()) return self.mgr.Function(fsymbol, args) # If we reach this point, we did not manage to translate the expression raise ConvertExpressionError(message=("Unsupported expression: %s" % (str(expr))), expression=expr)
def expression_evaluable(self, name): expr = self.expression_get(name) return z3.is_int_value(expr) or z3.is_bv_value(expr)
def _isNum(self, elem): return z3.is_rational_value(elem) or z3.is_int_value(elem)
def collect_numerals(z3term): if z3.is_int_value(z3term) or z3.is_bv_value(z3term): yield z3term elif z3.is_app_of(z3term, z3.Z3_OP_ITE): yield collect_numerals(z3term.arg(1)) yield collect_numerals(z3term.arg(2))
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
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): 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 _eval_int(expr: z3.ExprRef) -> str: # TODO: this should return int assert z3.is_int(expr), expr ans = z3model.eval(expr, model_completion=True) assert z3.is_int_value(ans), (expr, ans) return str(ans.as_long())
def _old_model_to_trace(z3model: z3.ModelRef, num_states: int, allow_undefined: bool = False) -> Trace: ''' Convert z3 model to Trace with given number of states. If allow_undefined is True, the resulting trace may leave some symbols undefined. ''' trace = Trace(num_states) keys = Z3Translator._get_keys(num_states) def rename(s: str) -> str: return s.replace('!val!', '').replace('@uc_', '') def _eval(expr: z3.ExprRef) -> z3.ExprRef: ans = z3model.eval(expr, model_completion=True) assert bool(ans) is True or bool(ans) is False, (expr, ans) return ans prog = syntax.the_program for z3sort in sorted(z3model.sorts(), key=str): sort = prog.scope.get_sort(str(z3sort)) assert sort is not None univ = z3model.get_universe(z3sort) trace.univs[sort] = tuple(sorted(rename(str(x)) for x in univ)) model_decls = z3model.decls() all_decls = model_decls for z3decl in sorted(all_decls, key=str): z3name = str(z3decl) for i, k in enumerate(keys): if z3name.startswith(k): name = z3name[len(k + '_'):] R = trace.rel_interps[i] C = trace.const_interps[i] F = trace.func_interps[i] break else: name = z3name R = trace.immut_rel_interps C = trace.immut_const_interps F = trace.immut_func_interps decl = prog.scope.get(name) assert not isinstance(decl, syntax.Sort) and \ not isinstance(decl, syntax.SortInferencePlaceholder) if decl is not None: if isinstance(decl, RelationDecl): if decl.arity: rl: RelationInterp = {} domains = [ z3model.get_universe(z3decl.domain(i)) for i in range(z3decl.arity()) ] if not any(x is None for x in domains): # Note: if any domain is None, we silently drop this symbol. # It's not entirely clear that this is an ok thing to do. g = product(*domains) for row in g: relation_expr = z3decl(*row) ans = _eval(relation_expr) rl[tuple(rename(str(col)) for col in row)] = bool(ans) assert decl not in R R[decl] = rl else: ans = z3model.eval(z3decl()) assert decl not in R R[decl] = {(): bool(ans)} elif isinstance(decl, FunctionDecl): fl: FunctionInterp = {} domains = [ z3model.get_universe(z3decl.domain(i)) for i in range(z3decl.arity()) ] if not any(x is None for x in domains): # Note: if any domain is None, we silently drop this symbol. # It's not entirely clear that this is an ok thing to do. g = product(*domains) for row in g: ans = z3model.eval(z3decl(*row)) if z3.is_int_value(ans): ans_str = str(ans.as_long()) else: ans_str = rename(ans.decl().name()) fl[tuple(rename(str(col)) for col in row)] = ans_str assert decl not in F F[decl] = fl else: assert isinstance(decl, ConstantDecl) v = z3model.eval(z3decl()) if z3.is_int_value(v) or isinstance(v, CVC4Int): v_str = str(v.as_long()) else: v_str = rename(v.decl().name()) assert decl not in C C[decl] = v_str else: if name.startswith(TRANSITION_INDICATOR + '_') and z3model.eval(z3decl()): name = name[len(TRANSITION_INDICATOR + '_'):] istr, name = name.split('_', maxsplit=1) i = int(istr) if i < len(trace.transitions): trace.transitions[i] = name else: # TODO: not sure what's going on here with check_bmc and pd.check_k_state_implication # assert False pass if allow_undefined: return trace def get_univ(d: SortDecl) -> Tuple[Element, ...]: if d not in trace.univs: trace.univs[d] = (d.name + '0', ) return trace.univs[d] def arbitrary_interp_r(r: RelationDecl) -> RelationInterp: doms = [get_univ(syntax.get_decl_from_sort(s)) for s in r.arity] return dict.fromkeys(product(*doms), False) def ensure_defined_r(r: RelationDecl) -> None: arb_interp: Optional[RelationInterp] = None for m in (trace.rel_interps if r.mutable else [trace.immut_rel_interps]): if r not in m: if arb_interp is None: arb_interp = arbitrary_interp_r(r) m[r] = arb_interp def arbitrary_interp_c(c: ConstantDecl) -> Element: if isinstance(c.sort, syntax._BoolSort): return 'false' elif isinstance(c.sort, syntax._IntSort): return '0' assert isinstance(c.sort, syntax.UninterpretedSort) sort = c.sort return get_univ(syntax.get_decl_from_sort(sort))[0] def ensure_defined_c(c: ConstantDecl) -> None: arb_interp = arbitrary_interp_c(c) for m in (trace.const_interps if c.mutable else [trace.immut_const_interps]): if c not in m: m[c] = arb_interp def arbitrary_interp_f(f: FunctionDecl) -> FunctionInterp: doms = [get_univ(syntax.get_decl_from_sort(s)) for s in f.arity] image = get_univ(syntax.get_decl_from_sort(f.sort))[0] return dict.fromkeys(product(*doms), image) def ensure_defined_f(f: FunctionDecl) -> None: arb_interp: Optional[FunctionInterp] = None for m in (trace.func_interps if f.mutable else [trace.immut_func_interps]): if f not in m: if arb_interp is None: arb_interp = arbitrary_interp_f(f) m[f] = arb_interp for decl in prog.relations_constants_and_functions(): if isinstance(decl, RelationDecl): ensure_defined_r(decl) elif isinstance(decl, ConstantDecl): ensure_defined_c(decl) elif isinstance(decl, FunctionDecl): ensure_defined_f(decl) else: assert False, decl return trace
def z3_expr_to_boogie(expr: z3.ExprRef) -> AstExpr: d = expr.decl() if (d.arity() == 0): # Literals and Identifiers if (isinstance(expr, z3.BoolRef)): if (z3.is_true(expr)): # No need for explicit ctx return AstTrue() elif (z3.is_false(expr)): # No need for explicit ctx return AstFalse() else: return AstId(d.name()) else: assert isinstance(expr.sort(), z3.ArithSortRef), \ "For now only handle bools and ints" if (z3.is_int_value(expr)): # No need for explicit ctx return AstNumber(int(str(expr))) else: return AstId(d.name()) elif (d.arity() == 1): # Unary operators arg = z3_expr_to_boogie(cast(z3.ExprRef, expr.children()[0])) boogie_op = { '-': '-', 'not': '!', }[d.name()] return AstUnExpr(boogie_op, arg) elif (d.name() == "if" and d.arity() == 2): c = cast(List[z3.ExprRef], expr.children()) cond = z3_expr_to_boogie(c[0]) thenB = z3_expr_to_boogie(c[1]) return AstBinExpr(cond, "==>", thenB) elif (d.arity() == 2): # Binary operators try: boogie_op, assoc = { "+": ("+", "left"), "-": ("-", "left"), "*": ("*", "left"), "div": ("div", "left"), "mod": ("mod", "none"), "=": ("==", "none"), "distinct": ("!=", "none"), "<": ("<", "none"), ">": (">", "none"), "<=": ("<=", "none"), ">=": (">=", "none"), "and": ("&&", "left"), "or": ("||", "left"), "=>": ("==>", "none"), "Implies": ("==>", "none"), }[d.name()] except: boogie_op, assoc = d.name(), "func" c = cast(List[z3.ExprRef], expr.children()) if assoc == "func": try: pars = list(map(z3_expr_to_boogie, c)) fun = AstFuncExpr(boogie_op, pars) except Exception as ex: error(str(ex)) return fun elif (assoc == "left"): return reduce( lambda acc, x: AstBinExpr(acc, boogie_op, z3_expr_to_boogie(x) ), c[1:], z3_expr_to_boogie(c[0])) elif (assoc == "none" or assoc == "right"): assert len(c) == 2, "NYI otherwise" lhs = z3_expr_to_boogie(c[0]) rhs = z3_expr_to_boogie(c[1]) return AstBinExpr(lhs, boogie_op, rhs) else: raise Exception("NYI") elif (d.name() == "if"): c = cast(List[z3.ExprRef], expr.children()) cond = z3_expr_to_boogie(c[0]) thenB = z3_expr_to_boogie(c[1]) elseB = z3_expr_to_boogie(c[2]) return AstBinExpr(AstBinExpr(cond, "==>", thenB), "&&", AstBinExpr(AstUnExpr("!", cond), "==>", elseB)) else: raise Exception("Can't translate z3 expression " + str(expr) + " to boogie.")