def __init__(self, solver: Solver) -> None: self.solver = solver prog = syntax.the_program if utils.args.automaton: automaton = prog.the_automaton() if automaton is None: utils.print_error_and_exit( None, 'updr --automaton requires the file to ' 'declare an automaton') else: the_phase = 'the_phase' pcs: List[syntax.PhaseComponent] = [] for t in prog.transitions(): pcs.append( syntax.PhaseTransitionDecl(None, t.name, None, the_phase)) for inv in prog.safeties(): pcs.append(inv) automaton = AutomatonDecl(None, [ syntax.InitPhaseDecl(None, the_phase), syntax.PhaseDecl(None, the_phase, pcs) ]) automaton.resolve(prog.scope) self.automaton = PhaseAutomaton(automaton) self.fs: List[Frame] = [] self.push_cache: List[Dict[Phase, Set[Expr]]] = [] self.counter = 0 self.predicates: List[Expr] = [] self.state_count = 0
def check_automaton_init(s: Solver, a: AutomatonDecl) -> None: utils.logger.always_print('checking automaton init:') prog = syntax.the_program t = s.get_translator(KEY_ONE) init_decl = a.the_init() assert init_decl is not None # checked by resolver init_phase = prog.scope.get_phase(init_decl.phase) assert init_phase is not None # checked by resolver with s: for init in prog.inits(): s.add(t.translate_expr(init.expr)) for inv in init_phase.invs(): with s: s.add(z3.Not(t.translate_expr(inv.expr))) if inv.tok is not None: msg = ' on line %d' % inv.tok.lineno else: msg = '' utils.logger.always_print(' implies phase invariant%s... ' % msg, end='') sys.stdout.flush() logic.check_unsat([ (inv.tok, 'phase invariant%s may not hold in initial state' % msg) ], s, [KEY_ONE])
def check_automaton_edge_covering(s: Solver, a: AutomatonDecl) -> None: utils.logger.always_print('checking automaton edge covering:') prog = syntax.the_program t = s.get_translator(KEY_NEW, KEY_OLD) for phase in a.phases(): utils.logger.always_print(' checking phase %s:' % phase.name) with s: for inv in phase.invs(): s.add(t.translate_expr(inv.expr, old=True)) for trans in prog.transitions(): if any(delta.transition == trans.name and delta.precond is None for delta in phase.transitions()): utils.logger.always_print(' transition %s is covered trivially.' % trans.name) continue utils.logger.always_print(' checking transition %s is covered... ' % trans.name, end='') with s: s.add(t.translate_transition(trans)) s.add(z3.And(*(z3.Not(t.translate_precond_of_transition(delta.precond, trans)) for delta in phase.transitions() if trans.name == delta.transition))) logic.check_unsat([(phase.tok, 'transition %s is not covered by this phase' % (trans.name, )), (trans.tok, 'this transition misses transitions from phase %s' % (phase.name,))], s, [KEY_OLD, KEY_NEW])
def __init__(self, solver: Solver) -> None: self.solver = solver prog = syntax.the_program if utils.args.automaton: automaton = prog.the_automaton() if automaton is None: utils.print_error_and_exit( None, 'updr --automaton requires the file to ' 'declare an automaton') else: the_phase = 'the_phase' pcs: List[syntax.PhaseComponent] = [] for t in prog.transitions(): pcs.append( syntax.PhaseTransitionDecl(None, t.name, None, the_phase)) for inv in prog.safeties(): pcs.append(inv) automaton = AutomatonDecl(None, [ syntax.InitPhaseDecl(None, the_phase), syntax.PhaseDecl(None, the_phase, pcs) ]) automaton.resolve(prog.scope) self.automaton = PhaseAutomaton(automaton) self.fs: List[Frame] = [] self.push_cache: List[Dict[Phase, Set[Expr]]] = [] self.counter = 0 self.predicates: List[Expr] = [] self.state_count = 0 self.inductive_invariant: Set[int] = set( ) # indices into predicates of currently inductive predicates self.human_invariant = tuple( itertools.chain(*(syntax.as_clauses(inv.expr) for inv in prog.invs() if not inv.is_safety))) # convert to CNF self.human_invariant_to_predicate: Dict[int, int] = dict( ) # dict mapping index of human_invariant to index of predicates self.human_invariant_proved: Set[int] = set( ) # indices into human_invariant that are implied by the current inductive_invariant self.human_invariant_implies: Set[int] = set( ) # indices into predicates of predicates that are implied by the human invariant self._first_frame()
def check_automaton_inductiveness(s: Solver, a: AutomatonDecl) -> None: utils.logger.always_print('checking automaton inductiveness:') prog = syntax.the_program t = s.get_translator(KEY_NEW, KEY_OLD) for phase in a.phases(): utils.logger.always_print(' checking phase %s:' % phase.name) with s: for inv in phase.invs(): s.add(t.translate_expr(inv.expr, old=True)) for delta in phase.transitions(): trans = prog.scope.get_definition(delta.transition) assert trans is not None precond = delta.precond target = prog.scope.get_phase( delta.target) if delta.target is not None else phase assert target is not None trans_pretty = '(%s, %s)' % (trans.name, str(precond) if (precond is not None) else 'true') utils.logger.always_print(' checking transition: %s' % trans_pretty) with s: s.add(t.translate_transition(trans, precond=precond)) for inv in target.invs(): with s: s.add(z3.Not(t.translate_expr(inv.expr))) if inv.tok is not None: msg = ' on line %d' % inv.tok.lineno else: msg = '' utils.logger.always_print( ' preserves invariant%s... ' % msg, end='') sys.stdout.flush() logic.check_unsat([ (inv.tok, 'invariant%s may not be preserved by transition %s in phase %s' % (msg, trans_pretty, phase.name)), (delta.tok, 'this transition may not preserve invariant%s' % (msg, )) ], s, [KEY_OLD, KEY_NEW])
def __init__(self, automaton_decl: AutomatonDecl) -> None: self.automaton_decl = automaton_decl self._phases: Dict[str, Phase] = OrderedDict() for p in self.automaton_decl.phases(): self._phases[p.name] = Phase(p) self._transitions = [ PhaseTransition( self._phases[p.name], self._phases[(delta.target if delta.target is not None else p.name)], delta) for p in self.automaton_decl.phases() for delta in p.transitions() ] init_decl = automaton_decl.the_init() assert init_decl is not None self._init_phase = self._phases[init_decl.phase] self.nontrivial = len(self._phases) > 1