def _get_desc_is_active( self, proc_index: int): # TODO: should not dependent on proc_index! #: :type: FuncDescription sends_func = self.outvar_desc_by_process[proc_index][ self._sends_signals[proc_index]] assert len(sends_func.inputs) == 1, 'consider easy case for now' assert list( sends_func.inputs )[0][0] == self.state_arg_name, 'consider easy case for now' sends_args = sends_func.get_args_list( {self.state_arg_name: self.state_arg_name}) #: :type: QuantifiedSignal sends_prev_signal = self._sends_prev_signals[proc_index] sched_eq_proc_arg_by_signal = self._get_equal_func_args( lmap(str, self._sched_signals), lmap(str, self._proc_signals)) sched_eq_proc_args = self._get_desc_equal_bools().get_args_list( sched_eq_proc_arg_by_signal) prev_is_sched_args = map(lambda signal_type: str(signal_type[0]), self._get_desc_prev_next_is_sched( True).inputs) # order is important if self.nof_processes > 1: body_template = '(or ({equal_bits} {sched_eq_proc_args}) \n' \ ' (and {sends_prev} ({prev_is_sched} {prev_is_sched_args}) )' \ ')' else: assert self.nof_processes == 1 body_template = '(or ({equal_bits} {sched_eq_proc_args}) \n' \ ' {sends_prev})' body = body_template.format_map({ 'equal_bits': self._EQUAL_BITS_NAME, 'sched_eq_proc_args': ' '.join(sched_eq_proc_args), 'prev_is_sched': self._PREV_IS_SCHED_NAME, 'prev_is_sched_args': ' '.join(prev_is_sched_args), 'sends_prev': str(sends_prev_signal), 'sends': sends_func.name, 'sends_args': ' '.join(sends_args), }) type_by_arg = dict([(sends_prev_signal, 'Bool')] + self._sched_arg_type_pairs + self._proc_arg_type_pairs) description = FuncDescription(self._IS_ACTIVE_NAME, type_by_arg, 'Bool', body) return description
def p_unit_data(p): """unit_data : empty | expressions """ if p[1] is None: p[0] = ([],[]) else: assumptions = lmap(lambda e: e.data, filter(lambda e: isinstance(e, Assumption), p[1])) guarantees = lmap(lambda e: e.data, filter(lambda e: isinstance(e, Guarantee), p[1])) p[0] = (assumptions, guarantees)
def __init__(self, top_formula: Expr, atm_by_p: Dict[Prop, Automaton], UCWs: Iterable[Automaton], tau_desc: FuncDesc, inputs: Iterable[Signal], desc_by_output: Dict[Signal, FuncDesc], all_model_states: Iterable[int], model_init_state: int = 0): self.top_formula = top_formula # type:Expr self.atm_by_sig = dict( map(lambda p_atm: (p_atm[0].arg1, p_atm[1]), atm_by_p.items())) # type: Dict[Signal, Automaton] self.UCWs = set(UCWs) # type: Set[Automaton] assert len(set(map(lambda n: n.name, chain(*lmap(lambda a: a.nodes, chain(atm_by_p.values(), self.atm_by_sig.values())))))) \ == \ len(set(chain(*lmap(lambda a: a.nodes, chain(atm_by_p.values(), self.atm_by_sig.values()))))), \ 'node names are not unique' self.inputs = set(inputs) # type: Set[Signal] self.tau_desc = tau_desc # type: FuncDesc self.desc_by_outSig = desc_by_output # type: Dict[Signal,FuncDesc] # we create fake outputs for A/E propositions; # they are defined via reach in `encode_headers`: # ( define-fun _prop ((m M)) Bool (__reach q0_prop m) ) self.desc_by_pSig = dict( map( lambda sig: (sig, FuncDesc(sig.name, {ARG_MODEL_STATE: TYPE_MODEL_STATE}, 'Bool' )), self.atm_by_sig)) self.desc_by_sig = dict( chain(self.desc_by_pSig.items(), self.desc_by_outSig.items())) assert set(map(lambda out_func: out_func.name, self.desc_by_outSig.values()))\ .isdisjoint(set(map(lambda prop_func:prop_func.name, self.desc_by_pSig.values()))),\ "output and prop func names should not collide" self.model_states = list(all_model_states) self.model_init_state = model_init_state # type: int self.last_allowed_states = None # type: List[int] reach_args = { ARG_A_STATE: TYPE_A_STATE, ARG_MODEL_STATE: TYPE_MODEL_STATE } r_args = reach_args self.reach_func_desc = FuncDesc(FUNC_REACH, reach_args, bool_type()) self.rank_func_desc = FuncDesc(FUNC_R, r_args, real_type())
def p_unit_data(p): """unit_data : empty | expressions """ if p[1] is None: p[0] = ([], []) else: assumptions = lmap(lambda e: e.data, filter(lambda e: isinstance(e, Assumption), p[1])) guarantees = lmap(lambda e: e.data, filter(lambda e: isinstance(e, Guarantee), p[1])) p[0] = (assumptions, guarantees)
def _accumulator(self, prev_proc, crt_proc, enum_clauses): equals_desc = self._get_desc_equal_bools() proc_eq_crt_args_dict = self._get_equal_func_args(lmap(str, self._proc_signals), crt_proc) sched_eq_prev_args_dict = self._get_equal_func_args(lmap(str, self._sched_signals), prev_proc) proc_eq_crt_args = equals_desc.get_args_list(proc_eq_crt_args_dict) sched_eq_prev_args = equals_desc.get_args_list(sched_eq_prev_args_dict) enum_clauses.append('(and ({equals} {proc_eq_crt}) ({equals} {sched_eq_prev}))'.format_map( { 'equals': self._EQUAL_BITS_NAME, 'proc_eq_crt': ' '.join(proc_eq_crt_args), 'sched_eq_prev': ' '.join(sched_eq_prev_args) }))
def __init__(self, automaton: Automaton, tau_desc: FuncDesc, inputs: Iterable[Signal], descr_by_output: Dict[Signal, FuncDesc], all_model_states: Iterable[int], max_k: int, model_init_state: int = 0 ): # the automata alphabet is inputs+outputs self.automaton = automaton self.inputs = list(inputs) # type: List[Signal] self.descr_by_output = descr_by_output # type: Dict[Signal,FuncDesc] self.tau_desc = tau_desc # type: FuncDesc self.max_model_states = list(all_model_states) reach_args_sig = { ARG_A_STATE: TYPE_A_STATE, ARG_MODEL_STATE: TYPE_MODEL_STATE } self.reach_func_desc = FuncDesc(FUNC_REACH, reach_args_sig, bool_type()) self.model_init_state = model_init_state # type: int self.last_allowed_states = None # type: List[int] self.max_k = max_k self.forbidding_atoms = lmap(lambda k: '__forbid%i' % k, range(self.max_k)) # type: List[str]
def _get_desc_tau_sched_wrapper(self, proc_index:int, all_models_inputs) -> FuncDescription: local_tau_input_signals = _filter_by_proc(proc_index, all_models_inputs) local_tau_arg_type_pairs = self._get_desc_local_tau(local_tau_input_signals).inputs type_by_signal = dict(local_tau_arg_type_pairs + self._sched_arg_type_pairs + self._proc_arg_type_pairs) local_tau_arg_type_pairs = list(map(lambda signal_type: signal_type[0], local_tau_arg_type_pairs)) is_active_desc = self._get_desc_is_active(proc_index) is_active_inputs = lmap(lambda signal: signal[0], is_active_desc.inputs) # TODO: hack: knowledge: var names are the same body = """ (ite ({is_active} {is_active_inputs}) ({tau} {local_tau_inputs}) {state}) """.format_map({'tau': self._TAU_NAME, 'local_tau_inputs': ' '.join(map(str, local_tau_arg_type_pairs)), 'state': self.state_arg_name, 'is_active': self._IS_ACTIVE_NAME, 'is_active_inputs': ' '.join(map(str, is_active_inputs))}) description = FuncDescription(self._TAU_SCHED_WRAPPER_NAME, type_by_signal, self._state_type, body) return description
def convert_aiger_model_to_tlsf_model(aiger_model: str, bad_name: str) -> str: """ :returns AIGER string with bad output removed and outputs have prefix 'controllable_' removed. The header is adapted. """ aiger_lines = aiger_model.splitlines() header_numbers = lmap(int, aiger_lines[0].split()[1:]) # aag M I L O A assert len(header_numbers) == 5, 'only old AIGER format is supported' new_header = 'aag ' + ' '.join( map(str, header_numbers[:3] + [header_numbers[3] - 1] + header_numbers[4:])) bad_def_line_idx, bad_sym_line_idx, bad_idx = _get_bad_line_indices( aiger_lines, bad_name) new_aiger_lines = [new_header] + \ aiger_lines[1:bad_def_line_idx] + \ aiger_lines[bad_def_line_idx+1:bad_sym_line_idx] + \ aiger_lines[bad_sym_line_idx+1:] symbols_table_start = 1 + sum(header_numbers[1:]) for i, l in enumerate(new_aiger_lines[symbols_table_start:]): if l[0] == 'o': cur_idx = int(l.split()[0][1:]) new_aiger_lines[symbols_table_start + i] = 'o{dec} {wo_prefix}'.format( dec=cur_idx - 1 if cur_idx > bad_idx else cur_idx, wo_prefix=' '.join( l.split()[1:])[len('controllable_'):]) if l[0] == 'c': break return '\n'.join( new_aiger_lines) + '\n' # some tools complain about not having this
def _get_desc_is_active(self, proc_index:int): # TODO: should not dependent on proc_index! #: :type: FuncDescription sends_func = self.outvar_desc_by_process[proc_index][self._sends_signals[proc_index]] assert len(sends_func.inputs) == 1, 'consider easy case for now' assert list(sends_func.inputs)[0][0] == self.state_arg_name, 'consider easy case for now' sends_args = sends_func.get_args_list({self.state_arg_name: self.state_arg_name}) #: :type: QuantifiedSignal sends_prev_signal = self._sends_prev_signals[proc_index] sched_eq_proc_arg_by_signal = self._get_equal_func_args(lmap(str, self._sched_signals), lmap(str, self._proc_signals)) sched_eq_proc_args = self._get_desc_equal_bools().get_args_list(sched_eq_proc_arg_by_signal) prev_is_sched_args = map(lambda signal_type: str(signal_type[0]), self._get_desc_prev_next_is_sched(True).inputs) # order is important if self.nof_processes > 1: body_template = '(or ({equal_bits} {sched_eq_proc_args}) \n' \ ' (and {sends_prev} ({prev_is_sched} {prev_is_sched_args}) )' \ ')' else: assert self.nof_processes == 1 body_template = '(or ({equal_bits} {sched_eq_proc_args}) \n' \ ' {sends_prev})' body = body_template.format_map({'equal_bits': self._EQUAL_BITS_NAME, 'sched_eq_proc_args': ' '.join(sched_eq_proc_args), 'prev_is_sched': self._PREV_IS_SCHED_NAME, 'prev_is_sched_args': ' '.join(prev_is_sched_args), 'sends_prev': str(sends_prev_signal), 'sends': sends_func.name, 'sends_args': ' '.join(sends_args), }) type_by_arg = dict([(sends_prev_signal, 'Bool')] + self._sched_arg_type_pairs + self._proc_arg_type_pairs) description = FuncDescription(self._IS_ACTIVE_NAME, type_by_arg, 'Bool', body) return description
def _accumulator(self, prev_proc, crt_proc, enum_clauses): equals_desc = self._get_desc_equal_bools() proc_eq_crt_args_dict = self._get_equal_func_args( lmap(str, self._proc_signals), crt_proc) sched_eq_prev_args_dict = self._get_equal_func_args( lmap(str, self._sched_signals), prev_proc) proc_eq_crt_args = equals_desc.get_args_list(proc_eq_crt_args_dict) sched_eq_prev_args = equals_desc.get_args_list(sched_eq_prev_args_dict) enum_clauses.append( '(and ({equals} {proc_eq_crt}) ({equals} {sched_eq_prev}))'. format_map({ 'equals': self._EQUAL_BITS_NAME, 'proc_eq_crt': ' '.join(proc_eq_crt_args), 'sched_eq_prev': ' '.join(sched_eq_prev_args) }))
def to_boolean_nusmv(lts: LTS, specification: SpecProperty) -> str: nof_state_bits = int(max(1, math.ceil(math.log(len(lts.states), 2)))) bits_by_state = dict((state, bin_fixed_list(i, nof_state_bits)) for (i, state) in enumerate(sorted(lts.states))) state_bits = lmap(_ith_state_bit, range(nof_state_bits)) _assert_no_intersection(state_bits, list(lts.input_signals) + lts.output_signals) dot_lines = StrAwareList() dot_lines += 'MODULE main' dot_lines += 'IVAR' dot_lines += [ ' {signal} : boolean;'.format(signal=s.name) for s in lts.input_signals ] dot_lines += 'VAR' dot_lines += [' {si} : boolean;'.format(si=si) for si in state_bits] dot_lines += 'DEFINE' dot_lines += [ ' {out_name} := {formula} ;'.format(out_name=out_name, formula=_get_formula( out_name, out_model, bits_by_state)) for (out_name, out_model) in lts.model_by_name.items() ] dot_lines += 'ASSIGN' for i, sb in enumerate(state_bits): sb_init = str(bits_by_state[list(lts.init_states)[0]][i]).upper() dot_lines += ' init({sb}) := {init_sb};'.format(sb=sb, init_sb=sb_init) dot_lines += ' next({sb}) := '.format(sb=sb) dot_lines += ' case' for (label, next_state) in lts.tau_model.items(): sb_next = str(bits_by_state[next_state][i]).upper() dot_lines += ' {formula} : {next_state};'.format( formula=_clause_to_formula(label, bits_by_state), next_state=sb_next) dot_lines += ' TRUE : FALSE;' # default: unreachable states, don't care dot_lines += ' esac;' expr = BinOp('->', and_expressions(specification.assumptions), and_expressions(specification.guarantees)) expr = WeakToUntilConverterVisitor().dispatch( expr) # SMV does not have Weak until dot_lines += 'LTLSPEC ' + AstToSmvProperty().dispatch(expr) return '\n'.join(dot_lines)
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)]
def lts_to_verilog(lts:LTS, module_name:str) -> str: s = StrAwareList() s += 'module {module}({inputs}, {outputs});'.format( inputs=', '.join(map(lambda sig: sig.name, lts.input_signals)), outputs=', '.join(map(lambda sig: sig.name, lts.output_signals)), module=module_name) s.newline() s += '\n'.join(['input {sig};'.format(sig=sig.name) for sig in lts.input_signals]) s.newline() s += '\n'.join(['output {sig};'.format(sig=sig.name) for sig in lts.output_signals]) s.newline() # TODO: don't use latches for state-less models nof_state_bits = math.ceil(math.log2(len(lts.states))) s += 'reg [{max_bit}:0] {state};'.format(max_bit=int(max(0., nof_state_bits-1)), # max_bit is at least 0 state=lts.state_name) s.newline() s += '\n'.join(['wire {out};'.format(out=sig.name) for sig in lts.output_signals]) s.newline() for out_sig, value_tuples in lts.output_models.items(): labels_true = lmap(lambda x: x[0], filter(lambda label_value: label_value[1], value_tuples.items())) assign = 'assign {sig} = {true_expr};'.format(sig=out_sig.name, true_expr=' || '.join(map(_label_to_verilog, labels_true)) if labels_true else '0') s += assign s.newline() s += 'initial begin' s += '{state} = 0;'.format(state=lts.state_name) s += 'end' s.newline() s += 'always@($global_clock)' s += 'begin' # you can also use '=' instead of '<=' here, but we will be strict tau_items = tuple(lts.tau_model.items()) s += 'if ({expr}) {state} <= {next_val};'.format(expr=_label_to_verilog(tau_items[0][0]), state=lts.state_name, next_val=tau_items[0][1]) for lbl, val in tau_items[1:]: s += 'else if ({expr}) {state} <= {next_val};'.format(expr=_label_to_verilog(lbl), state=lts.state_name, next_val=val) s += 'end' s += 'endmodule' return s.to_str()
def declare_fun(func_desc:FuncDescription) -> str: input_types = lmap(lambda i_t: i_t[1], func_desc.inputs) smt_str = '(declare-fun ' smt_str += func_desc.name + ' (' for var in input_types: smt_str += var + ' ' if len(input_types): smt_str = smt_str[:-1] smt_str += ') ' + str(func_desc.output) + ')\n' return smt_str
def declare_fun(func_desc: FuncDescription) -> str: input_types = lmap(lambda i_t: i_t[1], func_desc.inputs) smt_str = '(declare-fun ' smt_str += func_desc.name + ' (' for var in input_types: smt_str += var + ' ' if len(input_types): smt_str = smt_str[:-1] smt_str += ') ' + str(func_desc.output) + ')\n' return smt_str
def declare_fun(self) -> str: input_types = lmap(lambda i_t: i_t[1], self.inputs) smt_str = '(declare-fun ' smt_str += self.name + ' (' for var in input_types: smt_str += var + ' ' if len(input_types): smt_str = smt_str[:-1] smt_str += ') ' + str(self.output_ty) + ')\n' return smt_str
def lts_to_verilog(lts:LTS) -> str: s = StrAwareList() s += 'module model(i_clk, \n{inputs}, \n{outputs});'.format(inputs=', '.join(map(lambda sig: sig.name, lts.input_signals)), outputs=', '.join(map(lambda sig: sig.name, lts.output_signals))) s.newline() s += 'input i_clk;' s += '\n'.join(['input {sig};'.format(sig=sig.name) for sig in lts.input_signals]) s.newline() s += '\n'.join(['output {sig};'.format(sig=sig.name) for sig in lts.output_signals]) s.newline() nof_state_bits = max(1, math.ceil(math.log2(len(lts.states)))) s += 'reg [{max_bit}:0] {state};'.format(max_bit=nof_state_bits-1, state=lts.state_name) s.newline() s += '\n'.join(['wire {out};'.format(out=sig.name) for sig in lts.output_signals]) s.newline() for out_sig, value_tuples in lts.output_models.items(): labels_true = lmap(lambda x: x[0], filter(lambda label_value: label_value[1], value_tuples.items())) assign = 'assign {sig} = {true_expr};'.format(sig=out_sig.name, true_expr=' || '.join(map(_label_to_verilog, labels_true)) if labels_true else '0') s += assign s.newline() s += 'initial begin' s += '{state} = 0;'.format(state=lts.state_name) s += 'end' s.newline() s += 'always@(posedge i_clk)' s += 'begin' tau_items = tuple(lts.tau_model.items()) s += 'if ({expr}) {state} = {next_val};'.format(expr=_label_to_verilog(tau_items[0][0]), state=lts.state_name, next_val=tau_items[0][1]) for lbl, val in tau_items[1:]: s += 'else if ({expr}) {state} = {next_val};'.format(expr=_label_to_verilog(lbl), state=lts.state_name, next_val=val) s += 'end' s += 'endmodule' return s.to_str()
def _define_declare_functions(self, func_descs): #should preserve the order: some functions may depend on others desc_by_name = dict((desc.name, (i, desc)) for (i, desc) in enumerate(func_descs)) # TODO: cannot use set of func descriptions due to hack in FuncDescription unique_index_descs_sorted = sorted(desc_by_name.values(), key=lambda i_d: i_d[0]) unique_descs = lmap(lambda i_d: i_d[1], unique_index_descs_sorted) for desc in unique_descs: if desc.definition is not None: self._underlying_solver.define_fun(desc) else: self._underlying_solver.declare_fun(desc)
def _define_declare_functions(self, func_descs): # should preserve the order: some functions may depend on others desc_by_name = dict((desc.name, (i, desc)) for (i, desc) in enumerate(func_descs)) # TODO: cannot use set of func descriptions due to hack in FuncDescription unique_index_descs_sorted = sorted(desc_by_name.values(), key=lambda i_d: i_d[0]) unique_descs = lmap(lambda i_d: i_d[1], unique_index_descs_sorted) for desc in unique_descs: if desc.definition is not None: self._underlying_solver.define_fun(desc) else: self._underlying_solver.declare_fun(desc)
def _get_bad_line_indices(aiger_lines: List[str], bad_name: str) -> (int, int, int): """ :returns line_of_def, line_of_symbol, id """ header_numbers = lmap(int, aiger_lines[0].split()[1:]) # aag M I L O A symbols_table_start = 1 + sum(header_numbers[1:]) for i, l in enumerate(aiger_lines[symbols_table_start:]): if l == 'c': assert 0, 'name of the bad output was not found' if l[0] == 'o': # example: "o0 g_0" names = l.split()[1:] if bad_name in names: idx = int(l.split()[0][1:]) return (1 + header_numbers[1] + header_numbers[2] + idx), symbols_table_start + i, idx assert 0, 'name of the bad output was not found'
def to_boolean_nusmv(lts:LTS, specification:SpecProperty) -> str: nof_state_bits = int(max(1, math.ceil(math.log(len(lts.states), 2)))) bits_by_state = dict((state, bin_fixed_list(i, nof_state_bits)) for (i,state) in enumerate(sorted(lts.states))) state_bits = lmap(_ith_state_bit, range(nof_state_bits)) _assert_no_intersection(state_bits, list(lts.input_signals) + lts.output_signals) dot_lines = StrAwareList() dot_lines += 'MODULE main' dot_lines += 'IVAR' dot_lines += [' {signal} : boolean;'.format(signal=s.name) for s in lts.input_signals] dot_lines += 'VAR' dot_lines += [' {si} : boolean;'.format(si=si) for si in state_bits] dot_lines += 'DEFINE' dot_lines += [' {out_name} := {formula} ;'.format(out_name=out_name, formula=_get_formula(out_name, out_model, bits_by_state)) for (out_name,out_model) in lts.model_by_name.items()] dot_lines += 'ASSIGN' for i,sb in enumerate(state_bits): sb_init = str(bits_by_state[list(lts.init_states)[0]][i]).upper() dot_lines += ' init({sb}) := {init_sb};'.format(sb=sb, init_sb=sb_init) dot_lines += ' next({sb}) := '.format(sb=sb) dot_lines += ' case' for (label,next_state) in lts.tau_model.items(): sb_next = str(bits_by_state[next_state][i]).upper() dot_lines += ' {formula} : {next_state};'.format(formula=_clause_to_formula(label, bits_by_state), next_state=sb_next) dot_lines += ' TRUE : FALSE;' # default: unreachable states, don't care dot_lines += ' esac;' expr = BinOp('->', and_expressions(specification.assumptions), and_expressions(specification.guarantees)) expr = WeakToUntilConverterVisitor().dispatch(expr) # SMV does not have Weak until dot_lines += 'LTLSPEC ' + AstToSmvProperty().dispatch(expr) return '\n'.join(dot_lines)
def _get_all_possible_inputs(func_desc: FuncDesc, last_allowed_states): arg_type_pairs = func_desc.ordered_argname_type_pairs get_values = lambda t: { bool_type(): (true(), false()), TYPE_MODEL_STATE: [smt_name_m(m) for m in last_allowed_states], }[t] records = product(*[get_values(t) for (_, t) in arg_type_pairs]) args = lmap(lambda a_t: a_t[0], arg_type_pairs) dicts = [] for record in records: assert len(args) == len(record) arg_value_pairs = zip(args, record) dicts.append(dict(arg_value_pairs)) return dicts
def _get_desc_tau_sched_wrapper(self, proc_index: int, all_models_inputs) -> FuncDescription: local_tau_input_signals = _filter_by_proc(proc_index, all_models_inputs) local_tau_arg_type_pairs = self._get_desc_local_tau( local_tau_input_signals).inputs type_by_signal = dict(local_tau_arg_type_pairs + self._sched_arg_type_pairs + self._proc_arg_type_pairs) local_tau_arg_type_pairs = list( map(lambda signal_type: signal_type[0], local_tau_arg_type_pairs)) is_active_desc = self._get_desc_is_active(proc_index) is_active_inputs = lmap( lambda signal: signal[0], is_active_desc.inputs ) # TODO: hack: knowledge: var names are the same body = """ (ite ({is_active} {is_active_inputs}) ({tau} {local_tau_inputs}) {state}) """.format_map({ 'tau': self._TAU_NAME, 'local_tau_inputs': ' '.join(map(str, local_tau_arg_type_pairs)), 'state': self.state_arg_name, 'is_active': self._IS_ACTIVE_NAME, 'is_active_inputs': ' '.join(map(str, is_active_inputs)) }) description = FuncDescription(self._TAU_SCHED_WRAPPER_NAME, type_by_signal, self._state_type, body) return description
def _build_func_model_from_smt(self, func_smt_lines, func_desc:FuncDesc) -> dict: """ Return graph for the transition (or output) function: {label:output}. For label's keys are used: - for inputs/outputs: original signals - for LTS states: ARG_MODEL_STATE """ func_model = {} signals = set(list(self.inputs) + list(self.descr_by_output.keys())) for l in func_smt_lines: # (get-value ((tau t0 true true))) l = l.replace('get-value', '').replace('(', '').replace(')', '') tokens = l.split() func_name = tokens[0] arg_values_raw = lmap(self._parse_value, tokens[1:-1]) return_value_raw = tokens[-1] if func_name != func_desc.name: continue smt_args = func_desc.get_args_dict(arg_values_raw) args_label = Label(dict((smt_unname_if_signal(var, signals), val) for var, val in smt_args.items())) if func_desc.output_ty == TYPE_MODEL_STATE: return_value = smt_unname_m(return_value_raw) else: assert func_desc.output_ty == self.solver.TYPE_BOOL(), func_desc.output_ty assert return_value_raw.strip() == return_value_raw # TODO: remove after debugging phase return_value = (return_value_raw == self.solver.get_true()) func_model[args_label] = return_value return func_model
def _encode_automata_functions(self) -> List[str]: atm_states = chain(*lmap(lambda a: a.nodes, self.atm_by_sig.values())) return [declare_enum(TYPE_A_STATE, map(smt_name_q, atm_states))]
def _declare_forbidding_atoms(self) -> List[str]: return lmap(lambda a: declare_const(a, bool_type()), self.forbidding_atoms)
def encode_assumption_forbid_k(self, k: int) -> List[str]: # forbid states with counter being k or lower return self.forbidding_atoms[0:k + 1] + lmap( lambda e: op_not(e), self.forbidding_atoms[k + 1:])