public ReachabilityAutomaton(PushdownAutomaton <S, T> pda, bool allstatesarepositive = false) { this.pda = pda; this.q0 = (allstatesarepositive ? 0 : pda.automaton.MaxState + 1); this.__newStateId = (allstatesarepositive ? pda.automaton.MaxState + 1 : pda.automaton.MaxState + 2); this.start = new Tuple <int, int>(this.q0, pda.automaton.InitialState); this.Q.Add(this.q0); this.Q.UnionWith(pda.automaton.States); this.F.UnionWith(pda.automaton.GetFinalStates()); foreach (var s in pda.stackSymbols) { pushMap[s] = new HashSet <Trans>(); popMap[s] = new HashSet <Move <Sequence <T> > >(); } AddPush(this.start, pda.initialStackSymbol); #region initialize transitions foreach (int q in pda.automaton.States) { foreach (var move in pda.automaton.GetMovesFrom(q)) { if (move.Label.PushSymbols.IsEmpty) { AddPop(q, move.TargetState, move.Label.PopSymbol, move.Label.Input); } else { int s = q; int t = GetNewStateId(); this.Q.Add(t); var symbs = move.Label.PushSymbols.ToArray(); S a = move.Label.PopSymbol; var st = MkTrans(s, t); //first add the pop move s --(a-)--> t to intermediate new state t AddPop(s, t, a, move.Label.Input); //next add the intermediate push symbols, starting from the last for (int i = symbs.Length - 1; i > 0; i--) { s = t; t = GetNewStateId(); this.Q.Add(t); st = MkTrans(s, t); AddPush(st, symbs[i]); } //add the top push symbol to the original target state of the move AddPush(MkTrans(t, move.TargetState), symbs[0]); } } } #endregion #region initialize epsilon relation as the initial reflexive relation over states foreach (int q in Q) { var qq = new Trans(q, q); var set1 = new HashSet <int>(); set1.Add(q); forward[q] = set1; var set2 = new HashSet <int>(); set2.Add(q); inverse[q] = set2; witnessMap[qq] = Sequence <T> .Empty; epsilons.Add(qq); } #endregion }
PushdownAutomaton <S, T> Intersect1(IMinimalAutomaton <T> nfa) { //depth first product construction, PDA may have epsilon moves var stateIdMap = new Dictionary <Pair, int>(); int nextStateId = 1; var stack = new SimpleStack <Pair>(); var moves = new List <Move <PushdownLabel <S, T> > >(); var states = new List <int>(); var finalstates = new List <int>(); #region GetState: push the pair to stack if the state id was new and update final states as needed Func <Pair, int> GetState = (pair) => { int id; if (!stateIdMap.TryGetValue(pair, out id)) { id = nextStateId; nextStateId += 1; stateIdMap[pair] = id; stack.Push(pair); states.Add(id); if (this.automaton.IsFinalState(pair.Item1) && nfa.IsFinalState(pair.Item2)) { finalstates.Add(id); } } return(id); }; #endregion var initPair = new Pair(this.automaton.InitialState, nfa.InitialState); int initState = GetState(initPair); #region compute the product transitions with depth-first search while (stack.IsNonempty) { var sourcePair = stack.Pop(); var source = stateIdMap[sourcePair]; var pda_state = sourcePair.Item1; var aut_state = sourcePair.Item2; foreach (var pda_move in this.automaton.GetMovesFrom(pda_state)) { if (pda_move.IsEpsilon || pda_move.Label.InputIsEpsilon) { var targetPair = new Pair(pda_move.TargetState, aut_state); int target = GetState(targetPair); moves.Add(Move <PushdownLabel <S, T> > .Create(source, target, pda_move.Label)); } else { //assuming here that the automaton does not have epsilons foreach (var aut_move in nfa.GetMovesFrom(aut_state)) { if (aut_move.IsEpsilon) { throw new AutomataException(AutomataExceptionKind.AutomatonIsNotEpsilonfree); } var cond = nfa.Algebra.MkAnd(aut_move.Label, pda_move.Label.Input); //if the joint condition is not satisfiable then the //joint move does effectively not exist if (nfa.Algebra.IsSatisfiable(cond)) { var targetPair = new Pair(pda_move.TargetState, aut_move.TargetState); int target = GetState(targetPair); var label = new PushdownLabel <S, T>(cond, pda_move.Label.PushAndPop); var jointmove = Move <PushdownLabel <S, T> > .Create(source, target, label); moves.Add(jointmove); } } } } } #endregion //note: automaton creation eliminates unreachable states and deadend states from the product var productAutom = Automaton <PushdownLabel <S, T> > .Create(null, initState, finalstates, moves, true, true); var product = new PushdownAutomaton <S, T>(nfa.Algebra, productAutom, this.stackSymbols, this.initialStackSymbol); return(product); }