def model_value_to_python(value: z3.ExprRef) -> object: if z3.is_string_value(value): return value.as_string() elif z3.is_real(value): return float(value.as_fraction()) else: return ast.literal_eval(repr(value))
def function_symbols(s: z3.ExprRef) -> Set[z3.FuncDeclRef]: fsymbols = set() if is_function_symbol(s): fsymbols.add(s.decl()) for child in s.children(): fsymbols.update(function_symbols(child)) return fsymbols
def _get_expr_variables(expression: z3.ExprRef) -> List[z3.ExprRef]: """ Gets the variables that make up the current expression :param expression: :return: """ result = [] if not expression.children() and not isinstance(expression, z3.BitVecNumRef): result.append(expression) for child in expression.children(): c_children = _get_expr_variables(child) result.extend(c_children) return result
def recreate_variable(key: str, variable: z3.ExprRef) -> z3.ExprRef: """ Recreates the variable but renames it with a key that is used to make it distinct. :param key: :param variable: """ return z3.Const(f"{key}_{variable}", variable.sort())
def recreate_with_noise(expr: z3.ExprRef, variables: Dict[z3.ArithRef, float]) -> z3.ExprRef: recreate = Expression.recreate_with_noise logger.debug("recreating expression with noise: %s", expr) d = expr.decl() if str(d) != '==': children = [recreate(c, variables) for c in expr.children()] # TODO find a better solution if str(d) == 'And': return z3.And(*children, expr.ctx) elif str(d) == 'Or': return z3.Or(*children, expr.ctx) return d(*children) lhs, rhs = expr.children()[0], expr.children()[1] if not isinstance(lhs, z3.ArithRef) or \ not isinstance(rhs, z3.ArithRef): return d(lhs, rhs) def absolute(x): return z3.If(x > 0, x, -x, ctx=expr.ctx) expr = absolute(lhs - rhs) <= Expression.get_noise(expr, variables) logger.debug('recreated expression with noise: %s', expr) return expr
def is_function_symbol(s: z3.ExprRef) -> bool: if not z3.is_app(s): return False if z3.is_const(s): return False func = s.decl() if func.range() == z3.BoolSort(): # predicate symbol return False if func.name().lower() == 'if': return False return True
def eval(self, expression: z3.ExprRef, model_completion: bool = False) -> Union[None, z3.ExprRef]: """ Evaluate the expression using this model :param expression: The expression to evaluate :param model_completion: Use the default value if the model has no interpretation of the given expression :return: The evaluated expression """ for internal_model in self.raw: is_last_model = self.raw.index(internal_model) == len(self.raw) - 1 is_relevant_model = expression.decl() in list( internal_model.decls()) if is_relevant_model or is_last_model: return internal_model.eval(expression, model_completion) return None
def get_noise(expr: z3.ExprRef, variables: Dict[z3.ArithRef, float]) -> float: logger.debug("getting noise for expression: %s", expr) if len(expr.children()) == 0: if isinstance(expr, z3.ArithRef) and str(expr) in variables: return variables[str(expr)] else: return 0.0 noises = [Expression.get_noise(c, variables) for c in expr.children()] if str(expr.decl()) == '*': f = 1.0 for i in noises: f *= i return f elif str(expr.decl()) == '**': if isinstance(expr.children()[1], z3.IntNumRef): return math.pow(noises[0], int(expr.children()[1])) else: # TODO: FIX return noises[0] else: return math.fsum(noises)
def _eval(expr: z3.ExprRef) -> Element: assert sorts[expr.sort().name()] is sort, expr ans = z3model.eval(expr, model_completion=True) assert (sort, ans) in elements, (sort, expr, ans) return elements[sort, ans]
def __init__(self, expr: ExprRef): self._id = expr.get_id() self._expr = expr Clause.clause_cache[self._id] = self
def __new__(cls, expr: ExprRef): if expr.get_id() in Clause.clause_cache: return Clause.clause_cache[expr.get_id()] else: return super(Clause, cls).__new__(cls)
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.")
def fast_ne(a: ExprRef, b: ExprRef): """Equivalent of z3 __ne__.""" z3args = (Ast * 2)() z3args[0], z3args[1] = a.as_ast(), b.as_ast() return BoolRef(Z3_mk_distinct(CTX.ref(), 2, z3args), CTX)
def fast_eq(a: ExprRef, b: ExprRef): """Equivalent of z3 __eq__.""" return BoolRef(Z3_mk_eq(CTX.ref(), a.as_ast(), b.as_ast()), CTX)