/// <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> /// Returns the pairwise union (disjunction) of the enumerated pairs. /// </summary> /// <param name="predicates">given enumeration of predicate pairs</param> public Pair <S, T> MkOr(IEnumerable <Pair <S, T> > predicates) { var one = first.MkOr(EnumerateFirstComponents(predicates)); var two = second.MkOr(EnumerateSecondComponents(predicates)); if (one.Equals(first.False) && second.Equals(second.False)) { return(ff); } else if (one.Equals(first.True) && second.Equals(second.True)) { return(tt); } else { return(new Pair <S, T>(one, two)); } }
protected TERM Or(IBooleanAlgebra <TERM> solver, TERM a, TERM b) { if (a.Equals(solver.False)) { return(b); } else if (b.Equals(solver.False)) { return(a); } else if (b.Equals(a)) { return(a); } else { return(solver.MkOr(a, b)); } }
/// <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)); }
private Automaton <S> AlternateSFAs(int start, List <Automaton <S> > sfas, bool addEmptyWord, bool noWordBoundaries) { if (!noWordBoundaries) { var res0 = Automaton <S> .Create(solver, start, EnumFinStates(sfas), EnumMoves(start, sfas)); res0.AddWordBoundaries(EnumWordBounbdaries(sfas)); return(res0); } #region special cases for sfas.Count == 0 or sfas.Count == 1 if (sfas.Count == 0) { if (addEmptyWord) { return(this.epsilon); } else { return(this.empty); } } if (sfas.Count == 1) { if (addEmptyWord && !sfas[0].IsFinalState(sfas[0].InitialState)) { if (sfas[0].InitialStateIsSource) { sfas[0].MakeInitialStateFinal(); } else { sfas[0].AddNewInitialStateThatIsFinal(start); } } return(sfas[0]); } #endregion //special cases for sfas.Count == 0 or sfas.Count == 1 bool allSingleSource = true; #region check if all sfas have a single source foreach (var sfa in sfas) { if (!sfa.InitialStateIsSource) { allSingleSource = false; break; } } #endregion //check if all sfas have a single source bool isDeterministic = !sfas.Exists(IsNonDeterministic); bool isEpsilonFree = !sfas.Exists(HasEpsilons); bool allFinalSink = true; int sinkId; #region check if all sfas have a single final sink and calulate a representative sinkId as the maximum of the ids sinkId = int.MinValue; foreach (var sfa in sfas) { if (!sfa.HasSingleFinalSink) { allFinalSink = false; break; } else { sinkId = Math.Max(sfa.FinalState, sinkId); } } #endregion var finalStates = new List <int>(); if (addEmptyWord) { finalStates.Add(start); //epsilon is accepted so initial state is also final } var conditionMap = new Dictionary <Pair <int, int>, S>(); //for normalization of move conditions var eMoves = new HashSet <Pair <int, int> >(); if (!allSingleSource) { isDeterministic = false; isEpsilonFree = false; foreach (var sfa in sfas) //add initial epsilon transitions { eMoves.Add(new Pair <int, int>(start, sfa.InitialState)); } } else if (isDeterministic) { //check if determinism is preserved for (int i = 0; i < sfas.Count - 1; i++) { for (int j = i + 1; j < sfas.Count; j++) { S cond1 = solver.False; foreach (var move in sfas[i].GetMovesFrom(sfas[i].InitialState)) { cond1 = solver.MkOr(cond1, move.Label); } S cond2 = solver.False; foreach (var move in sfas[j].GetMovesFrom(sfas[j].InitialState)) { cond2 = solver.MkOr(cond2, move.Label); } S checkCond = solver.MkAnd(cond1, cond2); isDeterministic = (checkCond.Equals(solver.False)); if (!isDeterministic) { break; } } if (!isDeterministic) { break; } } } if (allFinalSink) { finalStates.Add(sinkId); //this will be the final state } Dictionary <int, int> stateRenamingMap = new Dictionary <int, int>(); foreach (var sfa in sfas) { foreach (var move in sfa.GetMoves()) { int source = (allSingleSource && sfa.InitialState == move.SourceState ? start : move.SourceState); int target = (allFinalSink && sfa.FinalState == move.TargetState ? sinkId : move.TargetState); var p = new Pair <int, int>(source, target); stateRenamingMap[move.SourceState] = source; stateRenamingMap[move.TargetState] = target; if (move.IsEpsilon) { if (source != target) { eMoves.Add(new Pair <int, int>(source, target)); } continue; } S cond; if (conditionMap.TryGetValue(p, out cond)) { conditionMap[p] = solver.MkOr(cond, move.Label); //join the conditions into a disjunction } else { conditionMap[p] = move.Label; } } if (!allFinalSink) { foreach (int s in sfa.GetFinalStates()) { int s1 = stateRenamingMap[s]; if (!finalStates.Contains(s1)) { finalStates.Add(s1); } } } } Automaton <S> res = Automaton <S> .Create(solver, start, finalStates, GenerateMoves(conditionMap, eMoves)); res.isDeterministic = isDeterministic; return(res); }