Exemple #1
0
        /// <summary>
        /// Given a transition and the residual weight of its source state, adds weighted non-zero probability character segments
        /// associated with the transition to the list.
        /// </summary>
        /// <param name="transition">The transition.</param>
        /// <param name="sourceStateResidualWeight">The logarithm of the residual weight of the source state of the transition.</param>
        /// <param name="bounds">The list for storing numbered segment bounds.</param>
        private static void AddTransitionCharSegmentBounds(
            Transition transition, Weight sourceStateResidualWeight, List <ValueTuple <int, TransitionCharSegmentBound> > bounds)
        {
            var    distribution     = transition.ElementDistribution.Value;
            var    ranges           = distribution.Ranges;
            int    commonValueStart = char.MinValue;
            Weight commonValue      = Weight.FromValue(distribution.ProbabilityOutsideRanges);
            Weight weightBase       = Weight.Product(transition.Weight, sourceStateResidualWeight);
            TransitionCharSegmentBound newSegmentBound;

            ////if (double.IsInfinity(weightBase.Value))
            ////{
            ////    Console.WriteLine("Weight base infinity");
            ////}

            foreach (var range in ranges)
            {
                if (range.StartInclusive > commonValueStart && !commonValue.IsZero)
                {
                    // Add endpoints for the common value
                    Weight segmentWeight = Weight.Product(commonValue, weightBase);
                    newSegmentBound = new TransitionCharSegmentBound(commonValueStart, transition.DestinationStateIndex, segmentWeight, true);
                    bounds.Add(new ValueTuple <int, TransitionCharSegmentBound>(bounds.Count, newSegmentBound));
                    newSegmentBound = new TransitionCharSegmentBound(range.StartInclusive, transition.DestinationStateIndex, segmentWeight, false);
                    bounds.Add(new ValueTuple <int, TransitionCharSegmentBound>(bounds.Count, newSegmentBound));
                }

                // Add segment endpoints
                Weight pieceValue = Weight.FromValue(range.Probability);
                if (!pieceValue.IsZero)
                {
                    Weight segmentWeight = Weight.Product(pieceValue, weightBase);
                    newSegmentBound = new TransitionCharSegmentBound(range.StartInclusive, transition.DestinationStateIndex, segmentWeight, true);
                    bounds.Add(new ValueTuple <int, TransitionCharSegmentBound>(bounds.Count, newSegmentBound));
                    newSegmentBound = new TransitionCharSegmentBound(range.EndExclusive, transition.DestinationStateIndex, segmentWeight, false);
                    bounds.Add(new ValueTuple <int, TransitionCharSegmentBound>(bounds.Count, newSegmentBound));
                }

                commonValueStart = range.EndExclusive;
            }

            if (!commonValue.IsZero && (ranges.Count == 0 || ranges[ranges.Count - 1].EndExclusive != DiscreteChar.CharRangeEndExclusive))
            {
                // Add endpoints for the last common value segment
                Weight segmentWeight = Weight.Product(commonValue, weightBase);
                newSegmentBound = new TransitionCharSegmentBound(commonValueStart, transition.DestinationStateIndex, segmentWeight, true);
                bounds.Add(new ValueTuple <int, TransitionCharSegmentBound>(bounds.Count, newSegmentBound));
                newSegmentBound = new TransitionCharSegmentBound(char.MaxValue + 1, transition.DestinationStateIndex, segmentWeight, false);
                bounds.Add(new ValueTuple <int, TransitionCharSegmentBound>(bounds.Count, newSegmentBound));
            }
        }
Exemple #2
0
        /// <summary>
        /// Given a transition and the residual weight of its source state, adds weighted non-zero probability character segments
        /// associated with the transition to the list.
        /// </summary>
        /// <param name="transition">The transition.</param>
        /// <param name="sourceStateResidualWeight">The logarithm of the residual weight of the source state of the transition.</param>
        /// <param name="bounds">The list for storing numbered segment bounds.</param>
        private static void AddTransitionCharSegmentBounds(
            Transition transition, Weight sourceStateResidualWeight, List <Tuple <int, TransitionCharSegmentBound> > bounds)
        {
            var    probs            = (PiecewiseVector)transition.ElementDistribution.GetProbs();
            int    commonValueStart = char.MinValue;
            Weight commonValue      = Weight.FromValue(probs.CommonValue);
            Weight weightBase       = Weight.Product(transition.Weight, sourceStateResidualWeight);
            TransitionCharSegmentBound newSegmentBound;

            ////if (double.IsInfinity(weightBase.Value))
            ////{
            ////    Console.WriteLine("Weight base infinity");
            ////}

            for (int i = 0; i < probs.Pieces.Count; ++i)
            {
                ConstantVector piece = probs.Pieces[i];
                if (piece.Start > commonValueStart && !commonValue.IsZero)
                {
                    // Add endpoints for the common value
                    Weight segmentWeight = Weight.Product(commonValue, weightBase);
                    newSegmentBound = new TransitionCharSegmentBound(commonValueStart, transition.DestinationStateIndex, segmentWeight, true);
                    bounds.Add(new Tuple <int, TransitionCharSegmentBound>(bounds.Count, newSegmentBound));
                    newSegmentBound = new TransitionCharSegmentBound(piece.Start, transition.DestinationStateIndex, segmentWeight, false);
                    bounds.Add(new Tuple <int, TransitionCharSegmentBound>(bounds.Count, newSegmentBound));
                }

                // Add segment endpoints
                Weight pieceValue = Weight.FromValue(piece.Value);
                if (!pieceValue.IsZero)
                {
                    Weight segmentWeight = Weight.Product(pieceValue, weightBase);
                    newSegmentBound = new TransitionCharSegmentBound(piece.Start, transition.DestinationStateIndex, segmentWeight, true);
                    bounds.Add(new Tuple <int, TransitionCharSegmentBound>(bounds.Count, newSegmentBound));
                    newSegmentBound = new TransitionCharSegmentBound(piece.End + 1, transition.DestinationStateIndex, segmentWeight, false);
                    bounds.Add(new Tuple <int, TransitionCharSegmentBound>(bounds.Count, newSegmentBound));
                }

                commonValueStart = piece.End + 1;
            }

            if (!commonValue.IsZero && (probs.Pieces.Count == 0 || probs.Pieces[probs.Pieces.Count - 1].End != char.MaxValue))
            {
                // Add endpoints for the last common value segment
                Weight segmentWeight = Weight.Product(commonValue, weightBase);
                newSegmentBound = new TransitionCharSegmentBound(commonValueStart, transition.DestinationStateIndex, segmentWeight, true);
                bounds.Add(new Tuple <int, TransitionCharSegmentBound>(bounds.Count, newSegmentBound));
                newSegmentBound = new TransitionCharSegmentBound(char.MaxValue + 1, transition.DestinationStateIndex, segmentWeight, false);
                bounds.Add(new Tuple <int, TransitionCharSegmentBound>(bounds.Count, newSegmentBound));
            }
        }
Exemple #3
0
        /// <summary>
        /// Computes a set of outgoing transitions from a given state of the determinization result.
        /// </summary>
        /// <param name="sourceState">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="sourceState"/>.
        /// 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 List <(DiscreteChar, Weight, Determinization.WeightedStateSet)> GetOutgoingTransitionsForDeterminization(
            Determinization.WeightedStateSet sourceState)
        {
            const double LogEps = -35; // Don't add transitions with log-weight less than this as they have been produced by numerical inaccuracies

            // Build a list of numbered non-zero probability character segment bounds (they are numbered here due to perf. reasons)
            var segmentBounds        = new List <ValueTuple <int, TransitionCharSegmentBound> >();
            int transitionsProcessed = 0;

            foreach (KeyValuePair <int, Weight> stateIdWeight in sourceState)
            {
                var state = this.States[stateIdWeight.Key];
                foreach (var transition in state.Transitions)
                {
                    AddTransitionCharSegmentBounds(transition, stateIdWeight.Value, segmentBounds);
                }

                transitionsProcessed += state.Transitions.Count;
            }

            // Sort segment bounds left-to-right, start-to-end
            var sortedIndexedSegmentBounds = segmentBounds.ToArray();

            if (transitionsProcessed > 1)
            {
                Array.Sort(sortedIndexedSegmentBounds, CompareSegmentBounds);

                int CompareSegmentBounds((int, TransitionCharSegmentBound) a, (int, TransitionCharSegmentBound) b) =>
                a.Item2.CompareTo(b.Item2);
            }

            // Produce an outgoing transition for each unique subset of overlapping segments
            var    result = new List <(DiscreteChar, Weight, Determinization.WeightedStateSet)>();
            Weight currentSegmentStateWeightSum = Weight.Zero;

            var currentSegmentStateWeights = new Dictionary <int, Weight>();

            foreach (var sb in segmentBounds)
            {
                currentSegmentStateWeights[sb.Item2.DestinationStateId] = Weight.Zero;
            }

            var activeSegments      = new HashSet <TransitionCharSegmentBound>();
            int currentSegmentStart = char.MinValue;

            foreach (var tup in sortedIndexedSegmentBounds)
            {
                TransitionCharSegmentBound segmentBound = tup.Item2;

                if (currentSegmentStateWeightSum.LogValue > LogEps && currentSegmentStart < segmentBound.Bound)
                {
                    // Flush previous segment
                    char         segmentEnd    = (char)(segmentBound.Bound - 1);
                    int          segmentLength = segmentEnd - currentSegmentStart + 1;
                    DiscreteChar elementDist   = DiscreteChar.InRange((char)currentSegmentStart, segmentEnd);

                    var destinationState = new Determinization.WeightedStateSet();
                    foreach (KeyValuePair <int, Weight> stateIdWithWeight in currentSegmentStateWeights)
                    {
                        if (stateIdWithWeight.Value.LogValue > LogEps)
                        {
                            Weight stateWeight = Weight.Product(stateIdWithWeight.Value, Weight.Inverse(currentSegmentStateWeightSum));
                            destinationState.Add(stateIdWithWeight.Key, stateWeight);
                        }
                    }

                    Weight transitionWeight = Weight.Product(Weight.FromValue(segmentLength), currentSegmentStateWeightSum);
                    result.Add((elementDist, transitionWeight, destinationState));
                }

                // Update current segment
                currentSegmentStart = segmentBound.Bound;

                if (segmentBound.IsStart)
                {
                    activeSegments.Add(segmentBound);
                    currentSegmentStateWeightSum = Weight.Sum(currentSegmentStateWeightSum, segmentBound.Weight);
                    currentSegmentStateWeights[segmentBound.DestinationStateId] = Weight.Sum(currentSegmentStateWeights[segmentBound.DestinationStateId], segmentBound.Weight);
                }
                else
                {
                    Debug.Assert(currentSegmentStateWeights.ContainsKey(segmentBound.DestinationStateId), "We shouldn't exit a state we didn't enter.");
                    activeSegments.Remove(segmentBounds[tup.Item1 - 1].Item2);  // End follows start in original.
                    if (double.IsInfinity(segmentBound.Weight.Value))
                    {
                        // Cannot subtract because of the infinities involved.
                        currentSegmentStateWeightSum = activeSegments.Select(sb => sb.Weight).Aggregate(Weight.Zero, (acc, w) => Weight.Sum(acc, w));
                        currentSegmentStateWeights[segmentBound.DestinationStateId] =
                            activeSegments.Where(sb => sb.DestinationStateId == segmentBound.DestinationStateId).Select(sb => sb.Weight).Aggregate(Weight.Zero, (acc, w) => Weight.Sum(acc, w));
                    }
                    else
                    {
                        currentSegmentStateWeightSum = activeSegments.Count == 0 ? Weight.Zero : Weight.AbsoluteDifference(currentSegmentStateWeightSum, segmentBound.Weight);

                        Weight prevStateWeight = currentSegmentStateWeights[segmentBound.DestinationStateId];
                        currentSegmentStateWeights[segmentBound.DestinationStateId] = Weight.AbsoluteDifference(
                            prevStateWeight, segmentBound.Weight);
                    }
                }
            }

            return(result);
        }