def _find_inconsistent(self, ot: utils.ObservationTable) -> Tuple[str, str, str, str]: """ Tries to find two inconsistent rows s1 and s2 in the observation table. s1 and s2 are elements of red. OT[s1] == OT[s2] and OT[s1.a][e] != OT[s2.a][e] where a is an element in the alphabet and e is an experiment (element in the set ot.exp) :param ot: The observation table to find two inconsistent red states. :type ot: ObservationTable :return: Inconsistent row :rtype: Tuple[str, str, str, str] """ self._logger.info('Trying to find two inconsistent rows in the table.') for s1 in self._red: for s2 in self._red: if s1 == s2: continue for a in self._alphabet: for e in ot.exp: if ot.get_row(s1) == ot.get_row(s2) and \ ot.entry_exists(s1 + a, e) and ot.entry_exists(s2 + a, e) \ and ot.get(s1 + a, e) != ot.get(s2 + a, e): self._logger.info('Found two inconsistent rows {} and {}' .format(s1, s2)) return s1, s2, a, e self._logger.info('Did not find a inconsistency in the table.') return '', '', '', ''
def _fill_holes(self, ot: utils.ObservationTable) -> Tuple[utils.ObservationTable, bool]: """ Tries to make the table complete by filling in all the entries that are None. :param ot: the updated observation table :return: updated ObservationTable and whether the method was successful. :rtype: tuple(ObservationTable, bool) """ self._logger.info('Try to make table complete by filling in * entries.') for p in self._blue: r = ot.find_compatible_row(p) if r is not None: for e in ot.exp: if ot.entry_exists(p, e) and ot.get(p, e) is not None: ot.put(r, e, ot.get(p, e)) else: return ot, True for r in self._red: for e in ot.exp: if ot.entry_exists(r, e) and ot.get(r, e) is None: ot.put(r, e, 1) for p in self._blue: r = ot.find_compatible_row(p) if r is not None: for e in ot.exp: if ot.entry_exists(p, e) and ot.get(p, e) is None: if ot.entry_exists(r, e): ot.put(p, e, ot.get(r, e)) else: return ot, True return ot, False
def _find_inconsistent( self, ot: utils.ObservationTable) -> Tuple[str, str, str, str]: """ Tries to find two inconsistent rows s1 and s2 in the observation table. s1 and s2 are elements of red. OT[s1] == OT[s2] and OT[s1.a][e] != OT[s2.a][e] where a is an element in the alphabet and e is an experiment (element in the set ot.exp) :param ot: The observation table to find two inconsistent red states. :type ot: ObservationTable :return: Inconsistent row :rtype: Tuple[str, str, str, str] """ for s1 in sorted(self._red): for s2 in sorted(self._red): if s1 == s2: continue for a in sorted(self._alphabet): for e in sorted(ot.exp): if ot.get_row(s1) == ot.get_row(s2) and \ ot.entry_exists(s1 + a, e) and ot.entry_exists(s2 + a, e) \ and ot.get(s1 + a, e) != ot.get(s2 + a, e): return s1, s2, a, e return '', '', '', ''
def _build_automaton(self, ot: utils.ObservationTable) -> automaton.DFA: """ Builds an automaton from the observation table. :param ot: The data to build the dfa from. :type ot: ObservationTable :return: The dfa built from the observation table. :rtype: DFA """ self._logger.info('Building DFA from the table.') dfa = automaton.DFA(self._alphabet) for u in self._red: for v in ot.ot.keys(): if u == v: continue if len(v) < len(u) and ot.get_row(v) != ot.get_row(u): dfa.states.add(automaton.State(u)) for u in dfa.states: if ot.entry_exists(u.name, ''): if ot.get(u.name, '') == 1: dfa.accept_states.add(u) elif ot.get(u.name, '') == 0: dfa.reject_states.add(u) for a in self._alphabet: for w in dfa.states: if ot.get_row(u.name + a) == ot.get_row(w.name): dfa.add_transition(u, w, a) return dfa.rename_states()
def _build_automaton(self, ot: utils.ObservationTable) -> automaton.DFA: """ Builds an automaton from the observation table. :type ot: ObservationTable :return: Automaton built from the observation table :rtype: Automaton """ dfa = automaton.DFA(self._alphabet) states = {automaton.State(i) for i in self._red} we = utils.break_strings_in_two(self._red) for w, e in we: we = w + e if we in self._red and ot.entry_exists(w, e): val = ot.get(w, e) state = automaton.State(we) if val == 1: dfa.accept_states.add(state) states.add(state) elif val == 0: dfa.reject_states.add(state) states.add(state) for w in states: for a in self._alphabet: for u in self._red: wa = w.name + a if ot.row_exists(u) and ot.row_exists(wa) and \ ot.get_row(u) == ot.get_row(wa): dfa.add_transition(w, automaton.State(u), a) return dfa