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 _useq(self, ot: utils.ObservationTable, answer: str) -> utils.ObservationTable: """ This method is called when the table is closed and complete. The algorithm then makes an equivalence query to the oracle, if the oracle is not satisfied and provides us with a counterexample, then this method is called with that counterexample. The method adds new rows to the observation table, to account for the new counterexample. :param ot: The observation table to update :type ot: ObservationTable :param answer: The counter-example given by the oracle :type answer: str :return: Updated ObservationTable :rtype: ObservationTable """ prefix_set = set(utils.prefix_set({answer}, self._alphabet)) self._logger.info('Updating table by adding the following prefixes: {}' .format(', '.join(prefix_set))) for p in prefix_set: if p not in self._red: if p not in self._blue: ot.add_row(p) self._red.add(p) self._blue.discard(p) for a in self._alphabet: pa = p + a if pa not in prefix_set: if pa not in self._blue: if pa not in self._red: ot.add_row(pa) self._blue.add(pa) self._red.discard(pa) for u, e in ot.find_holes(): ot.put(u, e, self._oracle.membership_query(u + e)) return ot
def _consistent(self, ot: utils.ObservationTable) -> utils.ObservationTable: """ Makes the observation table consistent by adding an extra column. :param ot: The observation table to make consistent. :type ot: ObservationTable :return: The consistent and updated observation table :rtype: ObservationTable """ self._logger.info('Making the table consistent by adding a column.') s1, s2, a, e = self._find_inconsistent(ot) ae = a + e ot.exp.add(ae) ot.add_column_to_table(ae) for u, e in ot.find_holes(): ot.put(u, e, self._oracle.membership_query(u + e)) return ot