def __init__(self, *args): super(to_smt_w_expt, self).__init__(*args) # I'm making the exponent have sort Real instead of Int because # the translator turns integerp to isReal! That's because the z3 # solver (understandably) chokes on mixed integer/real polynomials. self.expt = z3.Function('EXPT', z3.RealSort(), z3.RealSort(), z3.RealSort()) # self.b_sum = z3.Function('b_sum', z3.RealSort(), z3.RealSort(), z3.RealSort(), z3.RealSort(), z3.RealSort(), z3.RealSort(), z3.RealSort()) # self.b_expt = z3.Function('b_expt', z3.RealSort(), z3.RealSort(), z3.RealSort()) self.maxPowExpand = 10
def __init__(self): # positional stuff self.x = z3.FreshConst(z3.RealSort(), prefix='x') self.y = z3.FreshConst(z3.RealSort(), prefix='y') # attribute stuff self.material = z3.FreshConst(MaterialSort, prefix='mat') self.size = z3.FreshConst(SizeSort, prefix='size') self.shape = z3.FreshConst(ShapeSort, prefix='shape') self.color = z3.FreshConst(ColorSort, prefix='color')
def convert_type(T, ctx): if T.is_tvar(): return z3.DeclareSort(T.name, ctx) if T == NatType or T == IntType: return z3.IntSort(ctx) elif T == BoolType: return z3.BoolSort(ctx) elif T == RealType: return z3.RealSort(ctx) elif T.is_fun(): domainT = convert_type(T.domain_type(), ctx) rangeT = convert_type(T.range_type(), ctx) if isinstance(domainT, tuple): raise Z3Exception("convert: unsupported type " + repr(T)) if isinstance(rangeT, tuple): return tuple([domainT] + list(rangeT)) else: return (domainT, rangeT) elif T.is_tconst() and T.name == 'set': domainT = convert_type(T.args[0], ctx) if isinstance(domainT, tuple): raise Z3Exception("convert: unsupported type " + repr(T)) return (domainT, convert_type(BoolType, ctx)) else: raise Z3Exception("convert: unsupported type " + repr(T))
def type_to_data_sort(ty): dt_name = datatype_name(ty) if dt_name == types.TY_LOC: return data.Loc elif dt_name == types.TY_INT: return z3.IntSort() elif dt_name == types.TY_BOOL: return z3.BoolSort() elif dt_name == types.TY_FLOAT: return z3.RealSort() elif dt_name == types.TY_DEST: return data.Dest elif dt_name == types.TY_CHAR: return data.Char elif dt_name == types.TY_STR: return data.String elif dt_name == types.TY_LIST: elem_sort = type_to_data_sort(ty.arg(0)) return z3sc.listInfo(elem_sort)['sort'] elif dt_name == types.TY_TUPLE: sorts = [] while dt_name != types.TY_UNIT: sorts.append(type_to_data_sort(ty.arg(0))) ty = ty.arg(1) dt_name = datatype_name(ty) return z3sc.tupleInfo(*sorts)['sort'] elif dt_name == types.TY_MSET: elem_sort = type_to_data_sort(ty.arg(0)) return z3sc.setInfo(elem_sort)['sort'] elif dt_name == types.TY_ARROW: return None else: return data.Unknown
def helper(x): if (x is None): return x elif (self.is_uninterpreted_fun(x)): match = [f[1] for f in funQ if f[0] is x] if (len(match) == 1): # found a match return match[0] else: rangeSort = x.decl().range() varName = '|$' + str(x) + '|' if (rangeSort == z3.RealSort()): newVar = z3.Real(varName) elif (rangeSort == z3.IntSort()): newVar = z3.Int(varName) elif (rangeSort == z3.BoolSort()): newVar = z3.Bool(varName) else: raise ExptRewriteFailure( 'unknown sort for range of uninterpreted function -- ' + varName + ' returns a ' + rangeSort + ' ?') funQ.append((x, newVar)) return newVar else: ch = x.children() newch = self.fun_to_var(ch, report) if (len(ch) != len(newch)): raise ExptRewriteFailure('Internal error') elif (len(newch) == x.decl().arity()): return x.decl().__call__(*newch) elif ((x.decl().arity() == 2) and (len(newch) > 2)): return reduce(x.decl(), newch) else: raise ExptRewriteFailure('Internal error')
def __init__(cls, name: str, bases: tuple[type, ...], ns: Namespace): sorts = {bool: z3.BoolSort(), int: z3.IntSort(), float: z3.RealSort()} vars = {} try: for var, ann in cls.__annotations__.items(): if isinstance(ann, str): ann = eval(ann) if ann is bool: vars[var] = z3.Bool(var) elif ann is int: vars[var] = z3.Int(var) elif ann is float: vars[var] = z3.Real(var) elif isinstance(ann, dict): in_sort, out_sort = next(iter(ann.items())) out_sort = sorts[out_sort] if isinstance(in_sort, tuple): in_sort = (sorts[x] for x in in_sort) vars[var] = z3.Function(var, *in_sort, out_sort) else: in_sort = sorts[in_sort] vars[var] = z3.Function(var, in_sort, out_sort) except: pass solver = z3.Solver() for term in ns.assertions: solver.add(traverse(term, vars)) assert solver.check(), "Unsatisfiable constraints!" cls.__model = solver.model() cls.__vars = vars
def createZ3Sort (sort_kind, z3ctx) : if sort_kind == z3.Z3_BOOL_SORT : return z3.BoolSort (ctx=z3ctx) elif sort_kind == z3.Z3_REAL_SORT : return z3.RealSort (ctx=z3ctx) elif sort_kind == z3.Z3_INT_SORT : return z3.IntSort (ctx=z3ctx) else : raise Exception ('Unsupported Sort')
def _type_to_z3(self, tp): if tp == types.BOOL: return z3.BoolSort() elif tp == types.REAL: return z3.RealSort() elif tp == types.INT: return z3.IntSort() else: raise NotImplementedError
def const_vector(prefix, length, sort=z3.RealSort()): """ Returns a list of z3 constants of given sort. e.g. const_vector("foo", 5, z3.FloatSingle()) Returns a list of 5 FP """ names = [prefix + "__" + str(i) for i in range(length)] return z3.Consts(names, sort)
def _symbol(self, name): lightdp_type = self._type_map[name] if isinstance(lightdp_type, NumType): return z3.Real(name) elif isinstance(lightdp_type, ListType): if isinstance(lightdp_type.elem_type, NumType): return z3.Array(name, z3.RealSort(), z3.RealSort()) elif isinstance(lightdp_type.elem_type, BoolType): return z3.Array(name, z3.BoolSort(), z3.RealSort()) else: raise ValueError('Unsupported list inside list.') elif isinstance(lightdp_type, FunctionType): raise NotImplementedError( 'Function type is currently not supported.') elif isinstance(lightdp_type, BoolType): return z3.Bool(name) else: assert False, 'No such type %s' % lightdp_type
def _type_to_z3(self, tp): if tp.is_bool_type(): return z3.BoolSort() elif tp.is_real_type(): return z3.RealSort() elif tp.is_int_type(): return z3.IntSort() else: assert tp.is_bv_type() , "Unsupported type '%s'" % tp return z3.BitVecSort(tp.width)
def load(self): """Find the symbols for the SMT operators""" self.load_boolean() self.load_integer() self.load_real() self.load_real_integer() self.sorts_table[self.boolean_sort] = smt.BoolSort() self.sorts_table[self.integer_sort] = smt.IntSort() self.sorts_table[self.real_sort] = smt.RealSort()
def _getSort(expr_z3): assert isinstance(expr_z3, z3.ExprRef) if expr_z3.sort() == z3.Float32(): return Sort.Float32 if expr_z3.sort() == z3.Float64(): return Sort.Float64 if expr_z3.sort() == z3.RealSort(): return Sort.Real if expr_z3.sort() == z3.IntSort(): return Sort.Int return Sort.UNKNOWN
def z3_translate (x, ctx): """ A version of z3.AstRef.translate that handles sorts and function declarations correctly""" if x.ctx == ctx: return x if isinstance (x, z3.BoolSortRef): return z3.BoolSort (ctx) if z3.is_arith_sort (x): if x.is_int (): return z3.IntSort (ctx) else : assert x.is_real () return z3.RealSort (ctx) if isinstance (x, z3.FuncDeclRef): sorts = [z3_translate (x.domain (i), ctx) for i in range (decl.arity ())] sorts.append (z3_translate (x.range (), ctx)) return z3.Function (x.name (), *sorts) return x.translate (ctx)
def __getattr__(cls, attr): try: x = cls.__model[cls.__vars[attr]] if isinstance(x, z3.FuncInterp): pass else: if x.sort() == z3.BoolSort(): return bool(x) if x.sort() == z3.IntSort(): return x.as_long() if x.sort() == z3.RealSort(): if isinstance(x, z3.RatNumRef): return float(x.as_fraction()) return float(x.approx().as_fraction()) return x except Exception as e: raise AttributeError from e
def test_expression(): expr_string = "(= a true)" expr = Expression(expr_string) assert expr.expression == expr_string with pytest.raises(InvalidExpression, message="expected InvalidExpression"): assert Expression("((= a true)") ctx = z3.Context() var = Expression.create_z3_var(ctx, int, 'var') assert var.sort() == z3.IntSort(ctx=ctx) assert str(var) == 'var' assert var.ctx == ctx assert var.ctx != z3.main_ctx assert Expression.create_z3_var(None, bool, 'var').sort() == z3.BoolSort() assert Expression.create_z3_var(None, str, 'var').sort() == z3.StringSort() assert Expression.create_z3_var(None, float, 'var').sort() == z3.RealSort() with pytest.raises(UnsupportedVariableType, message="expected UnsupportedVariableType"): assert Expression.create_z3_var(None, list, 'var')
def equal(self, x, val): cons_list = [] if isinstance(x, z3.ExprRef): if x.sort() == z3.ArraySort(z3.BitVecSort(32), z3.BitVecSort(8)): for i in range(len(val)): c_equal = z3.Concat(x[INT_SIZE * i + 3], x[INT_SIZE * i + 2], x[INT_SIZE * i + 1], x[INT_SIZE * i + 0]) \ == val[i] cons_list.append(c_equal) elif x.sort() == z3.RealSort(): c_equal = x == val cons_list.append(c_equal) else: raise err.Fatal('unhandled sort x: {}'.format(x.sort())) elif isinstance(x, list): cons_list = map((lambda x, c: x == c), x, val) else: raise err.Fatal('unhandled type: {}'.format(type(x))) # # loop sentinel # if cons_list == []: # cons_list = True return z3.And(cons_list)
def str_to_sort(sort_str: str): if sort_str == "Bool": return z3.BoolSort() if sort_str == "Int": return z3.IntSort() if sort_str == "Real": return z3.RealSort() bitvec_pattern = re.compile(r"^\(BitVec ([0-9]+)\)$") match = bitvec_pattern.match(sort_str) if match is not None: size = int(match.groups()[0]) return z3.BitVecSort(size) enum_pattern = re.compile( r"^\(Enum \( ((?:[a-zA-Z_+\-*&|!~<>=/%?\.$\^][a-zA-Z_+\-*&|!~<>=/%?\.$\^0-9]* )+)\)\)$" ) match = enum_pattern.match(sort_str) if match is not None: values = match.groups()[0].strip() return z3.EnumSort("Enum( {} )".format(values), values.split()) raise ZynthesiserException(f"str_to_sort: unrecognised sort: {sort_str}")
def get_sort(self): return z3.RealSort()
import sys import fractions Forall, And, Implies = z3.ForAll, z3.And, z3.Implies #################################################################################################### # # These are the examples discussed in section 6 of the paper. # #################################################################################################### a, b, c, d, e, i, K, m, n = z3.Reals('a b c d e i K m n') r, s, t, u, v, w, x, y, z = z3.Reals('r s t u v w x y z') eps = z3.Real('eps') f = z3.Function('f', z3.RealSort(), z3.RealSort()) h = z3.Function('h', z3.RealSort(), z3.RealSort(), z3.RealSort()) g = z3.Function('g', z3.RealSort(), z3.RealSort(), z3.RealSort(), z3.RealSort()) log = z3.Function('log', z3.RealSort(), z3.RealSort()) exp = z3.Function('exp', z3.RealSort(), z3.RealSort()) ceil = z3.Function('ceil', z3.RealSort(), z3.RealSort()) abs = z3.Function('abs', z3.RealSort(), z3.RealSort()) # #mins = [z3.Function('min2', z3.RealSort(), z3.RealSort(), z3.RealSort()), # z3.Function('min2', z3.RealSort(), z3.RealSort(), z3.RealSort(), z3.RealSort()), # z3.Function('min2', z3.RealSort(), z3.RealSort(), z3.RealSort(), z3.RealSort(), # z3.RealSort()), # z3.Function('min2', z3.RealSort(), z3.RealSort(), z3.RealSort(), z3.RealSort(), # z3.RealSort(), z3.RealSort()) # # ]
def __init__(self, environment, z3_ctx): DagWalker.__init__(self, environment) self.mgr = environment.formula_manager self._get_type = environment.stc.get_type self._back_memoization = {} self.ctx = z3_ctx # Forward conversion self.set_function(p_(self.walk_nary, z3.Z3_mk_and), op.AND) self.set_function(p_(self.walk_nary, z3.Z3_mk_or), op.OR) self.set_function(p_(self.walk_nary, z3.Z3_mk_add), op.PLUS) self.set_function(p_(self.walk_nary, z3.Z3_mk_mul), op.TIMES) self.set_function(p_(self.walk_nary, z3.Z3_mk_sub), op.MINUS) self.set_function(p_(self.walk_binary, z3.Z3_mk_implies), op.IMPLIES) self.set_function(p_(self.walk_binary, z3.Z3_mk_le), op.LE) self.set_function(p_(self.walk_binary, z3.Z3_mk_lt), op.LT) self.set_function(p_(self.walk_binary, z3.Z3_mk_eq), op.EQUALS, op.IFF) self.set_function(p_(self.walk_binary, z3.Z3_mk_power), op.POW) self.set_function(p_(self.walk_binary, z3.Z3_mk_div), op.DIV) self.set_function(p_(self.walk_binary, z3.Z3_mk_bvult), op.BV_ULT) self.set_function(p_(self.walk_binary, z3.Z3_mk_bvule), op.BV_ULE) self.set_function(p_(self.walk_binary, z3.Z3_mk_bvslt), op.BV_SLT) self.set_function(p_(self.walk_binary, z3.Z3_mk_bvsle), op.BV_SLE) self.set_function(p_(self.walk_binary, z3.Z3_mk_concat), op.BV_CONCAT) self.set_function(p_(self.walk_binary, z3.Z3_mk_bvor), op.BV_OR) self.set_function(p_(self.walk_binary, z3.Z3_mk_bvand), op.BV_AND) self.set_function(p_(self.walk_binary, z3.Z3_mk_bvxor), op.BV_XOR) self.set_function(p_(self.walk_binary, z3.Z3_mk_bvadd), op.BV_ADD) self.set_function(p_(self.walk_binary, z3.Z3_mk_bvsub), op.BV_SUB) self.set_function(p_(self.walk_binary, z3.Z3_mk_bvmul), op.BV_MUL) self.set_function(p_(self.walk_binary, z3.Z3_mk_bvudiv), op.BV_UDIV) self.set_function(p_(self.walk_binary, z3.Z3_mk_bvurem), op.BV_UREM) self.set_function(p_(self.walk_binary, z3.Z3_mk_bvshl), op.BV_LSHL) self.set_function(p_(self.walk_binary, z3.Z3_mk_bvlshr), op.BV_LSHR) self.set_function(p_(self.walk_binary, z3.Z3_mk_bvsdiv), op.BV_SDIV) self.set_function(p_(self.walk_binary, z3.Z3_mk_bvsrem), op.BV_SREM) self.set_function(p_(self.walk_binary, z3.Z3_mk_bvashr), op.BV_ASHR) self.set_function(self.walk_quantifier, *op.QUANTIFIERS) # Back Conversion self._back_fun = { z3.Z3_OP_AND: lambda args, expr: self.mgr.And(args), z3.Z3_OP_OR: lambda args, expr: self.mgr.Or(args), z3.Z3_OP_MUL: lambda args, expr: self.mgr.Times(args), z3.Z3_OP_ADD: lambda args, expr: self.mgr.Plus(args), z3.Z3_OP_DIV: lambda args, expr: self.mgr.Div(args[0], args[1]), z3.Z3_OP_IFF: lambda args, expr: self.mgr.Iff(args[0], args[1]), z3.Z3_OP_XOR: lambda args, expr: self.mgr.Xor(args[0], args[1]), z3.Z3_OP_FALSE: lambda args, expr: self.mgr.FALSE(), z3.Z3_OP_TRUE: lambda args, expr: self.mgr.TRUE(), z3.Z3_OP_GT: lambda args, expr: self.mgr.GT(args[0], args[1]), z3.Z3_OP_GE: lambda args, expr: self.mgr.GE(args[0], args[1]), z3.Z3_OP_LT: lambda args, expr: self.mgr.LT(args[0], args[1]), z3.Z3_OP_LE: lambda args, expr: self.mgr.LE(args[0], args[1]), z3.Z3_OP_SUB: lambda args, expr: self.mgr.Minus(args[0], args[1]), z3.Z3_OP_NOT: lambda args, expr: self.mgr.Not(args[0]), z3.Z3_OP_IMPLIES: lambda args, expr: self.mgr.Implies(args[0], args[1]), z3.Z3_OP_ITE: lambda args, expr: self.mgr.Ite(args[0], args[1], args[2]), z3.Z3_OP_TO_REAL: lambda args, expr: self.mgr.ToReal(args[0]), z3.Z3_OP_BAND: lambda args, expr: self.mgr.BVAnd(args[0], args[1]), z3.Z3_OP_BOR: lambda args, expr: self.mgr.BVOr(args[0], args[1]), z3.Z3_OP_BXOR: lambda args, expr: self.mgr.BVXor(args[0], args[1]), z3.Z3_OP_BNOT: lambda args, expr: self.mgr.BVNot(args[0]), z3.Z3_OP_BNEG: lambda args, expr: self.mgr.BVNeg(args[0]), z3.Z3_OP_CONCAT: lambda args, expr: self.mgr.BVConcat(args[0], args[1]), z3.Z3_OP_ULT: lambda args, expr: self.mgr.BVULT(args[0], args[1]), z3.Z3_OP_ULEQ: lambda args, expr: self.mgr.BVULE(args[0], args[1]), z3.Z3_OP_SLT: lambda args, expr: self.mgr.BVSLT(args[0], args[1]), z3.Z3_OP_SLEQ: lambda args, expr: self.mgr.BVSLE(args[0], args[1]), z3.Z3_OP_UGT: lambda args, expr: self.mgr.BVUGT(args[0], args[1]), z3.Z3_OP_UGEQ: lambda args, expr: self.mgr.BVUGE(args[0], args[1]), z3.Z3_OP_SGT: lambda args, expr: self.mgr.BVSGT(args[0], args[1]), z3.Z3_OP_SGEQ: lambda args, expr: self.mgr.BVSGE(args[0], args[1]), z3.Z3_OP_BADD: lambda args, expr: self.mgr.BVAdd(args[0], args[1]), z3.Z3_OP_BMUL: lambda args, expr: self.mgr.BVMul(args[0], args[1]), z3.Z3_OP_BUDIV: lambda args, expr: self.mgr.BVUDiv(args[0], args[1]), z3.Z3_OP_BSDIV: lambda args, expr: self.mgr.BVSDiv(args[0], args[1]), z3.Z3_OP_BUREM: lambda args, expr: self.mgr.BVURem(args[0], args[1]), z3.Z3_OP_BSREM: lambda args, expr: self.mgr.BVSRem(args[0], args[1]), z3.Z3_OP_BSHL: lambda args, expr: self.mgr.BVLShl(args[0], args[1]), z3.Z3_OP_BLSHR: lambda args, expr: self.mgr.BVLShr(args[0], args[1]), z3.Z3_OP_BASHR: lambda args, expr: self.mgr.BVAShr(args[0], args[1]), z3.Z3_OP_BSUB: lambda args, expr: self.mgr.BVSub(args[0], args[1]), z3.Z3_OP_EXT_ROTATE_LEFT: lambda args, expr: self.mgr.BVRol(args[0], args[1]. bv_unsigned_value()), z3.Z3_OP_EXT_ROTATE_RIGHT: lambda args, expr: self.mgr.BVRor(args[0], args[1]. bv_unsigned_value()), z3.Z3_OP_POWER: lambda args, expr: self.mgr.Pow(args[0], args[1]), z3.Z3_OP_SELECT: lambda args, expr: self.mgr.Select(args[0], args[1]), z3.Z3_OP_STORE: lambda args, expr: self.mgr.Store(args[0], args[1], args[2]), # Actually use both args, expr z3.Z3_OP_SIGN_EXT: lambda args, expr: self.mgr.BVSExt(args[0], z3.get_payload( expr, 0)), z3.Z3_OP_ZERO_EXT: lambda args, expr: self.mgr.BVZExt(args[0], z3.get_payload( expr, 0)), z3.Z3_OP_ROTATE_LEFT: lambda args, expr: self.mgr.BVRol(args[0], z3.get_payload(expr, 0) ), z3.Z3_OP_ROTATE_RIGHT: lambda args, expr: self.mgr.BVRor(args[0], z3.get_payload(expr, 0) ), z3.Z3_OP_EXTRACT: lambda args, expr: self.mgr.BVExtract(args[ 0], z3.get_payload(expr, 1), z3.get_payload(expr, 0)), # Complex Back Translation z3.Z3_OP_EQ: self._back_z3_eq, z3.Z3_OP_UMINUS: self._back_z3_uminus, z3.Z3_OP_CONST_ARRAY: self._back_z3_const_array, } # Unique reference to Sorts self.z3RealSort = z3.RealSort(self.ctx) self.z3BoolSort = z3.BoolSort(self.ctx) self.z3IntSort = z3.IntSort(self.ctx) self.z3ArraySorts = {} self._z3BitVecSorts = {} # Unique reference to Function Declaration self._z3_func_decl_cache = {} return
class SimpleParser: precedence = ( ('left', 'ASSIGN'), ('right', 'QM', 'COLON'), ('left', 'OR'), ('left', 'AND'), ('left', 'BITOR'), ('left', 'BITXOR'), ('left', 'BITAND'), ('left', 'EQ', 'NEQ'), ('left', 'LT', 'GT', 'GTE', 'LTE'), ('left', 'LSHIFT', 'RSHIFT'), ('left', 'PLUS', 'MINUS'), ('left', 'TIME', 'DIVIDE', 'MODULO'), ('right', 'MINUS', 'PLUS', 'SIZEOF', 'NOT', 'BITNOT', 'PLUSPLUS', 'MINUSMINUS', 'INTCASTOR', 'INTARRCASTOR', 'REALCASTOR', 'BOOLCASTOR'), # Unary minus operator ('left', 'LBRACK', 'LPAREN', 'DOT', 'ARROW', 'PLUSPLUS', 'MINUSMINUS'), ) type_switch = { 'bool': z3.Bool, 'uchar': z3.Int, 'uint': z3.Int, 'ulong': z3.Int, 'byte': z3.Int, 'sbyte': z3.Int, 'ushort': z3.Int, 'char': z3.Int, 'int': z3.Int, 'long': z3.Int, 'short': z3.Int, 'float': z3.Real, 'double': z3.Real, 'intArray': lambda x: z3.Array(x, z3.IntSort(), z3.IntSort()), 'realArray': lambda x: z3.Array(x, z3.RealSort(), z3.IntSort()), 'string': lambda x: z3.Array(x, z3.IntSort(), z3.IntSort()), # <-- No clue if correct (04/17/2020) 'stringArray': lambda x: z3.Array(x, z3.IntSort(), z3.IntSort()) } unary_ops = { '!': z3.Not, '-': lambda x: -x, '+': lambda x: +x, # TODO (?): INTARRCASTOR. Look into ArraySort(). # 'INTARRCASTOR': lambda x: x if x.sort() != z3.ArraySort(z3.IntSort(), z3.IntSort()) else z3.Array(x, z3.IntSort(), z3.IntSort()), # 'INTARRCASTOR': None, # 'INTCASTOR': lambda x: x if x.sort() != z3.RealSort() else z3.ToInt(x), 'INTCASTOR': lambda x: x if isinstance(x, int) else (int(x) if isinstance(x, float) else (x if x.sort() != z3.RealSort() else z3.ToInt(x))), 'REALCASTOR': lambda x: x if isinstance(x, float) else (float(x) if isinstance(x, int) else (x if x.sort() != z3.IntSort() else z3.ToReal(x))) # 'REALCASTOR': lambda x: x if x.sort() != z3.IntSort() else z3.ToReal(x) } binary_ops = { '>': lambda x, y: x > y, '>=': lambda x, y: x >= y, '<': lambda x, y: x < y, '<=': lambda x, y: x <= y, '==': lambda x, y: x == y, '!=': lambda x, y: x != y, '+': lambda x, y: x + y, '-': lambda x, y: x - y, '*': lambda x, y: x * y, '/': lambda x, y: x / y, '%': lambda x, y: x % y, '||': z3.Or, '&&': z3.And, } tokens = ( # 'NULL', 'INT', # instant values 'REAL', 'CHAR', 'STRINGS', 'LBRACK', # Brackets 'RBRACK', 'LPAREN', 'RPAREN', 'VARIABLE', 'DOT', # Operators 'ARROW', 'SIZEOF', 'GT', 'GTE', 'LT', 'LTE', 'EQ', 'NEQ', 'PLUS', 'PLUSPLUS', 'MINUS', 'MINUSMINUS', 'TIME', 'DIVIDE', 'LSHIFT', 'RSHIFT', 'BITAND', 'BITOR', 'BITXOR', 'BITNOT', 'OR', 'AND', 'NOT', 'MODULO', 'ASSIGN', 'QM', 'COLON', 'BOOLT', 'INTT', 'REALT', 'COMMA', 'INTCASTOR', 'INTARRCASTOR', 'REALCASTOR', 'BOOLCASTOR', 'TOOBIG' ) def __init__(self, lexer, types, hooks=None, **kwargs): # self.parser = yacc.yacc(module=self, **kwargs) self.types = defaultdict(lambda: 'int') self.types.update(types) self.function_hooks = hooks if hooks else dict() self.lexer = lexer self.errored = False self.context = dict() self.parser = yacc.yacc(module=self, **kwargs) def p_end(self, p): """end : expr | empty """ if len(p) == 2: self.result = p[1] if not self.errored else False # print('p[1], self.errored',p[1], self.errored) # print('result:', self.result, 'errored: ', self.errored) self.errored = False def p_types(self, p): """inttype : INTT realtype : REALT booltype : BOOLT """ if len(p) == 2: p[0] = p[1] def p_leftv_expr(self, p): """expr : leftv """ p[0] = p[1] def p_define_new(self, p): """leftv : inttype VARIABLE | realtype VARIABLE | booltype VARIABLE | leftv DOT VARIABLE | VARIABLE """ if p.slice[1].type == 'inttype': p[0] = z3.Int(p[2]) p.slice[0].name = p[2] name = p[2] self.types[name] = 'int' elif p.slice[1].type == 'realtype': p[0] = z3.Real(p[2]) p.slice[0].name = p[2] name = p[2] self.types[name] = 'double' elif p.slice[1].type == 'booltype': p[0] = z3.Bool(p[2]) p.slice[0].name = p[2] name = p[2] self.types[name] = 'bool' elif len(p) == 2: if p[1] in self.context: p[0] = self.context[p[1]] p.slice[0].name = p[1] name = p[1] # print('{} in context, get {}'.format(name, p[0])) else: if p[1] not in self.types: print( 'Warning: Type of {} is undefined, using default type: int'.format(p[1])) p[0] = self.type_switch[self.types[p[1]]](p[1]) p.slice[0].name = p[1] name = p[1] elif len(p) == 4: var_name = '{}.{}'.format(p[1], p[3]) if var_name not in self.types: print( 'Warning: Type of {} is undefined, using default type: int'.format(var_name)) p[0] = self.type_switch[self.types[var_name]](var_name) p.slice[0].name = var_name name = var_name if len(p) > 2: self.context[name] = p[0] def p_variable_value(self, p): """expr : STRINGS | REAL | CHAR | INT """ p[0] = p[1] def p_assign(self, p): """expr : leftv ASSIGN expr """ key = getattr(p.slice[1], 'name') self.context[key] = p[3] p[1] = p[3] p[0] = True def p_expression(self, p): """expr : expr LBRACK expr RBRACK | LPAREN expr RPAREN """ if len(p) == 4: # binary ops, paren, element access if p.slice[2].type == 'binary_op': p[0] = self.binary_ops[p[2]](p[1], p[3]) elif p.slice[1].type == 'LPAREN': p[0] = p[2] elif len(p) == 5: # array access p[0] = p[1][p[3]] def p_qsmark_choice(self, p): """expr : expr QM expr COLON expr """ p[0] = z3.If(p[1], p[3], p[5]) print(p[1], p[3], p[5]) def p_binary_ops(self, p): """expr : expr GT expr | expr GTE expr | expr LT expr | expr LTE expr | expr EQ expr | expr NEQ expr | expr PLUS expr | expr TIME expr | expr MINUS expr | expr DIVIDE expr | expr MODULO expr | expr OR expr | expr AND expr """ if len(p) == 4: # print(p[1], p[3], p[2]) p[0] = self.binary_ops[p[2]](p[1], p[3]) # print(p[0]) elif len(p) == 2: p[0] = p[1] def p_unary_ops(self, p): """expr : MINUS expr | NOT expr """ p[0] = self.unary_ops[p[1]](p[2]) def p_casting(self, p): """expr : INTCASTOR expr | INTARRCASTOR expr | REALCASTOR expr | BOOLCASTOR expr """ p[0] = self.unary_ops[p.slice[1].type](p[2]) def p_function(self, p): """expr : leftv LPAREN paramList RPAREN paramList : paramList COMMA expr | expr """ if len(p) == 5: # TODO: Add `Math.Abs()` checker here!!!! if str(p[1]) not in self.function_hooks: print( 'Function {} not found, treating as plain string'.format(p[1])) p[0] = self.function_hooks[str(p[1])](*p[3]) elif len(p) == 4: p[0] = p[1] + [p[3], ] elif len(p) == 2: p[0] = [p[1], ] # def p_casting(self, p): # """castor : LPAREN inttype RPAREN # | LPAREN realtype RPAREN # """ # if p.slice[2].type == 'inttype': # p[0] = '2int' # elif p.slice[2].type == 'realtype': # p[0] = '2real' def p_empty(self, p): """empty : """ pass def p_error(self, p): print("Syntax error, treating as string: {}".format(p)) self.errored = True raise ValueError('Syntax error') def test(self, data): # data = 'a != (int[])null&&a[2] + a[3] < 4&&-51 < a[0]&&a[0] < 51&&-51 < a[1]&&a[1] < 51&&-51 < a[2]&&a[2] < 51&&a.Length == 3&&a[1] >= a[0]&&a[0] >= a[1]&&a[2] >= a[0]&&a[0] >= a[2]&&a[0] + a[2] * a[1]&&int s = a[0] - a[2]&&s > a[2] - a[1]&&(a[2]!=1 || a[2]!=4)&&4u < (uint)(1 + a[4])&&a[5] == \'c\'&&Math.floor(a[0])&&a[2] < a[1] ? a[0] % a[1] : a[1] % a[0]&&double s0 = 0.98&&s1 = 0.6&&s1 + -(double)((int)s0) != 0.49'.split('&&') # data = 'a != (int[])null&&-51 < a[0]&&a[0] < 51&&1 < a.Length&&-51 < a[1]&&a[1] < 51&&a[1] < a[0]&&a.Length == 2&&a[0] >= a[1]'.split('&&') # data = data.replace('\\r\\n', '') # data = data.split('&&') models = [] errors = [] toAdd = False # Don't add the preamble for d in data: if not d: continue # print(d) try: # print(d) ret = self.parse(d) # print(ret) if type(ret) == z3.z3.ArithRef: ret = z3.If(ret == 0, True, False) except (ValueError, KeyError) as e: ret = None except z3.z3types.Z3Exception as e: ret = None print('Z3 error', e) # Changed 'ret == False' -> 'ret is False' to avoid triggering int 0 if ret is False or ret == None: errors.append(d) else: models.append(ret) # self.parser.clear_context() # Checks if all eles in `models` eval to True retVal = '&&'.join(sorted(errors)), z3.simplify( reduce(z3.And, models, True)) if len(models) > 0 else z3.BoolVal(True) return retVal def test2(self, data: list): results = [] for d in data: print(d) try: self.parser.parse(d, lexer=self.lexer) except (ValueError, KeyError) as e: self.result = None except z3.z3types.Z3Exception as e: self.result = None print('Z3 error', e) # except ImportError as e: # pass print(self.result) self.errored = False print('-----') results.append(self.result) return results def parse(self, text): self.parser.parse(text, lexer=self.lexer.clone()) return self.result def predParse(self, pred): models = [] errors = [] try: ret = self.parse(pred) if type(ret) == z3.z3.ArithRef: ret = z3.If(ret == 0, True, False) except (ValueError, KeyError) as e: ret = None except z3.z3types.Z3Exception as e: ret = None print('Z3 error', e) # Changed 'ret == False' -> 'ret is False' to avoid triggering int 0 if ret is False or ret == None: errors.append(pred) else: models.append(ret) # Checks if all eles in `models` eval to True retVal = '&&'.join(sorted(errors)), z3.simplify( reduce(z3.And, models, True)) if len(models) > 0 else z3.BoolVal(True) return retVal[1] def clear_context(self): self.context = dict()
def as_z3(model, sort=z3.RealSort(), prefix=""): """ Calculate z3 constraints from a torch.nn.Sequential model. Returns (constraints, z3_input, z3_output) where: - constraints is a list of z3 constraints for the entire network - z3_input is z3.RealVector representing the input to the network - z3_output is a z3.RealVector representing output of the network There are several caveats: - The model must be a torch Sequential - The first layer must be Linear - Dropout layers are ignored - Identity layers are ignored - Supported layers are: Linear, ReLU, Hardtanh, Dropout, Identity - An Exception is raised on any other type of layer sort defaults to z3.RealSort(), but floating point sorts are permitted; note that z3.FloatSingle() matches the default behavior of PyTorch more accurately (but has different performance characteristics compared to a real arithmetic theory prefix is an optional string prefix for the generated z3 variables """ assert isinstance(model, nn.Sequential) modules = OrderedDict(model.named_modules()) # named_modules() has ("" -> the entire net) as first key/val pair; remove modules.pop("") constraints = [] first_vector = None previous_vector = None for name in modules: module = modules[name] if isinstance(module, nn.Linear): W, b = module.parameters() in_vector = previous_vector if in_vector is None: in_vector = const_vector("{}_lin{}_in".format(prefix, name), module.in_features, sort) first_vector = in_vector out_vector = const_vector("{}_lin{}_out".format(prefix, name), module.out_features, sort) constraints.extend(encode_linear(W, b, in_vector, out_vector)) elif isinstance(module, nn.ReLU): in_vector = previous_vector if in_vector is None: raise ValueError("First layer must be linear") out_vector = const_vector("{}_relu{}_out".format(prefix, name), len(in_vector), sort) constraints.extend(encode_relu(in_vector, out_vector)) elif isinstance(module, nn.Hardtanh): in_vector = previous_vector if in_vector is None: raise ValueError("First layer must be linear") out_vector = const_vector("{}_tanh{}_out".format(prefix, name), len(in_vector), sort) constraints.extend( encode_hardtanh(in_vector, out_vector, module.min_val, module.max_val)) elif isinstance(module, nn.Dropout): pass elif isinstance(module, nn.Identity): pass else: raise ValueError( "Don't know how to convert module: {}".format(module)) previous_vector = out_vector # previous_vector is vector associated with last layer output return (constraints, first_vector, previous_vector)
# Test model dnn.evaluate(test_x, test_y, verbose=2) # Get weights #print([(type(l.get_weights()), l.get_weights()) for l in dnn.layers]) """ Verify properties """ # We first create a solver and constants solver = z3.Solver() z3_move = [z3.Const("move_" + str(i), z3.BoolSort()) for i in range(36)] # Move z3_res = [z3.Const("res_" + str(i), z3.BoolSort()) for i in range(27)] # Result of move z3_inp = [z3.Const("inp_" + str(i), z3.RealSort()) for i in range(36)] # Input to nn # We get the weights and biases of the network weights = [l.get_weights()[0].tolist() for l in dnn.layers] biases = [l.get_weights()[1].tolist() for l in dnn.layers] # For Q3 # We assert that z3_move is valid assert_valid_move(solver, z3_move) # z3_res is the result of doing the move solver.add(encode_move(z3_move[:27], z3_res, z3_move[27:], 1)) # z3_inp encodes input for nn assert_input_encoding(solver, z3_move, z3_inp) # The expression encoding the output of the network
def __init__(self, environment, z3_ctx): DagWalker.__init__(self, environment) self.mgr = environment.formula_manager self._get_type = environment.stc.get_type self._back_memoization = {} self.ctx = z3_ctx # Back Conversion self._back_fun = { z3.Z3_OP_AND: lambda args, expr: self.mgr.And(args), z3.Z3_OP_OR: lambda args, expr: self.mgr.Or(args), z3.Z3_OP_MUL: lambda args, expr: self.mgr.Times(args), z3.Z3_OP_ADD: lambda args, expr: self.mgr.Plus(args), z3.Z3_OP_DIV: lambda args, expr: self.mgr.Div(args[0], args[1]), z3.Z3_OP_IDIV: lambda args, expr: self.mgr.Div(args[0], args[1]), z3.Z3_OP_MOD: lambda args, expr: self.mgr.Mod(args[0], args[1]), z3.Z3_OP_IFF: lambda args, expr: self.mgr.Iff(args[0], args[1]), z3.Z3_OP_XOR: lambda args, expr: self.mgr.Xor(args[0], args[1]), z3.Z3_OP_FALSE: lambda args, expr: self.mgr.FALSE(), z3.Z3_OP_TRUE: lambda args, expr: self.mgr.TRUE(), z3.Z3_OP_GT: lambda args, expr: self.mgr.GT(args[0], args[1]), z3.Z3_OP_GE: lambda args, expr: self.mgr.GE(args[0], args[1]), z3.Z3_OP_LT: lambda args, expr: self.mgr.LT(args[0], args[1]), z3.Z3_OP_LE: lambda args, expr: self.mgr.LE(args[0], args[1]), z3.Z3_OP_SUB: lambda args, expr: self.mgr.Minus(args[0], args[1]), z3.Z3_OP_NOT: lambda args, expr: self.mgr.Not(args[0]), z3.Z3_OP_IMPLIES: lambda args, expr: self.mgr.Implies(args[0], args[1]), z3.Z3_OP_ITE: lambda args, expr: self.mgr.Ite(args[0], args[1], args[2]), z3.Z3_OP_TO_REAL: lambda args, expr: self.mgr.ToReal(args[0]), z3.Z3_OP_BAND: lambda args, expr: self.mgr.BVAnd(args[0], args[1]), z3.Z3_OP_BOR: lambda args, expr: self.mgr.BVOr(args[0], args[1]), z3.Z3_OP_BXOR: lambda args, expr: self.mgr.BVXor(args[0], args[1]), z3.Z3_OP_BNOT: lambda args, expr: self.mgr.BVNot(args[0]), z3.Z3_OP_BNEG: lambda args, expr: self.mgr.BVNeg(args[0]), z3.Z3_OP_CONCAT: lambda args, expr: self.mgr.BVConcat(args[0], args[1]), z3.Z3_OP_ULT: lambda args, expr: self.mgr.BVULT(args[0], args[1]), z3.Z3_OP_ULEQ: lambda args, expr: self.mgr.BVULE(args[0], args[1]), z3.Z3_OP_SLT: lambda args, expr: self.mgr.BVSLT(args[0], args[1]), z3.Z3_OP_SLEQ: lambda args, expr: self.mgr.BVSLE(args[0], args[1]), z3.Z3_OP_UGT: lambda args, expr: self.mgr.BVUGT(args[0], args[1]), z3.Z3_OP_UGEQ: lambda args, expr: self.mgr.BVUGE(args[0], args[1]), z3.Z3_OP_SGT: lambda args, expr: self.mgr.BVSGT(args[0], args[1]), z3.Z3_OP_SGEQ: lambda args, expr: self.mgr.BVSGE(args[0], args[1]), z3.Z3_OP_BADD: lambda args, expr: self.mgr.BVAdd(args[0], args[1]), z3.Z3_OP_BMUL: lambda args, expr: self.mgr.BVMul(args[0], args[1]), z3.Z3_OP_BUDIV: lambda args, expr: self.mgr.BVUDiv(args[0], args[1]), z3.Z3_OP_BSDIV: lambda args, expr: self.mgr.BVSDiv(args[0], args[1]), z3.Z3_OP_BUREM: lambda args, expr: self.mgr.BVURem(args[0], args[1]), z3.Z3_OP_BSREM: lambda args, expr: self.mgr.BVSRem(args[0], args[1]), z3.Z3_OP_BSHL: lambda args, expr: self.mgr.BVLShl(args[0], args[1]), z3.Z3_OP_BLSHR: lambda args, expr: self.mgr.BVLShr(args[0], args[1]), z3.Z3_OP_BASHR: lambda args, expr: self.mgr.BVAShr(args[0], args[1]), z3.Z3_OP_BSUB: lambda args, expr: self.mgr.BVSub(args[0], args[1]), z3.Z3_OP_EXT_ROTATE_LEFT: lambda args, expr: self.mgr.BVRol(args[0], args[1]. bv_unsigned_value()), z3.Z3_OP_EXT_ROTATE_RIGHT: lambda args, expr: self.mgr.BVRor(args[0], args[1]. bv_unsigned_value()), z3.Z3_OP_BV2INT: lambda args, expr: self.mgr.BVToNatural(args[0]), z3.Z3_OP_POWER: lambda args, expr: self.mgr.Pow(args[0], args[1]), z3.Z3_OP_SELECT: lambda args, expr: self.mgr.Select(args[0], args[1]), z3.Z3_OP_STORE: lambda args, expr: self.mgr.Store(args[0], args[1], args[2]), # Actually use both args, expr z3.Z3_OP_SIGN_EXT: lambda args, expr: self.mgr.BVSExt(args[0], z3.get_payload( expr, 0)), z3.Z3_OP_ZERO_EXT: lambda args, expr: self.mgr.BVZExt(args[0], z3.get_payload( expr, 0)), z3.Z3_OP_ROTATE_LEFT: lambda args, expr: self.mgr.BVRol(args[0], z3.get_payload(expr, 0) ), z3.Z3_OP_ROTATE_RIGHT: lambda args, expr: self.mgr.BVRor(args[0], z3.get_payload(expr, 0) ), z3.Z3_OP_EXTRACT: lambda args, expr: self.mgr.BVExtract(args[ 0], z3.get_payload(expr, 1), z3.get_payload(expr, 0)), # Complex Back Translation z3.Z3_OP_EQ: self._back_z3_eq, z3.Z3_OP_UMINUS: self._back_z3_uminus, z3.Z3_OP_CONST_ARRAY: self._back_z3_const_array, } # Unique reference to Sorts self.z3RealSort = z3.RealSort(self.ctx) self.z3BoolSort = z3.BoolSort(self.ctx) self.z3IntSort = z3.IntSort(self.ctx) self._z3ArraySorts = {} self._z3BitVecSorts = {} self._z3Sorts = {} # Unique reference to Function Declaration self._z3_func_decl_cache = {} return
self._to_tensor = _to_tensor def to_tensor(self, s): return self._to_tensor(s) class BadShapeError(Exception): pass def require(b): if not b: raise BadShapeError() _relu = z3.Function("relu", z3.RealSort(), z3.RealSort()) def matmul_0(A, B): if isinstance(A, MagicConst): assert isinstance(B, Tensor) A = A.to_tensor((None, B.shape[0])) if isinstance(B, MagicConst): assert isinstance(A, Tensor) B = B.to_tensor((A.shape[1], None)) sa = A.shape sb = B.shape if len(sa) == len(sb) == 2: require(sa[1] == sb[0]) C = Tensor([[ sum(A[i, k] * B[k, j] for k in range(sa[1])) for j in range(sb[1])
def _handleNum(state,left,right,op): # Match our object types leftZ3Object,rightZ3Object = z3Helpers.z3_matchLeftAndRight(left,right,op) # Figure out what the op is and add constraint if type(op) == ast.Add: if type(left) is BitVec: # Check for over and underflows state.solver.add(z3Helpers.bvadd_safe(leftZ3Object,rightZ3Object)) # Keep this out of the Z3 solver! if left.isStatic() and right.isStatic(): ret = left.getValue() + right.getValue() else: ret = leftZ3Object + rightZ3Object elif type(op) == ast.Sub: if type(left) is BitVec: state.solver.add(z3Helpers.bvsub_safe(leftZ3Object,rightZ3Object)) # Keep this out of the Z3 solver! if left.isStatic() and right.isStatic(): ret = left.getValue() - right.getValue() else: ret = leftZ3Object - rightZ3Object elif type(op) == ast.Mult: if type(left) is BitVec: state.solver.add(z3Helpers.bvmul_safe(leftZ3Object,rightZ3Object)) # Keep this out of the Z3 solver! if left.isStatic() and right.isStatic(): ret = left.getValue() * right.getValue() else: ret = leftZ3Object * rightZ3Object elif type(op) == ast.Div: if type(left) is BitVec: state.solver.add(z3Helpers.bvdiv_safe(leftZ3Object,rightZ3Object)) # Keep this out of the Z3 solver! if left.isStatic() and right.isStatic(): ret = left.getValue() / right.getValue() else: ret = leftZ3Object / rightZ3Object elif type(op) == ast.Mod: # Z3 doesn't have native support for Real type modular arithmetic if z3.is_real(leftZ3Object): constraint = [] if z3.is_real(rightZ3Object): mod = z3.Function('mod', z3.RealSort(),z3.RealSort(), z3.RealSort()) quot = z3.Function('quot', z3.RealSort(),z3.RealSort(), z3.RealSort()) constraint += [z3Helpers.isInt(rightZ3Object)] else: mod = z3.Function('mod', z3.RealSort(),z3.IntSort(), z3.RealSort()) quot = z3.Function('quot', z3.RealSort(),z3.IntSort(), z3.RealSort()) constraint.append(0 <= mod(leftZ3Object,rightZ3Object)) constraint.append(mod(leftZ3Object,rightZ3Object) < rightZ3Object) constraint.append(rightZ3Object * quot(leftZ3Object,rightZ3Object) + mod(leftZ3Object,rightZ3Object) == leftZ3Object) constraint.append(z3Helpers.isInt(quot(leftZ3Object,rightZ3Object))) constraint.append(z3Helpers.isInt(leftZ3Object)) constraint.append(leftZ3Object >= 0) state.addConstraint(z3.And(constraint)) """ state.addConstraint(0 <= mod(leftZ3Object,rightZ3Object)) state.addConstraint(mod(leftZ3Object,rightZ3Object) < rightZ3Object) state.addConstraint(rightZ3Object * quot(leftZ3Object,rightZ3Object) + mod(leftZ3Object,rightZ3Object) == leftZ3Object) state.addConstraint(z3Helpers.isInt(quot(leftZ3Object,rightZ3Object))) state.addConstraint(z3Helpers.isInt(leftZ3Object)) state.addConstraint(leftZ3Object >= 0) """ ret = mod(leftZ3Object,rightZ3Object) else: # Keep this out of the Z3 solver! if left.isStatic() and right.isStatic(): ret = left.getValue() % right.getValue() else: ret = leftZ3Object % rightZ3Object elif type(op) == ast.BitXor: # Keep this out of the Z3 solver! if left.isStatic() and right.isStatic(): ret = left.getValue() ^ right.getValue() else: ret = leftZ3Object ^ rightZ3Object elif type(op) == ast.BitOr: # Keep this out of the Z3 solver! if left.isStatic() and right.isStatic(): ret = left.getValue() | right.getValue() else: ret = leftZ3Object | rightZ3Object elif type(op) == ast.BitAnd: # Keep this out of the Z3 solver! if left.isStatic() and right.isStatic(): ret = left.getValue() & right.getValue() else: ret = leftZ3Object & rightZ3Object elif type(op) == ast.LShift: # Keep this out of the Z3 solver! if left.isStatic() and right.isStatic(): ret = left.getValue() << right.getValue() else: ret = leftZ3Object << rightZ3Object elif type(op) == ast.RShift: # Keep this out of the Z3 solver! if left.isStatic() and right.isStatic(): ret = left.getValue() >> right.getValue() else: ret = leftZ3Object >> rightZ3Object # TODO: This one will fail if we use BitVecs.. Maybe think about check/convert? elif type(op) == ast.Pow: # Keep this out of the Z3 solver! if left.isStatic() and right.isStatic(): ret = left.getValue() ** right.getValue() # Z3 has some problems with forms of x ** 0.5, let's try to change it for Z3... elif type(rightZ3Object) is z3.RatNumRef and rightZ3Object.numerator().as_long() == 1 and rightZ3Object.denominator().as_long() > 1: tmp = state.getVar("tempRootVar",ctx=1,varType=Real) tmp.increment() # Rewrite as x ** 2 == y form state.addConstraint(tmp.getZ3Object() ** float(rightZ3Object.denominator().as_long()) == leftZ3Object) # Because we're dealing with square, let's make sure it's positive state.addConstraint(tmp.getZ3Object() >= 0) ret = tmp.getZ3Object() else: ret = leftZ3Object ** rightZ3Object #ret = leftZ3Object ** rightZ3Object else: err = "BinOP: Don't know how to handle op type {0} at line {1} col {2}".format(type(op),op.lineno,op.col_offset) logger.error(err) raise Exception(err) # TODO: Clean up code below... # Duplicate the object and create a pyObjectManager object left_t,left_args = pyState.duplicateSort(leftZ3Object) right_t,right_args = pyState.duplicateSort(rightZ3Object) if left_t in [Int,Real,BitVec] and right_t in [Int, Real, BitVec]: # Not handling this case well right now if left_t is Real or right_t is Real: args = left_args if left_t is Real else right_args # We want variables, not constants args.pop("value",None) if args is not None else None retVar = state.getVar(varName='BinOpTemp',varType=Real,kwargs = args) else: left_args.pop("value",None) if left_args is not None else None retVar = state.getVar(varName='BinOpTemp',varType=left_t,kwargs = left_args) retVar.increment() # Now that we have a clean variable to return, add constraints and return it logger.debug("Adding constraint {0} == {1}".format(retVar.getZ3Object(),ret)) # If it turns out we're dealing with constants, just set it directly. if type(ret) in [int,float]: retVar.setTo(ret) else: state.addConstraint(retVar.getZ3Object() == ret) #print([x for x in state.solver.assertions()]) return [retVar.copy()] else: err = "BinOP: Don't know how to handle variable type {0} at line {1} col {2}".format(t,op.lineno,op.col_offset) logger.error(err) raise Exception(err)