コード例 #1
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 = state.Owner.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;
                }
            }
コード例 #2
0
        /// <summary>
        /// Computes a set of outgoing transitions from a given state of the determinization result.
        /// </summary>
        /// <param name="sourceStateSet">The source state of the determinized automaton represented as
        /// a set of (stateId, weight) pairs, where state ids correspond to states of the original automaton.</param>
        /// <returns>
        /// A collection of (element distribution, weight, weighted state set) triples corresponding to outgoing
        /// transitions from <paramref name="sourceStateSet"/>.
        /// The first two elements of a tuple define the element distribution and the weight of a transition.
        /// The third element defines the outgoing state.
        /// </returns>
        protected override IEnumerable <Determinization.OutgoingTransition> GetOutgoingTransitionsForDeterminization(
            Determinization.WeightedStateSet sourceStateSet)
        {
            // Build a list of numbered non-zero probability character segment bounds (they are numbered here due to perf. reasons)
            var segmentBounds = new List <TransitionCharSegmentBound>();

            for (var i = 0; i < sourceStateSet.Count; ++i)
            {
                var sourceState = sourceStateSet[i];
                var state       = this.States[sourceState.Index];
                foreach (var transition in state.Transitions)
                {
                    AddTransitionCharSegmentBounds(transition, sourceState.Weight, segmentBounds);
                }
            }

            segmentBounds.Sort();

            // Produce an outgoing transition for each unique subset of overlapping segments
            var currentSegmentTotal = WeightSum.Zero();

            var currentSegmentStateWeights = new Dictionary <int, WeightSum>();
            var currentSegmentStart        = (int)char.MinValue;
            var destinationStateSetBuilder = Determinization.WeightedStateSetBuilder.Create();

            foreach (var segmentBound in segmentBounds)
            {
                if (currentSegmentTotal.Count != 0 && currentSegmentStart < segmentBound.Bound)
                {
                    // Flush previous segment
                    var segmentEnd     = (char)(segmentBound.Bound - 1);
                    var segmentLength  = segmentEnd - currentSegmentStart + 1;
                    var elementDist    = DiscreteChar.InRange((char)currentSegmentStart, segmentEnd);
                    var invTotalWeight = Weight.Inverse(currentSegmentTotal.Sum);

                    destinationStateSetBuilder.Reset();
                    foreach (var stateIdWithWeight in currentSegmentStateWeights)
                    {
                        var stateWeight = stateIdWithWeight.Value.Sum * invTotalWeight;
                        destinationStateSetBuilder.Add(stateIdWithWeight.Key, stateWeight);
                    }

                    var(destinationStateSet, destinationStateSetWeight) = destinationStateSetBuilder.Get();

                    var transitionWeight = Weight.Product(
                        Weight.FromValue(segmentLength),
                        currentSegmentTotal.Sum,
                        destinationStateSetWeight);
                    yield return(new Determinization.OutgoingTransition(
                                     elementDist, transitionWeight, destinationStateSet));
                }

                // Update current segment
                currentSegmentStart = segmentBound.Bound;

                if (segmentBound.IsStart)
                {
                    currentSegmentTotal += segmentBound.Weight;
                    if (currentSegmentStateWeights.TryGetValue(segmentBound.DestinationStateId, out var stateWeight))
                    {
                        currentSegmentStateWeights[segmentBound.DestinationStateId] =
                            stateWeight + segmentBound.Weight;
                    }
                    else
                    {
                        currentSegmentStateWeights[segmentBound.DestinationStateId] = new WeightSum(segmentBound.Weight);
                    }
                }
                else
                {
                    Debug.Assert(currentSegmentStateWeights.ContainsKey(segmentBound.DestinationStateId), "We shouldn't exit a state we didn't enter.");
                    Debug.Assert(!segmentBound.Weight.IsInfinity);
                    currentSegmentTotal -= segmentBound.Weight;

                    var prevStateWeight = currentSegmentStateWeights[segmentBound.DestinationStateId];
                    var newStateWeight  = prevStateWeight - segmentBound.Weight;
                    if (newStateWeight.Count == 0)
                    {
                        currentSegmentStateWeights.Remove(segmentBound.DestinationStateId);
                    }
                    else
                    {
                        currentSegmentStateWeights[segmentBound.DestinationStateId] = newStateWeight;
                    }
                }
            }
        }