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 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 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
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
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
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
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
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
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
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
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
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
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
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
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