Example #1
0
    def get_architecture_trans_assumption(self, label,
                                          sys_state_vector) -> str:
        """ It handles 'is_active' and 'tok' variables in the specification. """

        #TODO: here I can add G(tok -> !prev) for the hub abstraction instead of specifying this on LTL level

        active_signals = list(
            filter(lambda s: s in label, self._is_active_signals))
        assert len(active_signals
                   ) <= 1, 'spec cannot contain > 1 is_active as conjunction'

        index_of_prev = index_of(lambda s: s in label,
                                 self._sends_prev_signals)
        assert index_of_prev is None or self.nof_processes == 1, \
            'using prev in the spec is not supported; prev in async hub abstraction works with local properties only'

        if not active_signals and not index_of_prev:
            return ''

        if active_signals:
            #: :type: QuantifiedSignal
            active = active_signals[0]
            proc_index = active.binding_indices[0]
        else:
            proc_index = self._sends_prev_signals[
                index_of_prev].binding_indices[0]
            assert self.nof_processes == 1, 'should come here only in the case of async hub'

        sends_prev_signal = _filter_by_proc(proc_index,
                                            self._sends_prev_signals)[0]

        value_by_sched, _ = build_signals_values(self._sched_signals, label)

        if self.nof_processes > 1:
            sends_prev_value = self._get_wrapped_prev_expr(
                proc_index, sys_state_vector, value_by_sched)
        else:
            #async_hub
            value_by_signal, _ = build_signals_values([sends_prev_signal],
                                                      label)
            sends_prev_value = value_by_signal[sends_prev_signal]

        if not active_signals:
            return sends_prev_value

        value_by_proc = self._build_label_from_proc_index(proc_index)

        value_by_signal = add_dicts(
            value_by_sched, value_by_proc,
            {sends_prev_signal: sends_prev_value},
            {self.state_arg_name: sys_state_vector[proc_index]})

        is_active_func_desc = self._get_desc_is_active(proc_index)

        func = self.underlying_solver.call_func(is_active_func_desc,
                                                value_by_signal)

        return func
Example #2
0
    def get_architecture_trans_assumption(self, label, sys_state_vector) -> str:
        """ It handles 'is_active' and 'tok' variables in the specification. """

        #TODO: here I can add G(tok -> !prev) for the hub abstraction instead of specifying this on LTL level

        active_signals = list(filter(lambda s: s in label, self._is_active_signals))
        assert len(active_signals) <= 1, 'spec cannot contain > 1 is_active as conjunction'

        index_of_prev = index_of(lambda s: s in label, self._sends_prev_signals)
        assert index_of_prev is None or self.nof_processes == 1, \
            'using prev in the spec is not supported; prev in async hub abstraction works with local properties only'

        if not active_signals and not index_of_prev:
            return ''

        if active_signals:
            #: :type: QuantifiedSignal
            active = active_signals[0]
            proc_index = active.binding_indices[0]
        else:
            proc_index = self._sends_prev_signals[index_of_prev].binding_indices[0]
            assert self.nof_processes == 1, 'should come here only in the case of async hub'

        sends_prev_signal = _filter_by_proc(proc_index, self._sends_prev_signals)[0]

        value_by_sched, _ = build_signals_values(self._sched_signals, label)

        if self.nof_processes > 1:
            sends_prev_value = self._get_wrapped_prev_expr(proc_index,
                                                           sys_state_vector,
                                                           value_by_sched)
        else:
            #async_hub
            value_by_signal, _ = build_signals_values([sends_prev_signal], label)
            sends_prev_value = value_by_signal[sends_prev_signal]

        if not active_signals:
            return sends_prev_value

        value_by_proc = self._build_label_from_proc_index(proc_index)

        value_by_signal = add_dicts(value_by_sched,
                                    value_by_proc,
                                    {sends_prev_signal: sends_prev_value},
                                    {self.state_arg_name:sys_state_vector[proc_index]})

        is_active_func_desc = self._get_desc_is_active(proc_index)

        func = self.underlying_solver.call_func(is_active_func_desc, value_by_signal)

        return func
Example #3
0
    def get_proc_tau_additional_args(self, proc_label:Label, sys_state_vector, proc_index:int) -> dict:
        value_by_signal = dict()

        value_by_sched, _ = build_signals_values(self._sched_signals, proc_label)
        value_by_signal.update(value_by_sched)

        proc_index_label = self._build_label_from_proc_index(proc_index)  # assume the spec doesn't have proc_index
        value_by_proc, _ = build_signals_values(self._proc_signals, proc_index_label)
        value_by_signal.update(value_by_proc)

        if self.nof_processes > 1:  # for nof_processes=1 sends_prev_expr is not calculated, but an input
            sends_prev_signal = _filter_by_proc(proc_index, self._sends_prev_signals)[0]
            sends_prev_expr = self._get_wrapped_prev_expr(proc_index, sys_state_vector, value_by_sched)
            value_by_signal.update({sends_prev_signal: sends_prev_expr})

        return value_by_signal
Example #4
0
    def get_free_sched_vars(self, label) -> list:
        free_signals = set(
            filter(lambda sch: sch not in label, self._sched_signals))

        _, free_vars = build_signals_values(free_signals, Label())

        return free_vars
Example #5
0
    def _get_free_vars(self, label, impl):
        free_vars = set(chain(*[build_signals_values(impl.orig_inputs[proc_index], label)[1]
                                for proc_index in range(impl.nof_processes)]))

        free_vars.update(impl.get_free_sched_vars(label))

        return free_vars
Example #6
0
    def _get_free_vars(self, label, impl):
        free_vars = set(
            chain(
                *[
                    build_signals_values(impl.orig_inputs[proc_index], label)[1]
                    for proc_index in range(impl.nof_processes)
                ]
            )
        )

        free_vars.update(impl.get_free_sched_vars(label))

        return free_vars
Example #7
0
    def get_proc_tau_additional_args(self, proc_label: Label, sys_state_vector,
                                     proc_index: int) -> dict:
        value_by_signal = dict()

        value_by_sched, _ = build_signals_values(self._sched_signals,
                                                 proc_label)
        value_by_signal.update(value_by_sched)

        proc_index_label = self._build_label_from_proc_index(
            proc_index)  # assume the spec doesn't have proc_index
        value_by_proc, _ = build_signals_values(self._proc_signals,
                                                proc_index_label)
        value_by_signal.update(value_by_proc)

        if self.nof_processes > 1:  # for nof_processes=1 sends_prev_expr is not calculated, but an input
            sends_prev_signal = _filter_by_proc(proc_index,
                                                self._sends_prev_signals)[0]
            sends_prev_expr = self._get_wrapped_prev_expr(
                proc_index, sys_state_vector, value_by_sched)
            value_by_signal.update({sends_prev_signal: sends_prev_expr})

        return value_by_signal
Example #8
0
    def _get_next_state_restricted_condition(self, state, only_states, tau_desc: FuncDescription, state_arg_name: str):
        input_signals = [var for var, ty in tau_desc.inputs if var != state_arg_name]

        values_by_signal, free_vars = build_signals_values(input_signals, Label())

        args = {state_arg_name: state}
        args.update(values_by_signal)
        next_state_expr = self._underlying_solver.call_func(tau_desc, args)

        or_clauses = []
        for possible_state in only_states:
            or_clauses.append(self._underlying_solver.op_eq(next_state_expr, possible_state))

        condition = self._underlying_solver.forall_bool(free_vars, self._underlying_solver.op_or(or_clauses))
        return condition
Example #9
0
    def get_architecture_trans_assumption(self, label, sys_state_vector):
        # ignore active_i
        # add assumption 'G(!(tok & prev))' #TODO: add on LTL level?

        proc_state = sys_state_vector[0]

        prev_dict, _ = build_signals_values([self._sends_prev_signal], label)
        prev_expr = prev_dict[self._sends_prev_signal]

        #: :type: FuncDescription
        tok_func = self.outvar_desc_by_process[0][self._has_tok_signal]

        tok_expr = call_func(tok_func, {self.state_arg_name: proc_state})

        tok_and_prev = op_and([tok_expr, prev_expr])

        not_and_tok_sends_prev = op_not(tok_and_prev)

        return not_and_tok_sends_prev
Example #10
0
    def _get_next_state_restricted_condition(self, state, only_states,
                                             tau_desc:FuncDescription,
                                             state_arg_name:str):
        input_signals = [var for var,ty in tau_desc.inputs if var != state_arg_name]

        values_by_signal, free_vars = build_signals_values(input_signals, Label())

        args = {state_arg_name: state}
        args.update(values_by_signal)
        next_state_expr = self._underlying_solver.call_func(tau_desc, args)

        or_clauses = []
        for possible_state in only_states:
            or_clauses.append(self._underlying_solver.op_eq(next_state_expr,
                                                            possible_state))

        condition = self._underlying_solver.forall_bool(free_vars,
                                                        self._underlying_solver.op_or(or_clauses))
        return condition
Example #11
0
    def get_architecture_trans_assumption(self, label, sys_state_vector):
        # ignore active_i
        # add assumption 'G(!(tok & prev))' #TODO: add on LTL level?

        proc_state = sys_state_vector[0]

        prev_dict, _ = build_signals_values([self._sends_prev_signal], label)
        prev_expr = prev_dict[self._sends_prev_signal]

        #: :type: FuncDescription
        tok_func = self.outvar_desc_by_process[0][self._has_tok_signal]

        tok_expr = call_func(tok_func, {self.state_arg_name: proc_state})

        tok_and_prev = op_and([tok_expr, prev_expr])

        not_and_tok_sends_prev = op_not(tok_and_prev)

        return not_and_tok_sends_prev
Example #12
0
    def _get_proc_tau_args(self, sys_state_vector, label, proc_index: int, impl) -> dict:
        """ Return dict: name->value
            free variables (to be enumerated) have ?var_name value.
        """

        proc_label = impl.filter_label_by_process(label, proc_index)

        glob_tau_args = dict()

        proc_state = sys_state_vector[proc_index]
        glob_tau_args.update({impl.state_arg_name: proc_state})

        # TODO: try to use label instead of proc_label
        #      should be the same -- alleviate the need of impl.filter_label_by_process
        label_vals_dict, _ = build_signals_values(impl.orig_inputs[proc_index], proc_label)
        glob_tau_args.update(label_vals_dict)

        glob_tau_args.update(impl.get_proc_tau_additional_args(proc_label, sys_state_vector, proc_index))

        return glob_tau_args
Example #13
0
    def _get_proc_tau_args(self, sys_state_vector, label, proc_index:int, impl) -> dict:
        """ Return dict: name->value
            free variables (to be enumerated) have ?var_name value.
        """

        proc_label = impl.filter_label_by_process(label, proc_index)

        glob_tau_args = dict()

        proc_state = sys_state_vector[proc_index]
        glob_tau_args.update({impl.state_arg_name: proc_state})

        #TODO: try to use label instead of proc_label
        #      should be the same -- alleviate the need of impl.filter_label_by_process
        label_vals_dict, _ = build_signals_values(impl.orig_inputs[proc_index], proc_label)
        glob_tau_args.update(label_vals_dict)

        glob_tau_args.update(impl.get_proc_tau_additional_args(proc_label, sys_state_vector, proc_index))

        return glob_tau_args
Example #14
0
    def _get_tok_rings_safety_props(self) -> StrAwareList:  # TODO: should be able to specify states!
        """
        Return (in SMT form, constraints on non-wrapped tau function):
         G(tok & !sends -> Xtok(tau(!prev)))
         G(sends -> tok)
         G(sends -> X!tok(!prev))
         G(Xtok(prev))
         G(!tok -> !Xtok(!prev))
        """
        smt_lines = StrAwareList()

        tau_desc = self.taus_descs[0]
        tau_signals = self.orig_inputs[0]

        tok_func_desc = self.outvar_desc_by_process[0][self._has_tok_signal]
        sends_func_desc = self.outvar_desc_by_process[0][self._sends_signal]

        prev_is_false_label = Label({self._sends_prev_signal: False})
        prev_is_true_label = Label({self._sends_prev_signal: True})

        states = self.states_by_process[0]
        for state in states:
            state_arg = {self.state_arg_name: state}

            has_tok_expr = call_func(tok_func_desc, state_arg)
            sends_tok_expr = call_func(sends_func_desc, state_arg)

            _, free_vars = build_signals_values(tau_signals, prev_is_false_label)

            nprev_arg, _ = build_signals_values(tau_signals, prev_is_false_label)
            nprev_state_arg = add_dicts(nprev_arg, state_arg)

            prev_arg, _ = build_signals_values(tau_signals, prev_is_true_label)
            prev_state_arg = add_dicts(prev_arg, state_arg)

            tau_nprev_expr = call_func(tau_desc, nprev_state_arg)
            tok_of_tau_nprev_expr = call_func(tok_func_desc, {self.state_arg_name: tau_nprev_expr})

            tau_prev_expr = call_func(tau_desc, prev_state_arg)
            tok_of_tau_prev_expr = call_func(tok_func_desc, {self.state_arg_name: tau_prev_expr})

            #
            tok_dont_disappear = forall_bool(free_vars,
                                             op_implies(op_and([has_tok_expr, op_not(sends_tok_expr)]),
                                                        tok_of_tau_nprev_expr))

            sends_with_token_only = forall_bool(free_vars,
                                                op_implies(sends_tok_expr, has_tok_expr))

            sends_means_release = forall_bool(free_vars,
                                              op_implies(sends_tok_expr, op_not(tok_of_tau_nprev_expr)))

            sends_prev_means_acquire = forall_bool(free_vars,
                                                   tok_of_tau_prev_expr)

            no_sends_prev_no_tok_means_no_next_tok = forall_bool(free_vars,
                                                                 op_implies(op_not(has_tok_expr),
                                                                            op_not(tok_of_tau_nprev_expr)))

            smt_lines += [tok_dont_disappear,
                          sends_with_token_only,
                          sends_means_release,
                          sends_prev_means_acquire,
                          no_sends_prev_no_tok_means_no_next_tok]

        return smt_lines
Example #15
0
    def get_free_sched_vars(self, label) -> list:
        free_signals = set(filter(lambda sch: sch not in label, self._sched_signals))

        _, free_vars = build_signals_values(free_signals, Label())

        return free_vars
Example #16
0
    def _get_tok_rings_safety_props(
            self) -> StrAwareList:  # TODO: should be able to specify states!
        """
        Return (in SMT form, constraints on non-wrapped tau function):
         G(tok & !sends -> Xtok(tau(!prev)))
         G(sends -> tok)
         G(sends -> X!tok(!prev))
         G(Xtok(prev))
         G(!tok -> !Xtok(!prev))
        """
        smt_lines = StrAwareList()

        tau_desc = self.taus_descs[0]
        tau_signals = self.orig_inputs[0]

        tok_func_desc = self.outvar_desc_by_process[0][self._has_tok_signal]
        sends_func_desc = self.outvar_desc_by_process[0][self._sends_signal]

        prev_is_false_label = Label({self._sends_prev_signal: False})
        prev_is_true_label = Label({self._sends_prev_signal: True})

        states = self.states_by_process[0]
        for state in states:
            state_arg = {self.state_arg_name: state}

            has_tok_expr = call_func(tok_func_desc, state_arg)
            sends_tok_expr = call_func(sends_func_desc, state_arg)

            _, free_vars = build_signals_values(tau_signals,
                                                prev_is_false_label)

            nprev_arg, _ = build_signals_values(tau_signals,
                                                prev_is_false_label)
            nprev_state_arg = add_dicts(nprev_arg, state_arg)

            prev_arg, _ = build_signals_values(tau_signals, prev_is_true_label)
            prev_state_arg = add_dicts(prev_arg, state_arg)

            tau_nprev_expr = call_func(tau_desc, nprev_state_arg)
            tok_of_tau_nprev_expr = call_func(
                tok_func_desc, {self.state_arg_name: tau_nprev_expr})

            tau_prev_expr = call_func(tau_desc, prev_state_arg)
            tok_of_tau_prev_expr = call_func(
                tok_func_desc, {self.state_arg_name: tau_prev_expr})

            #
            tok_dont_disappear = forall_bool(
                free_vars,
                op_implies(op_and([has_tok_expr,
                                   op_not(sends_tok_expr)]),
                           tok_of_tau_nprev_expr))

            sends_with_token_only = forall_bool(
                free_vars, op_implies(sends_tok_expr, has_tok_expr))

            sends_means_release = forall_bool(
                free_vars,
                op_implies(sends_tok_expr, op_not(tok_of_tau_nprev_expr)))

            sends_prev_means_acquire = forall_bool(free_vars,
                                                   tok_of_tau_prev_expr)

            no_sends_prev_no_tok_means_no_next_tok = forall_bool(
                free_vars,
                op_implies(op_not(has_tok_expr),
                           op_not(tok_of_tau_nprev_expr)))

            smt_lines += [
                tok_dont_disappear, sends_with_token_only, sends_means_release,
                sends_prev_means_acquire,
                no_sends_prev_no_tok_means_no_next_tok
            ]

        return smt_lines