def simplify_constraints(spl_name, constraints, simplify_mode): """ This function simplifies the SMT constraint in input following the simplify_mode :param spl_name: the name of the spl from which the constraint has been extracted :param constraints: the extracted constraint (actually, a list of constraints) :param simplify_mode: mode of simplification. "default" means that :return: """ if simplify_mode == "default": formula = z3.simplify(smt_and(constraints)) if z3.is_false(formula): logging.warning("Dependencies in package " + spl_name + " make it uninstallable.") return [formula] elif simplify_mode == "individual": formulas = [] for c in constraints: formula = z3.simplify(c) if z3.is_false(formula): logging.warning("Dependencies in package " + spl_name + " make it uninstallable.") return [smt_false] formulas.append(formula) return formulas
def jumpi_(self, global_state): state = global_state.mstate disassembly = global_state.environment.code states = [] op0, condition = state.stack.pop(), state.stack.pop() try: jump_addr = util.get_concrete_int(op0) # FIXME: to broad exception handler except: logging.debug("Skipping JUMPI to invalid destination.") return [global_state] index = util.get_instruction_index(disassembly.instruction_list, jump_addr) if not index: logging.debug("Invalid jump destination: " + str(jump_addr)) return [global_state] instr = disassembly.instruction_list[index] # True case condi = simplify(condition) if type( condition) == BoolRef else condition != 0 if instr['opcode'] == "JUMPDEST": if (type(condi) == bool and condi) or (type(condi) == BoolRef and not is_false(condi)): new_state = copy(global_state) new_state.mstate.pc = index new_state.mstate.depth += 1 new_state.mstate.constraints.append(condi if type(condi) == bool else simplify(condi)) states.append(new_state) else: logging.debug("True, Pruned unreachable states. at %s" % (state.pc)) # False case negated = simplify( Not(condition)) if type(condition) == BoolRef else condition == 0 if (type(negated) == bool and negated) or (type(negated) == BoolRef and not is_false(negated)): new_state = copy(global_state) new_state.mstate.depth += 1 new_state.mstate.constraints.append(negated if type(negated) == bool else simplify(negated)) states.append(new_state) else: logging.debug("False, Pruned unreachable states. at %s" % (state.pc)) return states
def is_false(a: Bool) -> bool: """Returns whether the provided bool can be simplified to false. :param a: :return: """ return z3.is_false(a.raw)
def is_false(self) -> bool: """Specifies whether this variable can be simplified to false. :return: """ self.simplify() return z3.is_false(self.raw)
def false(value): """Syntactic sugar for `z3.is_false(simplify(value))`. i.e., return True iff `value` statically simplifies to False. """ return z3.is_false(simplify(value))
def marco(Pk): print 'Starting to think about...', Pk sys.stdout.flush() solver = z3.Solver() P = [] for line_number in conjecture_line_numbers: P.append(z3.Bool('P_' + str(line_number))) out = [] while True: if solver.check() == z3.sat: m = solver.model() #seed = [conjecture_line_numbers[i] for i, Pi in enumerate(P) if m.eval(Pi, model_completion=True)] seed = [conjecture_line_numbers[i] for i, Pi in enumerate(P) if not z3.is_false(m[Pi])] #print 'Got seed:', seed if query(Pk, set(seed), set()): seed = shrink(Pk, seed) #print 'Shrank to:', seed, 'which works' out.append(seed) block = z3.Or([z3.Not(P[i]) for i, line_number in enumerate(conjecture_line_numbers) if line_number in seed]) #print 'Blocking:', block solver.add(block) else: seed = grow(Pk, seed) #print 'Grew to:', seed, 'which does not work' block = z3.Or([P[i] for i, line_number in enumerate(conjecture_line_numbers) if line_number not in seed]) #print 'Blocking:', block solver.add(block) else: #print out break print 'Fully analyzed...', Pk sys.stdout.flush() return out
def _set(self, k, v): """An internal API used for actually building relations. Not meant to be used from outside the module. """ # Typechecking if not isinstance(k, tuple): raise TypeError(k) if not isinstance(v, z3.BoolRef) and not isinstance(v, bool): raise TypeError(v) # Make sure the arity of `k` matches the arity of other keys in self if self.arity is None: self.arity = len(k) elif self.arity != len(k): raise TypeError(f"`Relation` has arity {self.arity}, " f"but adding a key of arity {len(k)}") # No use adding `v` if it is known to be false. if v is True: # Convert Python type to z3 type super().__setitem__(k, z3.BoolVal(True)) elif v is not False: # v = simplify(v) # slower, but generates simpler expressions if not z3.is_false(v): super().__setitem__(k, v)
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 query(self, *query, **kwargs): if 'max_solutions' in kwargs: max_solutions = kwargs['max_solutions'] else: max_solutions = -1 body_atms = [x.as_muz() for x in query] self._solver.query(*body_atms) ans = self._solver.get_answer() query_vars = [x.get_variables() for x in query] query_vars = reduce(lambda x, y: x + [v for v in y if v not in x], query_vars, []) if is_false(ans): # no solution return [] elif not (is_and(ans) or is_or(ans)): # single solution, value of a single variable val = int(ans.children()[1].as_long()) #varb = query.get_variables()[0] varb = query_vars[0] return [{varb: c_id_to_const(val, varb.get_type())}] elif is_or(ans) and not (is_and(ans.children()[0]) or is_or(ans.children()[0])): # multiple solutions of single variable vals = [int(x.children()[1].as_long()) for x in ans.children()] #varbs = query.get_variables()[0] varbs = query_vars[0] varbs = [varbs] * len(vals) return [{ k: c_id_to_const(v, varbs[0].get_type()) } for k, v in zip(varbs, vals)] elif is_and(ans): # single solution of more than 1 variable ans = [int(x.children()[1].as_long()) for x in ans.children()] ans = [ans] elif is_or(ans): # multiple solutions of more than 1 variable ans = ans.children() ans = [[int(y.children()[1].as_long()) for y in x.children()] for x in ans] else: raise Exception(f"don't know how to parse {ans}") tmp_args = [v for x in query for v in x.get_variables()] args = reduce(lambda x, y: x + [y] if y not in x else x, tmp_args, []) answer = [ dict([(v, c_id_to_const(c, v.get_type().name)) for v, c in zip(args, x)]) for x in ans ] if max_solutions > 0: return answer[:max_solutions] else: return answer
def num_clauses(formula): if z3.is_and(formula): return len(formula.children()) elif formula == True or z3.is_true(formula) or \ formula == False or z3.is_false(formula): return 0 else: return 1
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 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 try_bool(b): b = try_simplify(b) # HACK: z3 python interface has bug/weird behavior where (x == y) is # always False for unknown x and y, so use is_true and is_false instead if z3.is_true(b): return True if z3.is_false(b): return False return None
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 l_get(self, ast): val = self.solver.model().eval(ast.ast) if val == None: return esbmc.solve.tvt(esbmc.solve.tvt_enum.unknown) elif z3.is_true(val): return esbmc.solve.tvt(esbmc.solve.tvt_enum.true) elif z3.is_false(val): return esbmc.solve.tvt(esbmc.solve.tvt_enum.false) else: raise Exception("Unknown model eval value from l_get")
def ite(x, y, z): if x is True: return y if x is False: return z x = z3.simplify(x) if z3.is_true(x): return y if z3.is_false(x): return z return z3.If(x, y, z)
def _extract_var(self, z3model, var): val = z3model[var] if val is None: return None if z3.is_rational_value(val): n = val.numerator_as_long() d = val.denominator_as_long() return float(n / d) if z3.is_true(val): return True if z3.is_false(val): return False raise RuntimeError("var not supported")
def generalize_cube(z3_formula, model, all_vars): assigned_vars = set([_v for _v in all_vars if model[_v] is not None]) my_model = MyModel({v: model[v] for v in assigned_vars}) go_over_vars = list(assigned_vars) for _var in go_over_vars: model_tag = MyModel(dict(my_model.assignment)) model_tag[_var] = BoolVal(is_false(my_model[_var])) z3_assigned = simplify( substitute(z3_formula, *[(_v, model_tag[_v]) for _v in assigned_vars])) if is_false(z3_assigned): continue s = SatSolverSelector.SatSolverCtor() res = s.add(z3_assigned) if res and s.check(): assigned_vars -= {_var} my_model.unassign(_var) return my_model
def branch(self, ctx, cond, cond_type, iftrue, iffalse): self.assertion(ctx, not cond.is_poison(), "path condition is poison") assert itypes.integer_size(cond_type) == 1 scond = util.simplify(cond) can_be_true = not z3.is_false(scond) can_be_false = not z3.is_true(scond) if ctx['depth'] >= ctx['prune_depth']: can_be_true = not z3.is_false( scond) and not util.path_condition_implies(ctx, z3.Not(scond)) can_be_false = not can_be_true or ( not z3.is_true(scond) and not util.path_condition_implies(ctx, scond)) true_branch_exc = None false_branch_exc = None trueval = None falseval = None if can_be_true: try: ctx.push(path_condition=scond) trueval = iftrue() except ex.UnreachableException, e: stacktrace = getattr(e, 'stacktrace', None) self.assertion(ctx, util.path_condition_implies(ctx, z3.BoolVal(False), print_model=True), "Panic " + repr(e), stacktrace=stacktrace) can_be_true = False except BaseException, e: true_branch_exc = e
def clause_model_simp(m, c): """ Simplify a clause by dropping literals while maintaining its truth in a model. """ res = [] for l in c: if not is_ground_lit(l): res.append(l) continue # if isinstance(l.atom,ivy_logic.And): # print "clause_model_simp: {}".format(c) v = m.eval(literal_to_z3(l)) if z3.is_true(v): return [l] if not z3.is_false(v): res.append(l) return res
def clause_model_simp(m, c): """ Simplify a clause by dropping literals while maintaining its truth in a model. """ res = [] for l in c: if not is_ground_lit(l): res.append(l) continue if isinstance(l.atom, ivy_logic.And): print "clause_model_simp: {}".format(c) v = m.eval(literal_to_z3(l)) if z3.is_true(v): return [l] if not z3.is_false(v): res.append(l) return res
def convert_patterns(pattern_repository, id_repository, patterns): spls = set() constraints = [] for pattern in patterns: new_spls = pattern_repository.get_with_default(pattern).matched_spls spls.update(new_spls) #print(core_data.pattern_to_atom(pattern) + " => " + str([spl.name for spl in new_spls])) constraint = z3.simplify( smt_or([get_spl_smt(id_repository, spl.name) for spl in new_spls])) if z3.is_false(constraint): logging.warning("atom \"" + (core_data.pattern_to_atom(pattern)) + "\" is satisfied by no ebuild") return set(), [] constraints.append(constraint) return spls, smt_list_to_strings(constraints)
def try_bool(b): # Just ignore attributes here if isinstance(b, Value): b = b.value if z3.is_bv(b) or isinstance(b, int): b = (b != 0) b = try_simplify(b) if isinstance(b, bool): return (b, None) # HACK: z3 python interface has bug/weird behavior where (x == y) is # always False for unknown x and y, so use is_true and is_false instead if z3.is_true(b): return (True, None) if z3.is_false(b): return (False, None) return (None, b)
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 build_rule(self, rule, env): vars = {} head = self.compile_atom(vars, rule.head, env) body = [ self.compile_atom(vars, atom, env) for atom in rule.body if atom is not None] if any(z3.is_false(at) for at in body): return body = [at for at in body if not z3.is_true(at)] body_conj = body[0] if len(body) == 1 else z3.And(*body) term1 = head if body == [] else z3.Implies(body_conj, head) term2 = ( term1 if vars == {} else z3.ForAll(list(vars.values()), term1)) self.context.rule(term2)
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 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 tfFlags(self, pred, flags_len): """ return two lists, one for true and one false flags """ false_idxs = list() true_idxs = list () if debug_cex: print "Get list of failing flags from : ", pred ch = pred.children() i=0 for val in ch[0:flags_len]: if z3.is_false(val): false_idxs.append(i) i+=1 elif z3.is_true(val): true_idxs.append(i) i+=1 else: i+=1 return true_idxs, false_idxs
def tfFlags(self, pred, flags_len): """ return two lists, one for true and one false flags """ false_idxs = list() true_idxs = list() if verbose: print "Get list of failing flags from : ", pred ch = pred.children() i = 0 for val in ch[0:flags_len]: if z3.is_false(val): false_idxs.append(i) i += 1 elif z3.is_true(val): true_idxs.append(i) i += 1 else: i += 1 return true_idxs, false_idxs
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 constant_from_z3(sort, c): if z3.is_true(c): return ivy_logic.And() if z3.is_false(c): return ivy_logic.Or() return ivy_logic.Constant(ivy_logic.Symbol(repr(c), sort))
print c4.result stop = time.time() print stop - start print "Running simple compression test" ResetZ3() start = time.time() out = TrivialWanOptimizer() result = out.check.CheckIsolationProperty(out.a, out.b) assert z3.sat == result.result, \ "Nothing is blocking the way, packets should get from A -> B" assert is_true(result.model.eval(out.ctx.send(out.w.z3Node, out.b.z3Node, result.violating_packet))), \ "Violating packet was never sent" assert is_true(result.model.eval(out.ctx.recv(out.w.z3Node, out.b.z3Node, result.violating_packet))), \ "Violating packet was never received" assert is_false(result.model.eval(out.ctx.recv(out.a.z3Node, out.w.z3Node, result.violating_packet))), \ "The packet should not get to b unmodified" assert is_false(result.model.eval(out.ctx.send(out.a.z3Node, out.w.z3Node, result.violating_packet))), \ "The packet should not get to b unmodified" stop = time.time() print stop - start print "Running simple compression-decompression test" ResetZ3() start = time.time() out = TrivialWanOptimizerDeOptimizer() result = out.check.CheckIsolatedIf(lambda p: z3.Not(out.ctx.send(out.w0.z3Node, out.w1.z3Node, p)), out.a, out.b) assert z3.sat == result.result, \ "Nothing is blocking the way, packets should get from A -> B" assert is_true(result.model.eval(out.ctx.send(out.w1.z3Node, out.b.z3Node, result.violating_packet))), \ "Violating packet was never sent"
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_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 maxSAT(self, solver, var_weight_pairs): # A classic argmax loop, holding on to our best cost and the # cooresponding solution. min_cost = None best_solution = None # The variables that keep us from trying a solution we've # already tried, or a subset of that solution. conflictVars = [] # Get our first solver result, the solution if we don't need # to accomplish any of our weighted vars. next_solver_result = solver.check() while(next_solver_result == z3.sat): # The cost of this solution. cost = 0 # Get the solvers model. model = solver.model() # For each soft variable that was set to false in the # current solution, incur a cost. for var, weight in var_weight_pairs: if self.debugPrint: print "adding cost of " + str(var) + ": " + str(weight) + " * "\ + str(not z3.is_false(model[var])) if z3.is_false(model[var]): cost += weight # Extract a solution object. We would just save the model, # but it turns out z3 models are invalidated when you next # run the solver. solution = self.modelToSolution(model) # If our new cost is the best cost we've seen so far, # update our best. if min_cost == None or cost < min_cost: min_cost = cost best_solution = solution if self.debugPrint: print "found solution: " self.printSolution(solution) print "with cost " + str(cost) # Create a fresh variable that blocks any future solution # that does not include at least one of the tasks that # were excluded from this solution. That statement may # take a bit of unpacking. Basically the idea is, if we # have some solution, then there exists no better solution # which only does a subset of the tasks which this # solution does. So, we block all solutions which don't # include at least one other task that this solution # doesn't have. I got the algorithm from this paper: # http://research.microsoft.com/en-US/peopleb/nbjorner/scss2014.pdf # The paper actually shows that another algorithm is more # efficient, but this one is simpler, so we use this one # until we hit a performance bottleneck with it. fresh_var_name = "block" interp = [v for v,w in var_weight_pairs \ if z3.is_false(model[v])] for v in interp: fresh_var_name += "_" + str(v) fresh_var = z3.Bool(fresh_var_name) # Tie our blocking constraint to a new "conflict # variable," and add that variable to our set of # assumptions. block_constraint = Or(Not(fresh_var), *interp) if self.debugPrint: print "adding block constraint " + str(block_constraint) solver.add(block_constraint) conflictVars.append(fresh_var) # Get a new result for the next time around the while loop. next_solver_result = solver.check(*conflictVars) if self.debugPrint: print "best solution was " self.printSolution(best_solution) print "with cost " + str(min_cost) return best_solution
def evaluate(self, t): s = self.solver.model().eval(t.z3Node()) assert z3.is_true(s) or z3.is_false(s) return z3.is_true(s)