def _get_wrapped_prev_expr(self, proc_index, sys_states_vector, value_by_sched: dict) -> str: assert self.nof_processes > 1, 'nonsense' prev_proc = (proc_index - 1) % self.nof_processes prev_proc_state = sys_states_vector[prev_proc] #: :type: QuantifiedSignal sends_signal = _filter_by_proc(prev_proc, self._sends_signals)[0] #: :type: FuncDescription sends_func_desc = self.outvar_desc_by_process[prev_proc][sends_signal] sends_prev_call = self.underlying_solver.call_func( sends_func_desc, {self.state_arg_name: prev_proc_state}) prev_is_sched_func = self._get_desc_prev_next_is_sched(True) curr_proc_index_label = self._build_label_from_proc_index(proc_index) prev_is_sched_args = add_dicts(value_by_sched, curr_proc_index_label) prev_is_sched_expr = self.underlying_solver.call_func( prev_is_sched_func, prev_is_sched_args) expr = self.underlying_solver.op_and( [sends_prev_call, prev_is_sched_expr]) return expr
def _get_wrapped_prev_expr(self, proc_index, sys_states_vector, value_by_sched:dict) -> str: assert self.nof_processes > 1, 'nonsense' prev_proc = (proc_index - 1) % self.nof_processes prev_proc_state = sys_states_vector[prev_proc] #: :type: QuantifiedSignal sends_signal = _filter_by_proc(prev_proc, self._sends_signals)[0] #: :type: FuncDescription sends_func_desc = self.outvar_desc_by_process[prev_proc][sends_signal] sends_prev_call = self.underlying_solver.call_func(sends_func_desc, {self.state_arg_name:prev_proc_state}) prev_is_sched_func = self._get_desc_prev_next_is_sched(True) curr_proc_index_label = self._build_label_from_proc_index(proc_index) prev_is_sched_args = add_dicts(value_by_sched, curr_proc_index_label) prev_is_sched_expr = self.underlying_solver.call_func(prev_is_sched_func, prev_is_sched_args) expr = self.underlying_solver.op_and([sends_prev_call, prev_is_sched_expr]) return expr
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
def _build_srcdst_to_io_labels(lts:LTS, outvars_treated_as_moore) -> dict: srcdst_to_io_labels = dict() for label, next_state in lts.tau_model.items(): crt_state = label['state'] i_label = _get_inputvals(label) o_label = _get_outputvals(label, lts, outvars_treated_as_moore) io_label = add_dicts(i_label, o_label) srcdst_to_io_labels[(crt_state, next_state)] = srcdst_to_io_labels.get((crt_state, next_state), list()) srcdst_to_io_labels[(crt_state, next_state)].append(io_label) return srcdst_to_io_labels
def _build_edge_labels(lts:LTS, state_variable, moore_signals) -> dict: edge_labels = dict() for label, next_state in lts.tau_model.items(): # TODO: bad: it assumes that label enumerates ALL possible values! crt_state = label[state_variable] i_label = _get_i_label(label, state_variable) o_label = _get_o_label(label, lts, moore_signals) io_label = add_dicts(i_label, o_label) edge_labels[(crt_state, next_state)] = edge_labels.get((crt_state, next_state), list()) edge_labels[(crt_state, next_state)].append(io_label) return edge_labels
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
def _build_edge_labels(lts: LTS, state_variable, moore_signals) -> dict: edge_labels = dict() for label, next_state in lts.tau_model.items( ): # TODO: bad: it assumes that label enumerates ALL possible values! crt_state = label[state_variable] i_label = _get_i_label(label, state_variable) o_label = _get_o_label(label, lts, moore_signals) io_label = add_dicts(i_label, o_label) edge_labels[(crt_state, next_state)] = edge_labels.get( (crt_state, next_state), list()) edge_labels[(crt_state, next_state)].append(io_label) return edge_labels
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
PAR_INPUT_VARIABLES = 'INPUT_VARIABLES' PAR_OUTPUT_VARIABLES = 'OUTPUT_VARIABLES' PAR_ASSUMPTIONS = 'ASSUMPTIONS' PAR_GUARANTEES = 'GUARANTEES' PAR_GENERAL_TEMPLATE_COUNT = "templates" PAR_SECTIONS = (PAR_GENERAL, PAR_INPUT_VARIABLES, PAR_OUTPUT_VARIABLES, PAR_ASSUMPTIONS, PAR_GUARANTEES) #reserved words: syntactic sugar to help to match exactly reserved word reserved_section_names = dict((s, s) for s in PAR_SECTIONS) reserved_bools = dict((s, s) for s in ('TRUE', 'FALSE')) reserved_quantifiers = {'Forall': 'QUANTIFIER'} reserved_all = add_dicts(reserved_bools, reserved_quantifiers, reserved_section_names) #states = ( # ('quantified', 'inclusive'), #) tokens = ['COMMA', 'SIGNAL_NAME', 'NUMBER', 'BOOL', 'TEMPORAL_UNARY', 'NEG', 'TEMPORAL_BINARY', 'OR', 'AND', 'IMPLIES', 'EQUIV', 'EQUALS', 'LPAREN', 'RPAREN', 'LBRACKET', 'RBRACKET', 'SEP' ] +\ list(reserved_section_names.values()) + \ list(set(reserved_quantifiers.values())) # list(reserved_bools.values()) #i use BOOL currently
from helpers.python_ext import add_dicts PAR_INPUT_VARIABLES = 'INPUT_VARIABLES' PAR_OUTPUT_VARIABLES = 'OUTPUT_VARIABLES' PAR_ASSUMPTIONS = 'ASSUMPTIONS' PAR_GUARANTEES = 'GUARANTEES' PAR_SECTIONS = (PAR_INPUT_VARIABLES, PAR_OUTPUT_VARIABLES, PAR_ASSUMPTIONS, PAR_GUARANTEES) #reserved words: syntactic sugar to help to match exactly reserved word reserved_section_names = dict((s, s) for s in PAR_SECTIONS) reserved_bools = dict((s, s) for s in ('TRUE', 'FALSE')) reserved_quantifiers = {'Forall': 'QUANTIFIER'} reserved_all = add_dicts(reserved_bools, reserved_quantifiers, reserved_section_names) #states = ( # ('quantified', 'inclusive'), #) tokens = ['COMMA', 'SIGNAL_NAME', 'NUMBER', 'BOOL', 'TEMPORAL_UNARY', 'NEG', 'TEMPORAL_BINARY', 'OR', 'AND', 'IMPLIES', 'EQUIV', 'EQUALS', 'LPAREN', 'RPAREN', 'LBRACKET', 'RBRACKET', 'SEP' ] +\ list(reserved_section_names.values()) + \ list(set(reserved_quantifiers.values())) # list(reserved_bools.values()) #i use BOOL currently #constant to ensure consistency of the code
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