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 Diff line number Diff line
@@ -312,26 +312,30 @@ class DFA:
        return name

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

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

            for character in characters:
                if (actual, character) in dfa.transition and dfa.transition[actual, character] in remain:
                    queue.append(dfa.transition[actual, character])
                    remain.remove(dfa.transition[actual, character])

            # use self.bijective26(i) for base-26 alphabetic names
            dfa.rename_state(actual, str(i + 1))
            i += 1
        return dfa
                tgt = self.transition.get((actual, character))
                if tgt is not None and tgt not in state_map.keys():
                    queue.append(tgt)

        return DFA(set(state_map.values()),
                   deepcopy(self.characters),
                   {(state_map[st], ch): state_map[tgt]
                    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
    def terminating_states(self, states: Set[State], pred: Dict[State, Set[State]]) -> Set[State]: