def emit_app(self,header,code): # handle interpreted ops if slv.solver_name(self.func) == None: if self.func.name in il.sig.interp: op = il.sig.interp[self.func.name] emit_special_op(self,op,header,code) return assert len(self.args) == 2 # handle only binary ops for now if is_bv_term(self): emit_bv_op(self,header,code) return code.append('(') self.args[0].emit(header,code) code.append(' {} '.format(self.func.name)) self.args[1].emit(header,code) code.append(')') return # handle uninterpreted ops code.append(varname(self.func.name)) global is_derived if self.func in is_derived: code.append('(') first = True for a in self.args: if not first: code.append(',') a.emit(header,code) first = False code.append(')') else: for a in self.args: code.append('[') a.emit(header,code) code.append(']')
def emit_app(self, header, code): # handle interpreted ops if slv.solver_name(self.func) == None: if self.func.name in il.sig.interp: op = il.sig.interp[self.func.name] emit_special_op(self, op, header, code) return assert len(self.args) == 2 # handle only binary ops for now if is_bv_term(self): emit_bv_op(self, header, code) return code.append('(') self.args[0].emit(header, code) code.append(' {} '.format(self.func.name)) self.args[1].emit(header, code) code.append(')') return # handle uninterpreted ops code.append(varname(self.func.name)) global is_derived if self.func in is_derived: code.append('(') first = True for a in self.args: if not first: code.append(',') a.emit(header, code) first = False code.append(')') else: for a in self.args: code.append('[') a.emit(header, code) code.append(']')
def __init__(self, clauses, model, vocab, top_level=True): TraceBase.__init__(self) self.clauses = clauses self.model = model self.vocab = vocab self.top_level = top_level if clauses is not None: ignore = lambda s: islv.solver_name(s) == None mod_clauses = islv.clauses_model_to_clauses(clauses, model=model, numerals=True, ignore=ignore) self.eqs = defaultdict(list) for fmla in mod_clauses.fmlas: if lg.is_eq(fmla): lhs, rhs = fmla.args if lg.is_app(lhs): self.eqs[lhs.rep].append(fmla) elif isinstance(fmla, lg.Not): app = fmla.args[0] if lg.is_app(app): self.eqs[app.rep].append(lg.Equals(app, lg.Or())) else: if lg.is_app(fmla): self.eqs[fmla.rep].append(lg.Equals(fmla, lg.And()))
def emit_action_gen(header, impl, name, action, classname): global indent_level caname = varname(name) upd = action.update(im.module, None) pre = tr.reverse_image(ilu.true_clauses(), ilu.true_clauses(), upd) pre_clauses = ilu.trim_clauses(pre) pre_clauses = ilu.and_clauses( pre_clauses, ilu.Clauses([df.to_constraint() for df in im.module.concepts])) pre = pre_clauses.to_formula() syms = [ x for x in ilu.used_symbols_ast(pre) if x.name not in il.sig.symbols ] header.append("class " + caname + "_gen : public gen {\n public:\n") for sym in syms: if not sym.name.startswith('__ts') and sym not in pre_clauses.defidx: declare_symbol(header, sym) header.append(" {}_gen();\n".format(caname)) impl.append(caname + "_gen::" + caname + "_gen(){\n") indent_level += 1 emit_sig(impl) for sym in syms: emit_decl(impl, sym) indent(impl) impl.append('add("(assert {})");\n'.format( slv.formula_to_z3(pre).sexpr().replace('\n', '\\\n'))) indent_level -= 1 impl.append("}\n") header.append(" bool generate(" + classname + "&);\n};\n") impl.append("bool " + caname + "_gen::generate(" + classname + "& obj) {\n push();\n") indent_level += 1 pre_used = ilu.used_symbols_ast(pre) for sym in all_state_symbols(): if sym in pre_used and sym not in pre_clauses.defidx: # skip symbols not used in constraint if slv.solver_name(sym) != None: # skip interpreted symbols global is_derived if sym not in is_derived: emit_set(impl, sym) for sym in syms: if not sym.name.startswith('__ts') and sym not in pre_clauses.defidx: emit_randomize(impl, sym) impl.append(""" bool res = solve(); if (res) { """) indent_level += 1 for sym in syms: if not sym.name.startswith('__ts') and sym not in pre_clauses.defidx: emit_eval(impl, sym) indent_level -= 2 impl.append(""" } pop(); obj.___ivy_gen = this; return res; } """)
def assign_symbol_from_model(header,sym,m): if slv.solver_name(sym) == None: return # skip interpreted symbols name, sort = sym.name,sym.sort if hasattr(sort,'dom'): for args in itertools.product(*[range(sort_card(s)) for s in sym.sort.dom]): term = sym(*[il.Symbol(str(a),s) for a,s in zip(args,sym.sort.dom)]) val = m.eval_to_constant(term) header.append(varname(sym.name) + ''.join('['+str(a)+']' for a in args) + ' = ') header.append(str(val) + ';\n') else: header.append(varname(sym.name) + ' = ' + m.eval_to_constant(sym) + ';\n')
def declare_symbol(header,sym,c_type = None): if slv.solver_name(sym) == None: return # skip interpreted symbols name, sort = sym.name,sym.sort if not c_type: c_type = 'bool' if sort.is_relational() else 'int' header.append(' ' + c_type + ' ') header.append(varname(sym.name)) if hasattr(sort,'dom'): for d in sort.dom: header.append('[' + str(sort_card(d)) + ']') header.append(';\n')
def emit_action_gen(header,impl,name,action,classname): global indent_level caname = varname(name) upd = action.update(im.module,None) pre = tr.reverse_image(ilu.true_clauses(),ilu.true_clauses(),upd) pre_clauses = ilu.trim_clauses(pre) pre_clauses = ilu.and_clauses(pre_clauses,ilu.Clauses([df.to_constraint() for df in im.module.concepts])) pre = pre_clauses.to_formula() syms = [x for x in ilu.used_symbols_ast(pre) if x.name not in il.sig.symbols] header.append("class " + caname + "_gen : public gen {\n public:\n") for sym in syms: if not sym.name.startswith('__ts') and sym not in pre_clauses.defidx: declare_symbol(header,sym) header.append(" {}_gen();\n".format(caname)) impl.append(caname + "_gen::" + caname + "_gen(){\n"); indent_level += 1 emit_sig(impl) for sym in syms: emit_decl(impl,sym) indent(impl) impl.append('add("(assert {})");\n'.format(slv.formula_to_z3(pre).sexpr().replace('\n','\\\n'))) indent_level -= 1 impl.append("}\n"); header.append(" bool generate(" + classname + "&);\n};\n"); impl.append("bool " + caname + "_gen::generate(" + classname + "& obj) {\n push();\n") indent_level += 1 pre_used = ilu.used_symbols_ast(pre) for sym in all_state_symbols(): if sym in pre_used and sym not in pre_clauses.defidx: # skip symbols not used in constraint if slv.solver_name(sym) != None: # skip interpreted symbols global is_derived if sym not in is_derived: emit_set(impl,sym) for sym in syms: if not sym.name.startswith('__ts') and sym not in pre_clauses.defidx: emit_randomize(impl,sym) impl.append(""" bool res = solve(); if (res) { """) indent_level += 1 for sym in syms: if not sym.name.startswith('__ts') and sym not in pre_clauses.defidx: emit_eval(impl,sym) indent_level -= 2 impl.append(""" } pop(); obj.___ivy_gen = this; return res; } """)
def declare_symbol(header, sym, c_type=None): if slv.solver_name(sym) == None: return # skip interpreted symbols name, sort = sym.name, sym.sort if not c_type: c_type = 'bool' if sort.is_relational() else 'int' header.append(' ' + c_type + ' ') header.append(varname(sym.name)) if hasattr(sort, 'dom'): for d in sort.dom: header.append('[' + str(sort_card(d)) + ']') header.append(';\n')
def emit_init_gen(header, impl, classname): global indent_level header.append(""" class init_gen : public gen { public: init_gen(); """) impl.append("init_gen::init_gen(){\n") indent_level += 1 emit_sig(impl) indent(impl) impl.append('add("(assert (and\\\n') constraints = [im.module.init_cond.to_formula()] for a in im.module.axioms: constraints.append(a) for df in im.module.concepts: constraints.append(df.to_constraint()) for c in constraints: fmla = slv.formula_to_z3(c).sexpr().replace('\n', ' ') indent(impl) impl.append(" {}\\\n".format(fmla)) indent(impl) impl.append('))");\n') indent_level -= 1 impl.append("}\n") header.append(" bool generate(" + classname + "&);\n};\n") impl.append("bool init_gen::generate(" + classname + "& obj) {\n") indent_level += 1 for sym in all_state_symbols(): if slv.solver_name(sym) != None: # skip interpreted symbols global is_derived if sym not in is_derived: emit_randomize(impl, sym) indent_level -= 1 impl.append(""" bool res = solve(); if (res) { """) indent_level += 2 emit_eval_sig(impl, 'obj') emit_clear_progress(impl, 'obj') indent_level -= 2 impl.append(""" } return res; } """)
def emit_init_gen(header,impl,classname): global indent_level header.append(""" class init_gen : public gen { public: init_gen(); """) impl.append("init_gen::init_gen(){\n"); indent_level += 1 emit_sig(impl) indent(impl) impl.append('add("(assert (and\\\n') constraints = [im.module.init_cond.to_formula()] for a in im.module.axioms: constraints.append(a) for df in im.module.concepts: constraints.append(df.to_constraint()) for c in constraints: fmla = slv.formula_to_z3(c).sexpr().replace('\n',' ') indent(impl) impl.append(" {}\\\n".format(fmla)) indent(impl) impl.append('))");\n') indent_level -= 1 impl.append("}\n"); header.append(" bool generate(" + classname + "&);\n};\n") impl.append("bool init_gen::generate(" + classname + "& obj) {\n") indent_level += 1 for sym in all_state_symbols(): if slv.solver_name(sym) != None: # skip interpreted symbols global is_derived if sym not in is_derived: emit_randomize(impl,sym) indent_level -= 1 impl.append(""" bool res = solve(); if (res) { """) indent_level += 2 emit_eval_sig(impl,'obj') emit_clear_progress(impl,'obj') indent_level -= 2 impl.append(""" } return res; } """)
def assign_symbol_from_model(header, sym, m): if slv.solver_name(sym) == None: return # skip interpreted symbols name, sort = sym.name, sym.sort if hasattr(sort, 'dom'): for args in itertools.product( *[range(sort_card(s)) for s in sym.sort.dom]): term = sym( *[il.Symbol(str(a), s) for a, s in zip(args, sym.sort.dom)]) val = m.eval_to_constant(term) header.append( varname(sym.name) + ''.join('[' + str(a) + ']' for a in args) + ' = ') header.append(str(val) + ';\n') else: header.append( varname(sym.name) + ' = ' + m.eval_to_constant(sym) + ';\n')
def emit_decl(header,symbol): name = symbol.name sname = slv.solver_name(symbol) if sname == None: # this means the symbol is interpreted in some theory return cname = varname(name) sort = symbol.sort rng_name = "Bool" if sort.is_relational() else sort.rng.name domain = sort_domain(sort) if len(domain) == 0: indent(header) header.append('mk_const("{}","{}");\n'.format(sname,rng_name)) else: card = len(domain) indent(header) header.append("const char *{}_domain[{}]".format(cname,card) + " = {" + ','.join('"{}"'.format(s.name) for s in domain) + "};\n"); indent(header) header.append('mk_decl("{}",{},{}_domain,"{}");\n'.format(sname,card,cname,rng_name))
def emit_randomize(header,symbol): global indent_level name = symbol.name sname = slv.solver_name(symbol) cname = varname(name) sort = symbol.sort domain = sort_domain(sort) for idx,dsort in enumerate(domain): dcard = sort_card(dsort) indent(header) header.append("for (int X{} = 0; X{} < {}; X{}++)\n".format(idx,idx,dcard,idx)) indent_level += 1 indent(header) header.append('randomize("{}"'.format(sname) + ''.join(",X{}".format(idx) for idx in range(len(domain))) + ");\n") for idx,dsort in enumerate(domain): indent_level -= 1
def emit_randomize(header, symbol): global indent_level name = symbol.name sname = slv.solver_name(symbol) cname = varname(name) sort = symbol.sort domain = sort_domain(sort) for idx, dsort in enumerate(domain): dcard = sort_card(dsort) indent(header) header.append("for (int X{} = 0; X{} < {}; X{}++)\n".format( idx, idx, dcard, idx)) indent_level += 1 indent(header) header.append('randomize("{}"'.format(sname) + ''.join(",X{}".format(idx) for idx in range(len(domain))) + ");\n") for idx, dsort in enumerate(domain): indent_level -= 1
def emit_eval(header,symbol,obj=None): global indent_level name = symbol.name sname = slv.solver_name(symbol) cname = varname(name) sort = symbol.sort domain = sort_domain(sort) for idx,dsort in enumerate(domain): dcard = sort_card(dsort) indent(header) header.append("for (int X{} = 0; X{} < {}; X{}++)\n".format(idx,idx,dcard,idx)) indent_level += 1 indent(header) header.append((obj + '.' if obj else '') + cname + ''.join("[X{}]".format(idx) for idx in range(len(domain))) + ' = eval_apply("{}"'.format(sname) + ''.join(",X{}".format(idx) for idx in range(len(domain))) + ");\n") for idx,dsort in enumerate(domain): indent_level -= 1
def emit_eval(header, symbol, obj=None): global indent_level name = symbol.name sname = slv.solver_name(symbol) cname = varname(name) sort = symbol.sort domain = sort_domain(sort) for idx, dsort in enumerate(domain): dcard = sort_card(dsort) indent(header) header.append("for (int X{} = 0; X{} < {}; X{}++)\n".format( idx, idx, dcard, idx)) indent_level += 1 indent(header) header.append((obj + '.' if obj else '') + cname + ''.join("[X{}]".format(idx) for idx in range(len(domain))) + ' = eval_apply("{}"'.format(sname) + ''.join(",X{}".format(idx) for idx in range(len(domain))) + ");\n") for idx, dsort in enumerate(domain): indent_level -= 1
def emit_decl(header, symbol): name = symbol.name sname = slv.solver_name(symbol) if sname == None: # this means the symbol is interpreted in some theory return cname = varname(name) sort = symbol.sort rng_name = "Bool" if sort.is_relational() else sort.rng.name domain = sort_domain(sort) if len(domain) == 0: indent(header) header.append('mk_const("{}","{}");\n'.format(sname, rng_name)) else: card = len(domain) indent(header) header.append("const char *{}_domain[{}]".format(cname, card) + " = {" + ','.join('"{}"'.format(s.name) for s in domain) + "};\n") indent(header) header.append('mk_decl("{}",{},{}_domain,"{}");\n'.format( sname, card, cname, rng_name))
def emit_eval_sig(header,obj=None): for symbol in all_state_symbols(): if slv.solver_name(symbol) != None: # skip interpreted symbols global is_derived if symbol not in is_derived: emit_eval(header,symbol,obj)
def emit_templates(self): add_impl( """ int CLASSNAME::temp_counter = 0; std::ostream &operator <<(std::ostream &s, const CLASSNAME &t){ s << "{"; switch (t.tag) { """.replace('CLASSNAME',self.short_name())) for idx,var in enumerate(self.variants): sort,ctype = var add_impl(' case {}: s << "{}:" << {}; break;\n'.format(idx,sort.name,self.downcast(idx,'t'))) add_impl( """ } s << "}"; return s; } template <> CLASSNAME _arg<CLASSNAME>(std::vector<ivy_value> &args, unsigned idx, long long bound) { if (args[idx].atom.size()) throw out_of_bounds("unexpected value for sort SORTNAME: " + args[idx].atom,args[idx].pos); if (args[idx].fields.size() == 0) return CLASSNAME(); if (args[idx].fields.size() != 1) throw out_of_bounds("too many fields for sort SORTNAME (expected one)",args[idx].pos); """.replace('CLASSNAME',self.short_name()).replace('SORTNAME',self.sort.name)) for idx,var in enumerate(self.variants): sort,ctype = var add_impl(' if (args[idx].fields[0].atom == "{}") return {};\n'.format(sort.name,self.upcast(idx,'_arg<{}>(args[idx].fields[0].fields,0,0)'.format(ctype)))) add_impl( """ throw out_of_bounds("unexpected field sort SORTNAME: " + args[idx].fields[0].atom, args[idx].pos); } template <> void __ser<CLASSNAME>(ivy_ser &res, const CLASSNAME &inp) { """.replace('CLASSNAME',self.short_name())) for idx,var in enumerate(self.variants): sort,ctype = var add_impl(' if (inp.tag == {}) {{res.open_tag({},"{}"); __ser(res,{}); res.close_tag();}}\n'.format(idx,idx,sort.name,self.downcast(idx,'inp'))) add_impl( """ } template <> void __deser<CLASSNAME>(ivy_deser &res, CLASSNAME &inp) { std::vector<std::string> tags; """.replace('CLASSNAME',self.short_name())) for idx,var in enumerate(self.variants): sort,ctype = var add_impl(' tags.push_back("{}");\n'.format(sort.name)) add_impl( """ int tag = res.open_tag(tags); switch (tag) { """.replace('CLASSNAME',self.short_name())) for idx,var in enumerate(self.variants): sort,ctype = var add_impl(' case {}: {{{} tmp; __deser(res,tmp); inp = {}; break;}} \n'.format(idx,ctype,self.upcast(idx,'tmp'))) add_impl( """ } res.close_tag(); } #ifdef Z3PP_H_ template <> void __from_solver<CLASSNAME>( gen &g, const z3::expr &v, CLASSNAME &res) { """.replace('CLASSNAME',self.short_name())) for idx,var in enumerate(self.variants): sort,ctype = var pto = ivy_solver.solver_name(ivy_logic.Symbol('*>',ivy_logic.RelationSort([self.sort,sort]))) add_impl(' {\n') add_impl(' z3::sort sort = g.sort("{}");\n'.format(sort.name)) add_impl(' z3::func_decl pto = g.ctx.function("{}",g.sort("{}"),g.sort("{}"),g.ctx.bool_sort());\n'.format(pto,self.sort.name,sort.name)) add_impl(' // std::cout << g.model << std::endl;\n') add_impl(' Z3_ast_vector av = Z3_model_get_sort_universe(g.ctx, g.model, sort);\n') add_impl(' if (av) {\n') add_impl(' z3::expr_vector univ(g.ctx,av);\n') add_impl(' for (unsigned i = 0; i < univ.size(); i++){\n') add_impl(' if (eq(g.model.eval(pto(v,univ[i]),true),g.ctx.bool_val(true))){\n') add_impl(' {} tmp;\n'.format(ctype)) add_impl(' __from_solver(g,univ[i],tmp);') add_impl(' res = {};\n'.format(self.upcast(idx,'tmp'))) add_impl(' }\n') add_impl(' }\n') add_impl(' }\n') add_impl(' }\n') add_impl( """ } template <> z3::expr __to_solver<CLASSNAME>( gen &g, const z3::expr &v, CLASSNAME &val) { // std::cout << v << ":" << v.get_sort() << std::endl; """.replace('CLASSNAME',self.short_name())) for idx,var in enumerate(self.variants): sort,ctype = var pto = ivy_solver.solver_name(ivy_logic.Symbol('*>',ivy_logic.RelationSort([self.sort,sort]))) add_impl(' if (val.tag == {}) {{\n'.format(idx)) add_impl(' z3::func_decl pto = g.ctx.function("{}",g.sort("{}"),g.sort("{}"),g.ctx.bool_sort());\n'.format(pto,self.sort.name,sort.name)) add_impl(' z3::expr X = g.ctx.constant("X",g.sort("{}"));\n'.format(sort.name)) add_impl(' {} tmp = {};\n'.format(ctype,self.downcast(idx,'val'))) add_impl(' return exists(X,pto(v,X) && __to_solver(g,X,tmp));\n') add_impl(' }\n') add_impl( """ z3::expr conj = g.ctx.bool_val(false); """.replace('CLASSNAME',self.short_name())) for idx,var in enumerate(self.variants): sort,ctype = var pto = ivy_solver.solver_name(ivy_logic.Symbol('*>',ivy_logic.RelationSort([self.sort,sort]))) add_impl(' {\n') add_impl(' z3::func_decl pto = g.ctx.function("{}",g.sort("{}"),g.sort("{}"),g.ctx.bool_sort());\n'.format(pto,self.sort.name,sort.name)) add_impl(' z3::expr Y = g.ctx.constant("Y",g.sort("{}"));\n'.format(sort.name)) add_impl(' conj = conj && forall(Y,!pto(v,Y));\n') add_impl(' }\n') add_impl( """ return conj; } template <> void __randomize<CLASSNAME>( gen &g, const z3::expr &apply_expr) { std::ostringstream os; os << "__SORTNAME__tmp" << CLASSNAME::temp_counter++; std::string temp = os.str(); z3::sort range = apply_expr.get_sort(); z3::expr disj = g.ctx.bool_val(false); """.replace('CLASSNAME',self.short_name()).replace('SORTNAME',self.sort.name)) add_impl('int tag = rand() % {};\n'.format(len(self.variants))) for idx,var in enumerate(self.variants): sort,ctype = var pto = ivy_solver.solver_name(ivy_logic.Symbol('*>',ivy_logic.RelationSort([self.sort,sort]))) add_impl(' if (tag == {}) {{\n'.format(idx)) add_impl(' z3::func_decl pto = g.ctx.function("{}",g.sort("{}"),g.sort("{}"),g.ctx.bool_sort());\n'.format(pto,self.sort.name,sort.name)) add_impl(' z3::expr X = g.ctx.constant(temp.c_str(),g.sort("{}"));\n'.format(sort.name)) add_impl(' z3::expr pred = pto(apply_expr,X);\n') add_impl(' g.add_alit(pred);\n') add_impl(' __randomize<{}>(g,X);\n'.format(ctype)) add_impl(' }\n') add_impl( """ } #endif """.replace('CLASSNAME',self.short_name()))
def emit_eval_sig(header, obj=None): for symbol in all_state_symbols(): if slv.solver_name(symbol) != None: # skip interpreted symbols global is_derived if symbol not in is_derived: emit_eval(header, symbol, obj)