Exemplo n.º 1
0
        /// <summary>
        /// Recursively builds the projection of a given automaton onto this transducer.
        /// The projected automaton must be epsilon-free.
        /// </summary>
        /// <param name="destAutomaton">The projection being built.</param>
        /// <param name="mappingState">The currently traversed state of the transducer.</param>
        /// <param name="srcState">The currently traversed state of the automaton being projected.</param>
        /// <param name="destStateCache">The cache of the created projection states.</param>
        /// <returns>The state of the projection corresponding to the given mapping state and the position in the projected sequence.</returns>
        private Automaton <TDestSequence, TDestElement, TDestElementDistribution, TDestSequenceManipulator, TDestAutomaton> .State BuildProjectionOfAutomaton(
            TDestAutomaton destAutomaton,
            PairListAutomaton.State mappingState,
            Automaton <TSrcSequence, TSrcElement, TSrcElementDistribution, TSrcSequenceManipulator, TSrcAutomaton> .State srcState,
            Dictionary <IntPair, Automaton <TDestSequence, TDestElement, TDestElementDistribution, TDestSequenceManipulator, TDestAutomaton> .State> destStateCache)
        {
            Debug.Assert(mappingState != null && srcState != null, "Valid states must be provided.");
            Debug.Assert(!ReferenceEquals(srcState.Owner, destAutomaton), "Cannot build a projection in place.");

            //// The code of this method has a lot in common with the code of Automaton<>.BuildProduct.
            //// Unfortunately, it's not clear how to avoid the duplication in the current design.

            // State already exists, return its index
            var statePair = new IntPair(mappingState.Index, srcState.Index);

            Automaton <TDestSequence, TDestElement, TDestElementDistribution, TDestSequenceManipulator, TDestAutomaton> .State destState;
            if (destStateCache.TryGetValue(statePair, out destState))
            {
                return(destState);
            }

            destState = destAutomaton.AddState();
            destStateCache.Add(statePair, destState);

            // Iterate over transitions from mappingState
            for (int mappingTransitionIndex = 0; mappingTransitionIndex < mappingState.TransitionCount; mappingTransitionIndex++)
            {
                var mappingTransition = mappingState.GetTransition(mappingTransitionIndex);
                var childMappingState = mappingState.Owner.States[mappingTransition.DestinationStateIndex];

                // Epsilon transition case
                if (IsSrcEpsilon(mappingTransition))
                {
                    TDestElementDistribution destElementDistribution = mappingTransition.ElementDistribution == null ? null : mappingTransition.ElementDistribution.Second;
                    var childDestState = this.BuildProjectionOfAutomaton(destAutomaton, childMappingState, srcState, destStateCache);
                    destState.AddTransition(destElementDistribution, mappingTransition.Weight, childDestState, mappingTransition.Group);
                    continue;
                }

                // Iterate over states and transitions in the closure of srcState
                for (int srcTransitionIndex = 0; srcTransitionIndex < srcState.TransitionCount; srcTransitionIndex++)
                {
                    var srcTransition = srcState.GetTransition(srcTransitionIndex);
                    Debug.Assert(!srcTransition.IsEpsilon, "The automaton being projected must be epsilon-free.");

                    var srcChildState = srcState.Owner.States[srcTransition.DestinationStateIndex];

                    TDestElementDistribution destElementDistribution;
                    double projectionLogScale = mappingTransition.ElementDistribution.ProjectFirst(
                        srcTransition.ElementDistribution, out destElementDistribution);
                    if (double.IsNegativeInfinity(projectionLogScale))
                    {
                        continue;
                    }

                    Weight destWeight     = Weight.Product(mappingTransition.Weight, srcTransition.Weight, Weight.FromLogValue(projectionLogScale));
                    var    childDestState = this.BuildProjectionOfAutomaton(destAutomaton, childMappingState, srcChildState, destStateCache);
                    destState.AddTransition(destElementDistribution, destWeight, childDestState, mappingTransition.Group);
                }
            }

            destState.EndWeight = Weight.Product(mappingState.EndWeight, srcState.EndWeight);
            return(destState);
        }
Exemplo n.º 2
0
 /// <summary>
 /// Checks whether this object is equal to a given pair.
 /// </summary>
 /// <param name="pair">The pair to compare with.</param>
 /// <returns><see langword="true"/> if this pair is equal to the given one, <see langword="false"/> otherwise.</returns>
 public bool Equals(IntPair pair)
 {
     return(this.First == pair.First && this.Second == pair.Second);
 }
Exemplo n.º 3
0
        /// <summary>
        /// Recursively builds the projection of a given sequence onto this transducer.
        /// </summary>
        /// <param name="destAutomaton">The projection being built.</param>
        /// <param name="mappingState">The currently traversed state of the transducer.</param>
        /// <param name="srcSequence">The sequence being projected.</param>
        /// <param name="srcSequenceIndex">The current index in the sequence being projected.</param>
        /// <param name="destStateCache">The cache of the created projection states.</param>
        /// <returns>The state of the projection corresponding to the given mapping state and the position in the projected sequence.</returns>
        private Automaton <TDestSequence, TDestElement, TDestElementDistribution, TDestSequenceManipulator, TDestAutomaton> .State BuildProjectionOfSequence(
            TDestAutomaton destAutomaton,
            PairListAutomaton.State mappingState,
            TSrcSequence srcSequence,
            int srcSequenceIndex,
            Dictionary <IntPair, Automaton <TDestSequence, TDestElement, TDestElementDistribution, TDestSequenceManipulator, TDestAutomaton> .State> destStateCache)
        {
            //// The code of this method has a lot in common with the code of Automaton<>.BuildProduct.
            //// Unfortunately, it's not clear how to avoid the duplication in the current design.

            var sourceSequenceManipulator =
                Automaton <TSrcSequence, TSrcElement, TSrcElementDistribution, TSrcSequenceManipulator, TSrcAutomaton> .SequenceManipulator;

            var statePair = new IntPair(mappingState.Index, srcSequenceIndex);

            Automaton <TDestSequence, TDestElement, TDestElementDistribution, TDestSequenceManipulator, TDestAutomaton> .State destState;
            if (destStateCache.TryGetValue(statePair, out destState))
            {
                return(destState);
            }

            destState = destAutomaton.AddState();
            destStateCache.Add(statePair, destState);

            int srcSequenceLength = sourceSequenceManipulator.GetLength(srcSequence);

            // Enumerate transitions from the current mapping state
            for (int i = 0; i < mappingState.TransitionCount; i++)
            {
                var mappingTransition = mappingState.GetTransition(i);
                var destMappingState  = mappingState.Owner.States[mappingTransition.DestinationStateIndex];

                // Epsilon transition case
                if (IsSrcEpsilon(mappingTransition))
                {
                    TDestElementDistribution destElementWeights = mappingTransition.ElementDistribution == null ? null : mappingTransition.ElementDistribution.Second;
                    var childDestState = this.BuildProjectionOfSequence(
                        destAutomaton, destMappingState, srcSequence, srcSequenceIndex, destStateCache);
                    destState.AddTransition(destElementWeights, mappingTransition.Weight, childDestState, mappingTransition.Group);
                    continue;
                }

                // Normal transition case - Find epsilon-reachable states
                if (srcSequenceIndex < srcSequenceLength)
                {
                    var srcSequenceElement = sourceSequenceManipulator.GetElement(srcSequence, srcSequenceIndex);

                    TDestElementDistribution destElementDistribution;
                    double projectionLogScale = mappingTransition.ElementDistribution.ProjectFirst(
                        srcSequenceElement, out destElementDistribution);
                    if (double.IsNegativeInfinity(projectionLogScale))
                    {
                        continue;
                    }

                    Weight weight         = Weight.Product(mappingTransition.Weight, Weight.FromLogValue(projectionLogScale));
                    var    childDestState = this.BuildProjectionOfSequence(
                        destAutomaton, destMappingState, srcSequence, srcSequenceIndex + 1, destStateCache);
                    destState.AddTransition(destElementDistribution, weight, childDestState, mappingTransition.Group);
                }
            }

            destState.EndWeight = srcSequenceIndex == srcSequenceLength ? mappingState.EndWeight : Weight.Zero;
            return(destState);
        }