def op_to_z3(e, slv=None): "translate op expression into its z3 form" e.simplify() l, r = e.l, e.r op = e.op if op.symbol == ">>": op = z3.LShR elif op.symbol == "//": op = operator.rshift elif op.symbol == ">>>": op = z3.RotateRight elif op.symbol == "<<<": op = z3.RotateLeft elif op.symbol == "**": l = l.zeroextend(2 * l.size) r = r.zeroextend(2 * r.size) op = (l * r).op z3l = l.to_smtlib(slv) z3r = r.to_smtlib(slv) if z3.is_bool(z3l): z3l = _bool2bv1(z3l) if z3.is_bool(z3r): z3r = _bool2bv1(z3r) if z3l.size() != z3r.size(): greatest = max(z3l.size(), z3r.size()) z3l = z3.ZeroExt(greatest - z3l.size(), z3l) z3r = z3.ZeroExt(greatest - z3r.size(), z3r) res = op(z3l, z3r) if z3.is_bool(res): res = _bool2bv1(res) return res
def op_to_z3(e, slv=None): e.simplify() l, r = e.l, e.r op = e.op if op.symbol == '>>': op = z3.LShR elif op.symbol == '//': op = operator.rshift elif op.symbol == '>>>': op = z3.RotateRight elif op.symbol == '<<<': op = z3.RotateLeft elif op.symbol == '**': l = l.zeroextend(2 * l.size) r = r.zeroextend(2 * r.size) op = (l * r).op z3l = l.to_smtlib(slv) z3r = r.to_smtlib(slv) if z3.is_bool(z3l): z3l = _bool2bv1(z3l) if z3.is_bool(z3r): z3r = _bool2bv1(z3r) if z3l.size() != z3r.size(): greatest = max(z3l.size(), z3r.size()) z3l = z3.ZeroExt(greatest - z3l.size(), z3l) z3r = z3.ZeroExt(greatest - z3r.size(), z3r) res = op(z3l, z3r) if z3.is_bool(res): res = _bool2bv1(res) return res
def visitCompare(self, node): children = node.getChildren() if len(children) == 3: left = node.getChildren()[0] op = str(node.getChildren()[1]) if op == "==" or op == "!=": right = node.getChildren()[2] left_z3 = self.visit(left) right_z3 = self.visit(right) if z3.is_string(left_z3) and z3.is_string( right_z3) or z3.is_bool(left_z3) and z3.is_bool( right_z3): if op == "==": result = z3.simplify( z3.Not(z3.Distinct(left_z3, right_z3))) return result elif op == "!=": # sys.stderr.write("%s != %s\n" % (left_z3, right_z3)) result = z3.simplify(z3.Distinct(left_z3, right_z3)) return result # elif z3.is_string(left_z3) and z3.is_bool(right_z3): # if op == "==": # pass # elif op == "!=": # pass # elif z3.is_bool(left_z3) and z3.is_string(right_z3): # if op == "==": # pass # elif op == "!=": # pass # this expression is not supported, so make a predicate variable for it predicate = str(node) return z3.Bool("PREDICATE_%s" % (predicate))
def xor(self, ctx, return_type, a, atype, b, btype): assert atype == return_type assert atype == btype if z3.is_bool(a) or z3.is_bool(b): a = util.as_bool(a) b = util.as_bool(b) assert return_type.size() == 1 return z3.Xor(a, b) else: return a ^ b
def vec_to_z3(e, slv=None): "translate vec expression into z3 Or form" # flatten vec: e.simplify() # translate vec list to z3: beqs = [] for x in e.l: zx = x.to_smtlib() beqs.append(zx) if len(beqs) == 0: return exp(e.size) if slv is None: # if no solver is provided, it needs to be # a list of boolean equations if all([z3.is_bool(x) for x in beqs]): if len(beqs) == 1: return beqs[0] return z3.Or(*beqs) else: return top_to_z3(top(e.size)) else: # if the solver is provided (default) # then a new local variable is added which # should equal one of the z3 expression. var = newvar("_var", e, slv) slv.solver.add(z3.Or([var == x for x in beqs])) return var
def visitNot(self, node): # sys.stderr.write("not %s\n" % (str(node))) operand = self.visit(node.expr) if z3.is_bool(operand): return z3.Not(operand) else: return z3.BoolVal(True)
def checkFormat(self, formula): """Check if the formula for a given predicate is of the supported format Supported formats include: 1. A Bool Ref such as A_x 2. An Arithmetic Ref such as a <= x or x <= a where a is number and x is Real/IntRef 3. An Arithmetic Ref such as a >= x or x >= a where a is number and x is Real/IntRef """ nbGroundAtoms = self.countGroundAtoms(formula) if not z3.is_bool(formula): raise Exception( "Predicate formula is not Bool: {}".format(formula)) #print("Bool formula: {},{},{}, nbGroundAtoms: {}".format(formula, type(formula), formula.children(),nbGroundAtoms)) if len(formula.children()) == 0: #print("Boring old Variables such as A_x") return False if len(formula.children()) == 2: if nbGroundAtoms == 1: if z3.is_le(formula) or z3.is_ge(formula): #print("Two Children, and <= or => and nbGroundAtoms == 1") return True else: raise Exception("Not supported expression type f: {}, type: {}, nbGroundAtoms: {}".format(\ formula,type(formula), nbGroundAtoms)) else: raise AbstractionCondition( "Not supported number of groundVariables: {}, nbGroundAtoms: {}" .format(formula, nbGroundAtoms)) else: raise Exception("Predicate formula has an unsupported number of children: {}, type: {}, nbChidren: {}".format(\ formula,type(formula),formula.children()))
def getNearestFeasible(self, coord): # get the variables corresponding to the axis names for i in self.axis_names: locals()[i] = Globals.z3variables[i] # Convert into parameters rpp = self.search.coordToPerfParams(coord) for i, name in enumerate(self.axis_names): if not self.z3IsNumeric(i): rpp[name] = Globals.z3types[name].index(rpp[name]) # create a new scope self.optim.push() # Get a possible point that minimizes the 1-norm distance to this random point # forget the booleans l = [] for name in self.axis_names: if not z3.is_bool(locals()[name]): l.append(self.z3abs(locals()[name] - rpp[name])) definition = z3.Sum(l) self.optim.minimize(definition) # For some reason, it does not work with a list comprehension. # self.optim.minimize( z3.Sum( [ self.z3abs( locals()[name] - rpp[name] )for name in self.axis_names if not z3.is_bool( locals()[name] ) ] ) ) if z3.unsat == self.optim.check(): return None model = self.optim.model() # restore the state (exit the scope) self.optim.pop() return self.z3ToPoint(model)
def is_atom(a): """ Check if the input formula is an atom. In FOL, atoms are defined as atom := t1 = t2 | R(t1,..,tn) where ti are terms. In addition, this function also allows Bool variable to be terms (in propositional logic, a bool variable is considered term) Example: >>> from z3 import * >>> is_atom(3) False >>> is_atom(Bool('b')) True >>> is_atom(Int('x')) False >>> is_atom(TRUE) False >>> is_atom(FALSE) False >>> is_atom(Int('x') + Int('y') > 3) True >>> is_atom(Bool('x') == TRUE) True >>> is_atom(Int('x') == 3) True >>> is_atom(IntVal(3)) False >>> is_atom(Not(TRUE)) False >>> is_atom(Or(TRUE,FALSE)) False >>> is_atom(Or(Bool('b'),Bool('y'))) False """ if not is_bool(a): return False if is_expr_val(a): return False if is_expr_var(a): return True return is_app(a) and a.decl().kind() not in CONNECTIVE_OPS and\ all(is_term(c) for c in a.children())
def conjuncts(exp): assert z3.is_bool(exp) if z3.is_and(exp): for i in range(exp.num_args()): yield exp.arg(i) else: yield exp
def is_term(a): """ Check if the input formula is a term. In FOL, terms are defined as term := const | var | f(t1,...,tn) where ti are terms. Examples: >>> from z3 import * >>> assert is_term(TRUE) >>> assert is_term(Bool('x')) >>> assert not is_term(And(Bool('x'),Bool('y'))) >>> assert not is_term(And(Bool('x'),Not(Bool('y')))) >>> assert is_term(IntVal(3)) >>> assert is_term(Int('x')) >>> assert is_term(Int('x') + Int('y')) >>> assert not is_term(Int('x') + Int('y') > 3) >>> assert not is_term(And(Int('x')==0,Int('y')==3)) >>> assert not is_term(Int('x')==0) >>> assert not is_term(3) >>> assert not is_term(Bool('x') == (Int('y')==Int('z'))) """ if not is_expr(a): return False if is_const(a): #covers both const value and var return True else: #covers f(t1,..,tn) return not is_bool(a) and all(is_term(c) for c in a.children())
def simplify_z3_constraints(constraints): """ Simplifies the constraint list, only by expressions that can be determined to evaluate to a a specific boolean value :param constraints: :return: """ simp_const = constraints # Currently not running the individual simplification algorithm on every simplification call for # simp_const = simplify_constraints_individually(constraints) simp_const = list( filter(lambda c: not is_bool(c) or not is_true(c), simp_const)) falses = list(filter(lambda c: is_bool(c) and is_false(c), simp_const)) if len(falses) > 0: return [deepcopy(falses[0])] return simp_const
def elim_bool_ite(exp): if z3.is_quantifier(exp): (qvars, matrix) = strip_qblock(exp) matrix = elim_bool_ite(matrix) if exp.is_forall(): e = z3.ForAll(qvars, matrix) else: e = z3.Exists(qvars, matrix) return e if not z3.is_bool(exp): return exp if z3.is_true(exp) or z3.is_false(exp): return exp assert z3.is_app(exp) decl = exp.decl() args = map(elim_bool_ite, exp.children()) # need to worry about And and Or because they can take >2 args and # decl(*args) doesn't seem to work with the py interface if z3.is_and(exp): return z3.And(*args) elif z3.is_or(exp): return z3.Or(*args) elif is_ite(exp): impl1 = z3.Implies(args[0], args[1]) impl2 = z3.Implies(z3.Not(args[0]), args[2]) return z3.And(impl1, impl2) else: return decl(*args)
def sext(self, ctx, return_type, a, atype, **kwargs): outsize = itypes.integer_size(return_type) insize = itypes.integer_size(atype) assert outsize > insize if z3.is_bool(a): return util.If(a, z3.BitVecVal(1, outsize), z3.BitVecVal(0, outsize)) return z3.SignExt(outsize - insize, a)
def cast_z3_bool(x, slv=None): "translate boolean expression into its z3 bool form" b = x.to_smtlib(slv) if not z3.is_bool(b): assert b.size() == 1 b = b == z3.BitVecVal(1, 1) return b
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 uop_to_z3(e,solver=None): e.simplify() r = e.r op = e.op z3r = r.to_smtlib(solver) if z3.is_bool(z3r): z3r = _bool2bv1(z3r) return op(z3r)
def get(self, v): assert self._model is not None assert type(v) is Z3BoolRef v = self._model.eval(v.val, model_completion=True) assert z3.is_bool(v) t = z3.is_true(v) f = z3.is_false(v) assert t or f, f'bad {v}' return int(t)
def uop_to_z3(e, slv=None): "translate uop expression into its z3 form" e.simplify() r = e.r op = e.op z3r = r.to_smtlib(slv) if z3.is_bool(z3r): z3r = _bool2bv1(z3r) return op(z3r)
def cast_z3_bv(x, slv=None): """ translate expression x to its z3 form, if x.size==1 the returned formula is (If x ? 1 : 0). """ b = x.to_smtlib(slv) if z3.is_bool(b): b = z3.If(b, z3.BitVecVal(1, 1), z3.BitVecVal(0, 1)) return b
def simplify_constraints(constraints): """ Simplifies the list of constraints, as well as the constraints individually. :param constraints: in Annotary representation, z3 constraints and metadata. :return: the simplified constraints. """ for const in constraints: const.simplify() # Todo simplification of the sum of constraints simp_const = list( filter( lambda c: not is_bool(c.constraint) or not is_true(c.constraint), constraints)) falses = list( filter(lambda c: is_bool(c.constraint) and is_false(c.constraint), simp_const)) if len(falses) > 0: return [deepcopy(falses[0])] return simp_const
def _enc_bool_expr(self, c): if z3.is_bool(c): return c elif isinstance(c, bool): return c elif isinstance(c, VerifierBoolExpr): return self._enc_verifier_bool_expr(c) else: raise RuntimeError("unsupported expression of type " + type(c).__qualname__)
def op_to_z3(e, solver=None): e.simplify() l, r = e.l, e.r op = e.op if op.symbol == '>>': op = z3.LShR elif op.symbol == '//': op = operator.rshift elif op.symbol == '>>>': op = z3.RotateRight elif op.symbol == '<<<': op = z3.RotateLeft z3l = l.to_smtlib(solver) z3r = r.to_smtlib(solver) if z3.is_bool(z3l): z3l = _bool2bv1(z3l) if z3.is_bool(z3r): z3r = _bool2bv1(z3r) if z3l.size() != z3r.size(): greatest = max(z3l.size(), z3r.size()) z3l = z3.ZeroExt(greatest - z3l.size(), z3l) z3r = z3.ZeroExt(greatest - z3r.size(), z3r) return op(z3l, z3r)
def visitOr(self, node): # sys.stderr.write("or %s\n" % (str(node))) children = node.getChildren() # sys.stderr.write("%s\n" % str(children)) operands = [self.visit(child) for child in children] # sys.stderr.write("%s\n" % str(operands)) # for child in operands: # sys.stderr.write("%s\n" % str(child)) # sys.stderr.write("%s\n" % str(z3.is_bool(child))) operands = [(child if z3.is_bool(child) else z3.BoolVal(False)) for child in operands] return z3.Or(operands)
def resolveOpsOnParent(op_obj, types): # this is parent or nothing if len(op_obj['old_ops']) < 1: return None val = createZ3ExpressionFromConstraint({'identifier': op_obj['old_identifier'], 'ops': op_obj['old_ops']}, types) if val is None or (val.decl().kind() == z3.Z3_OP_UNINTERPRETED and not z3.is_array(val)): # this is the case when the parent elems have no ops on them return None if z3.is_bool(val) and len(val.children()) and val.children()[0].decl().kind() == z3.Z3_OP_UNINTERPRETED: return None val = transformNonBooleanLazyEvaluations(val) return val
def unveil(solver, item, phase=0): if type(item) == list: for i in item: indent = lambda n: ''.join(['\t'] * (n)) if type(i) != list: i = ["else", i] if is_bool(i[1]): print(indent(phase), i[0], '->', evaluate(solver, i[1])) else: print(indent(phase), i[0], '->') unveil(solver, i[1], phase + 1) else: if is_bool(item): return item elif is_as_array(item): return unveil(solver, as_list(solver, item), phase) elif item.decl().name() == 'if': return unveil(solver, [list(i) for i in zip(ITE, item.children())], phase) elif is_ast(item): return unveil(solver, evaluate(solver, item), phase) else: return "#unspecified"
def test_feature(pred, test_case, cache): try: pred_smt = cache[test_case.type_model] except KeyError: smt = Encoder(test_case.type_model) pre = smt(pred) assert not (pre.defined or pre.nonpoison or pre.aux or pre.qvars) pred_smt = (pre.safe, pre.value) cache[test_case.type_model] = pred_smt if pred_smt[0]: safe = z3.simplify(z3.substitute(mk_and(pred_smt[0]), *test_case.values)) assert z3.is_bool(safe) if z3.is_false(safe): return UNSAFE e = z3.simplify(z3.substitute(pred_smt[1], *test_case.values)) assert z3.is_bool(e) if z3.is_true(e): return ACCEPT return REJECT
def quantifier_free(self, formula): term = self.convert(formula) if not z3.is_bool(term): return term if term in self.cache_qf: return self.cache_qf[term] simplifier = z3.Tactic('simplify') eliminator = z3.Tactic('qe') res = term res = simplifier(res, elim_and=True, pull_cheap_ite=True, ite_extra_rules=True ).as_expr() res = eliminator(res).as_expr() # print(term, " -> ", res) self.cache_qf[term] = res return res
def createZ3ForBool(var): if z3.is_int(var): return var != z3.IntVal(0) elif z3.is_string(var): return var != z3.StringVal('') elif z3.is_array(var): return z3.BoolVal(True) elif z3.is_bool(var): return var elif var is None: # this should be the case when we have a JSON value that is just inside a conditional etc return None elif z3.is_seq(var): # not string but still something ref-like we only found cases where this was string comparisons using <, >, etc. return var else: raise Exception('unhandled type in uninterpreted if')
def __init__(self, input_module: InputModule, forall_mode: ForallMode, smt_program): self.variables = input_module.variables.values() self.forall_mode = forall_mode self.input_module = input_module self.smt_program = smt_program self._function_types: Dict[int, Any] = dict() self._z3_var_list = [var.variable for var in self.variables] self._z3_sorts = [ z3_variable.sort() for z3_variable in self._z3_var_list ] self._z3_local_var_list = [ Bool("var_" + str(var)) if is_bool(var) else INPUTPROGRAM.INT_CTOR("var_" + str(var)) for var in self._z3_var_list ] self._z3_local_subst = [(old_var, self._z3_local_var_list[i]) for i, old_var in enumerate(self._z3_var_list)] self.macro_substs = self._get_macro_substs(input_module)
def conjuncts (exp) : assert z3.is_bool (exp) if z3.is_and (exp) : for i in range (exp.num_args ()) : yield exp.arg (i) else : yield exp
def get_conjuncts (exp) : assert z3.is_bool (exp) if z3.is_and (exp) : return exp.children () else : return [exp]