Commit 8fbb8218 authored by Vladimír Štill's avatar Vladimír Štill
Browse files

lib: Fix conversion to canonic automaton

In some cases, the states could be spuriously merged when converting to canonic
automaton. This is now fixed.
parent 13980904
Loading
Loading
Loading
Loading
Loading
+19 −15
Original line number Original line Diff line number Diff line
@@ -312,26 +312,30 @@ class DFA:
        return name
        return name


    def canonize(self) -> DFA:
    def canonize(self) -> DFA:
        dfa = deepcopy(self)
        characters = self.sorted_characters()
        remain = deepcopy(self.states)
        state_map: Dict[State, State] = {}
        characters = dfa.sorted_characters()


        i = 0
        i = 1
        queue = deque([dfa.init])
        queue = deque([self.init])
        while len(queue) > 0:
        while len(queue) > 0:
            actual = queue.popleft()
            actual = queue.popleft()
            if actual in remain:
            if actual in state_map.keys():
                remain.remove(actual)
                continue
            # alternatively, use self.bijective26(i) for base-26 alpha. names
            state_map[actual] = State(str(i))
            i += 1


            for character in characters:
            for character in characters:
                if (actual, character) in dfa.transition and dfa.transition[actual, character] in remain:
                tgt = self.transition.get((actual, character))
                    queue.append(dfa.transition[actual, character])
                if tgt is not None and tgt not in state_map.keys():
                    remain.remove(dfa.transition[actual, character])
                    queue.append(tgt)


            # use self.bijective26(i) for base-26 alphabetic names
        return DFA(set(state_map.values()),
            dfa.rename_state(actual, str(i + 1))
                   deepcopy(self.characters),
            i += 1
                   {(state_map[st], ch): state_map[tgt]
        return dfa
                    for (st, ch), tgt in self.transition.items()},
                   state_map[self.init],
                   {state_map[st] for st in self.final})


    # support function: decides from which of reachable states there is a way to final state
    # support function: decides from which of reachable states there is a way to final state
    def terminating_states(self, states: Set[State], pred: Dict[State, Set[State]]) -> Set[State]:
    def terminating_states(self, states: Set[State], pred: Dict[State, Set[State]]) -> Set[State]: