/// <summary> /// Initializes a new instance of the <see cref="EpsilonClosure"/> class. /// </summary> /// <param name="automaton">The automaton from to which <paramref name="state"/> belongs.</param> /// <param name="state">The state, which epsilon closure this instance will represent.</param> internal EpsilonClosure( Automaton <TSequence, TElement, TElementDistribution, TSequenceManipulator, TThis> automaton, State state) { this.weightedStates = new List <(State, Weight)>(DefaultStateListCapacity); // Optimize for a very common case: a single-node closure bool singleNodeClosure = true; Weight selfLoopWeight = Weight.Zero; foreach (var transition in state.Transitions) { if (transition.IsEpsilon) { if (transition.DestinationStateIndex != state.Index) { singleNodeClosure = false; break; } selfLoopWeight += transition.Weight; } } if (singleNodeClosure) { Weight stateWeight = Weight.ApproximateClosure(selfLoopWeight); this.weightedStates.Add((state, stateWeight)); this.EndWeight = stateWeight * state.EndWeight; } else { Condensation condensation = automaton.ComputeCondensation(state, tr => tr.IsEpsilon, true); for (int i = 0; i < condensation.ComponentCount; ++i) { StronglyConnectedComponent component = condensation.GetComponent(i); for (int j = 0; j < component.Size; ++j) { State componentState = component.GetStateByIndex(j); this.weightedStates.Add((componentState, condensation.GetWeightFromRoot(componentState))); } } this.EndWeight = condensation.GetWeightToEnd(state.Index); } }