public override SSA <SYMBOL> Collapse(SSA <SYMBOL> m) { m = m.RemoveEpsilons(); Dictionary <int, Set <int> > labels = MakeLabels(m); if (heuristic.HasValue) { /* remove ignored states from labels */ foreach (int state in new List <int>(labels.Keys)) { labels[state] -= ignoredLabels; } } return(m.Collapse((_, q1, q2) => labels[q1] == labels[q2])); }
/// <summary> /// Applies this transducer to automaton M in order to create a new automaton /// that accepts the translations of all words in L(M). /// </summary> public SSA <SYMBOL> Apply(SSA <SYMBOL> m) { if (this.Algebra.Alphabet != m.Algebra.Alphabet) { throw SSTException.IncompatibleAlphabets(); } m = m.RemoveEpsilons(); Automaton <Label <SYMBOL> > tau = this.automaton; var stack = new Stack <Tuple <int, int> >(); var finalStates = new List <int>(); var moves = new List <Move <Predicate <SYMBOL> > >(); var stateDict = new Dictionary <Tuple <int, int>, int>(); int id = 0; var init = new Tuple <int, int>(tau.InitialState, m.InitialState); stateDict[init] = id++; // initial state will be 0 stack.Push(init); Action <Tuple <int, int>, Tuple <int, int>, Predicate <SYMBOL> > addMove = (sourcePair, targetPair, label) => { int targetState; if (!stateDict.TryGetValue(targetPair, out targetState)) { stateDict[targetPair] = targetState = id++; stack.Push(targetPair); } moves.Add(new Move <Predicate <SYMBOL> >(stateDict[sourcePair], targetState, label)); }; while (stack.Count > 0) { Tuple <int, int> sourcePair = stack.Pop(); int tauState = sourcePair.Item1; int mState = sourcePair.Item2; foreach (Move <Label <SYMBOL> > tauMove in tau.GetMovesFrom(tauState)) { if (tauMove.Label.Input == null) { addMove( sourcePair, new Tuple <int, int>(tauMove.TargetState, mState), tauMove.Label.IsIdentity ? null : tauMove.Label.Output ); continue; } foreach (Move <Predicate <SYMBOL> > mMove in m.GetMovesFrom(mState)) { if (!m.Algebra.IsSatisfiable(tauMove.Label.Input & mMove.Label)) { continue; } Predicate <SYMBOL> newLabel; if (tauMove.Label.IsIdentity) { newLabel = tauMove.Label.Input & mMove.Label; } else { newLabel = tauMove.Label.Output; if (newLabel != null && !m.Algebra.IsSatisfiable(newLabel)) { continue; } } addMove( sourcePair, new Tuple <int, int>(tauMove.TargetState, mMove.TargetState), newLabel ); } } } foreach (var pair in stateDict) { if (tau.IsFinalState(pair.Key.Item1) && m.IsFinalState(pair.Key.Item2)) { finalStates.Add(pair.Value); } } return(new SSA <SYMBOL>(0, finalStates, moves, m.Algebra.Alphabet)); }
public override void Refine(SSA <SYMBOL> m, SSA <SYMBOL> x) { int offset = predicateAutomata.Sum(pred => pred.States.Count()); x = x.RemoveEpsilons().Normalize(offset); predicateAutomata.Add(x); if (heuristic.HasValue) { var xStates = new Set <int>(x.States); /* find important states (appear in labels) */ Dictionary <int, Set <int> > labels = MakeLabels(m); var importantStates = new Set <int>(); foreach (int mState in m.States) { foreach (int xState in labels[mState]) { if (xState < offset || xState >= xStates.Count + offset) { continue; } importantStates.Add(xState); } } if (((Config.PredHeuristic)heuristic) == Config.PredHeuristic.KeyStates) { /* try to find one key state among important states */ foreach (int state in importantStates) { /* try ignoring all but one state */ ignoredLabels += xStates; ignoredLabels.Remove(state); /* check if the collapsed automaton still intersects */ if (SSA <SYMBOL> .ProductIsEmpty(Collapse(m), x)) { return; } /* failed, restore temporarily ignored states */ ignoredLabels -= xStates; } /* couldn't find just one key state, try to find two */ foreach (int state1 in importantStates) { foreach (int state2 in importantStates.Where(s => s != state1)) { ignoredLabels += xStates; ignoredLabels.Remove(state1); ignoredLabels.Remove(state2); if (SSA <SYMBOL> .ProductIsEmpty(Collapse(m), x)) { return; } ignoredLabels -= xStates; } } /* fall back on important states heuristic */ } /* ignore all unimportant states */ ignoredLabels += xStates - importantStates; } }