def _promote(self, qu: automaton.State, dfa: automaton.DFA) -> automaton.DFA: """ Given a state blue state qu, this method promotes this state ro red and all the successors in the dfa. The method returns the updated dfa. :param qu: State with colour blue :type qu: State :param dfa: the dfa :type dfa: Automaton :return: Updated dfa :rtype: Automaton """ self._logger.info('Promoting state {} from blue to red'.format( qu.name)) self._red.add(qu) self._blue.update({ dfa.transition(qu, a) for a in self._alphabet if dfa.transition_exists(qu, a) }) self._blue.discard(qu) return dfa
def _merge(self, dfa: automaton.DFA, q: automaton.State, q_prime: automaton.State) -> automaton.DFA: """ Takes as arguments a red state q and a blue state q'. The method first finds the unique pair (qf, a) such that q' = delta(qf, a). The method then redirects delta(qf, a) to q. After that the tree rooted in q' is folded into the rest of the DFA. The possible intermediate situations of non-determinism are dealt with during the recursive calls to fold. :param dfa: the automaton to update with a merge :type dfa: Automaton :param q: State from the red set :type q: State :param q_prime: State from the blue :type q_prime: State :return: updated Automaton :rtype: Automaton """ self._logger.info('Merging the two states {} and {}'.format( q.name, q_prime.name)) qf, a = dfa.find_transition_to_q(q_prime) if qf is None or a is None: return dfa dfa.add_transition(qf, q, a) return self._fold(dfa, q, q_prime)
def _fold(self, dfa: automaton.DFA, q: automaton.State, q_prime: automaton.State) -> automaton.DFA: """ Folds the tree rooted in q' into the rest of the DFA. The possible intermediate situations of non-determinism are dealt with during the recursive calls. :param dfa: the automaton to update with a folding of states :type dfa: Automaton :param q: State :type q: State :param q_prime: State to fold :type q_prime: State :return: updated Automaton :rtype: Automaton """ self._logger.info('Folding the tree rooted in the state {}'.format( q_prime.name)) if q_prime in dfa.accept_states: dfa.accept_states.add(q) for a in self._alphabet: if dfa.transition_exists(q_prime, a): if dfa.transition_exists(q, a): dfa = self._fold(dfa, dfa.transition(q, a), dfa.transition(q_prime, a)) else: dfa.add_transition(q, dfa.transition(q_prime, a), a) return dfa
def _compatible(self, dfa: automaton.DFA) -> bool: """ Determines whether the current automaton can parse any string in the set of negative example strings. Returns True if the current automaton cannot parse any string from the negative examples, returns False if some counter-example is accepted by the current automaton. :param dfa: the dfa :type dfa: Automaton :return: Boolean indicating whether the dfa is compatible. :rtype: bool """ return not any(dfa.parse_string(w)[1] for w in self._neg_examples)