private void DiscardNotReachable(Partition blocks, List <Transition> transitionList, Func <Transition, int> getFrom, Func <Transition, int> getTo) { var adjacentTransitions = new AdjacentTransitions(StateCount, transitionList, getFrom); foreach (var state in blocks.Marked(0)) { foreach (var transition in adjacentTransitions[state]) { blocks.Mark(getTo(transitionList[transition])); } } blocks.DiscardUnmarked(); transitionList.RemoveAll(transition => blocks.SetOf(getFrom(transition)) == -1); }
public Tuple <IReadOnlyDictionary <State, State>, DFA <TData> > Minimize(Func <State, State, bool> areEquivalent, Func <TData, TData, TData> combine) { var transitionList = MakeTransitionsList(); var blocks = new Partition(StateCount); // Reachable from start foreach (var startState in StartStates) { blocks.Mark(startState.Index); } DiscardNotReachable(blocks, transitionList, t => t.From, t => t.To); // Reachable from final var finalStates = States.Where(IsFinal).ToList(); foreach (var finalState in finalStates) { blocks.Mark(finalState.Index); } DiscardNotReachable(blocks, transitionList, t => t.To, t => t.From); // Split final states from non-final foreach (var finalState in finalStates) { blocks.Mark(finalState.Index); } blocks.SplitSets(); // Split final states from other non-equivalent final states var possibleEquivalentStates = finalStates; while (possibleEquivalentStates.Any()) { var state = possibleEquivalentStates.First(); var equivalentStatesLookup = possibleEquivalentStates.Skip(1).ToLookup(s => areEquivalent(state, s)); // Mark states blocks.Mark(state.Index); foreach (var finalState in equivalentStatesLookup[true]) { blocks.Mark(finalState.Index); } blocks.SplitSets(); possibleEquivalentStates = equivalentStatesLookup[false].ToList(); } // Cords partition to manage transitions var cords = new Partition(transitionList.Count); // Sort transitions by input cords.PartitionBy(transition => transitionList[transition].OnInput); //Split blocks and cords var adjacentTransitions = new AdjacentTransitions(StateCount, transitionList, t => t.To); var blockSet = 1; for (var cordSet = 0; cordSet < cords.SetCount; cordSet++) { foreach (var transition in cords.Set(cordSet)) { blocks.Mark(transitionList[transition].From); } blocks.SplitSets(); for (; blockSet < blocks.SetCount; blockSet++) { foreach (var state in blocks.Set(blockSet)) { foreach (var transition in adjacentTransitions[state]) { cords.Mark(transition); } } cords.SplitSets(); } } // Generate minimized DFA var minDFA = new DFA <TData>(InputValueCount, blocks.SetCount); // Create states for (var set = 0; set < blocks.SetCount; set++) { var data = blocks.Set(set).Select(s => GetData(new State(s))).Aggregate(combine); var state = minDFA.AddState(data); // Sets are either all final or non-final states if (IsFinal(new State(blocks.SomeElementOf(set)))) { minDFA.SetFinal(state); } } // Create Start State Map var startStateMap = (IReadOnlyDictionary <State, State>)StartStates.ToDictionary(s => s, s => new State(blocks.SetOf(s.Index))); // Mark Start States foreach (var startState in startStateMap.Values) { minDFA.SetStart(startState); } // Create transitions for (var set = 0; set < cords.SetCount; set++) { var transition = transitionList[cords.SomeElementOf(set)]; var from = new State(blocks.SetOf(transition.From)); var to = new State(blocks.SetOf(transition.To)); minDFA.SetTransition(from, new Input(transition.OnInput), to); } return(Tuple.Create(startStateMap, minDFA)); }