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 _close(self, ot: utils.ObservationTable) -> utils.ObservationTable: """ Closes the observation table by adding an extra row. :param ot: The observation table to close. :type ot: ObservationTable :return: The closed and updated observation table :rtype: ObservationTable """ self._logger.info('Closing the table by adding a row.') for s in self._blue.copy(): if not all([ot.get_row(s) != ot.get_row(u) for u in self._red]): continue self._red.add(s) self._blue.remove(s) for a in self._alphabet: sa = s + a if sa not in self._blue: self._blue.add(sa) ot.add_row(sa) for u, e in ot.find_holes(): ot.put(u, e, self._oracle.membership_query(u + e)) return ot
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 _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
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 test_ot_03(self): ot = ObservationTable(set(), {''}, set()) ot.add_row('a') self.assertEqual({}, ot.get_row('a')) ot.put('a', 'a', 1) ot.put('a', 'b', 0) self.assertEqual(0, ot.get('a', 'b')) self.assertEqual(True, ot.row_exists('a')) self.assertEqual(False, ot.row_exists('b')) try: ot.get('a', 'c') self.fail('Indexing row and column that' ' is not defined should throw an exception!') except KeyError: self.assertTrue(True)
def test_ot_01(self): ot = ObservationTable(set(), {''}, set()) ot.put('', '', 1) self.assertEqual(1, ot.get('', '')) self.assertEqual({'': 1}, ot.get_row(''))
def test_ot_02(self): ot = ObservationTable(set(), {''}, set()) ot.add_row('a') self.assertEqual({}, ot.get_row('a')) ot.put('a', 'b', 0) self.assertEqual(0, ot.get('a', 'b'))