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 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 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) 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 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 summarize_isolate(mod): global check_lineno check_lineno = act.checked_assert.get() if check_lineno == "": check_lineno = None # print 'check_lineno: {}'.format(check_lineno) check = not opt_summary.get() subgoalmap = dict((x.id, y) for x, y in im.module.subgoals) axioms = [m for m in mod.labeled_axioms if m.id not in subgoalmap] schema_instances = [m for m in mod.labeled_axioms if m.id in subgoalmap] if axioms: print "\n The following properties are assumed as axioms:" for lf in axioms: print pretty_lf(lf) if mod.definitions: print "\n The following definitions are used:" for lf in mod.definitions: print pretty_lf(lf) if (mod.labeled_props or schema_instances) and not checked_action.get(): print "\n The following properties are to be checked:" if check: for lf in schema_instances: print pretty_lf(lf) + " [proved by axiom schema]" ag = ivy_art.AnalysisGraph() clauses1 = lut.true_clauses(annot=act.EmptyAnnotation()) pre = itp.State(value=clauses1) props = [x for x in im.module.labeled_props if not x.temporal] fcs = ([ (ConjAssumer if prop.id in subgoalmap else ConjChecker)(prop) for prop in props ]) check_fcs_in_state(mod, ag, pre, fcs) else: for lf in schema_instances + mod.labeled_props: print pretty_lf(lf) # after checking properties, make them axioms im.module.labeled_axioms.extend(im.module.labeled_props) im.module.update_theory() if mod.labeled_inits: print "\n The following properties are assumed initially:" for lf in mod.labeled_inits: print pretty_lf(lf) if mod.labeled_conjs: print "\n The inductive invariant consists of the following conjectures:" for lf in mod.labeled_conjs: print pretty_lf(lf) apply_conj_proofs(mod) if mod.isolate_info.implementations: print "\n The following action implementations are present:" for mixer, mixee, action in sorted(mod.isolate_info.implementations, key=lambda x: x[0]): print " {}implementation of {}".format( pretty_lineno(action), mixee) if mod.isolate_info.monitors: print "\n The following action monitors are present:" for mixer, mixee, action in sorted(mod.isolate_info.monitors, key=lambda x: x[0]): print " {}monitor of {}".format(pretty_lineno(action), mixee) # if mod.actions: # print "\n The following actions are present:" # for actname,action in sorted(mod.actions.iteritems()): # print " {}{}".format(pretty_lineno(action),actname) if mod.initializers: print "\n The following initializers are present:" for actname, action in sorted(mod.initializers, key=lambda x: x[0]): print " {}{}".format(pretty_lineno(action), actname) if mod.labeled_conjs and not checked_action.get(): print "\n Initialization must establish the invariant" if check: with itp.EvalContext(check=False): ag = ivy_art.AnalysisGraph(initializer=lambda x: None) check_conjs_in_state(mod, ag, ag.states[0]) else: print '' if mod.initializers: print "\n Any assertions in initializers must be checked", if check: ag = ivy_art.AnalysisGraph(initializer=lambda x: None) fail = itp.State(expr=itp.fail_expr(ag.states[0].expr)) check_safety_in_state(mod, ag, fail) checked_actions = get_checked_actions() if checked_actions and mod.labeled_conjs: print "\n The following set of external actions must preserve the invariant:" for actname in sorted(checked_actions): action = act.env_action(actname) print " {}{}".format(pretty_lineno(action), actname) if check: ag = ivy_art.AnalysisGraph() pre = itp.State() pre.clauses = get_conjs(mod) with itp.EvalContext(check=False): # don't check safety # post = ag.execute(action, pre, None, actname) post = ag.execute(action, pre) check_conjs_in_state(mod, ag, post, indent=12) else: print '' callgraph = defaultdict(list) for actname, action in mod.actions.iteritems(): for called_name in action.iter_calls(): callgraph[called_name].append(actname) some_assumps = False for actname, action in mod.actions.iteritems(): assumptions = [ sub for sub in action.iter_subactions() if isinstance(sub, act.AssumeAction) ] if assumptions: if not some_assumps: print "\n The following program assertions are treated as assumptions:" some_assumps = True callers = callgraph[actname] if actname in mod.public_actions: callers.append("the environment") prettyname = actname[4:] if actname.startswith('ext:') else actname prettycallers = [ c[4:] if c.startswith('ext:') else c for c in callers ] print " in action {} when called from {}:".format( prettyname, ','.join(prettycallers)) for sub in assumptions: print " {}assumption".format(pretty_lineno(sub)) tried = set() some_guarants = False for actname, action in mod.actions.iteritems(): guarantees = [ sub for sub in action.iter_subactions() if isinstance(sub, (act.AssertAction, act.Ranking)) ] if check_lineno is not None: guarantees = [ sub for sub in guarantees if sub.lineno == check_lineno ] if guarantees: if not some_guarants: print "\n The following program assertions are treated as guarantees:" some_guarants = True callers = callgraph[actname] if actname in mod.public_actions: callers.append("the environment") prettyname = actname[4:] if actname.startswith('ext:') else actname prettycallers = [ c[4:] if c.startswith('ext:') else c for c in callers ] print " in action {} when called from {}:".format( prettyname, ','.join(prettycallers)) roots = set(iu.reachable([actname], lambda x: callgraph[x])) for sub in guarantees: print " {}guarantee".format(pretty_lineno(sub)), if check and any(r in roots and (r, sub.lineno) not in tried for r in checked_actions): print_dots() old_checked_assert = act.checked_assert.get() act.checked_assert.value = sub.lineno some_failed = False for root in checked_actions: if root in roots: tried.add((root, sub.lineno)) action = act.env_action(root) ag = ivy_art.AnalysisGraph() pre = itp.State() pre.clauses = get_conjs(mod) with itp.EvalContext(check=False): post = ag.execute(action, prestate=pre) fail = itp.State(expr=itp.fail_expr(post.expr)) if not check_safety_in_state( mod, ag, fail, report_pass=False): some_failed = True break if not some_failed: print 'PASS' act.checked_assert.value = old_checked_assert else: print ""
def get_conjs(mod): fmlas = [lf.formula for lf in mod.labeled_conjs if not lf.explicit] return lut.Clauses(fmlas, annot=act.EmptyAnnotation())
def module_new_state(self, clauses): if isinstance(clauses, Clauses) and clauses.annot is None: clauses = Clauses(clauses.fmlas, clauses.defs, ivy_actions.EmptyAnnotation()) return State(self, clauses)