def fp_get_preds (fp): seen = set () res = list () for rule in fp.get_rules (): pred = rule # A rule is of the form # FORALL? (BODY IMPLIES)? PRED if z3.is_quantifier (pred): pred = pred.body () if is_implies (pred): pred = pred.arg (1) decl = pred.decl () assert is_uninterpreted (decl) if z3key (decl) in seen: continue seen.add (z3key (decl)) # if the rule contains a universal quantifier, replace # variables by properly named constants if z3.is_quantifier (rule): sub = [ z3.Const (bound_var_name (rule, i), bound_var_sort (rule, i)) for i in range (0, rule.num_vars ()) ] pred = substitute_vars (pred, *sub) res.append (pred) return res
def get_preds(fp): seen = set() res = list() for rule in fp.get_rules(): pred = rule # A rule is of the form # FORALL? (BODY IMPLIES)? PRED if z3.is_quantifier(pred): pred = pred.body() if is_implies(pred): pred = pred.arg(1) decl = pred.decl() assert is_uninterpreted(decl) if z3key(decl) in seen: continue seen.add(z3key(decl)) # if the rule contains a universal quantifier, replace # variables by properly named constants if z3.is_quantifier(rule): sub = [ z3.Const(bound_var_name(rule, i), bound_var_sort(rule, i)) for i in range(0, rule.num_vars()) ] pred = substitute_vars(pred, *sub) res.append(pred) return res
def num_univ_clauses(formula): if z3.is_and(formula): fs = formula.children() n = 0 for f in fs: if z3.is_quantifier(f) and f.is_forall(): n += 1 return n elif z3.is_quantifier(formula) and formula.is_forall(): return 1 else: return 0
def _update(self): if not self.has_formula(): return rels = list() find_all_uninterp_consts(self._formula, rels) self._rels = frozenset(rels) body = self._formula if z3.is_quantifier(body): body, self._bound_constants = ground_quantifier(body) if z3.is_implies(body): self._head = body.arg(1) body = body.arg(0) if z3.is_and(body): body = body.children() else: body = [body] else: self._head = body body = [] if len(body) > 0: self._body = body for i in range(len(body)): f = body[i] if z3.is_app(f) and f.decl() in self._rels: self._uninterp_sz += 1 else: break assert (self._head is not None)
def write_clause_smt2(forall, pref, writer): if not (z3.is_quantifier(forall) and forall.is_forall()): raise Exception("Illegal clause for write_clause_smt2: {}".format( forall.decl())) writer.write("{}(forall (".format(pref)) for idx in range(0, forall.num_vars()): writer.write(" ({} {})".format(forall.var_name(idx), forall.var_sort(idx).sexpr())) writer.write(" ) \n".format(pref)) implication = forall.body() subst = list( reversed([ z3.Const(forall.var_name(n), forall.var_sort(n)) for n in range(0, forall.num_vars()) ])) implication = z3.substitute_vars(implication, *subst) write_implication_smt2(implication, pref + ' ', None, writer) writer.write("\n{})".format(pref))
def stripQuantifierBlock (expr) : """ strips the outermost quantifier block in a given expression and returns the pair (<list of consts replacing free vars>, <body with consts substituted for de-bruijn variables>) Example: assume expr.is_forall () vars, body = strip_quantifier (expr) qexpr = z3.ForAll (vars, body) assert qexpr.eq (expr) """ if not z3.is_quantifier (expr) : return ([], expr) global qb_counter z3ctx = expr.ctx consts = list () # outside-in order of variables; z3 numbers variables inside-out but # substitutes outside-in for i in reversed (range (expr.num_vars ())) : #v_name = expr.var_name (i) + "!" + str(qb_counter) v_name = expr.var_name (i) qb_counter+=1 v_sort = expr.var_sort (i) consts.append (z3.Const (v_name, z3_translate (v_sort, z3ctx))) matrix = z3.substitute_vars (expr.body (), *consts) return (consts, matrix)
def merge_queries_new_pred(clauses, queries, decls): if len(queries) > 1: false1 = z3.Bool("CHC_COMP_FALSE") decls.add(false1.decl()) for query in queries: assert (z3.is_quantifier(query) and query.is_forall()) qvars = [ z3.Const(query.var_name(n), query.var_sort(n)) for n in range(0, query.num_vars()) ] body = query.body() assert (body.decl().kind() == z3.Z3_OP_IMPLIES) kids = body.children() assert (kids[1] == z3.BoolVal(False)) newBody = z3.Implies(kids[0], false1) newClause = z3.ForAll(qvars, newBody) clauses.append(newClause) queries.clear() queries.append( z3.ForAll(z3.Bool("CHC_COMP_UNUSED"), z3.Implies(z3.And(false1), z3.BoolVal(False))))
def partial_leaf_substitution(expr, substitution_dict): """Replaces consts/vars in `expr` according to `substitution_dict`. If a const/var is not in `substitution_dict.keys()`, it remains unchanged. >>> a, b, c = sl.list.locs("a b c") >>> subst = {b : c} >>> partial_leaf_substitution(sl.sepcon(sl.list("a"), sl.list("b")), subst) sl.sepcon(sl.list(a), sl.list(c)) >>> i, j = Ints("i j") >>> subst = {sl.alpha : i, sl.beta : j} >>> partial_leaf_substitution(sl.alpha < sl.beta, subst) i < j """ if z3.is_const(expr) or z3.is_var(expr): return substitution_dict.get(expr, expr) elif z3.is_app(expr): new_args = [ partial_leaf_substitution(child, substitution_dict) for child in expr.children() ] return replace_args(expr, new_args) else: assert (z3.is_quantifier(expr)) new_arg = partial_leaf_substitution(expr.body(), substitution_dict) return replace_args(expr, new_arg)
def infix_args_core(self, a, d, xs, r): sz = len(r) k = a.decl().kind() p = self.get_precedence(k) first = True for child in a.children(): child_pp = self.pp_expr(child, d + 1, xs) child_k = None if z3.is_app(child): child_k = child.decl().kind() if k == child_k and (self.is_assoc(k) or (first and self.is_left_assoc(k))): self.infix_args_core(child, d, xs, r) sz = len(r) if sz > self.max_args: return elif self.is_infix_unary(child_k): child_p = self.get_precedence(child_k) if p > child_p or (_is_add(k) and _is_sub(child_k)) or (_is_sub(k) and first and _is_add(child_k)): r.append(child_pp) else: r.append(self.add_paren(child_pp)) sz = sz + 1 elif z3.is_quantifier(child): r.append(self.add_paren(child_pp)) else: r.append(child_pp) sz = sz + 1 if sz > self.max_args: r.append(self.pp_ellipses()) return first = False
def run(self, query_index): self.fp.set(engine='spacer') if self.args.stat: self.fp.set('print_statistics', True) if self.args.z3_verbose: z3.set_option(verbose=1) if self.args.utvpi: self.fp.set('pdr.utvpi', False) self.fp.set('use_heavy_mev', True) self.fp.set('pdr.flexible_trace', True) self.fp.set('reset_obligation_queue', False) self.fp.set('spacer.elim_aux', False) if not self.args.pp: self.log.info("No pre-processing") self.fp.set('xform.slice', False) self.fp.set('xform.inline_linear', False) self.fp.set('xform.inline_eager', False) queries = self.fp.parse_file(self.smt2_file) self.preds = get_preds(self.fp) out = "" query = queries[query_index] if z3.is_quantifier(query): decl = query.body().decl() self.function_name = str(decl).split("@")[0] out = self.checkFeas(query) return out else: function_name = str(query.decl()).split("@")[0] out = out_message % (function_name, "FEASIBLE", "", "", "", "", "") out = bcolors.OKGREEN + out + bcolors.ENDC return out
def translate(self, expr, bound_variables=[]): if z3.is_const(expr): return self.mk_const(expr) # raise Z3_Unexpected_Expression('Unrecognized constant') elif z3.is_var(expr): # a de Bruijn indexed bound variable bv_length = len(bound_variables) return bound_variables[bv_length - z3.get_var_index(expr) - 1] elif z3.is_app(expr): args = [self.translate(expr.arg(i), bound_variables) for i in range(expr.num_args())] return self.mk_fun(expr.decl())(*args) # else: # raise Z3_Unexpected_Expression(expr) elif z3.is_quantifier(expr): num_vars = expr.num_vars() # vars = [language.const_dict[expr.var_name(i)] # for i in range(num_vars)] vars = [const(expr.var_name(i), self.mk_sort(expr.var_sort(i))) \ for i in range(num_vars)] new_bound_variables = bound_variables + vars body = self.translate(expr.body(), new_bound_variables) if expr.is_forall(): return forall(vars, body) else: return exists(vars, body) elif z3.is_func_decl(expr): return self.mk_fun(expr) else: print expr.kind raise Z3_Unexpected_Expression(expr)
def infix_args_core(self, a, d, xs, r): sz = len(r) k = a.decl().kind() p = self.get_precedence(k) first = True for child in a.children(): child_pp = self.pp_expr(child, d+1, xs) child_k = None if z3.is_app(child): child_k = child.decl().kind() if k == child_k and (self.is_assoc(k) or (first and self.is_left_assoc(k))): self.infix_args_core(child, d, xs, r) sz = len(r) if sz > self.max_args: return elif self.is_infix_unary(child_k): child_p = self.get_precedence(child_k) if p > child_p or (_is_add(k) and _is_sub(child_k)) or (_is_sub(k) and first and _is_add(child_k)): r.append(child_pp) else: r.append(self.add_paren(child_pp)) sz = sz + 1 elif z3.is_quantifier(child): r.append(self.add_paren(child_pp)) else: r.append(child_pp) sz = sz + 1 if sz > self.max_args: r.append(self.pp_ellipses()) return first = False
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 stripQuantifierBlock (expr) : """ strips the outermost quantifier block in a given expression and returns the pair (<list of consts replacing free vars>, <body with consts substituted for de-bruijn variables>) Example: assume expr.is_forall () vars, body = strip_quantifier (expr) qexpr = z3.ForAll (vars, body) assert qexpr.eq (expr) """ if not z3.is_quantifier (expr) : return ([], expr) global qb_counter z3ctx = expr.ctx consts = list () # outside-in order of variables; z3 numbers variables inside-out but # substitutes outside-in for i in reversed (range (expr.num_vars ())) : v_name = expr.var_name (i) + "!" + str(qb_counter) qb_counter+=1 v_sort = expr.var_sort (i) consts.append (z3.Const (v_name, z3_translate (v_sort, z3ctx))) matrix = z3.substitute_vars (expr.body (), *consts) return (consts, matrix)
def run(self, query_index): self.fp.set (engine='spacer') if self.args.stat: self.fp.set('print_statistics',True) if self.args.z3_verbose: z3.set_option (verbose=1) if self.args.utvpi: self.fp.set('pdr.utvpi', False) self.fp.set('use_heavy_mev',True) self.fp.set('pdr.flexible_trace',True) self.fp.set('reset_obligation_queue',False) self.fp.set('spacer.elim_aux',False) if not self.args.pp: self.log.info("No pre-processing") self.fp.set ('xform.slice', False) self.fp.set ('xform.inline_linear',False) self.fp.set ('xform.inline_eager',False) queries = self.fp.parse_file (self.smt2_file) self.preds = get_preds(self.fp) out = "" query = queries[query_index] if z3.is_quantifier(query): decl = query.body().decl() self.function_name = str(decl).split("@")[0] out = self.checkFeas(query) return out else: function_name = str(query.decl()).split("@")[0] out = out_message % (function_name, "FEASIBLE", "", "", "", "", "") out = bcolors.OKGREEN + out + bcolors.ENDC return out
def fix_quantifier(clause): if z3.is_quantifier(clause): assert (clause.is_forall() ), 'expected universal quantifier, found {}'.format( clause.sexpr()) return clause else: return z3.ForAll(z3.Const("CHC-COMP::unused", z3.IntSort()), clause)
def __init__(self,rule): """ unpacks a rule of the kind (I) z3.Forall(variables, head) or (II) z3.Forall(variables, z3.Implies(z3.And([tail,children]),head)) """ self.rule = rule # original rule self.variables = None # quantified variables self.predicate = None # predicate declaration: name(pc,...) self.tail = None # body predicate self.children = None # other body elements self.head = None # head predicate # the rule is a z3 quantifier if z3.is_quantifier(rule): # quantified variables self.variables = list() for i in range(rule.num_vars()): sort = self.var_sort(rule,i).kind() if sort == z3.Z3_INT_SORT: self.variables.append(z3.Int(self.var_name(rule,i))) elif sort == z3.Z3_BOOL_SORT: self.variables.append(z3.Bool(self.var_name(rule,i))) else: raise ValueError('unsopported sort:',sort) # unpacks the rule body head = rule.body() if z3.is_app_of(head,z3.Z3_OP_IMPLIES): # the rule is of kind (II) body = head.arg(0) # z3.Implies body if z3.is_app_of(body,z3.Z3_OP_AND): # unpacks the other body elements # (assumes single uninterpreted predicate in body) self.children = list() for c in body.children(): child = z3.substitute_vars(c,*self.variables) # unpacks the body predicate if z3.is_app_of(child,z3.Z3_OP_UNINTERPRETED) \ and self.tail is None: self.tail = child # body predicate else: self.children.append(child) else: raise ValueError('unsupported implication body:',body) head = head.arg(1) # z3.Implies head if z3.is_app_of(head,z3.Z3_OP_UNINTERPRETED): # the rule is of kind (I) name = head.decl().name() # predicate name parameters = list() # predicate parameters arguments = list() # predicate arguments for i in range(head.num_args()): arg = head.arg(i) parameters.append(arg.sort()) arguments.append(z3.substitute_vars(arg,*self.variables)) parameters.append(z3.BoolSort()) self.predicate = z3.Function(name,*parameters) self.head = self.predicate(*arguments) # head predicate else: raise ValueError('unsupported rule body:',body)
def qe_lite(exp): if not z3.is_quantifier(exp): return exp e = exp t = z3.Tactic('qe-light', ctx=exp.ctx) # invoke qe_lite once per quantified variable, for better result for i in range(exp.num_vars()): e = t(e).as_expr() if not z3.is_quantifier(e): return e if z3.is_quantifier(e): # invoke qe_lite for each variable, separately (qvars, matrix) = strip_qblock(e) for v in qvars: if exp.is_forall(): matrix = t(z3.ForAll([v], matrix)).as_expr() else: matrix = t(z3.Exists([v], matrix)).as_expr() e = matrix return e
def __init__(self, rule): """ unpacks a rule of the kind (I) z3.Forall(variables, head) or (II) z3.Forall(variables, z3.Implies(z3.And([tail,children]),head)) """ self.rule = rule # original rule self.variables = None # quantified variables self.predicate = None # predicate declaration: name(pc,...) self.tail = None # body predicate self.children = None # other body elements self.head = None # head predicate # the rule is a z3 quantifier if z3.is_quantifier(rule): # quantified variables self.variables = list() for i in range(rule.num_vars()): sort = self.var_sort(rule, i).kind() if sort == z3.Z3_INT_SORT: self.variables.append(z3.Int(self.var_name(rule, i))) elif sort == z3.Z3_BOOL_SORT: self.variables.append(z3.Bool(self.var_name(rule, i))) else: raise ValueError("unsopported sort:", sort) # unpacks the rule body head = rule.body() if z3.is_app_of(head, z3.Z3_OP_IMPLIES): # the rule is of kind (II) body = head.arg(0) # z3.Implies body if z3.is_app_of(body, z3.Z3_OP_AND): # unpacks the other body elements # (assumes single uninterpreted predicate in body) self.children = list() for c in body.children(): child = z3.substitute_vars(c, *self.variables) # unpacks the body predicate if z3.is_app_of(child, z3.Z3_OP_UNINTERPRETED) and self.tail is None: self.tail = child # body predicate else: self.children.append(child) else: raise ValueError("unsupported implication body:", body) head = head.arg(1) # z3.Implies head if z3.is_app_of(head, z3.Z3_OP_UNINTERPRETED): # the rule is of kind (I) name = head.decl().name() # predicate name parameters = list() # predicate parameters arguments = list() # predicate arguments for i in range(head.num_args()): arg = head.arg(i) parameters.append(arg.sort()) arguments.append(z3.substitute_vars(arg, *self.variables)) parameters.append(z3.BoolSort()) self.predicate = z3.Function(name, *parameters) self.head = self.predicate(*arguments) # head predicate else: raise ValueError("unsupported rule body:", body)
def strip_qblock(expr): if not z3.is_quantifier(expr): return ([], expr) consts = list() for i in reversed(range(expr.num_vars())): v_name = expr.var_name(i) v_sort = expr.var_sort(i) consts.append(z3.Const(v_name, v_sort)) matrix = z3.substitute_vars(expr.body(), *consts) return (consts, matrix)
def cofactor_term_ite(exp): if z3.is_quantifier(exp): (qvars, matrix) = strip_qblock(exp) matrix = cofactor_term_ite(matrix) if exp.is_forall(): return z3.ForAll(qvars, matrix) else: return z3.Exists(qvars, matrix) t = z3.Tactic('cofactor-term-ite', ctx=exp.ctx) return t(exp).as_expr()
def get_implication_kids(expr, quant_okay): if z3.is_quantifier(expr) and expr.is_forall(): if quant_okay: return get_implication_kids(expr.body(), False) else: raise Exc('Illegal chc: nested foralls') elif expr.decl().kind() == z3.Z3_OP_IMPLIES: return expr.children() else: raise Exc('Illegal chc: ' 'expected forall or implication, got {}'.format( expr.sexpr()))
def check_chc(expr): if not z3.is_quantifier(expr) or not expr.is_forall(): raise Exception("illegal chc: expected forall, got {}".format( expr.sexpr())) implies = expr.body() decl = implies.decl() if decl is None or decl.kind() != z3.Z3_OP_IMPLIES: raise Exception("illegal chc: expected implication, got {}".format( implies.sexpr())) check_chc_tail(implies.children()[0]) is_query = check_chc_head(implies.children()[1]) return is_query
def fix_quantifier(expr): if z3.is_quantifier(expr): assert (expr.is_forall() ), 'expected universal quantifier, found {}'.format( expr.sexpr()) qvars = [ z3.Const(expr.var_name(n), expr.var_sort(n)) for n in range(0, expr.num_vars()) ] return qvars, fix_implies(expr.body()) else: return [], fix_implies(expr)
def pp_expr(self, a, d, xs): self.visited = self.visited + 1 if d > self.max_depth or self.visited > self.max_visited: return self.pp_ellipses() if z3.is_app(a): return self.pp_app(a, d, xs) elif z3.is_quantifier(a): return self.pp_quantifier(a, d, xs) elif z3.is_var(a): return self.pp_var(a, d, xs) else: return to_format(self.pp_unknown())
def formula2dimacs(z3_formula, output_filename, append_to_file=False, verbose=False): seen_literals = {} number_of_clauses = 0 clauses = [] if append_to_file: if not os.path.isfile(output_filename): print('{} does not exist! Exiting...') exit(1) cnf_clauses = [] # Z3 expressions can be applications, quantifiers and bounded/free variables # FIXME for expr in z3_formula: if z3.is_quantifier(expr): print('Expecting {} to be OR, got quantifier in CNF!'.format(expr)) return #print(expr) if z3.is_or(expr): or_clause = ''.join( [translate2(lit, seen_literals) for lit in expr.children()]) cnf_clauses.append(or_clause) else: lit = translate2(expr, seen_literals) cnf_clauses.append(lit) if not append_to_file: with open(output_filename, 'w') as f: f.write('p cnf {} {}\n'.format(len(seen_literals), len(cnf_clauses))) for clause in cnf_clauses: f.write('{}0\n'.format(clause)) else: (num_vars, num_clauses) = parse_dimacs_header(output_filename) with open(output_filename, 'r') as from_file: tmp_path = output_filename + ".tmp" with open(tmp_path, 'w') as tmp_file: tmp_file.write('p cnf {} {}\n'.format( num_vars + len(seen_literals), num_clauses + len(cnf_clauses))) line = from_file.readline() for line in from_file.readlines(): tmp_file.write(line) for clause in cnf_clauses: tmp_file.write('{}0\n'.format(clause)) os.rename(tmp_path, output_filename)
def visitor(e, seen): if e in seen: return seen[e] = True yield e if is_app(e): for ch in e.children(): for e in visitor(ch, seen): yield e return if is_quantifier(e): for e in visitor(e.body(), seen): yield e return
def under_approx_qe(exp, side_cons=None): assert z3.is_quantifier(exp) assert not exp.is_forall() (qvars, matrix) = strip_qblock(exp) s = z3.Solver(ctx=exp.ctx) s.add(matrix) if side_cons is not None: for c in side_cons: s.add(c) res = s.check() if res == z3.unsat: return mk_false(ctx=exp.ctx) m = s.model() sub = mk_subst_from_model(m, qvars, model_completion=True) return z3.substitute(matrix, *sub)
def bv_length(e): li = [-1] if e in seen: return -1 if (z3.is_bv(e) and z3.is_const(e) and e.decl().kind() == z3.Z3_OP_UNINTERPRETED): li.append(e.size()) seen.add(e) if z3.is_app(e): for ch in e.children(): li.append(bv_length(ch)) elif z3.is_quantifier(e): for ch in e.body().children(): li.append(bv_length(ch)) return max(li)
def pp_unary(self, a, d, xs): k = a.decl().kind() p = self.get_precedence(k) child = a.children()[0] child_k = None if z3.is_app(child): child_k = child.decl().kind() child_pp = self.pp_expr(child, d + 1, xs) if k != child_k and self.is_infix_unary(child_k): child_p = self.get_precedence(child_k) if p <= child_p: child_pp = self.add_paren(child_pp) if z3.is_quantifier(child): child_pp = self.add_paren(child_pp) name = self.pp_name(a) return compose(to_format(name), indent(_len(name), child_pp))
def pp_unary(self, a, d, xs): k = a.decl().kind() p = self.get_precedence(k) child = a.children()[0] child_k = None if z3.is_app(child): child_k = child.decl().kind() child_pp = self.pp_expr(child, d+1, xs) if k != child_k and self.is_infix_unary(child_k): child_p = self.get_precedence(child_k) if p <= child_p: child_pp = self.add_paren(child_pp) if z3.is_quantifier(child): child_pp = self.add_paren(child_pp) name = self.pp_name(a) return compose(to_format(name), indent(_len(name), child_pp))
def qe_array(exp): if not z3.is_quantifier(exp): return exp is_forall = False if exp.is_forall(): is_forall = True (qvars, matrix) = strip_qblock(exp) exp = z3.Exists(qvars, z3.Not(matrix)) qf_exp = z3.Tactic('qe-array', ctx=exp.ctx)(exp).as_expr() if is_forall: (qvars, matrix) = strip_qblock(qf_exp) if len(qvars) > 0: res = z3.ForAll(qvars, z3.Not(matrix)) else: res = z3.Not(matrix) else: res = qf_exp return res
def tagged_conditional_rewrite(s, rewriting_dict, leaf_fn, default_fn): """ Apply given rewriter to subexpressions of s bottom up """ todo = [] todo.append(s) cache = {} while todo: n = todo[len(todo) - 1] #print("Rewriting {}".format(n)) #print("Current cache: {}".format(cache)) if z3.is_var(n): # No rewriting for variables todo.pop() # TODO: This is one difference => Could be added as leaf_fn to standard rewrite as well cache[n] = leaf_fn(n) elif z3.is_app(n): # Add non-rewritten children to rewriting stack processed_all_children = True for arg in n.children(): if arg not in cache: todo.append(arg) processed_all_children = False # All children haven been rewritten, so now rewrite n itself if processed_all_children: todo.pop() new_args = [cache[arg] for arg in n.children()] enabled_rewriter = rewriting_dict.get(n.decl()) if enabled_rewriter is not None: cache[n] = enabled_rewriter(n, new_args) else: #cache[n] = replace_args(n, new_args) cache[n] = default_fn(n, new_args) else: assert (z3.is_quantifier(n)) b = n.body() if b in cache: # The argument of the quantifier has already been rewritten # Substitute this rewritten term todo.pop() # TODO: Another difference (but actually not even relevant in our setting). This could also be encapsulated in a function argument which could default to replace_args in the non-tagged setting rewritten_arg, tag = cache[b] cache[n] = (replace_args(n, [rewritten_arg]), tags) else: todo.append(b) return cache[s]
def find_all_uninterp_consts(formula, res): if z3.is_quantifier(formula): formula = formula.body() worklist = [] if z3.is_implies(formula): worklist.append(formula.arg(1)) arg0 = formula.arg(0) if z3.is_and(arg0): worklist.extend(arg0.children()) else: worklist.append(arg0) else: worklist.append(formula) for t in worklist: if z3.is_app(t) and t.decl().kind() == z3.Z3_OP_UNINTERPRETED: res.append(t.decl())
def write_clauses_datalog(declarations, clauses, writer): reserved_exit_point = 'reserved_exit_point' writer.write('(declare-rel {} ())\n\n'.format(reserved_exit_point)) for decl in declarations: symbol = quote_symbol_if_needed(decl.name()) writer.write('(declare-rel {} ('.format(symbol)) for n in range(0, decl.arity()): writer.write((" {}".format(decl.domain(n)))) writer.write(' ))\n') known_vars = set([]) implications = [] writer.write('\n') for clause in clauses: if not (z3.is_quantifier(clause) and clause.is_forall()): raise Exception("Illegal clause for write_clause_smt2: {}".format( clause.decl())) for idx in range(0, clause.num_vars()): if (clause.var_name(idx), clause.var_sort(idx)) not in known_vars: known_vars.add((clause.var_name(idx), clause.var_sort(idx))) writer.write("(declare-var {} {})\n".format( clause.var_name(idx), clause.var_sort(idx).sexpr())) implication = clause.body() subst = list( reversed([ z3.Const(clause.var_name(n), clause.var_sort(n)) for n in range(0, clause.num_vars()) ])) implications.append(z3.substitute_vars(implication, *subst)) writer.write('\n') for implication in implications: writer.write('(rule\n') write_implication_smt2(implication, ' ', reserved_exit_point, writer) writer.write('\n)\n') writer.write('\n\n(query {})\n\n'.format(reserved_exit_point))
def negated_body(formula): """Given a z3.QuantiferRef formula with z3.Int variables, return negation of the body. Returns: A z3.BoolRef which is the negation of the formula body. """ assert z3.is_quantifier(formula), ('Formula is not a quantifier:\n', formula) var_names = [formula.var_name(i) for i in range(formula.num_vars())] vs = [z3.Int(n) for n in var_names] # Here simply doing z3.Not(formula.body()) doesn't work. formula.body() # returns an expression without any bounded variable, i.e., it refers # variables using indices in the order they appear instead of its names, # Var(0), Var(1), Var(2). Thus, we have to re-bind the variables using # substitute_vars. It is also necessary to reverse the list of variables. # See https://github.com/Z3Prover/z3/issues/402 for more details. return z3.Not(z3.substitute_vars(formula.body(), *reversed(vs)))
def conditional_rewrite(s, rewriting_dict, default_fn=replace_args): """ Apply given rewriter to subexpressions of s bottom up """ todo = [] todo.append(s) cache = {} while todo: n = todo[len(todo) - 1] #print(n) if z3.is_var(n): # No rewriting for variables todo.pop() cache[n] = default_leaf_fn(n) elif z3.is_app(n): # Add non-rewritten children to rewriting stack processed_all_children = True for arg in n.children(): if arg not in cache: todo.append(arg) processed_all_children = False # All children haven been rewritten, so now rewrite n itself if processed_all_children: todo.pop() new_args = [cache[arg] for arg in n.children()] enabled_rewriter = rewriting_dict.get(n.decl()) if enabled_rewriter is not None: #print("Match for {}".format(n.decl())) cache[n] = enabled_rewriter(n, new_args) else: #cache[n] = replace_args(n, new_args) cache[n] = default_fn(n, new_args) else: assert (z3.is_quantifier(n)) b = n.body() if b in cache: # The argument of the quantifier has already been rewritten # Substitute this rewritten term todo.pop() cache[n] = replace_args(n, [cache[b]]) else: todo.append(b) return cache[s]
def solve(self, smt2_file): """ Start solving """ self.fp.set (engine='spacer') if self.args.stat: self.fp.set('print_statistics',True) if self.args.z3_verbose: z3.set_option (verbose=1) self.fp.set('use_heavy_mev',True) self.fp.set('pdr.flexible_trace',True) self.fp.set('reset_obligation_queue',False) self.fp.set('spacer.elim_aux',False) if self.args.utvpi: self.fp.set('pdr.utvpi', False) if not self.args.pp: self.fp.set ('xform.slice', False) self.fp.set ('xform.inline_linear',False) self.fp.set ('xform.inline_eager',False) with stats.timer ('Parse'): queries = self.fp.parse_file (smt2_file) stats.stop('Parse') self.preds = get_preds(self.fp) n_function = len(queries) stat("Function_Numbers", n_function) # TODO: Put them in a multithreading function all_results = "" for q in queries: if z3.is_quantifier(q): decl = q.body().decl() function_name = str(decl).split("@")[0] try: out = self.checkFeasibility(q, function_name) all_results += out + "\n-----------------------\n" except Exception as e: print "Solving " + function_name else: function_name = str(q.decl()).split("@")[0] out = out_message % (function_name, "CONSISTENT", "", "Trivial", "") all_results += bcolors.OKGREEN + out + bcolors.ENDC print "\n\t ========= SEAHORN INCONSISTENCY RESULTS ========" print all_results
def find_atomic_terms (exp, terms = list (), seen = set ()): """ Finds all declarations in an expression """ if (z3.is_quantifier (exp)): return find_atomic_terms (exp.body (), terms, seen) if not (z3.is_app (exp)) : return terms if z3AstRefKey (exp) in seen: return terms seen.add (z3AstRefKey (exp)) decl = exp.decl () # atomic term if decl.kind () == z3.Z3_OP_UNINTERPRETED: if z3AstRefKey (decl) not in seen: seen.add (z3AstRefKey (decl)) terms.append (decl) # uninterpreted can also have kids for k in exp.children (): find_atomic_terms (k, terms, seen) return terms
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 _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 getFunctionName(self, query): if z3.is_quantifier(query): decl = query.body().decl() return str(decl).split("@")[0] else: return str(query.decl()).split("@")[0]
def _back_single_term(self, expr, args, model=None): assert z3.is_expr(expr) if z3.is_quantifier(expr): raise NotImplementedError( "Quantified back conversion is currently not supported") assert not len(args) > 2 or \ (z3.is_and(expr) or z3.is_or(expr) or z3.is_add(expr) or z3.is_mul(expr) or (len(args) == 3 and (z3.is_ite(expr) or z3.is_array_store(expr)))),\ "Unexpected n-ary term: %s" % expr res = None try: decl = z3.Z3_get_app_decl(expr.ctx_ref(), expr.as_ast()) kind = z3.Z3_get_decl_kind(expr.ctx.ref(), decl) # Try to get the back-conversion function for the given Kind fun = self._back_fun[kind] return fun(args, expr) except KeyError as ex: pass if z3.is_const(expr): # Const or Symbol if z3.is_rational_value(expr): n = expr.numerator_as_long() d = expr.denominator_as_long() f = Fraction(n, d) return self.mgr.Real(f) elif z3.is_int_value(expr): n = expr.as_long() return self.mgr.Int(n) elif z3.is_bv_value(expr): n = expr.as_long() w = expr.size() return self.mgr.BV(n, w) elif z3.is_as_array(expr): if model is None: raise NotImplementedError("As-array expressions cannot be" \ " handled as they are not " \ "self-contained") else: interp_decl = z3.get_as_array_func(expr) interp = model[interp_decl] default = self.back(interp.else_value(), model=model) assign = {} for i in xrange(interp.num_entries()): e = interp.entry(i) assert e.num_args() == 1 idx = self.back(e.arg_value(0), model=model) val = self.back(e.value(), model=model) assign[idx] = val arr_type = self._z3_to_type(expr.sort()) return self.mgr.Array(arr_type.index_type, default, assign) elif z3.is_algebraic_value(expr): # Algebraic value return self.mgr._Algebraic(Numeral(expr)) else: # it must be a symbol try: return self.mgr.get_symbol(str(expr)) except UndefinedSymbolError: import warnings symb_type = self._z3_to_type(expr.sort()) warnings.warn("Defining new symbol: %s" % str(expr)) return self.mgr.FreshSymbol(symb_type, template="__z3_%d") elif z3.is_function(expr): # This needs to be after we try to convert regular Symbols fsymbol = self.mgr.get_symbol(expr.decl().name()) return self.mgr.Function(fsymbol, args) # If we reach this point, we did not manage to translate the expression raise ConvertExpressionError(message=("Unsupported expression: %s" % (str(expr))), expression=expr)