def encode_initialization(self) -> List[str]:
        # Recall that the running example is:
        #   AGEF(~g) & EFG(g) & ~g
        # where after atomizing we have:
        #   p2 & p1 & ~g
        class TopExprWalker(Visitor):
            def visit_unary_op(self, unary_op: UnaryOp):
                assert unary_op.name == '!', unary_op
                return op_not(self.dispatch(unary_op.arg))

            def visit_binary_op(me, binary_op: BinOp):
                assert binary_op.name in '=*+', binary_op
                if binary_op.name == '=':
                    assert binary_op.arg2 == Number(1), binary_op
                    return call_func(
                        self.desc_by_sig[binary_op.arg1],
                        {ARG_MODEL_STATE: smt_name_m(self.model_init_state)})

                else:
                    op = (op_and, op_or)[binary_op.name == '+']
                    smt1 = me.dispatch(binary_op.arg1)
                    smt2 = me.dispatch(binary_op.arg2)
                    return op([smt1, smt2])

        return [assertion(TopExprWalker().dispatch(self.top_formula))]
Exemple #2
0
    def encode_initialization(self) -> List[str]:
        q_init = self.aht.init_node
        m_init = self.model_init_state
        reach_args = {
            ARG_A_STATE: smt_name_q(q_init),
            ARG_MODEL_STATE: smt_name_m(m_init)
        }

        return [assertion(call_func(self.reach_func_desc, reach_args))]
Exemple #3
0
def _encode_transitions_ucw(reach_func_desc: FuncDesc,
                            rank_func_desc: FuncDesc,
                            tau_desc: FuncDesc,
                            desc_by_output: Dict[Signal, FuncDesc],
                            inputs: List[Signal],
                            q: Node,
                            m: int,
                            i_o: Label,
                            state_to_final_scc: dict = None) -> List[str]:
    # syntax sugar
    def smt_r(smt_m: str, smt_q: str):
        return call_func(rank_func_desc, {
            ARG_MODEL_STATE: smt_m,
            ARG_A_STATE: smt_q
        })

    def smt_reach(smt_m: str, smt_q: str):
        return call_func(reach_func_desc, {
            ARG_MODEL_STATE: smt_m,
            ARG_A_STATE: smt_q
        })

    def smt_tau(smt_m: str, i_o: Label):
        tau_args = build_tau_args_dict(inputs, smt_m, i_o)
        return call_func(tau_desc, tau_args)

    #

    smt_m, smt_q = smt_name_m(m), smt_name_q(q)
    smt_m_next = smt_tau(smt_m, i_o)

    smt_pre = op_and(
        [smt_reach(smt_m, smt_q),
         smt_out(smt_m, i_o, inputs, desc_by_output)])

    smt_post_conjuncts = []
    for q_next, is_fin in q.transitions[i_o]:
        if is_final_sink(q_next):
            smt_post_conjuncts = [false()]
            break

        smt_q_next = smt_name_q(q_next)

        smt_post_conjuncts.append(smt_reach(smt_m_next, smt_q_next))

        greater_op = _get_greater_op_ucw(q, is_fin, q_next, state_to_final_scc)
        if greater_op is not None:
            smt_post_conjuncts.append(
                greater_op(smt_r(smt_m, smt_q), smt_r(smt_m_next, smt_q_next)))

    smt_post = op_and(smt_post_conjuncts)
    pre_implies_post = op_implies(smt_pre, smt_post)
    free_input_args = get_free_input_args(i_o, inputs)

    return [assertion(forall_bool(free_input_args, pre_implies_post))]
 def encode_initialization(self) -> List[str]:
     assertions = []
     for q, m in product(self.automaton.init_nodes,
                         [self.model_init_state]):
         vals_by_vars = {
             ARG_MODEL_STATE: smt_name_m(m),
             ARG_A_STATE: smt_name_q(q)
         }
         assertions.append(
             assertion(call_func(self.reach_func_desc, vals_by_vars)))
     return assertions
Exemple #5
0
def _encode_transitions_nbw(m: int, q: Node, reach_func_desc: FuncDesc,
                            rank_func_desc: FuncDesc, tau_desc: FuncDesc,
                            desc_by_output: Dict[Signal, FuncDesc],
                            inputs: List[Signal]) -> List[str]:
    # syntax sugar
    def smt_r(smt_m: str, smt_q: str):
        return call_func(rank_func_desc, {
            ARG_MODEL_STATE: smt_m,
            ARG_A_STATE: smt_q
        })

    def smt_reach(smt_m: str, smt_q: str):
        return call_func(reach_func_desc, {
            ARG_MODEL_STATE: smt_m,
            ARG_A_STATE: smt_q
        })

    def smt_tau(smt_m: str, i_o: Label):
        tau_args = build_tau_args_dict(inputs, smt_m, i_o)
        return call_func(tau_desc, tau_args)

    # reach(q,t) ->
    #     OR{(q,io,q') \in \delta(q)}:
    #         sys_out=o & reach(q',t') & rank(q,t,q',t')

    s_m = smt_name_m(m)
    s_q = smt_name_q(q)
    s_pre = smt_reach(s_m, s_q)

    s_disjuncts = list()  # type: List[str]
    for lbl, qn_flag_pairs in q.transitions.items(
    ):  # type: (Label, Set[Tuple[Node, bool]])
        s_m_next = smt_tau(s_m, lbl)
        s_out = smt_out(s_m, lbl, inputs, desc_by_output)
        free_inputs = get_free_input_args(lbl, inputs)
        for (q_next, is_acc) in qn_flag_pairs:
            if is_final_sink(q_next):
                s_disj = exists_bool(free_inputs, s_out)
                s_disjuncts.append(s_disj)
                break
            s_q_next = smt_name_q(q_next)
            s_reach = smt_reach(s_m_next, s_q_next)
            if is_acc:
                s_rank = true()  # TODO: SCCs
            else:
                s_rank = op_gt(smt_r(s_m, s_q), smt_r(s_m_next, s_q_next))

            s_disj = exists_bool(free_inputs, op_and([s_out, s_reach, s_rank]))
            s_disjuncts.append(s_disj)

    s_assertion = op_implies(s_pre, op_or(s_disjuncts))
    return [assertion(s_assertion)]
 def _encode_meaning_of_forbidding_atoms(self) -> List[str]:
     res = list()
     for k, a in enumerate(self.forbidding_atoms):
         states_to_forbid = set(
             filter(lambda n: n.k <= k, self.automaton.nodes))
         forbid_k_meaning = op_implies(
             a,
             op_and(
                 map(
                     lambda q_m: op_not(
                         call_func(
                             self.reach_func_desc, {
                                 ARG_A_STATE: smt_name_q(q_m[0]),
                                 ARG_MODEL_STATE: smt_name_m(q_m[1])
                             })),
                     product(states_to_forbid, self.max_model_states))))
         res.append(assertion(forbid_k_meaning))
     return res
Exemple #7
0
    def _encode_state(self, q: Node, m: int) -> List[str]:
        q_transitions = lfilter(lambda t: t.src == q, self.aht_transitions)

        # Encoding:
        # - if q is existential, then one of the transitions must fire:
        #
        #     reach(q,t) ->
        #                OR{state_label \in q_transitions}: sys_out=state_label & reach(q',t')
        #
        # - if q is universal, then all transitions of that system output should fire
        #
        #     reach(q,t) ->
        #                AND{state_label \in q_transitions}: sys_out=state_label -> reach(q',t')
        #

        # build s_premise `reach(q,t)`
        s_m = smt_name_m(m)
        s_q = smt_name_q(q)
        s_premise = call_func(self.reach_func_desc, {
            ARG_MODEL_STATE: s_m,
            ARG_A_STATE: s_q
        })

        # build s_conclusion `exists`
        s_conclusion_out_sExpr_pairs = set()  # type: Set[Tuple[str, str]]
        for t in q_transitions:  # type: Transition
            s_t_state_label = smt_out(s_m, t.state_label, self.inputs,
                                      self.descr_by_output)
            s_dst_expr = self._translate_dst_expr_into_smt(t.dst_expr, q, m)
            s_conclusion_out_sExpr_pairs.add((s_t_state_label, s_dst_expr))

        if q.is_existential:
            s_conclusion_elements = lmap(lambda sce: op_and(sce),
                                         s_conclusion_out_sExpr_pairs)
        else:
            s_conclusion_elements = lmap(
                lambda sce: op_implies(sce[0], sce[1]),
                s_conclusion_out_sExpr_pairs)

        s_conclusion = (op_and, op_or)[q.is_existential](s_conclusion_elements)

        s_assertion = op_implies(s_premise, s_conclusion)

        return [assertion(s_assertion)]
Exemple #8
0
def encode_model_bound(allowed_model_states: Iterable[int],
                       tau_desc: FuncDesc) -> List[str]:
    res = [comment('encoding model bound: ' + str(allowed_model_states))]

    # all args of tau function are quantified
    args_dict = dict((a, smt_name_free_arg(a))
                     for (a, ty) in tau_desc.ordered_argname_type_pairs)

    free_vars = [(args_dict[a], ty)
                 for (a, ty) in tau_desc.ordered_argname_type_pairs]

    smt_m_next = call_func(tau_desc, args_dict)

    disjuncts = []
    for allowed_m in iter(allowed_model_states):
        disjuncts.append(op_eq(smt_m_next, smt_name_m(allowed_m)))

    condition = forall(free_vars, op_or(disjuncts))
    res.append(assertion(condition))

    return res