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 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 make_check_art(act_name=None, precond=[]): action = act.env_action(act_name) ag = art.AnalysisGraph() pre = itp.State() pre.clauses = lut.and_clauses(*precond) if precond else lut.true_clauses() pre.clauses.annot = act.EmptyAnnotation() with itp.EvalContext(check=False): # don't check safety post = ag.execute(action, pre) post.clauses = lut.true_clauses() fail = itp.State(expr=itp.fail_expr(post.expr)) return ag, post, fail
def learnWeekestInv(mod, clf, actname): ''' candInv and coincide will be of type ivy_logic_utils.Clauses. coincide is a Clause object representing samples which cannot be distinguish by feature set ''' global candInv, coincide candInv, coincide = true_clauses(), false_clauses() while True: spos = samplePos(mod, candInv, coincide, actname) # Generating positve sample sneg = sampleNeg(mod, candInv, actname) if spos is None and sneg is None: break spos, sneg = Sample(spos, '1'), Sample(sneg, '0') print "Pos Sample", spos.unv.unvsize() if hasattr(spos, 'interp') else None print "Neg Sample", sneg.unv.unvsize() if hasattr(sneg, 'interp') else None # if hasattr(spos, 'interp'): # spos is not None # print "<plearn> + sample interpretation : ",spos.interp, "\n" # for detailed information # spos.displaySample() # for displaying the sample # if hasattr(sneg, 'interp'): # sneg is not None # print "<plearn> - sample interpretation : ",sneg.interp, "\n" # for detailed information # sneg.displaySample() clf.addSample(spos) # adding Positive sample clf.addSample(sneg) print "<plearn> done adding samples" import sys sys.stdout.flush() candInv, coincide = clf.learn() print "<plearn> candidate Invariant", candInv sys.stdout.flush() # print "coincide Clause", coincide # a = raw_input('One iteration of loop completed, press enter:') return candInv
def learnInv(mod): print "\n" * 2 print "<plearn> Directed to learning Algorithm" global silent, module, numVarFS, featureset silent = True updatenvi(mod) module = mod while True: print "Checking Inductiveness of the Invariant" maxunv, isInvInd = icheck.isInvInductive(mod) print "Invariant is{} Inductive\n".format('' if isInvInd else ' NOT') if isInvInd: # its Inductive so nothing to do silent = False checkInitialCond(mod) break # testfunc(mod) for actname in sorted(mod.public_actions): print "learning Invariant for action {}".format(actname) clf = Classifier() # new classifier newInv = learnWeekestInv(mod, clf, actname) print "\n" * 2 print "<plearn> new Invariant:", newInv a = raw_input('new Invariant learned, press enter to continue') print "\n" * 2 numVarFS = {} # resetting numVarFS featureset = [] # resetting featuerset if newInv != true_clauses(): lf = ivy_ast.LabeledFormula(*[ ivy_ast.Atom('learnedInv' + actname), logic.And(*newInv.fmlas) ]) mod.labeled_conjs.append( lf) # modifying mod and module, obj are copied by refr. updatenvi(mod) # takes care of numVarInv
def process_actions(self): for name, action in self.mod.actions.iteritems(): # print(type(action)) # print ("action2: ", ia.action_def_to_str(name, action)) ag = ivy_art.AnalysisGraph() pre = itp.State() pre.clauses = lut.true_clauses() # print(pre.to_formula()) post = ag.execute(action, pre) history = ag.get_history(post) clauses = lut.and_clauses(history.post) f = self.get_formula(clauses) conjuncts = clauses.fmlas defn = lut.close_epr(lg.And(*conjuncts)) # print(defn) # assert(0) update = action.update(pre.domain, pre.in_scope) sf = self.standardize_action(f, update[0], name) self.add_new_constants(sf) actname = "action_" + name self.actions.add(actname) res = (sf, actname, "action", name) self.vmt[actname] = res
def clear(self): # these fields represent all the module declarations self.all_relations = [ ] # this includes both base and derived relations in declaration order self.concepts = [] # TODO: these are actually "derived" relations self.labeled_axioms = [] self.labeled_inits = [] self.init_cond = lu.true_clauses() self.relations = dict() # TODO: this is redundant, remove self.functions = dict() # TODO: this is redundant, remove self.updates = [] self.schemata = dict() self.instantiations = [] self.concept_spaces = [] self.labeled_conjs = [] # conjectures self.hierarchy = defaultdict(set) self.actions = {} self.predicates = {} self.assertions = [] self.mixins = defaultdict(list) self.public_actions = set() self.isolates = {} self.exports = [] self.delegates = [] self.public_actions = set() # hash of the exported actions self.progress = [] # list of progress properties self.rely = [] # list of rely relations self.mixord = [] # list of mixin order relations self.destructor_sorts = {} self.sort_destructors = defaultdict(list) self.sig = il.sig.copy() # capture the current signature
def clear(self): # these fields represent all the module declarations self.all_relations = [ ] # this includes both base and derived relations in declaration order self.definitions = [] # TODO: these are actually "derived" relations self.labeled_axioms = [] self.labeled_props = [] self.labeled_inits = [] self.init_cond = lu.true_clauses() self.relations = dict() # TODO: this is redundant, remove self.functions = dict() # TODO: this is redundant, remove self.updates = [] self.schemata = dict() self.theorems = dict() self.instantiations = [] self.concept_spaces = [] self.labeled_conjs = [] # conjectures self.labeled_templates = [] # conjectures self.hierarchy = defaultdict(set) self.actions = {} self.predicates = {} self.assertions = [] self.mixins = defaultdict(list) self.public_actions = set() self.isolates = {} self.exports = [] self.imports = [] self.delegates = [] self.public_actions = set() # hash of the exported actions self.progress = [] # list of progress properties self.rely = [] # list of rely relations self.mixord = [] # list of mixin order relations self.destructor_sorts = {} self.sort_destructors = defaultdict(list) self.privates = set() # set of string (names of private actions) self.interps = defaultdict( list) # maps type names to lists of labeled interpretions self.natives = [] # list of NativeDef self.native_definitions = [ ] # list of definitions whose rhs is NativeExpr self.initializers = [] # list of name,action pairs self.params = [] self.ghost_sorts = set() # set of sort names self.native_types = {} # map from sort names to ivy_ast.NativeType self.sort_order = [] # list of sorts names in order declared self.symbol_order = [] # list of symbols in order declared self.aliases = {} # map from name to name self.before_export = {} # map from string to action self.attributes = {} # map from name to atom self.variants = defaultdict(list) # map from sort name to list of sort self.ext_preconds = {} # map from action name to formula self.proofs = [] # list of pair (labeled formula, proof) self.named = [] # list of pair (labeled formula, atom) self.subgoals = [] # (labeled formula * labeled formula list) list self.isolate_info = None # IsolateInfo or None self.conj_actions = dict() # map from conj names to action name list self.sig = il.sig.copy() # capture the current signature
def clear(self): # these fields represent all the module declarations self.all_relations = [] # this includes both base and derived relations in declaration order self.concepts = [] # TODO: these are actually "derived" relations self.labeled_axioms = [] self.labeled_inits = [] self.init_cond = lu.true_clauses() self.relations = dict() # TODO: this is redundant, remove self.functions = dict() # TODO: this is redundant, remove self.updates = [] self.schemata = dict() self.instantiations = [] self.concept_spaces = [] self.labeled_conjs = [] # conjectures self.hierarchy = defaultdict(set) self.actions = {} self.predicates = {} self.assertions = [] self.mixins = defaultdict(list) self.public_actions = set() self.isolates = {} self.exports = [] self.delegates = [] self.public_actions = set() # hash of the exported actions self.progress = [] # list of progress properties self.rely = [] # list of rely relations self.mixord = [] # list of mixin order relations self.destructor_sorts = {} self.sort_destructors = defaultdict(list) self.privates = set() # set of string (names of private actions) self.sig = il.sig.copy() # capture the current signature
def process_actions(self): if ivy_compiler.isolate.get(): st = ivy_compiler.isolate.get().split('.')[0] else: st = '' st = [st, 'timeout', 'handle', 'recv'] for name in self.mod.public_actions: print >> sys.stderr, "action:\t", name if not (ivy_compiler.isolate.get() == None or any(s in name for s in st)): continue action = ia.env_action(name) # print ("action2: ", ia.action_def_to_str(name, action)) ag = ivy_art.AnalysisGraph() pre = itp.State() pre.clauses = lut.true_clauses() # print(pre.to_formula()) with itp.EvalContext(check=False): post = ag.execute(action, pre) history = ag.get_history(post) clauses = lut.and_clauses(history.post) f = self.get_formula(clauses) conjuncts = clauses.fmlas defn = lut.close_epr(lg.And(*conjuncts)) # print(defn) # assert(0) update = action.update(pre.domain, pre.in_scope) sf = self.standardize_action(f, update[0], name) self.add_new_constants(sf, 'action') actname = "action_" + name self.actions.add(actname) res = (sf, actname, "action", name) self.vmt[actname] = res
def int_update(self,domain,pvars): update = ([],true_clauses(),false_clauses()) axioms = domain.background_theory(pvars) for op in self.args: thing = op.int_update(domain,pvars); # print "op: {}, thing: {}".format(op,thing) update = compose_updates(update,axioms,thing) return update
def int_update(self, domain, pvars): update = ([], true_clauses(), false_clauses()) axioms = domain.background_theory(pvars) for op in self.args: thing = op.int_update(domain, pvars) # print "op: {}, thing: {}".format(op,thing) update = compose_updates(update, axioms, thing) return update
def action_update(self, domain, pvars): type_check(domain, self.args[0]) check_can_assert(self.args[0], self) # print type(self.args[0]) if iu.new_assert_impl.get(): return assert_action(self.args[0]) else: cl = formula_to_clauses(dual_formula(self.args[0])) return SemActionValue([], true_clauses(), cl)
def action_update(self,domain,pvars): type_check(domain,self.args[0]) check_can_assert(self.args[0],self) # print type(self.args[0]) if iu.new_assert_impl.get(): return assert_action(self.args[0]) else: cl = formula_to_clauses(dual_formula(self.args[0])) return SemActionValue([],true_clauses(),cl)
def clear(self): # these fields represent all the module declarations self.all_relations = [] # this includes both base and derived relations in declaration order self.definitions = [] # TODO: these are actually "derived" relations self.labeled_axioms = [] self.labeled_props = [] self.labeled_inits = [] self.init_cond = lu.true_clauses() self.relations = dict() # TODO: this is redundant, remove self.functions = dict() # TODO: this is redundant, remove self.updates = [] self.schemata = dict() self.instantiations = [] self.concept_spaces = [] self.labeled_conjs = [] # conjectures self.hierarchy = defaultdict(set) self.actions = {} self.predicates = {} self.assertions = [] self.mixins = defaultdict(list) self.public_actions = set() self.isolates = {} self.exports = [] self.imports = [] self.delegates = [] self.public_actions = set() # hash of the exported actions self.progress = [] # list of progress properties self.rely = [] # list of rely relations self.mixord = [] # list of mixin order relations self.destructor_sorts = {} self.sort_destructors = defaultdict(list) self.privates = set() # set of string (names of private actions) self.interps = defaultdict(list) # maps type names to lists of labeled interpretions self.natives = [] # list of NativeDef self.native_definitions = [] # list of definitions whose rhs is NativeExpr self.initializers = [] # list of name,action pairs self.params = [] self.ghost_sorts = set() # set of sort names self.native_types = {} # map from sort names to ivy_ast.NativeType self.sort_order = [] # list of sorts names in order declared self.symbol_order = [] # list of symbols in order declared self.aliases = {} # map from name to name self.before_export = {} # map from string to action self.attributes = {} # map from name to atom self.variants = defaultdict(list) # map from sort name to list of sort self.ext_preconds = {} # map from action name to formula self.proofs = [] # list of pair (labeled formula, proof) self.named = [] # list of pair (labeled formula, atom) self.subgoals = [] # (labeled formula * labeled formula list) list self.isolate_info = None # IsolateInfo or None self.conj_actions = dict() # map from conj names to action name list self.sig = il.sig.copy() # capture the current signature
def clauses_model_to_diagram(clauses1,ignore = None, implied = None,model = None,axioms=None,weaken=True,numerals=True): """ Return a diagram of a model of clauses1 or None. The function "ignore", if provided, returns true for symbols that should be ignored in the diagram. """ # print "clauses_model_to_diagram clauses1 = {}".format(clauses1) if axioms == None: axioms = true_clauses() h = model_if_none(and_clauses(clauses1,axioms),implied,model) ignore = ignore if ignore != None else lambda x: False res = model_facts(h,(lambda x: False),clauses1,upclose=True) # why not pass axioms? # print "clauses_model_to_diagram res = {}".format(res) # find representative elements # find representatives of universe elements if numerals: reps = numeral_assign(res,h) else: reps = dict() for c in used_constants_clauses(clauses1): # print "constant: {}".format(c) mc = get_model_constant(h.model,ivy_logic.Constant(c)) # print "value: {}".format(mc) if mc.rep not in reps or reps[mc.rep].rep.is_skolem() and not c.is_skolem(): reps[mc.rep] = ivy_logic.Constant(c) for s in h.sorts(): for e in h.sort_universe(s): if e.rep not in reps: reps[e.rep] = e.rep.skolem()() # print "clauses_model_to_diagram reps = {}".format(reps) # filter out clauses using universe elements without reps # res = [cls for cls in res if all(c in reps for c in used_constants_clause(cls))] # replace universe elements with their reps # print "clauses_model_to_diagram res = {}".format(res) res = substitute_constants_clauses(res,reps) # filter defined skolems # this caused a bug in the leader example. the generated diagram did not satisfy clauses1 res.fmlas = [f for f in res.fmlas if not any((x.is_skolem() and x in clauses1.defidx) for x in used_symbols_ast(f))] # print "clauses_model_to_diagram res = {}".format(res) uc = Clauses([[ivy_logic._eq_lit(ivy_logic.Variable('X',c.get_sort()),reps[c.rep]) for c in h.sort_universe(s)] for s in h.sorts()]) # print "clauses_model_to_diagram uc = {}".format(uc) # uc = true_clauses() if weaken: res = unsat_core(res,and_clauses(uc,axioms),clauses1) # implied not used here # print "clauses_model_to_diagram res = {}".format(res) # print "foo = {}".format(unsat_core(and_clauses(uc,axioms),true_clauses(),clauses1)) # filter out non-rep skolems repset = set(c.rep for e,c in reps.iteritems()) # print "clauses_model_to_diagram repset = {}".format(repset) ign = lambda x,ignore=ignore: (ignore(x) and not x in repset) res = Clauses([cl for cl in res.fmlas if not any(ign(c) for c in used_symbols_ast(cl))]) # print "clauses_model_to_diagram res = {}".format(res) return res
def action_update(self,domain,pvars): type_check(domain,self.args[0]) # print type(self.args[0]) ca = checked_assert.get() if ca: if ca != self.lineno: return ([],formula_to_clauses(self.args[0]),false_clauses()) cl = formula_to_clauses(dual_formula(self.args[0])) # return ([],formula_to_clauses_tseitin(self.args[0]),cl) return ([],true_clauses(),cl)
def is_sufficient(self, button=None): """ Check if the active conjecture is sufficient to imply the current CTI conjecture at the next step TODO: this has a lot in common with check_inductiveness, should refactor common parts out """ import ivy_transrel import ivy_solver from proof import ProofGoal from ivy_logic_utils import Clauses, and_clauses, dual_clauses from random import randrange with self.ui_parent.run_context(): conj = self.get_selected_conjecture() target_conj = self.parent.current_conjecture ag = self.parent.new_ag() pre = State() pre.clauses = and_clauses(conj, *self.parent.conjectures) pre.clauses.annot = ia.EmptyAnnotation() action = ia.env_action(None) post = ag.execute(action, pre) post.clauses = ilu.true_clauses(annot=ia.EmptyAnnotation()) assert target_conj.is_universal_first_order() used_names = frozenset(x.name for x in il.sig.symbols.values()) def witness(v): c = lg.Const('@' + v.name, v.sort) assert c.name not in used_names return c clauses = dual_clauses(target_conj, witness) clauses.annot = ia.EmptyAnnotation() res = ivy_trace.check_final_cond(ag, post, clauses, [], True) text = '(1) ' + str(conj.to_formula()) + '\n(2) ' + str( target_conj.to_formula()) if res is not None: self.ui_parent.text_dialog( '(1) does not imply (2) at the next time. View counterexample?', text, command_label='View', command=lambda: self.ui_parent.add(res)) return False else: self.ui_parent.text_dialog('(1) implies (2) at the next time:', text, on_cancel=None) return True
def top_bottom(node): # TODO: change this to use the concrete post already there preds, action = arg_get_preds_action(node) assert action != "join" assert len(preds) == 1 pred = preds[0] implied = implied_facts(forward_image(arg_get_fact(pred), action), [false_clauses()]) if len(implied) == 1: node.clauses = false_clauses() else: node.clauses = true_clauses()
def __init__(self,nodes): self.all_nodes = [GraphNode(n,f,s) for (n,f,s) in nodes] self.relations = [] self.pred = None self.status = dict() self.solver = z3.Solver() self.solver.push() self.constraints = true_clauses() self.needs_recompute = False self.nodes = [] self.edges = [] self.enabled_relations = set()
def propagate_and_conjectures(node): """ Propagate clauses from predecessor """ preds, action = arg_get_preds_action(node) assert action != "join" assert len(preds) == 1 pred = preds[0] implied = implied_facts(forward_image(arg_get_fact(pred), action), list(_ivy_interp.conjs)) node.clauses = true_clauses() for fact in implied: arg_add_facts(node, fact)
def arg_add_action_node(pre, action, abstractor=None): """ Add a new node with an action edge from pre, and return it. """ try: label = [k for k, v in _ivy_ag.actions.iteritems() if v == action][0] except IndexError: label = None node = _ivy_ag.execute(action, pre, abstractor, label) if abstractor is None: node.clauses = true_clauses() return node
def __init__(self, nodes): self.all_nodes = [GraphNode(n, f, s) for (n, f, s) in nodes] self.relations = [] self.pred = None self.status = dict() self.solver = z3.Solver() self.solver.push() self.constraints = true_clauses() self.needs_recompute = False self.nodes = [] self.edges = [] self.enabled_relations = set()
def get_update_axioms(self,updated,action): # print "get_update_axioms: {}, {}".format(map(str,updated),action) for x in updated: if x in self.dependencies.symbols: updated = updated + [y for y in self.defines.symbols if y not in updated] try: precond,postcond = next(y for y in (p.match(action) for p in self.patterns.args) if y != None) except StopIteration: raise IvyError(action,'No matching update axiom for ' + str(x)) postcond = state_to_action((updated,postcond,precond)) # print "update axioms: {}, {}, {}".format(map(str,postcond[0]),postcond[1],postcond[2]) return (updated,postcond[1],precond) return (updated,true_clauses(),false_clauses())
def get_update_axioms(self, updated, action): # print "get_update_axioms: {}, {}".format(map(str,updated),action) for x in updated: if x in self.dependencies.symbols: updated = updated + [y for y in self.defines.symbols if y not in updated] try: precond, postcond = next(y for y in (p.match(action) for p in self.patterns.args) if y != None) except StopIteration: raise IvyError(action, "No matching update axiom for " + str(x)) postcond = state_to_action((updated, postcond, precond)) # print "update axioms: {}, {}, {}".format(map(str,postcond[0]),postcond[1],postcond[2]) return (updated, postcond[1], precond) return (updated, true_clauses(), false_clauses())
def top_bottom(node): # TODO: change this to use the concrete post already there preds, action = arg_get_preds_action(node) assert action != 'join' assert len(preds) == 1 pred = preds[0] implied = implied_facts( forward_image(arg_get_fact(pred), action), [false_clauses()], ) if len(implied) == 1: node.clauses = false_clauses() else: node.clauses = true_clauses()
def is_inductive(self, button=None): """ Check if the active conjecture implies itself at the next step TODO: this has a lot in common with check_inductiveness and is_sufficient, should refactor common parts out """ import ivy_transrel import ivy_solver from proof import ProofGoal from ivy_logic_utils import Clauses, and_clauses, dual_clauses from random import randrange with self.ui_parent.run_context(): conj = self.get_selected_conjecture() target_conj = conj ag = self.parent.new_ag() pre = State() pre.clauses = and_clauses(conj, *self.parent.conjectures) action = im.module.actions['ext'] post = ag.execute(action, pre, None, 'ext') post.clauses = ilu.true_clauses() assert target_conj.is_universal_first_order() used_names = frozenset(x.name for x in il.sig.symbols.values()) def witness(v): c = lg.Const('@' + v.name, v.sort) assert c.name not in used_names return c clauses = dual_clauses(target_conj, witness) res = ag.bmc(post, clauses) text = '(1) ' + str(conj.to_formula()) if res is not None: self.ui_parent.text_dialog( '(1) is not relatively inductive. View counterexample?', text, command_label='View', command=lambda: self.ui_parent.add(res)) return False else: self.ui_parent.text_dialog('(1) is relatively inductive:', text, on_cancel=None) return True
def recompute(self): if not self.needs_recompute: ## print "skipped recompute" return self.needs_recompute = False ## print "did recompute" self.solver.pop() self.solver.push() self.solver_clauses = true_clauses() self.get_solver_clauses() for n in self.all_nodes: self.check_node(n) self.nodes = [GraphNode(n.name,n.fmla,n.sort) for n in self.all_nodes if n.status != "false"] for r in self.relations: r.compute_edges(self.solver)
def propagate(node): """ Propagate clauses from predecessor """ preds, action = arg_get_preds_action(node) assert action != 'join' assert len(preds) == 1 pred = preds[0] implied = implied_facts( forward_image(arg_get_fact(pred), action), list(arg_get_conjuncts(pred)), ) node.clauses = true_clauses() for fact in implied: arg_add_facts(node, fact)
def propagate_and_conjectures(node): """ Propagate clauses from predecessor """ preds, action = arg_get_preds_action(node) assert action != 'join' assert len(preds) == 1 pred = preds[0] implied = implied_facts( forward_image(arg_get_fact(pred), action), list(_ivy_interp.conjs), ) node.clauses = true_clauses() for fact in implied: arg_add_facts(node, fact)
def __init__(self,nodes,parent_state=None): self.parent_state = parent_state self.all_nodes = [GraphNode(n,f,s) for (n,f,s) in nodes] self.relations = [] self.pred = None self.status = dict() self.solver = z3.Solver() self.solver.push() self.constraints = true_clauses() self.needs_recompute = False self.nodes = [] self.edges = [] self.enabled_relations = set() self.concept_domain = initial_concept_domain([s for n,f,s in nodes]) self.widget = ConceptStateViewWidget() self.session = cis.ConceptInteractiveSession(self.concept_domain,And(),And(),widget=self.widget)
def is_sufficient(self, button=None): """ Check if the active conjecture is sufficient to imply the current CTI conjecture at the next step TODO: this has a lot in common with check_inductiveness, should refactor common parts out """ import ivy_transrel import ivy_solver from proof import ProofGoal from ivy_logic_utils import Clauses, and_clauses, dual_clauses from random import randrange with self.ui_parent.run_context(): conj = self.get_selected_conjecture() target_conj = self.parent.current_conjecture ag = self.parent.new_ag() pre = State() pre.clauses = and_clauses(conj, *self.parent.conjectures) action = im.module.actions['ext'] post = ag.execute(action, pre, None, 'ext') post.clauses = ilu.true_clauses() assert target_conj.is_universal_first_order() used_names = frozenset(x.name for x in il.sig.symbols.values()) def witness(v): c = lg.Const('@' + v.name, v.sort) assert c.name not in used_names return c clauses = dual_clauses(target_conj, witness) res = ag.bmc(post, clauses) text = '(1) ' + str(conj.to_formula()) + '\n(2) ' + str(target_conj.to_formula()) if res is not None: self.ui_parent.text_dialog('(1) does not imply (2) at the next time. View counterexample?', text,command_label='View',command = lambda: self.ui_parent.add(res)) return False else: self.ui_parent.text_dialog('(1) implies (2) at the next time:',text,on_cancel=None) return True
def clear(self): # these fields represent all the module declarations self.all_relations = [] # this includes both base and derived relations in declaration order self.definitions = [] # TODO: these are actually "derived" relations self.labeled_axioms = [] self.labeled_props = [] self.labeled_inits = [] self.init_cond = lu.true_clauses() self.relations = dict() # TODO: this is redundant, remove self.functions = dict() # TODO: this is redundant, remove self.updates = [] self.schemata = dict() self.instantiations = [] self.concept_spaces = [] self.labeled_conjs = [] # conjectures self.hierarchy = defaultdict(set) self.actions = {} self.predicates = {} self.assertions = [] self.mixins = defaultdict(list) self.public_actions = set() self.isolates = {} self.exports = [] self.imports = [] self.delegates = [] self.public_actions = set() # hash of the exported actions self.progress = [] # list of progress properties self.rely = [] # list of rely relations self.mixord = [] # list of mixin order relations self.destructor_sorts = {} self.sort_destructors = defaultdict(list) self.privates = set() # set of string (names of private actions) self.interps = defaultdict(list) # maps type names to lists of labeled interpretions self.natives = [] # list of NativeDef self.initializers = [] # list of name,action pairs self.params = [] self.ghost_sorts = set() # set of sort names self.native_types = {} # map from sort names to ivy_ast.NativeType self.sort_order = [] # list of sorts names in order declared self.symbol_order = [] # list of symbols in order declared self.aliases = {} # map from name to name self.sig = il.sig.copy() # capture the current signature
def diagram(self): from ivy_solver import clauses_model_to_diagram, get_model_clauses from ivy_transrel import is_skolem, reverse_image if not self.have_cti: if self.check_inductiveness() or len(self.g.states) != 2: return conj = self.current_conjecture post = ilu.dual_clauses(conj) if conj != None else ilu.true_clauses() pre = self.g.states[0].clauses axioms = im.module.background_theory() rev = ilu.and_clauses(reverse_image(post,axioms,self.g.states[1].update), axioms) clauses = ilu.and_clauses(pre,rev) mod = get_model_clauses(clauses) assert mod != None diag = clauses_model_to_diagram(rev,is_skolem,model=mod) self.g.states[0].clauses = diag self.view_state(self.g.states[0], reset=True) self.show_used_relations(diag,both=True)
def recompute(self): if not self.needs_recompute: ## print "skipped recompute" return self.needs_recompute = False ## print "did recompute" self.solver.pop() self.solver.push() self.solver_clauses = true_clauses() self.get_solver_clauses() for n in self.all_nodes: self.check_node(n) self.nodes = [ GraphNode(n.name, n.fmla, n.sort) for n in self.all_nodes if n.status != "false" ] for r in self.relations: r.compute_edges(self.solver)
def diagram(self): from ivy_solver import clauses_model_to_diagram, get_model_clauses from ivy_transrel import is_skolem, reverse_image if not self.have_cti: if self.check_inductiveness() or len(self.g.states) != 2: return conj = self.current_conjecture post = ilu.dual_clauses(conj) if conj != None else ilu.true_clauses() pre = self.g.states[0].clauses axioms = im.module.background_theory() rev = ilu.and_clauses( reverse_image(post, axioms, self.g.states[1].update), axioms) clauses = ilu.and_clauses(pre, rev) mod = get_model_clauses(clauses) assert mod != None diag = clauses_model_to_diagram(rev, is_skolem, model=mod) self.g.states[0].clauses = diag self.view_state(self.g.states[0], reset=True) self.show_used_relations(diag, both=True)
def make_vc(action, precond=[], postcond=[], check_asserts=True): ag = art.AnalysisGraph() pre = itp.State() pre.clauses = lut.Clauses([lf.formula for lf in precond]) pre.clauses.annot = act.EmptyAnnotation() with itp.EvalContext(check=False): # don't check safety post = ag.execute(action, pre) post.clauses = lut.true_clauses() fail = itp.State(expr=itp.fail_expr(post.expr)) history = ag.get_history(post) axioms = im.module.background_theory() clauses = history.post #Tricky: fix the annotation so it matches the original action stack = [] while isinstance(clauses.annot, act.RenameAnnotation): stack.append(clauses.annot.map) clauses.annot = clauses.annot.arg clauses.annot = clauses.annot.args[1] while stack: clauses.annot = act.RenameAnnotation(clauses.annot, stack.pop()) clauses = lut.and_clauses(clauses, axioms) fc = lut.Clauses([lf.formula for lf in postcond]) fc.annot = act.EmptyAnnotation() used_names = frozenset(x.name for x in lg.sig.symbols.values()) def witness(v): c = lg.Symbol('@' + v.name, v.sort) assert c.name not in used_names return c fcc = lut.dual_clauses(fc, witness) clauses = lut.and_clauses(clauses, fcc) return clauses
def set_state(self,clauses,recomp=True): self.state = clauses self.solver_clauses = true_clauses() self.predicates = self.get_predicates(clauses) sig = self.parent_state.domain.sig ufs = [x for x,arity in self.parent_state.domain.functions.iteritems() if arity == 1 and not has_enumerated_sort(sig,x)] if not hasattr(self,'brels'): self.brels = ([self.make_rel_lit(r,['X','Y']) for r,arity in self.parent_state.domain.all_relations if arity == 2] + [Literal(1,Atom(equals,[App(f,Variable('X',f.sort.dom[0])),Variable('Y',f.sort.rng)])) for f in ufs]) # brels = list(used_binary_relations_clauses(clauses)) # brels = [r for r in brels if ((r != equals) and not r.startswith('__'))] ## print "brels: %s" % brels self.relations = [GraphRelation(self,rel) for rel in self.brels] self.relations += [GraphRelationUnary(self,rel) for rel in self.predicates if not isinstance(rel,tuple) and used_variables_ast(rel)] self.relations += [GraphFunctionUnary(self,Literal(1,rel[0])) for rel in self.predicates if isinstance(rel,tuple)] self.needs_recompute = True if recomp: self.recompute()
def set_state(self, clauses, recomp=True): self.state = clauses self.solver_clauses = true_clauses() self.predicates = self.get_predicates(clauses) sig = self.parent_state.domain.sig ufs = [ x for x, arity in self.parent_state.domain.functions.iteritems() if arity == 1 and not has_enumerated_sort(sig, x) ] if not hasattr(self, 'brels'): self.brels = ([ self.make_rel_lit(r, ['X', 'Y']) for r, arity in self.parent_state.domain.all_relations if arity == 2 ] + [ Literal( 1, Atom(equals, [ App(f, Variable('X', f.sort.dom[0])), Variable('Y', f.sort.rng) ])) for f in ufs ]) # brels = list(used_binary_relations_clauses(clauses)) # brels = [r for r in brels if ((r != equals) and not r.startswith('__'))] ## print "brels: %s" % brels self.relations = [GraphRelation(self, rel) for rel in self.brels] self.relations += [ GraphRelationUnary(self, rel) for rel in self.predicates if not isinstance(rel, tuple) and used_variables_ast(rel) ] self.relations += [ GraphFunctionUnary(self, Literal(1, rel[0])) for rel in self.predicates if isinstance(rel, tuple) ] self.needs_recompute = True if recomp: self.recompute()
def assert_action(fmla): fail_flag = Symbol("sys:fail",RelationSort([])) return SemActionValue([fail_flag],true_clauses(), Clauses(defs = [Definition(new(fail_flag),Or(fail_flag,Not(fmla)))]))
def int_update(self,domain,pvars): return ([], true_clauses(), false_clauses())
def action_failure(action): assert isinstance(action,SemActionValue) upd,tr,pre = action.comps print "action_failure upd: {}".format([str(x) for x in upd]) return type(action)(upd,pre,true_clauses())
def null_update(): return SemActionValue([],true_clauses(),false_clauses())
def get_update_axioms(self,updated,action): defines = self.defn.args[0].rep if defines not in updated and any(x in self.dependencies for x in updated): updated.append(defines) return (updated,true_clauses(),false_clauses())
def action_failure(action): upd,tr,pre = action return upd,pre,true_clauses()
def get_update_axioms(self, updated, action): defines = self.defn.args[0].rep if defines not in updated and any(x in self.dependencies for x in updated): updated.append(defines) return (updated, true_clauses(), false_clauses())
def null_update(): return ([], true_clauses(), false_clauses())
def action_failure(action): upd, tr, pre = action return upd, pre, true_clauses()
def top_state(): return pure_state(true_clauses())
def null_update(): return ([],true_clauses(),false_clauses())
def check_inductiveness(self, button=None): import ivy_transrel from ivy_solver import get_small_model from proof import ProofGoal from ivy_logic_utils import Clauses, and_clauses, dual_clauses from random import randrange with self.ui_parent.run_context(): ag = self.new_ag() pre = State() pre.clauses = and_clauses(*self.conjectures) action = im.module.actions['ext'] with EvalContext(check=False): # don't check safety post = ag.execute(action, pre, None, 'ext') post.clauses = ilu.true_clauses() to_test = list(self.conjectures) + [None] # None = check safety while len(to_test) > 0: # choose randomly, so the user can get another result by # clicking again conj = to_test.pop(randrange(len(to_test))) assert conj == None or conj.is_universal_first_order() used_names = frozenset(x.name for x in il.sig.symbols.values()) def witness(v): c = lg.Const('@' + v.name, v.sort) assert c.name not in used_names return c # TODO: this is still a bit hacky, and without nice error reporting if self.relations_to_minimize.value == 'relations to minimize': self.relations_to_minimize.value = ' '.join(sorted( k for k, v in il.sig.symbols.iteritems() if (type(v.sort) is lg.FunctionSort and v.sort.range == lg.Boolean and v.name not in self.transitive_relations and '.' not in v.name ) )) if conj == None: # check safety clauses = ilu.true_clauses() rels_to_min = [il.sig.symbols[x] for x in self.relations_to_minimize.value.split()] else: clauses = dual_clauses(conj, witness) history = ag.get_history(post) rels_to_min = [ # TODO: this is still a bit hacky, and without nice error reporting history.maps[0].get(relation, relation) for x in self.relations_to_minimize.value.split() for relation in [il.sig.symbols[x]] ], _get_model_clauses = lambda clauses, final_cond=False: get_small_model( clauses, sorted(il.sig.sorts.values()), rels_to_min, final_cond = final_cond ) if conj == None: print "check safety" res = ag.check_bounded_safety(post, _get_model_clauses) else: res = ag.bmc(post, clauses, None, None, _get_model_clauses) if res is not None: self.current_conjecture = conj assert len(res.states) == 2 # self.set_states(res.states[0], res.states[1]) # self.cti = self.ui_parent.add(res) self.g = res self.rebuild() self.view_state(self.g.states[0], reset=True) self.show_used_relations(clauses) #self.post_graph.selected = self.get_relevant_elements(self.post_state[2], clauses) if conj == None: self.ui_parent.ok_dialog('An assertion failed. A failing state is displayed. You can decompose\nthe failing action observe the failing execution. ') else: self.ui_parent.text_dialog('The following conjecture is not relatively inductive:', str(conj.to_formula()),on_cancel=None) self.have_cti = True return False # self.set_states(False, False) self.ui_parent.text_dialog('Inductive invariant found:', '\n'.join(str(conj) for conj in self.conjectures)) self.have_cti = False return True
def check_inductiveness(self, button=None): import ivy_transrel from ivy_solver import get_small_model from proof import ProofGoal from ivy_logic_utils import Clauses, and_clauses, dual_clauses from random import randrange from ivy_art import AnalysisGraph with self.ui_parent.run_context(): ag, succeed, fail = ivy_trace.make_check_art( precond=self.conjectures) to_test = [None] + list(self.conjectures) # None = check safety while len(to_test) > 0: # choose randomly, so the user can get another result by # clicking again # conj = to_test.pop(randrange(len(to_test))) conj = to_test.pop(0) assert conj == None or conj.is_universal_first_order() used_names = frozenset(x.name for x in il.sig.symbols.values()) def witness(v): c = lg.Const('@' + v.name, v.sort) assert c.name not in used_names return c # TODO: this is still a bit hacky, and without nice error reporting if self.relations_to_minimize.value == 'relations to minimize': self.relations_to_minimize.value = ' '.join( sorted(k for k, v in il.sig.symbols.iteritems() if ( type(v.sort) is lg.FunctionSort and v.sort.range == lg.Boolean and v.name not in self.transitive_relations # and '.' not in v.name ))) if conj == None: # check safety clauses = ilu.true_clauses() post = fail else: clauses = dual_clauses(conj, witness) post = succeed history = ag.get_history(post) rels_to_min = [] for x in self.relations_to_minimize.value.split(): relation = il.sig.symbols[x] relation = history.maps[0].get(relation, relation) rels_to_min.append(relation) clauses.annot = ia.EmptyAnnotation() res = ivy_trace.check_final_cond(ag, post, clauses, rels_to_min, True) # res = ag.bmc(post, clauses, None, None, _get_model_clauses) if res is not None: self.current_conjecture = conj assert len(res.states) == 2 self.g = res self.rebuild() self.view_state(self.g.states[0], reset=True) self.show_used_relations(clauses) #self.post_graph.selected = self.get_relevant_elements(self.post_state[2], clauses) if conj == None: self.ui_parent.ok_dialog( 'An assertion failed. A failing state is displayed. You can step into\nthe failing action to observe the failing execution. ' ) else: self.ui_parent.text_dialog( 'The following conjecture is not relatively inductive:', str(il.drop_universals(conj.to_formula())), on_cancel=None) self.have_cti = True return False # self.set_states(False, False) self.ui_parent.text_dialog( 'Inductive invariant found:', '\n'.join(str(conj) for conj in self.conjectures)) self.have_cti = False return True
def action_update(self, domain, pvars): type_check(domain, self.args[0]) # print type(self.args[0]) cl = formula_to_clauses(dual_formula(self.args[0])) return ([], true_clauses(), cl)