private bool AreDistinguishable(ThreeAutomaton <S> fa, Equivalence E, Tuple <int, int> pq, IBooleanAlgebraPositive <S> solver) { foreach (Move <S> from_p in fa.GetMovesFrom(pq.Item1)) { foreach (Move <S> from_q in fa.GetMovesFrom(pq.Item2)) { if (from_p.TargetState != from_q.TargetState && !E.AreEquiv(from_p.TargetState, from_q.TargetState)) { if (solver.IsSatisfiable(solver.MkAnd(from_p.Label, from_q.Label))) { return(true); } } } } return(false); }
/// <summary> /// Checks that for all states q, if q has two or more outgoing /// moves then the conditions of the moves are pairwise disjoint, i.e., /// their conjunction is unsatisfiable. /// If the check succeeds, sets IsDeterministic to true. /// Throws AutomataException if the FSA is not epsilon-free. /// </summary> /// <param name="solver">used to make conjunctions and to check satisfiability of resulting conditions</param> public void CheckDeterminism(IBooleanAlgebraPositive <S> solver, bool resetIsDeterministicToFalse = false) { if (resetIsDeterministicToFalse) { isDeterministic = false; } if (isDeterministic) //already known to be deterministic { return; } foreach (int state in States) { //Normal Moves var moves = delta[state]; int k = moves.Count; if (k > 1) { S sofar = moves[0].action.guard; for (int i = 1; i < k; i++) { var sofar_and_i = solver.MkAnd(sofar, moves[i].action.guard); if (solver.IsSatisfiable(sofar_and_i)) { isDeterministic = false; return; //nondeterministic } if (i < k - 1) { sofar = solver.MkOr(sofar, moves[i].action.guard); } } } //Final moves var finmoves = deltaFinal[state]; k = finmoves.Count; if (k > 1) { S sofar = finmoves[0].action.guard; for (int i = 1; i < k; i++) { var sofar_and_i = solver.MkAnd(sofar, finmoves[i].action.guard); if (solver.IsSatisfiable(sofar_and_i)) { isDeterministic = false; return; //nondeterministic } if (i < k - 1) { sofar = solver.MkOr(sofar, finmoves[i].action.guard); } } } //Fin vs nonfin foreach (var move in delta[state]) { foreach (var finalMove in deltaFinal[state]) { if (move.action.lookahead <= finalMove.action.lookahead) //Move does not have longer lookahead than fin move { if (solver.IsSatisfiable(solver.MkAnd(move.action.guard, finalMove.action.guard))) { isDeterministic = false; return; //nondeterministic } } } } } isDeterministic = true; //deterministic }