Esempio n. 1
0
def verify_inductive_invariant(s: Solver, inv: List[Expr]) -> None:
    prog = syntax.the_program
    inits = [init.expr for init in prog.inits()]
    safeties = [inv.expr for inv in prog.invs() if inv.is_safety]

    assert logic.check_implication(s, inits, inv) is None
    assert logic.check_implication(s, inv, safeties) is None
    assert logic.check_two_state_implication_all_transitions(
        s, inv, syntax.And(*inv), minimize=False) is None
Esempio n. 2
0
 def record_predicate(self, e: Expr) -> None:
     for x in self.predicates:
         if x == e or (logic.check_implication(self.solver, [x], [e],
                                               minimize=False) is None
                       and logic.check_implication(self.solver, [e], [x],
                                                   minimize=False) is None):
             break
     else:
         self.predicates.append(e)
         utils.logger.info(
             f'learned new predicate, now have {len(self.predicates)} {e}')
Esempio n. 3
0
def brat_next_frame(s: Solver, prev_frame: List[Expr], bound: int,
                    inits: List[Expr], safety: Expr, bad_cache: Set[Diagram],
                    minimize: bool) -> List[Expr]:
    current_frame: List[Expr] = new_frame(s, prev_frame)

    for bad_model in bad_cache:
        if logic.check_implication(s, current_frame,
                                   [syntax.Not(bad_model.to_ast())]) is None:
            continue
        current_frame.append(
            post_image_prime_consequence(
                s,
                prev_frame,
                inits,
                bad_model,
                gen_order=utils.args.generalization_order))

    while (bad_trace := bmc_upto_bound(
            s,
            safety,
            bound,
            preconds=current_frame,
            minimize=minimize,
            relaxed_semantics=utils.args.relax_backwards)) is not None:
        bad_model = Diagram(bad_trace.as_state(0))
        utils.logger.debug("Example to block: %s" % str(bad_model))
        bad_cache.add(bad_model)
        learned_clause = post_image_prime_consequence(
            s,
            prev_frame,
            inits,
            bad_model,
            gen_order=utils.args.generalization_order)
        utils.logger.info("Learned clause: %s" % str(learned_clause))
        current_frame.append(learned_clause)
Esempio n. 4
0
File: updr.py Progetto: aatxe/mypyvy
    def record_predicate(self, e: Expr) -> None:
        for x in self.predicates:
            if x == e or equiv_expr(self.solver, x, e):
                break
        else:
            j = len(self.predicates)
            self.predicates.append(e)
            if logic.check_implication(self.solver,
                                       self.human_invariant, [e],
                                       minimize=False) is None:
                self.human_invariant_implies.add(j)
                for i, q in enumerate(self.human_invariant):
                    if equiv_expr(self.solver, e, q):
                        msg = '(which is a clause of the human invariant)'
                        assert i not in self.human_invariant_to_predicate
                        self.human_invariant_to_predicate[i] = j
                        break
                else:
                    msg = '(which is implied by the human invariant)'
            else:
                msg = ''

            utils.logger.info(
                f'learned new predicate, now have {len(self.predicates)} {e} {msg}'
            )
Esempio n. 5
0
File: updr.py Progetto: aatxe/mypyvy
 def is_frame_inductive(self, i: int) -> bool:
     for p in self.automaton.phases():
         if logic.check_implication(self.solver,
                                    self[i + 1].summary_of(p),
                                    self[i].summary_of(p),
                                    minimize=False) is not None:
             return False
     return True
Esempio n. 6
0
File: updr.py Progetto: aatxe/mypyvy
    def print_status(self) -> None:
        '''Print information useful for comparison with primal dual houdini

        TODO: convert from barbaric print() to civilized xml logging
        '''

        # update self.inductive_invariant
        inv = set(range(len(self.predicates)))
        changes = True
        while changes:
            changes = False
            for i in sorted(inv - self.inductive_invariant):
                if logic.check_two_state_implication_all_transitions(
                        self.solver, [self.predicates[j] for j in sorted(inv)],
                        self.predicates[i],
                        minimize=False) is not None:
                    changes = True
                    inv.remove(i)
        self.inductive_invariant |= inv
        # print information
        print(
            f'\n[{datetime.now()}] Current predicates ({len(self.predicates)} total, {len(self.inductive_invariant)} proven, {len(self.human_invariant_implies)} implied by human invariant):'
        )
        for i, p in enumerate(self.predicates):
            note = '({})'.format({
                phase.name(): max((j for j, f in enumerate(self.fs)
                                   if p in f.summary_of(phase)),
                                  default=-1)
                for phase in self.automaton.phases()
            })
            if i in self.inductive_invariant:
                note += f' (invariant)'
            if i in self.human_invariant_implies:
                note += f' (implied by human invariant)'
            print(f'  predicates[{i:3}]{note}: {self.predicates[i]}')
        for i, p in enumerate(self.human_invariant):
            if (i not in self.human_invariant_proved
                    and len(self.inductive_invariant) > 0
                    and logic.check_implication(self.solver, [
                        self.predicates[j]
                        for j in sorted(self.inductive_invariant)
                    ], [p],
                                                minimize=False) is None):
                self.human_invariant_proved.add(i)
        print(
            f'\n[{datetime.now()}] Current human invariant ({len(self.human_invariant)} total, {len(self.human_invariant_to_predicate)} learned, {len(self.human_invariant_proved)} proven):'
        )
        for i, p in enumerate(self.human_invariant):
            notes = []
            if i in self.human_invariant_proved:
                notes.append('proved')
            if i in self.human_invariant_to_predicate:
                notes.append(
                    f'learned as predicates[{self.human_invariant_to_predicate[i]}]'
                )
            note = '(' + ', '.join(notes) + ')'
            print(f'  human_invariant[{i:3}]{note}: {p}')
        print()
Esempio n. 7
0
 def _simplify_summary(self, f: MySet[Expr]) -> None:
     l = []
     for c in reversed(f.l):
         f_minus_c = [x for x in f.l if x in f.s and x is not c]
         if c not in self.safeties and \
            logic.check_implication(self.solver, f_minus_c, [c], minimize=False) is None:
             f.s.remove(c)
         else:
             l.append(c)
     l.reverse()
     f.l = l
Esempio n. 8
0
File: updr.py Progetto: aatxe/mypyvy
 def _simplify_summary(self, f: MySet[Expr], p: Phase) -> None:
     l = []
     for c in reversed(f.l):
         f_minus_c = [x for x in f.l if x in f.s and x is not c]
         if c not in phases.phase_safety(p) and \
            logic.check_implication(self.solver, f_minus_c, [c], minimize=False) is None:
             utils.logger.debug('removed %s' % c)
             f.s.remove(c)
         else:
             l.append(c)
     l.reverse()
     f.l = l
Esempio n. 9
0
File: updr.py Progetto: 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)
Esempio n. 10
0
def itp_gen(s: Solver) -> None:
    k = 4

    prog = syntax.the_program
    safety = syntax.And(*(inv.expr for inv in prog.invs() if inv.is_safety))
    inits = [init.expr for init in prog.inits()]

    utils.logger.info("initial state: %s" % str(inits))
    utils.logger.info("proving safety property: %s" % safety)

    candidate = [safety]
    while True:
        cti = get_cti(s, syntax.And(*candidate))
        if cti is None:
            break

        pre_diag = cti[0]

        with logic.BoundedReachabilityCheck(s, syntax.the_program,
                                            k) as bmc_checker:
            core = bmc_checker.check_and_core(pre_diag)
        pre_diag.minimize_from_core(core)

        pre_diag.generalize(
            s, lambda diag: generalize_cex_omission_checker(s, diag, k))

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

        utils.logger.info('adding new clause to the invariant: %s' % str(e))
        candidate.append(e)

    res = logic.check_implication(s, inits, candidate)
    if res is not None:
        utils.logger.always_print(
            "Failure: candidate %s excludes initial states" %
            ' & '.join(str(clause) for clause in candidate))
    else:
        utils.logger.always_print("Success! Inductive invariant:")
        for clause in candidate:
            utils.logger.always_print(str(clause))
Esempio n. 11
0
def brat(s: Solver) -> None:
    k = utils.args.depth

    prog = syntax.the_program
    safety = syntax.And(*(inv.expr for inv in prog.invs() if inv.is_safety))
    inits = [init.expr for init in prog.inits()]

    utils.logger.info("initial state: %s" % str(inits))
    utils.logger.info("proving safety property: %s" % safety)

    current_frame = inits
    prev_frame: List[Expr] = [syntax.FalseExpr]

    bad_cache: Set[Diagram] = set()

    idx = 0
    while logic.check_implication(s, current_frame, prev_frame,
                                  minimize=False) is not None:
        idx += 1
        prev_frame = current_frame
        if not utils.args.decrease_depth:
            current_depth = k
        else:
            current_depth = k - idx + 1
            if current_depth <= 0:
                assert False, "exhaused bmc depth: becoming non-positive"

        current_frame = brat_next_frame(s, prev_frame, current_depth, inits,
                                        safety, bad_cache,
                                        utils.args.minimize_models)
        utils.logger.info("Frame: %d" % idx)
        for c in current_frame:
            utils.logger.info(str(c))

    utils.logger.always_print("Success! Inductive invariant:")
    for clause in current_frame:
        utils.logger.always_print(str(clause))
    verify_inductive_invariant(s, current_frame)
Esempio n. 12
0
def itp_gen(s: Solver) -> None:
    k = utils.args.forward_depth

    prog = syntax.the_program
    safety = syntax.And(*(inv.expr for inv in prog.invs() if inv.is_safety))
    inits = [init.expr for init in prog.inits()]

    utils.logger.info("initial state: %s" % str(inits))
    utils.logger.info("proving safety property: %s" % safety)

    candidate = [safety]

    while True:
        cti = get_cti(s, syntax.And(*candidate))
        if cti is None:
            break

        pre_diag = cti[0]

        pre_diag.generalize(s,
                            lambda diag: bmc_upto_bound(
                                s, syntax.Not(diag.to_ast()), k) is None,
                            order=utils.args.generalization_order)

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

        utils.logger.info('adding new clause to the invariant: %s' % str(e))
        candidate.append(e)

    if logic.check_implication(s, inits, candidate) is not None:
        utils.logger.always_print(
            "Failure: candidate %s excludes initial states" %
            ' & '.join(str(clause) for clause in candidate))
    else:
        utils.logger.always_print("Success! Inductive invariant:")
        for clause in candidate:
            utils.logger.always_print(str(clause))
Esempio n. 13
0
File: updr.py Progetto: aatxe/mypyvy
 def valid_in_initial_frame(self, s: Solver, p: Phase,
                            diag: Diagram) -> Optional[z3.ModelRef]:
     return logic.check_implication(s, self.fs[0].summary_of(p),
                                    [syntax.Not(diag.to_ast())])
Esempio n. 14
0
 def valid_in_initial_frame(self, e: Expr) -> bool:
     return logic.check_implication(self.solver, self.fs[0].summary(), [e], minimize=False) is None
Esempio n. 15
0
def equiv_expr(solver: Solver, e1: Expr, e2: Expr) -> bool:
    return (logic.check_implication(solver, [e1], [e2], minimize=False) is None and
            logic.check_implication(solver, [e2], [e1], minimize=False) is None)
Esempio n. 16
0
 def is_frame_inductive(self, i: int) -> bool:
     res = logic.check_implication(self.solver, self[i + 1].summary(), self[i].summary(), minimize=False)
     return res is None
Esempio n. 17
0
            bstate_min = min(self.backwards_reachable_states,
                             key=lambda b: (b.known_absent_until_frame, b.num_steps_to_bad),
                             default=None)

            if bstate_min is None or (min_frame_no := bstate_min.known_absent_until_frame) == len(self) - 1:
                break

            if isinstance(state := bstate_min.state_or_expr, State):
                eval_res = state.eval(syntax.And(*(self[min_frame_no + 1].summary())))
                assert isinstance(eval_res, bool)
                if eval_res:
                    return bstate_min
            else:
                expr = state
                res = logic.check_implication(self.solver,
                                              self[min_frame_no + 1].summary(),
                                              [syntax.Not(expr)],
                                              minimize=False)
                if res is not None:
                    return bstate_min

            bstate_min.known_absent_until_frame += 1

        utils.logger.info('no existing states to block. looking for a new state.')

        f = self.fs[-1]
        if len(self.safeties) == 0 or (res := logic.check_implication(self.solver, f.summary(), self.safeties)) is None:
            utils.logger.info('frontier is safe. nothing new to block either.')
            return None

        state = Z3Translator.model_to_trace(res, 1).as_state(0)
        assert len(self) >= 2
Esempio n. 18
0
def valid_in_initial_frame(s: Solver, inits: List[Expr], e: Expr) -> bool:
    return logic.check_implication(s, inits, [e], minimize=False) is None