def check_sequence(assume_assert_list, reporter): """True if clauses1 imply clauses2. """ s = z3.Solver() res = [] for aa in assume_assert_list: if isinstance(aa, Assume): # print "assume {}".format(aa.clauses) if reporter is not None: reporter.start(False, aa.doc) z1 = clauses_to_z3(aa.clauses) s.add(z1) res.append(True) else: # print "assert {}".format(aa.clauses) if reporter is not None: reporter.start(True, aa.doc) clauses2 = dual_clauses(aa.clauses) z2 = clauses_to_z3(clauses2) s.push() s.add(z2) res.append(s.check() == z3.unsat) if reporter is not None: if not reporter.end(s.check() == z3.unsat, aa.doc): return res s.pop() return res
def check_isolate(n_steps): step_action = ia.env_action(None) conjectures = im.module.conjs conj = ilu.and_clauses(*conjectures) 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 = ilu.dual_clauses(conj, witness) ag = art.AnalysisGraph() with ag.context as ac: # post = ac.new_state(ag.init_cond) ag.add_initial_state(ag.init_cond) post = ag.states[0] if 'initialize' in im.module.actions: init_action = im.module.actions['initialize'] post = ag.execute(init_action, None, None, 'initialize') for n in range(n_steps + 1): print 'Checking invariants at depth {}...'.format(n) res = ivy_trace.check_final_cond(ag,post,clauses,[],True) if res is not None: print 'BMC with bound {} found a counter-example...'.format(n) print print res exit(0) post = ag.execute(step_action)
def __init__(self, conj, report_pass=True, invert=True): self.fc = lut.formula_to_clauses(conj) if invert: def witness(v): return lg.Symbol('@' + v.name, v.sort) self.fc = lut.dual_clauses(self.fc, witness) self.report_pass = report_pass self.failed = False
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 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 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 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 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 check_sequence(assume_assert_list): """True if clauses1 imply clauses2. """ s = z3.Solver() res = [] for aa in assume_assert_list: if isinstance(aa, Assume): print "assume {}".format(aa.clauses) z1 = clauses_to_z3(aa.clauses) s.add(z1) res.append(True) else: print "assert {}".format(aa.clauses) clauses2 = dual_clauses(aa.clauses) z2 = clauses_to_z3(clauses2) s.push() s.add(z2) res.append(s.check() == z3.unsat) s.pop() return res
def bmc_conjecture(self, button=None, bound=None, conjecture=None, verbose=False, tell_unsat=True): import ivy_transrel import ivy_solver from proof import ProofGoal from ivy_logic_utils import Clauses, and_clauses, dual_clauses # get the bound, if not specified if bound is None: iv = self.current_bound if hasattr(self, 'current_bound') else None c = lambda b: self.bmc_conjecture(button=button, bound=b, conjecture=conjecture, verbose=verbose, tell_unsat=tell_unsat) self.ui_parent.int_dialog('Number of steps to check:', command=c, minval=0, initval=iv) return with self.ui_parent.run_context(): step_action = ia.env_action(None) n_steps = bound self.current_bound = bound conj = conjecture if conj is None: conj = and_clauses(*self.conjectures) assert 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(conj, witness) ag = self.new_ag() with ag.context as ac: # post = ac.new_state(ag.init_cond) ag.add_initial_state(ag.init_cond) post = ag.states[0] if 'initialize' in im.module.actions: print "got here" init_action = im.module.actions['initialize'] post = ag.execute(init_action, None, None, 'initialize') for n in range(n_steps + 1): res = ivy_trace.check_final_cond(ag, post, clauses, [], True) # res = ag.bmc(post, clauses) if verbose: if res is None: msg = 'BMC with bound {} did not find a counter-example to:\n{}'.format( n, str(conj.to_formula()), ) else: msg = 'BMC with bound {} found a counter-example to:\n{}'.format( n, str(conj.to_formula()), ) print '\n' + msg + '\n' if res is not None: # ta.step() cmd = lambda: self.ui_parent.add( res, ui_class=ivy_ui.AnalysisGraphUI) self.ui_parent.text_dialog( 'BMC with bound {} found a counter-example to:'.format( n), str(conj.to_formula()), command=cmd, command_label='View') return True post = ag.execute(step_action) if tell_unsat: self.ui_parent.text_dialog( 'BMC with bound {} did not find a counter-example to:'. format(n_steps), str(conj.to_formula()), on_cancel=None) return False
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 bmc_conjecture(self, button=None, bound = None, conjecture=None, verbose=False, add_to_crg=True): import ivy_transrel import ivy_solver from proof import ProofGoal from ivy_logic_utils import Clauses, and_clauses, dual_clauses # get the bound, if not specified if bound is None: iv = self.current_bound if hasattr(self,'current_bound') else None c = lambda b: self.bmc_conjecture(button=button, bound=b, conjecture=conjecture, verbose=verbose, add_to_crg=add_to_crg) self.ui_parent.int_dialog('Number of steps to check:', command = c, minval=0, initval=iv) return with self.ui_parent.run_context(): step_action = im.module.actions['ext'] n_steps = bound self.current_bound = bound if conjecture is None: conj = self.get_selected_conjecture() else: conj = conjecture assert 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(conj, witness) ag = self.parent.new_ag() with ag.context as ac: post = ac.new_state(ag.init_cond) if 'initialize' in im.module.actions: init_action = im.module.actions['initialize'] post = ag.execute(init_action, None, None, 'initialize') for n in range(n_steps + 1): res = ag.bmc(post, clauses) if verbose: if res is None: msg = 'BMC with bound {} did not find a counter-example to:\n{}'.format( n, str(conj.to_formula()), ) else: msg = 'BMC with bound {} found a counter-example to:\n{}'.format( n, str(conj.to_formula()), ) print '\n' + msg + '\n' if res is not None: # ta.step() cmd = lambda: self.ui_parent.add(res,ui_class=ivy_ui.AnalysisGraphUI) self.ui_parent.text_dialog('BMC with bound {} found a counter-example to:'.format(n), str(conj.to_formula()), command = cmd, command_label = 'View') return True post = ag.execute(step_action, None, None, 'ext') # self.ui_parent.text_dialog('BMC with bound {} did not find a counter-example to:'.format(n_steps), # str(conj.to_formula()), # on_cancel = None) return False
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 __init__(self,conj,report_pass=True): self.fc = lut.dual_clauses(lut.formula_to_clauses(conj)) self.report_pass = report_pass
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 __init__(self,conj,report_pass=True,invert=True): self.fc = lut.formula_to_clauses(conj) if invert: self.fc = lut.dual_clauses(self.fc) self.report_pass = report_pass self.failed = False