Example #1
0
File: updr.py Project: aatxe/mypyvy
        def edge_covering_checker(p: Phase) -> Optional[Tuple[Phase, Diagram]]:
            t = self.solver.get_translator(KEY_NEW, KEY_OLD)
            f = self.fs[-1]
            prog = syntax.the_program

            with self.solver:
                for c in f.summary_of(p):
                    self.solver.add(t.translate_expr(c, old=True))

                transitions_from_phase = self.automaton.transitions_from(p)

                for trans in prog.transitions():
                    edges_from_phase_matching_prog_trans = [
                        t for t in transitions_from_phase
                        if t.prog_transition_name() == trans.name
                    ]
                    if any(delta.precond is None
                           for delta in edges_from_phase_matching_prog_trans):
                        utils.logger.debug(
                            'transition %s is covered trivially by %s' %
                            (trans.name, p.name()))
                        continue

                    utils.logger.debug(
                        'checking transition %s is covered by %s' %
                        (trans.name, p.name()))

                    with self.solver:
                        self.solver.add(t.translate_transition(trans))
                        preconds = (
                            z3.Not(
                                t.translate_precond_of_transition(
                                    delta.precond(), trans))
                            for delta in edges_from_phase_matching_prog_trans)
                        self.solver.add(z3.And(*preconds))

                        if self.solver.check() != z3.unsat:
                            utils.logger.debug(
                                'phase %s cex to edge covering of transition %s'
                                % (p.name(), trans.name))
                            z3m: z3.ModelRef = self.solver.model()
                            mod = Trace.from_z3([KEY_OLD, KEY_NEW], z3m)
                            self.record_state(mod)
                            diag = mod.as_diagram(i=0)
                            return (p, diag)

                        utils.logger.debug(
                            'transition %s is covered non-trivially by %s' %
                            (trans.name, p.name()))
                        continue

                utils.logger.debug('all edges covered from phase %s' %
                                   p.name())
                return None
Example #2
0
File: updr.py Project: aatxe/mypyvy
        def safety_property_checker(
                p: Phase) -> Optional[Tuple[Phase, Diagram]]:
            res = logic.check_implication(self.solver, f.summary_of(p),
                                          (inv.expr
                                           for inv in phases.phase_safety(p)))

            if res is None:
                utils.logger.debug(
                    "Frontier frame phase %s implies safety, summary is %s" %
                    (p.name(), f.summary_of(p)))
                return None

            utils.logger.debug("Frontier frame phase %s cex to safety" %
                               p.name())
            z3m: z3.ModelRef = res
            mod = Trace.from_z3([KEY_ONE], z3m)
            self.record_state(mod)
            diag = mod.as_diagram()
            return (p, diag)
Example #3
0
File: updr.py Project: aatxe/mypyvy
    def add(self, p: Phase, e: Expr, depth: Optional[int] = None) -> None:
        self.counter += 1

        self.record_predicate(e)

        if depth is None:
            depth = len(self)

        if utils.args.smoke_test and utils.logger.isEnabledFor(logging.DEBUG):
            utils.logger.debug('smoke testing at depth %s...' % (depth, ))
            logic.check_bmc(self.solver, e, depth)

        self.debug_assert_inductive_trace()
        for i in range(depth + 1):
            self[i].strengthen(p, e)
            utils.logger.debug("%d %s %s" % (i, p.name(), e))
            self.debug_assert_inductive_trace()
        self.debug_assert_inductive_trace()
Example #4
0
File: updr.py Project: aatxe/mypyvy
    def find_predecessor(
        self, pre_frame: Frame, current_phase: Phase, diag: Diagram
    ) -> Tuple[z3.CheckSatResult, Union[Optional[MySet[int]], Tuple[
            PhaseTransition, Tuple[Phase, Diagram]]]]:
        t = self.solver.get_translator(KEY_NEW, KEY_OLD)

        if utils.args.use_z3_unsat_cores:
            core: Optional[MySet[int]] = MySet()
        else:
            core = None

        with self.solver:
            with self.solver.mark_assumptions_necessary():
                self.solver.add(diag.to_z3(t))

                transitions_into = self.automaton.transitions_to_grouped_by_src(
                    current_phase)
                for src in self._predecessor_precedence(
                        current_phase, list(transitions_into.keys())):
                    transitions = transitions_into[src]
                    assert transitions
                    utils.logger.debug(
                        "check predecessor of %s from %s by %s" %
                        (current_phase.name(), src.name(), transitions))
                    (sat_res, pre_diag) = self.find_predecessor_from_src_phase(
                        t, pre_frame, src, transitions, diag, core)
                    if sat_res == z3.unsat:
                        continue
                    return (sat_res, pre_diag)

                if utils.args.use_z3_unsat_cores:
                    assert core is not None
                    ret_core: Optional[MySet[int]] = MySet(sorted(core))
                else:
                    ret_core = None

                return (z3.unsat, ret_core)
Example #5
0
File: updr.py Project: aatxe/mypyvy
    def block(self,
              diag: Diagram,
              j: int,
              p: Phase,
              trace: Optional[RelaxedTrace] = None,
              safety_goal: bool = True) -> Union[Blocked, CexFound]:
        if trace is None:
            trace = []
        if j == 0 or (j == 1 and self.valid_in_initial_frame(
                self.solver, p, diag) is not None):
            if safety_goal:
                utils.logger.always_print('\n'.join(
                    ((t.pp() + ' ') if t is not None else '') + str(diag)
                    for t, diag in trace))
                print(
                    'abstract counterexample: the system has no universal inductive invariant proving safety'
                )
                # TODO: placeholder for analyzing relaxed trace
                # import relaxed_traces
                # print(relaxed_traces.diagram_trace_to_explicitly_relaxed_trace(trace, phases.phase_safety(p)))
                if utils.args.checkpoint_out:
                    self.store_frames(utils.args.checkpoint_out)
                raise AbstractCounterexample()
            else:
                if utils.logger.isEnabledFor(logging.DEBUG):
                    utils.logger.debug('failed to block diagram')
                return CexFound()

        while True:
            with utils.LogTag(utils.logger, 'block-attempt'):
                if utils.logger.isEnabledFor(logging.DEBUG):
                    utils.logger.debug('blocking diagram in frame %s' % j)
                    utils.logger.debug(str(diag))

                    self.print_frame(j - 1, lvl=logging.DEBUG)
                res, x = self.find_predecessor(self[j - 1], p, diag)
                if res == z3.unsat:
                    utils.logger.debug('no predecessor: blocked!')
                    assert x is None or isinstance(x, MySet)
                    core: Optional[MySet[int]] = x
                    self.augment_core_for_init(p, diag, core)
                    break
                assert isinstance(x, tuple), (res, x)
                trans, (pre_phase, pre_diag) = x

                trace.append((trans, pre_diag))
                ans = self.block(pre_diag, j - 1, pre_phase, trace,
                                 safety_goal)
                if not isinstance(ans, Blocked):
                    return ans
                trace.pop()

        if utils.logger.isEnabledFor(logging.DEBUG) and core is not None:
            utils.logger.debug('core %s' % core)
            utils.logger.debug('unminimized diag\n%s' % diag)

        diag.minimize_from_core(core)
        diag.generalize(self.solver, self[j - 1],
                        self.automaton.transitions_to_grouped_by_src(p),
                        p == self.automaton.init_phase(), j)

        e = syntax.Not(diag.to_ast())

        if utils.logger.isEnabledFor(logging.DEBUG):
            utils.logger.debug(
                'adding new clause to frames 0 through %d phase %s' %
                (j, p.name()))
        if utils.logger.isEnabledFor(logging.INFO):
            utils.logger.info("[%d] %s" % (j, str(e)))

        self.add(p, e, j)
        utils.logger.debug("Done blocking")

        return Blocked()
Example #6
0
File: updr.py Project: aatxe/mypyvy
    def push_conjunct(self,
                      frame_no: int,
                      c: Expr,
                      p: Phase,
                      frame_old_count: Optional[int] = None) -> None:
        is_safety = c in phases.phase_safety(p)

        f = self.fs[frame_no]
        while True:
            with utils.LogTag(utils.logger,
                              'pushing-conjunct-attempt',
                              lvl=logging.DEBUG,
                              frame=str(frame_no),
                              conj=str(c)):
                utils.logger.debug('frame %s phase %s attempting to push %s' %
                                   (frame_no, p.name(), c))

                res = self.clause_implied_by_transitions_from_frame(
                    f, p, c, minimize=is_safety or utils.args.block_may_cexs)
                if res is None:
                    utils.logger.debug('frame %s phase %s managed to push %s' %
                                       (frame_no, p.name(), c))

                    if utils.args.smoke_test and utils.logger.isEnabledFor(
                            logging.DEBUG):
                        utils.logger.debug('smoke testing...')
                        # TODO: phases
                        logic.check_bmc(self.solver, c, frame_no + 1)

                    # assert self.clause_implied_by_transitions_from_frame(f, p, c) is None
                    self[frame_no + 1].strengthen(p, c)
                    self.debug_assert_inductive_trace()
                    break

                pre_phase, (m, t) = res
                mod = Trace.from_z3([KEY_OLD, KEY_NEW], m)
                self.record_state(mod)
                diag = mod.as_diagram(i=0)

                if utils.logger.isEnabledFor(logging.DEBUG):
                    utils.logger.debug(
                        'frame %s failed to immediately push %s due to '
                        'transition %s' % (frame_no, c, t.pp()))
                    # utils.logger.debug(str(mod))
                if is_safety:
                    utils.logger.debug(
                        'note: current clause is safety condition')
                    self.block(diag,
                               frame_no,
                               pre_phase, [(None, c), (t, diag)],
                               safety_goal=True)
                else:
                    if utils.args.block_may_cexs:
                        ans = self.block(diag,
                                         frame_no,
                                         pre_phase, [(None, c), (t, diag)],
                                         safety_goal=False)
                        if isinstance(ans, CexFound):
                            break
                    else:
                        break
Example #7
0
    def block(self,
              diag: Diagram,
              j: int,
              p: Phase,
              trace: Optional[List[Tuple[Optional[PhaseTransition],
                                         Union[Diagram, Expr]]]] = None,
              safety_goal: bool = True) -> Union[Blocked, CexFound]:
        if trace is None:
            trace = []
        if j == 0 or (j == 1 and self.valid_in_initial_frame(
                self.solver, p, diag) is not None):
            if safety_goal:
                utils.logger.always_print('\n'.join(
                    ((t.pp() + ' ') if t is not None else '') + str(diag)
                    for t, diag in trace))
                print('abstract counterexample')
                raise Exception('abstract counterexample')
            else:
                if utils.logger.isEnabledFor(logging.DEBUG):
                    utils.logger.debug('failed to block diagram')
                    # utils.logger.debug(str(diag))
                return CexFound()

        # print fs
        while True:
            with utils.LogTag(utils.logger, 'block-attempt'):
                if utils.logger.isEnabledFor(logging.DEBUG):
                    utils.logger.debug('blocking diagram in frame %s' % j)
                    utils.logger.debug(str(diag))

                    self.print_frame(j - 1, lvl=logging.DEBUG)
                res, x = self.find_predecessor(self[j - 1], p, diag)
                if res == z3.unsat:
                    utils.logger.debug('no predecessor: blocked!')
                    assert x is None or isinstance(x, MySet)
                    core: Optional[MySet[int]] = x
                    self.augment_core_for_init(p, diag, core)
                    break
                assert isinstance(x, tuple), (res, x)
                trans, (pre_phase, pre_diag) = x

                trace.append((trans, pre_diag))
                ans = self.block(pre_diag, j - 1, pre_phase, trace,
                                 safety_goal)
                if not isinstance(ans, Blocked):
                    return ans
                trace.pop()

        if utils.logger.isEnabledFor(logging.DEBUG) and core is not None:
            utils.logger.debug('core %s' % core)
            utils.logger.debug('unminimized diag\n%s' % diag)

        diag.minimize_from_core(core)
        diag.generalize(self.solver, self[j - 1],
                        self.automaton.transitions_to_grouped_by_src(p),
                        p == self.automaton.init_phase(), j)

        e = syntax.Not(diag.to_ast())

        if utils.logger.isEnabledFor(logging.DEBUG):
            utils.logger.debug(
                'adding new clause to frames 0 through %d phase %s' %
                (j, p.name()))
        if utils.logger.isEnabledFor(logging.INFO):
            utils.logger.info("[%d] %s" % (j, str(e)))

        self.add(p, e, j)
        utils.logger.debug("Done blocking")

        return Blocked()