Example #1
0
def assert_any_transition(s: Solver,
                          t: Z3Translator,
                          state_index: int,
                          allow_stutter: bool = False) -> None:
    prog = syntax.the_program
    uid = str(state_index)

    tids = []
    for transition in prog.transitions():
        tid = z3.Bool(get_transition_indicator(uid, transition.name))
        tids.append(tid)
        s.add(
            z3.Implies(
                tid,
                t.translate_expr(
                    New(transition.as_twostate_formula(prog.scope),
                        state_index))))

    if allow_stutter:
        tid = z3.Bool(get_transition_indicator(uid, '$stutter'))
        tids.append(tid)
        frame = syntax.And(*DefinitionDecl._frame(prog.scope, mods=()))
        s.add(z3.Implies(tid, t.translate_expr(New(frame, state_index))))

    s.add(z3.Or(*tids))
Example #2
0
def check_bmc(s: Solver, safety: Expr, depth: int, preconds: Optional[Iterable[Expr]] = None,
              minimize: Optional[bool] = None) -> Optional[Trace]:
    prog = syntax.the_program

    if preconds is None:
        preconds = (init.expr for init in prog.inits())

    t = s.get_translator(depth + 1)

    with s.new_frame():
        for precond in preconds:
            s.add(t.translate_expr(precond))

        s.add(t.translate_expr(syntax.New(syntax.Not(safety), depth)))

        for i in range(depth):
            s.add(t.translate_expr(New(safety, i)))
            assert_any_transition(s, t, i, allow_stutter=False)

        res = s.check()
        if res == solver.sat:
            z3m = s.model(minimize=minimize)
            m = Z3Translator.model_to_trace(z3m, depth + 1)
            return m
        elif res == solver.unknown:
            print('unknown!')
        return None
Example #3
0
 def add_states(self, num_states: int) -> None:
     assert self.include_program
     assert self.z3solver.num_scopes() == 0, (
         'the first time get_translator is called with new states, '
         'there must be no scopes pushed on the Z3 stack!')
     t = self.translator_factory(self.scope, num_states)
     for i in range(self.num_states, num_states):
         for a in self.mutable_axioms:
             self.add(t.translate_expr(New(a, i)))
     self.num_states = num_states
Example #4
0
def bmc_trace(prog: syntax.Program,
              trace: syntax.TraceDecl,
              s: Solver,
              sat_checker: Callable[[Solver, int], Optional[logic.Trace]],
              log: bool = False) -> Optional[logic.Trace]:
    n_states = len(list(trace.transitions())) + 1
    if log:
        print('%s states' % (n_states, ))

    lator = s.get_translator(n_states)

    with s.new_frame():
        if len(trace.components) > 0 and not isinstance(
                trace.components[0], syntax.AssertDecl):
            for init in prog.inits():
                s.add(lator.translate_expr(init.expr))

        i = 0
        for c in trace.components:
            if isinstance(c, syntax.AssertDecl):
                if c.expr is None:
                    if i != 0:
                        utils.print_error_and_exit(
                            c.span,
                            'assert init is only allowed in the first state')
                    for init in prog.inits():
                        assert i == 0
                        s.add(lator.translate_expr(init.expr))
                else:
                    s.add(lator.translate_expr(New(c.expr, i)))
            else:
                te: syntax.TransitionExpr = c.transition
                if isinstance(te, syntax.AnyTransition):
                    logic.assert_any_transition(s,
                                                lator,
                                                i,
                                                allow_stutter=True)
                else:
                    l = []
                    for call in te.calls:
                        tid = z3.Bool(
                            logic.get_transition_indicator(
                                str(i), call.target))
                        l.append(tid)
                        s.add(
                            z3.Implies(
                                tid,
                                translate_transition_call(s, lator, i, call)))
                    s.add(z3.Or(*l))

                i += 1

        return sat_checker(s, n_states)
Example #5
0
def translate_transition_call(s: Solver, lator: translator.Z3Translator,
                              state_index: int,
                              c: syntax.TransitionCall) -> z3.ExprRef:
    prog = syntax.the_program
    ition = prog.scope.get_definition(c.target)
    assert ition is not None
    bs = lator.bind(ition.binder)
    qs: List[Optional[z3.ExprRef]] = [b for b in bs]
    if c.args is not None:
        for j, a in enumerate(c.args):
            if not isinstance(a, syntax.Star):
                bs[j] = lator.translate_expr(New(a, state_index))
                qs[j] = None

    qs1 = [q for q in qs if q is not None]
    with lator.scope.in_scope(ition.binder, bs):
        body = lator.translate_expr(
            New(ition._framed_body(lator.scope), state_index))
    if qs1:
        return z3.Exists(qs1, body)
    else:
        return body
Example #6
0
 def to_z3(self, t: Z3Translator, new: bool = False) -> z3.ExprRef:
     # TODO: make this return Expr, not z3.ExprRef
     bs = t.bind(self.binder)
     with t.scope.in_scope(self.binder, bs):
         z3conjs = []
         self.trackers = []
         self.reverse_map: List[Tuple[_RelevantDecl, int]] = []
         i = 0
         for (d, j, c) in self.conjuncts():
             p = z3.Bool('p%d' % i)
             self.trackers.append(p)
             self.reverse_map.append((d, j))
             z3conjs.append(p == t.translate_expr(New(c) if new else c))
             i += 1
     if bs:
         return z3.Exists(bs, z3.And(*z3conjs))
     else:
         return z3.And(*z3conjs)
Example #7
0
def check_two_state_implication_all_transitions(
        s: Solver,
        old_hyps: Iterable[Expr],
        new_conc: Expr,
        minimize: Optional[bool] = None,
) -> Optional[Tuple[z3.ModelRef, DefinitionDecl]]:
    t = s.get_translator(2)
    prog = syntax.the_program
    with s.new_frame():
        for h in old_hyps:
            s.add(t.translate_expr(h))
        s.add(t.translate_expr(New(Not(new_conc))))
        for trans in prog.transitions():
            with s.new_frame():
                s.add(t.translate_expr(trans.as_twostate_formula(prog.scope)))
                res = s.check()
                assert res in (solver.sat, solver.unsat), res
                if res != solver.unsat:
                    return s.model(minimize=minimize), trans
        return None
Example #8
0
def check_transitions(
        s: Solver,
        minimize: Optional[bool] = None,
        verbose: bool = True
) -> Optional[Tuple[syntax.InvariantDecl, Trace, DefinitionDecl]]:
    lator = s.get_translator(2)
    prog = syntax.the_program

    with s.new_frame():
        for inv in prog.invs():
            s.add(lator.translate_expr(inv.expr))

        for ition in prog.transitions():
            if 'check_transition' in utils.args and \
               utils.args.check_transition is not None and \
               ition.name not in utils.args.check_transition:
                continue

            if verbose:
                utils.logger.always_print('checking transition %s:' % (ition.name,))

            with s.new_frame():
                s.add(lator.translate_expr(ition.as_twostate_formula(prog.scope)))
                for inv in prog.invs():
                    if 'check_invariant' in utils.args and \
                       utils.args.check_invariant is not None and \
                       inv.name not in utils.args.check_invariant:
                        continue

                    with s.new_frame():
                        s.add(lator.translate_expr(New(Not(inv.expr))))

                        if inv.name is not None:
                            msg = ' ' + inv.name
                        elif inv.span is not None:
                            msg = ' on line %d' % inv.span[0].lineno
                        else:
                            msg = ''
                        if verbose:
                            utils.logger.always_print('  preserves invariant%s... ' % msg, end='')
                            sys.stdout.flush()

                        res = check_unsat([(inv.span, 'invariant%s is not preserved by transition %s'
                                            % (msg, ition.name)),
                                           (ition.span, 'this transition does not preserve invariant%s'
                                            % (msg,))],
                                          s, 2, minimize=minimize, verbose=verbose)
                        if res is not None:
                            if utils.args.smoke_test_solver:
                                pre_state = res.as_state(i=0)
                                for ax in prog.axioms():
                                    if pre_state.eval(ax.expr) is not True:
                                        print('\n\n'.join(str(x) for x in s.debug_recent()))
                                        print(res)
                                        assert False, f'bad transition counterexample for axiom {ax.expr} in pre state'
                                for pre_inv in prog.invs():
                                    if pre_state.eval(pre_inv.expr) is not True:
                                        print('\n\n'.join(str(x) for x in s.debug_recent()))
                                        print(res)
                                        msg = f'bad transition counterexample for invariant {pre_inv.expr} in pre state'
                                        assert False, msg
                                # need to implement mypyvy-level transition->expression translation
                                # res.eval_double_vocabulary(transition, start_location=0)
                                post_state = res.as_state(i=1)
                                if post_state.eval(inv.expr) is not False:
                                    print('\n\n'.join(str(x) for x in s.debug_recent()))
                                    print(res)
                                    msg = f'bad transition counterexample for invariant {inv.expr} in post state'
                                    assert False, msg

                            return inv, res, ition
    return None
Example #9
0
 def to_z3() -> z3.ExprRef:
     if isinstance(diag_or_expr, Diagram):
         return diag_or_expr.to_z3(t, new=True)
     else:
         return t.translate_expr(New(diag_or_expr))