package pl.edu.amu.wmi.daut.base; import java.util.ArrayList; import java.util.HashMap; import java.util.List; /** * Abstrakcyjny opis automatu deterministycznego. */ public abstract class DeterministicAutomatonSpecification extends AutomatonSpecification { /** * Zwraca stan, jaki zostanie osiągnięty przy przejściu ze stanu * from przez znak c. Zwraca null, jeśli nie istnieje przejście * ze stanu from przez znak c. */ public abstract State targetState(State from, char c); /** * Zwraca liste stanów z których przejścia wychodzą do podanego stanu. */ public List<State> findPreviousState(State nextState, DeterministicAutomatonSpecification automaton) { List<State> previousStates = new ArrayList<State>(); for (State state : automaton.allStates()) { for (OutgoingTransition transition : automaton.allOutgoingTransitions(state)) { if (transition.getTargetState() == nextState) { previousStates.add(state); } } } return previousStates; } /** * Pobiera dwa stany, zwraca przejścia między nimi. */ public List<OutgoingTransition> findPreviousStateTransitions( State previousState, State nextState, DeterministicAutomatonSpecification automaton) { List<OutgoingTransition> needTransitions = new ArrayList<OutgoingTransition>(); for (OutgoingTransition transition : automaton.allOutgoingTransitions(previousState)) { if (transition.getTargetState() == nextState) needTransitions.add(transition); } return needTransitions; } /** * Usuwa zbędne stany. To znaczy takie, do których nie można, * dojść ze stanu początkowego. */ public List<State> returnUselessStates() { State startState = getInitialState(); List<State> startStates = new ArrayList<State>(); List<State> uselessStates = new ArrayList<State>(); uselessStates.addAll(allStates()); uselessStates.remove(getInitialState()); for (OutgoingTransition transition : allOutgoingTransitions(startState)) { startStates.add(transition.getTargetState()); uselessStates.remove(transition.getTargetState()); } while (!startStates.isEmpty()) { for (int i = 0; i < startStates.size(); i++) { for (OutgoingTransition transition : allOutgoingTransitions( startStates.get(i))) { if (uselessStates.contains(transition.getTargetState())) { startStates.add(transition.getTargetState()); uselessStates.remove(transition.getTargetState()); } } startStates.remove(startStates.get(i)); } } return uselessStates; } private void buildMinimal(DeterministicAutomatonSpecification automatonToBeMinimized, HashMap<State, State> similarStates) { List<State> states = automatonToBeMinimized.allStates(); List<State> prevStates; List<OutgoingTransition> prevTransitions; HashMap<State, State> getOldStates = new HashMap<State, State>(); HashMap<State, State> getStates = new HashMap<State, State>(); for (State state : states) { if (!similarStates.containsKey(state) && !similarStates.containsValue(state)) { State newState = this.addState(); getOldStates.put(newState, state); getStates.put(state, newState); if (state == automatonToBeMinimized.getInitialState()) this.markAsInitial(newState); if (automatonToBeMinimized.isFinal(state)) this.markAsFinal(newState); } } for (State state : allStates()) { List<OutgoingTransition> transitions = automatonToBeMinimized .allOutgoingTransitions(getOldStates.get(state)); for (OutgoingTransition transition : transitions) { this.addTransition(state, getStates .get(transition.getTargetState()), transition.getTransitionLabel()); } } HashMap<State, State> simStates = new HashMap<State, State>(similarStates); for (State state : simStates.keySet()) { for (State state1 : simStates.keySet()) { if ((similarStates.get(state) == similarStates.get(state1)) && !(state == state1)) { if ((automatonToBeMinimized.getInitialState() == state1) || (automatonToBeMinimized .getInitialState() == similarStates.get(state1))) { similarStates.remove(state); break; } else { similarStates.remove(state1); continue; } } } } for (State state : similarStates.keySet()) { State newState = addState(); getStates.put(state, newState); getStates.put(similarStates.get(state), newState); if (state == automatonToBeMinimized.getInitialState()) this.markAsInitial(newState); if (automatonToBeMinimized.isFinal(state)) this.markAsFinal(newState); prevStates = automatonToBeMinimized.findPreviousState(state, automatonToBeMinimized); for (State prevState : prevStates) { prevTransitions = findPreviousStateTransitions(prevState, state, automatonToBeMinimized); for (OutgoingTransition transition : prevTransitions) addTransition(getStates.get(prevState), newState, transition.getTransitionLabel()); prevTransitions = findPreviousStateTransitions(prevState, similarStates.get(state), automatonToBeMinimized); for (OutgoingTransition transition : prevTransitions) addTransition(getStates.get(prevState), newState, transition.getTransitionLabel()); } for (OutgoingTransition transition : automatonToBeMinimized .allOutgoingTransitions(state)) addTransition(newState, getStates.get(transition.getTargetState()), transition.getTransitionLabel()); for (OutgoingTransition transition : automatonToBeMinimized .allOutgoingTransitions(similarStates.get(state))) addTransition(newState, getStates.get(transition.getTargetState()), transition.getTransitionLabel()); } } /** * Pobiera automat na wejściu. * Zwraca zminimalizowany automat. Jeżeli automat był nie pełny, zostanie * dodany stan śmietnik. W takiej sytuacji funkcja zwróci automat * o liczbie stanów o jeden większej. */ public void makeMinimal( DeterministicAutomatonSpecification automatonToBeMinimized, String alphabet) { automatonToBeMinimized.makeFull(alphabet); List<State> states = automatonToBeMinimized.allStates(); List<State> uselessStates = automatonToBeMinimized.returnUselessStates(); HashMap<State, Integer> indexStates = new HashMap<State, Integer>(); HashMap<State, State> similarStates = new HashMap<State, State>(); if (!uselessStates.isEmpty()) { states.removeAll(uselessStates); } int index = 0; boolean changed; for (State state : states) { indexStates.put(state, index); index++; } int size = states.size(); boolean[][] mark = new boolean[size][size]; for (int i = 0; i < size; i++) { for (int j = 0; j < size; j++) mark[i][j] = true; } for (int i = 0; i < size - 1; i++) { for (int j = (i + 1); j < size; j++) { if (((automatonToBeMinimized.isFinal(states.get(i)) && !automatonToBeMinimized.isFinal(states.get(j)))) || ((!automatonToBeMinimized.isFinal(states.get(i)) && automatonToBeMinimized.isFinal(states.get(j))))) { mark[i][j] = false; mark[j][i] = false; } } } do { changed = false; for (int c = 0; c < alphabet.length(); c++) { for (int i = 0; i < (size - 1); i++) { for (int j = (i + 1); j < size; j++) { for (OutgoingTransition itransition : automatonToBeMinimized .allOutgoingTransitions(states.get(i))) { for (OutgoingTransition atransition : automatonToBeMinimized .allOutgoingTransitions(states.get(j))) { if (!((itransition.getTransitionLabel() .canAcceptCharacter(alphabet.charAt(c))) && (atransition.getTransitionLabel() .canAcceptCharacter(alphabet .charAt(c))))) { continue; } State state1 = itransition.getTargetState(); State state2 = atransition.getTargetState(); if (state1 == state2) break; if (!mark[indexStates.get(state1)] [indexStates.get(state2)] && mark[i][j]) { mark[i][j] = false; mark[j][i] = false; changed = true; } } } } } } } while(changed); for (int i = 0; i < (size - 1); i++) { for (int j = (i + 1); j < size; j++) { if (mark[i][j]) { similarStates.put(states.get(i), states.get(j)); } } } buildMinimal(automatonToBeMinimized, similarStates); } }