/// <summary> /// The sink state will be the state with the largest id. /// </summary> public ThreeAutomaton <S> MakeTotal() { var aut = this; int deadState = aut.maxState + 1; var newMoves = new List <Move <S> >(); foreach (int state in aut.States) { var cond = algebra.MkNot(algebra.MkOr(aut.EnumerateConditions(state))); if (algebra.IsSatisfiable(cond)) { newMoves.Add(Move <S> .Create(state, deadState, cond)); } } if (newMoves.Count == 0) { return(this); } newMoves.Add(Move <S> .Create(deadState, deadState, algebra.True)); newMoves.AddRange(GetMoves()); return(ThreeAutomaton <S> .Create(algebra, aut.initialState, aut.rejectingStateSet, aut.acceptingStateSet, newMoves)); }
/// <summary> /// Extension of standard minimization of FAs, use timeout. /// </summary> ThreeAutomaton <S> MinimizeClassical(IBooleanAlgebra <S> solver, int timeout) { var fa = this.MakeTotal(); Equivalence E = new Equivalence(); //initialize E, all nonfinal states are equivalent //and all final states are equivalent and all dontcare are equivalent List <int> stateList = new List <int>(fa.States); for (int i = 0; i < stateList.Count; i++) { //E.Add(stateList[i], stateList[i]); for (int j = 0; j < stateList.Count; j++) { int p = stateList[i]; int q = stateList[j]; bool pIsFinal = fa.IsFinalState(p); bool qIsFinal = fa.IsFinalState(q); if (pIsFinal == qIsFinal) { if (pIsFinal) { E.Add(p, q); } else { bool pIsRej = fa.IsRejectingState(p); bool qIsRej = fa.IsRejectingState(q); if (pIsRej == qIsRej) { E.Add(p, q); } } } } } //refine E bool continueRefinement = true; List <int> statesList = new List <int>(fa.States); while (continueRefinement) { continueRefinement = false; for (int i = 0; i < statesList.Count; i++) { for (int j = 0; j < statesList.Count; j++) { Tuple <int, int> pq = new Tuple <int, int>(statesList[i], statesList[j]); if (E.Contains(pq)) { if (pq.Item1 != pq.Item2 && AreDistinguishable(fa, E, pq, solver)) { E.Remove(pq); continueRefinement = true; } } } } } //create id's for equivalence classes Dictionary <int, int> equivIdMap = new Dictionary <int, int>(); List <int> mfaStates = new List <int>(); foreach (Tuple <int, int> pq in E) { int equivId; if (equivIdMap.TryGetValue(pq.Item1, out equivId)) { equivIdMap[pq.Item2] = equivId; } else if (equivIdMap.TryGetValue(pq.Item2, out equivId)) { equivIdMap[pq.Item1] = equivId; } else { equivIdMap[pq.Item1] = pq.Item1; equivIdMap[pq.Item2] = pq.Item1; mfaStates.Add(pq.Item1); } } //remaining states map to themselves foreach (int state in fa.States) { if (!equivIdMap.ContainsKey(state)) { equivIdMap[state] = state; mfaStates.Add(state); } } int mfaInitialState = equivIdMap[fa.InitialState]; //group together transition conditions for transitions on equivalent states Dictionary <Tuple <int, int>, S> combinedConditionMap = new Dictionary <Tuple <int, int>, S>(); foreach (int state in fa.States) { int fromStateId = equivIdMap[state]; foreach (Move <S> trans in fa.GetMovesFrom(state)) { int toStateId = equivIdMap[trans.TargetState]; S cond; var p = new Tuple <int, int>(fromStateId, toStateId); if (combinedConditionMap.TryGetValue(p, out cond)) { combinedConditionMap[p] = solver.MkOr(cond, trans.Label); } else { combinedConditionMap[p] = trans.Label; } } } //form the transitions of the mfa List <Move <S> > mfaTransitions = new List <Move <S> >(); foreach (var kv in combinedConditionMap) { mfaTransitions.Add(Move <S> .Create(kv.Key.Item1, kv.Key.Item2, kv.Value)); } //accepting states and rejecting HashSet <int> mfaAccStates = new HashSet <int>(); HashSet <int> mfaRejStates = new HashSet <int>(); foreach (int state in acceptingStateSet) { mfaAccStates.Add(equivIdMap[state]); } foreach (int state in rejectingStateSet) { mfaRejStates.Add(equivIdMap[state]); } return(ThreeAutomaton <S> .Create(algebra, mfaInitialState, mfaRejStates, mfaAccStates, mfaTransitions)); }
/// <summary> /// Make a complement of the automaton. /// Assumes that the automaton is deterministic, otherwise throws AutomataException. /// </summary> /// <param name="solver">solver for character constraints</param> /// <returns>Complement of this automaton</returns> public ThreeAutomaton <S> MkComplement() { return(ThreeAutomaton <S> .Create(algebra, initialState, acceptingStateSet, rejectingStateSet, this.GetMoves())); }
public static ThreeAutomaton <S> MkProduct(ThreeAutomaton <S> aut1, ThreeAutomaton <S> aut2, IBooleanAlgebra <S> solver, bool inters) { var a = aut1.MakeTotal(); var b = aut2.MakeTotal(); var stateIdMap = new Dictionary <Tuple <int, int>, int>(); var initPair = new Tuple <int, int>(a.InitialState, b.InitialState); var frontier = new Stack <Tuple <int, int> >(); frontier.Push(initPair); stateIdMap[initPair] = 0; var delta = new Dictionary <int, List <Move <S> > >(); delta[0] = new List <Move <S> >(); var states = new List <int>(); states.Add(0); var accStates = new List <int>(); var rejStates = new List <int>(); if (inters) { if (a.IsFinalState(a.InitialState) && b.IsFinalState(b.InitialState)) { accStates.Add(0); } else if (a.IsRejectingState(a.InitialState) || b.IsRejectingState(b.InitialState)) { rejStates.Add(0); } } else { if (a.IsRejectingState(a.InitialState) && b.IsRejectingState(b.InitialState)) { rejStates.Add(0); } else if (a.IsFinalState(a.InitialState) || b.IsFinalState(b.InitialState)) { accStates.Add(0); } } int n = 1; while (frontier.Count > 0) { var currPair = frontier.Pop(); int source = stateIdMap[currPair]; var outTransitions = delta[source]; foreach (var t1 in a.GetMovesFrom(currPair.Item1)) { foreach (var t2 in b.GetMovesFrom(currPair.Item2)) { var cond = solver.MkAnd(t1.Label, t2.Label); if (!solver.IsSatisfiable(cond)) { continue; //ignore the unsatisfiable move } Tuple <int, int> targetPair = new Tuple <int, int>(t1.TargetState, t2.TargetState); int target; if (!stateIdMap.TryGetValue(targetPair, out target)) { //state has not yet been found target = n; n += 1; stateIdMap[targetPair] = target; states.Add(target); delta[target] = new List <Move <S> >(); frontier.Push(targetPair); if (inters) { if (a.IsFinalState(t1.TargetState) && b.IsFinalState(t2.TargetState)) { accStates.Add(target); } else if (a.IsRejectingState(t1.TargetState) || b.IsRejectingState(t2.TargetState)) { rejStates.Add(target); } } else { if (a.IsRejectingState(t1.TargetState) && b.IsRejectingState(t2.TargetState)) { rejStates.Add(target); } else if (a.IsFinalState(t1.TargetState) || b.IsFinalState(t2.TargetState)) { accStates.Add(target); } } } outTransitions.Add(Move <S> .Create(source, target, cond)); } } } var incomingTransitions = new Dictionary <int, List <Move <S> > >(); foreach (int state in states) { incomingTransitions[state] = new List <Move <S> >(); } foreach (int state in states) { foreach (Move <S> t in delta[state]) { incomingTransitions[t.TargetState].Add(t); } } return(ThreeAutomaton <S> .Create(aut1.algebra, 0, rejStates, accStates, EnumerateMoves(delta))); }