/// <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); } }
/// <summary> /// Initializes a new instance of the <see cref="EpsilonClosure"/> class. /// </summary> /// <param name="state">The state, which epsilon closure this instance will represent.</param> internal EpsilonClosure(State state) { Argument.CheckIfValid(!state.IsNull, nameof(state)); // Optimize for a very common case: a single-node closure bool singleNodeClosure = true; Weight selfLoopWeight = Weight.Zero; for (int i = 0; i < state.TransitionCount; ++i) { Transition transition = state.GetTransition(i); if (transition.IsEpsilon) { if (transition.DestinationStateIndex != state.Index) { singleNodeClosure = false; break; } selfLoopWeight = Weight.Sum(selfLoopWeight, transition.Weight); } } if (singleNodeClosure) { Weight stateWeight = Weight.ApproximateClosure(selfLoopWeight); this.weightedStates.Add(Pair.Create(state, stateWeight)); this.EndWeight = Weight.Product(stateWeight, state.EndWeight); } else { Condensation condensation = state.Owner.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(Pair.Create(componentState, condensation.GetWeightFromRoot(componentState))); } } this.EndWeight = condensation.GetWeightToEnd(state); } }