internal static Dictionary <int, TThis> ExtractGroups(Automaton <TSequence, TElement, TElementDistribution, TSequenceManipulator, TThis> automaton) { var order = ComputeTopologicalOrderAndGroupSubgraphs(automaton, out var subGraphs); return(BuildSubautomata(automaton.States, order, subGraphs)); }
/// <summary> /// Creates an automaton <c>f'(s) = sum_{tu=s} f(t)g(u)</c>, where <c>f(t)</c> is the current /// automaton (in builder) and <c>g(u)</c> is the given automaton. /// The resulting automaton is also known as the Cauchy product of two automata. /// </summary> public void Append( Automaton <TSequence, TElement, TElementDistribution, TSequenceManipulator, TThis> automaton, int group = 0, bool avoidEpsilonTransitions = true) { var oldStateCount = this.states.Count; foreach (var state in automaton.States) { var stateBuilder = this.AddState(); stateBuilder.SetEndWeight(state.EndWeight); foreach (var transition in state.Transitions) { var updatedTransition = transition; updatedTransition.DestinationStateIndex += oldStateCount; if (group != 0) { updatedTransition.Group = group; } stateBuilder.AddTransition(updatedTransition); } } var secondStartState = this[oldStateCount + automaton.Start.Index]; if (avoidEpsilonTransitions && (AllEndStatesHaveNoTransitions() || !automaton.Start.HasIncomingTransitions)) { // Remove start state of appended automaton and copy all its transitions to previous end states for (var i = 0; i < oldStateCount; ++i) { var endState = this[i]; if (!endState.CanEnd) { continue; } for (var iterator = secondStartState.TransitionIterator; iterator.Ok; iterator.Next()) { var transition = iterator.Value; if (group != 0) { transition.Group = group; } if (transition.DestinationStateIndex == secondStartState.Index) { transition.DestinationStateIndex = endState.Index; } else { transition.Weight *= endState.EndWeight; } endState.AddTransition(transition); } endState.SetEndWeight(endState.EndWeight * secondStartState.EndWeight); } this.RemoveState(secondStartState.Index); } else { // Just connect all end states with start state of appended automaton for (var i = 0; i < oldStateCount; i++) { var state = this[i]; if (state.CanEnd) { state.AddEpsilonTransition(state.EndWeight, secondStartState.Index, group); state.SetEndWeight(Weight.Zero); } } } bool AllEndStatesHaveNoTransitions() { for (var i = 0; i < oldStateCount; ++i) { var state = this.states[i]; if (!state.EndWeight.IsZero && state.FirstTransitionIndex != -1) { return(false); } } return(true); } }