/// <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)
            {
                // 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 = new[] { (state, stateWeight) };
            /// <summary>
            /// Computes the total weights between each pair of states in the component
            /// using the <a href="http://www.cs.nyu.edu/~mohri/pub/hwa.pdf">generalized Floyd's algorithm</a>.
            /// </summary>
            private void ComputePairwiseWeightsMatrix()
            {
                this.pairwiseWeights = Util.ArrayInit(this.Size, this.Size, (i, j) => Weight.Zero);
                for (int srcStateIndexInComponent = 0; srcStateIndexInComponent < this.Size; ++srcStateIndexInComponent)
                {
                    State state = this.statesInComponent[srcStateIndexInComponent];
                    for (int transitionIndex = 0; transitionIndex < state.TransitionCount; ++transitionIndex)
                    {
                        Transition transition = state.GetTransition(transitionIndex);
                        State      destState  = state.Owner.States[transition.DestinationStateIndex];
                        int        destStateIndexInComponent;
                        if (this.transitionFilter(transition) && (destStateIndexInComponent = this.GetIndexByState(destState)) != -1)
                        {
                            this.pairwiseWeights[srcStateIndexInComponent, destStateIndexInComponent] = Weight.Sum(
                                this.pairwiseWeights[srcStateIndexInComponent, destStateIndexInComponent], transition.Weight);
                        }
                    }
                }

                for (int k = 0; k < this.Size; ++k)
                {
                    Weight loopWeight =
                        this.useApproximateClosure ? Weight.ApproximateClosure(this.pairwiseWeights[k, k]) : Weight.Closure(this.pairwiseWeights[k, k]);

                    for (int i = 0; i < this.Size; ++i)
                    {
                        if (i == k || this.pairwiseWeights[i, k].IsZero)
                        {
                            continue;
                        }

                        for (int j = 0; j < this.Size; ++j)
                        {
                            if (j == k || this.pairwiseWeights[k, j].IsZero)
                            {
                                continue;
                            }

                            Weight additionalWeight = Weight.Product(
                                this.pairwiseWeights[i, k], loopWeight, this.pairwiseWeights[k, j]);
                            this.pairwiseWeights[i, j] = Weight.Sum(this.pairwiseWeights[i, j], additionalWeight);
                        }
                    }

                    for (int i = 0; i < this.Size; ++i)
                    {
                        this.pairwiseWeights[i, k] = Weight.Product(this.pairwiseWeights[i, k], loopWeight);
                        this.pairwiseWeights[k, i] = Weight.Product(this.pairwiseWeights[k, i], loopWeight);
                    }

                    this.pairwiseWeights[k, k] = loopWeight;
                }
            }
示例#3
0
            /// <summary>
            /// Computes the total weights between each pair of states in the component
            /// using the <a href="http://www.cs.nyu.edu/~mohri/pub/hwa.pdf">generalized Floyd's algorithm</a>.
            /// </summary>
            private void ComputePairwiseWeightsMatrix()
            {
                this.pairwiseWeights = Util.ArrayInit(this.Size, this.Size, (i, j) => Weight.Zero);
                for (int srcStateIndexInComponent = 0; srcStateIndexInComponent < this.Size; ++srcStateIndexInComponent)
                {
                    State state = this.statesInComponent[srcStateIndexInComponent];
                    foreach (var transition in state.Transitions)
                    {
                        State destState = this.Automaton.States[transition.DestinationStateIndex];
                        int   destStateIndexInComponent;
                        if (this.transitionFilter(transition) && (destStateIndexInComponent = this.GetIndexByState(destState)) != -1)
                        {
                            this.pairwiseWeights[srcStateIndexInComponent, destStateIndexInComponent] += transition.Weight;
                        }
                    }
                }

                for (int k = 0; k < this.Size; ++k)
                {
                    Weight loopWeight =
                        this.useApproximateClosure ? Weight.ApproximateClosure(this.pairwiseWeights[k, k]) : Weight.Closure(this.pairwiseWeights[k, k]);

                    for (int i = 0; i < this.Size; ++i)
                    {
                        if (i == k || this.pairwiseWeights[i, k].IsZero)
                        {
                            continue;
                        }

                        for (int j = 0; j < this.Size; ++j)
                        {
                            if (j == k || this.pairwiseWeights[k, j].IsZero)
                            {
                                continue;
                            }

                            this.pairwiseWeights[i, j] += Weight.Product(
                                this.pairwiseWeights[i, k], loopWeight, this.pairwiseWeights[k, j]);
                        }
                    }

                    for (int i = 0; i < this.Size; ++i)
                    {
                        this.pairwiseWeights[i, k] *= loopWeight;
                        this.pairwiseWeights[k, i] *= loopWeight;
                    }

                    this.pairwiseWeights[k, k] = loopWeight;
                }
            }
示例#4
0
            /// <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);
                }
            }
示例#5
0
            /// <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);
                }
            }
            /// <summary>
            /// Gets the total weight between two given states in the component.
            /// </summary>
            /// <param name="srcStateIndexInComponent">The index of the source state in the component.</param>
            /// <param name="destStateIndexInComponent">The index of the destination state in the component.</param>
            /// <returns>The total weight between the given states in the component.</returns>
            public Weight GetWeight(int srcStateIndexInComponent, int destStateIndexInComponent)
            {
                Argument.CheckIfInRange(
                    srcStateIndexInComponent >= 0 && srcStateIndexInComponent < this.Size,
                    "srcStateIndexInComponent",
                    "The given index is out of range.");
                Argument.CheckIfInRange(
                    destStateIndexInComponent >= 0 && destStateIndexInComponent < this.Size,
                    "destStateIndexInComponent",
                    "The given index is out of range.");

                if (this.Size == 1)
                {
                    if (!this.singleStatePairwiseWeight.HasValue)
                    {
                        // Optimize for a common case
                        State state = this.statesInComponent[0];
                        this.singleStatePairwiseWeight = Weight.Zero;
                        for (int i = 0; i < state.TransitionCount; ++i)
                        {
                            Transition transition = state.GetTransition(i);
                            if (this.transitionFilter(transition) && transition.DestinationStateIndex == state.Index)
                            {
                                this.singleStatePairwiseWeight = Weight.Sum(
                                    this.singleStatePairwiseWeight.Value, transition.Weight);
                            }
                        }

                        this.singleStatePairwiseWeight =
                            this.useApproximateClosure
                                ? Weight.ApproximateClosure(this.singleStatePairwiseWeight.Value)
                                : Weight.Closure(this.singleStatePairwiseWeight.Value);
                    }

                    return(this.singleStatePairwiseWeight.Value);
                }

                if (this.pairwiseWeights == null)
                {
                    this.ComputePairwiseWeightsMatrix();
                }

                return(this.pairwiseWeights[srcStateIndexInComponent, destStateIndexInComponent]);
            }