internal static bool MoveSemanticTagRight(Arc arc) { State end = arc.End; Arc first = end.OutArcs.First; if (end.InArcs.CountIsOne && end.OutArcs.CountIsOne && CanTagsBeMoved(arc, first)) { Arc.CopyTags(arc, first, Direction.Right); return(true); } return(arc.IsPropertylessTransition); }
internal static bool MoveSemanticTagLeft(Arc arc) { State start = arc.Start; Arc first = start.InArcs.First; if (start.InArcs.CountIsOne && start.OutArcs.CountIsOne && CanTagsBeMoved(first, arc)) { Arc.CopyTags(arc, first, Direction.Left); return(true); } return(arc.IsPropertylessTransition); }
/// <summary> /// Move any semantic tag ownership and optionally references to a unique /// previous arc, if possible. /// /// MoveReferences = true: Return if arc is propertyless after the move. /// MoveReferences = false: Return if arc does not own semantic tag after the move. /// The arc can still be referenced by other semantic tags. /// </summary> internal static bool MoveSemanticTagLeft(Arc arc) { // This changes the range of words spanned by the tag, which is a bug for SAPI grammars. State startState = arc.Start; // Can only move ownership/references if there is an unique input and output arc from the start state. // Cannot concatenate semantic tags. (SemanticInterpretation script can arguably be concatenated.) // Cannot move ownership across RuleRef (to maintain semantics of $$ in SemanticTag JScript). // Cannot move semantic tag to special transition. (SREngine may return multiple result arcs for the transition.) Arc previousArc = startState.InArcs.First; if ((startState.InArcs.CountIsOne) && (startState.OutArcs.CountIsOne) && CanTagsBeMoved(previousArc, arc)) { // Move semantic tag ownership to the previous arc. Arc.CopyTags(arc, previousArc, Direction.Left); // Semantic tag and optionally references have been moved successfully. return(true); } return(arc.IsPropertylessTransition); }
/// <summary> /// Move any semantic tag ownership and optionally references to a unique /// next arc, if possible. /// /// MoveReferences = true: Return if arc is propertyless after the move. /// MoveReferences = false: Return if arc does not own semantic tag after the move. /// The arc can still be referenced by other semantic tags. /// /// Force semantic tag references to always move with tag. /// This changes the range of words spanned by the tag, which is a bug for SAPI grammars. /// </summary> internal static bool MoveSemanticTagRight(Arc arc) { System.Diagnostics.Debug.Assert(arc.End != null); State endState = arc.End; // Can only move ownership/references if there is an unique input and output arc from the end state. // Cannot concatenate semantic tags. (SemanticInterpretation script can arguably be concatenated.) // Cannot move ownership across RuleRef (to maintain semantics of $$ in SemanticTag JScript). // Cannot move semantic tag to special transition. (SREngine may return multiple result arcs for the transition.) Arc pNextArc = endState.OutArcs.First; if ((endState.InArcs.CountIsOne) && (endState.OutArcs.CountIsOne) && CanTagsBeMoved(arc, pNextArc)) { // Move semantic tag ownership to the next arc. Arc.CopyTags(arc, pNextArc, Direction.Right); // Semantic tag and optionally references have been moved successfully. return(true); } return(arc.IsPropertylessTransition); }
private void MergeDuplicateOutputTransitions(ArcList arcs, Stack <State> mergeStates) { List <Arc> list = null; Arc arc = null; bool flag = false; foreach (Arc arc5 in arcs) { bool flag2 = arc5.End == null || !arc5.End.InArcs.CountIsOne; if (arc != null && Arc.CompareContent(arc5, arc) == 0) { if (!flag2) { if (list == null) { list = new List <Arc>(); } if (!flag) { list.Add(arc); flag = true; } list.Add(arc5); } } else { arc = (flag2 ? null : arc5); flag = false; } } if (list != null) { list.Sort(Arc.CompareForDuplicateOutputTransitions); arc = null; Arc arc3 = null; State state = null; bool flag3 = false; foreach (Arc item in list) { if (arc == null || Arc.CompareContent(item, arc) != 0) { arc = item; if (flag3) { AddToMergeStateList(mergeStates, state); } arc3 = null; state = null; flag3 = false; } Arc arc4 = item; State end = arc4.End; if (end != end.Rule._firstState && MoveSemanticTagRight(arc4)) { if (arc3 != null) { if (!flag3) { foreach (Arc outArc in state.OutArcs) { outArc.Weight *= arc3.Weight; } flag3 = true; } foreach (Arc outArc2 in end.OutArcs) { outArc2.Weight *= arc4.Weight; } arc4.Weight += arc3.Weight; Arc.CopyTags(arc3, arc4, Direction.Right); DeleteTransition(arc3); MoveOutputTransitionsAndDeleteState(state, end); } arc3 = arc4; state = end; } } if (flag3) { AddToMergeStateList(mergeStates, state); } } }
/// <summary> /// Description: /// Sort and iterate through the output arcs and remove duplicate output transitions. /// /// Algorithm: /// - MergeIdenticalTransitions(Arcs) /// - Sort the output transitions from the state (by content and # input arcs from end state) /// - For each set of transitions with identical content, EndState != null, and EndState.InputArcs.Count() == 1 /// - Move semantic properties to the right, if necessary. /// - Label the first property-less transition as CommonArc /// - For each property-less transition (DuplicateArc) including CommonArc /// - Multiply the weights of output transitions from DuplicateArc.EndState by DuplicateArc.Weight. /// - If DuplicateArc != CommonArc /// - CommonArc.Weight += DuplicateArc.Weight /// - Delete DuplicateArc /// - MoveOutputTransitionsAndDeleteState(DuplicateArc.EndState, CommonArc.EndState) /// - Normalize weights of output transitions from CommonArc.EndState. /// - Add CommonArc.EndtState to ToDoList if not there already. /// /// Moving SemanticTag: /// - Duplicate output transitions can move its semantic tag ownerships/references to the right. /// </summary> /// <param name="arcs">Collection of output transitions to collapse</param> /// <param name="mergeStates">Collection of states with potential transitions to merge</param> private void MergeDuplicateOutputTransitions(ArcList arcs, Stack <State> mergeStates) { List <Arc> arcsToMerge = null; // Reference Arc Arc refArc = null; bool refSet = false; // Build a list of possible arcs to Merge foreach (Arc arc in arcs) { // Skip transitions whose end state has other incoming transitions or if the end state has more than one incoming transition bool skipTransition = arc.End == null || !arc.End.InArcs.CountIsOne; // Find next set of duplicate output transitions (potentially with properties). if (refArc != null && Arc.CompareContent(arc, refArc) == 0) { if (!skipTransition) { // Lazy init as entering this loop is a rare event if (arcsToMerge == null) { arcsToMerge = new List <Arc>(); } // Add the first element if (!refSet) { arcsToMerge.Add(refArc); refSet = true; } arcsToMerge.Add(arc); } } else { // New word, reset everything refArc = skipTransition ? null : arc; refSet = false; } } // Combine the arcs if possible if (arcsToMerge != null) { // Sort the arc per content and output transition arcsToMerge.Sort(Arc.CompareForDuplicateOutputTransitions); refArc = null; Arc commonArc = null; // Common property-less transition to merge into State commonEndState = null; bool fCommonEndStateChanged = false; // Did CommonEndState change and need re-optimization? foreach (Arc arc in arcsToMerge) { if (refArc == null || Arc.CompareContent(arc, refArc) != 0) { // Purge the last operations and reset all the local refArc = arc; // If CommonEndState changed, renormalize weights and add it to MergeStates for reoptimization. if (fCommonEndStateChanged) { AddToMergeStateList(mergeStates, commonEndState); } // Reset the arcs commonArc = null; commonEndState = null; fCommonEndStateChanged = false; } // For each property-less duplicate transition Arc duplicatedArc = arc; State duplicatedEndState = duplicatedArc.End; // Attempt to move properties referencing duplicate arc to the right. // Optimization can only be applied when the duplicate arc is not referenced by any properties // and the duplicate end state is not the RuleInitalState. if ((duplicatedEndState != duplicatedEndState.Rule._firstState) && MoveSemanticTagRight(duplicatedArc)) { // duplicatedArc != commonArc if (commonArc != null) { if (!fCommonEndStateChanged) { // Processing first duplicate arc. // Multiply the weights of transitions from CommonEndState by CommonArc.Weight. foreach (Arc arcOut in commonEndState.OutArcs) { arcOut.Weight *= commonArc.Weight; } fCommonEndStateChanged = true; // Output transitions of CommonEndState changed. } // Multiply the weights of transitions from DuplicateEndState by DuplicateArc.Weight. foreach (Arc arcOut in duplicatedEndState.OutArcs) { arcOut.Weight *= duplicatedArc.Weight; } duplicatedArc.Weight += commonArc.Weight; // Merge duplicate arc weight with common arc Arc.CopyTags(commonArc, duplicatedArc, Direction.Right); DeleteTransition(commonArc); // Delete successive duplicate transitions // Move outputs of duplicate state to common state; Delete duplicate state MoveOutputTransitionsAndDeleteState(commonEndState, duplicatedEndState); } // Label first property-less transition as CommonArc commonArc = duplicatedArc; commonEndState = duplicatedEndState; } } // If CommonEndState changed, renormalize weights and add it to MergeStates for reoptimization. if (fCommonEndStateChanged) { AddToMergeStateList(mergeStates, commonEndState); } } }