/* * JFLAP - Formal Languages and Automata Package * * * Susan H. Rodger * Computer Science Department * Duke University * August 27, 2009 * Copyright (c) 2002-2009 * All rights reserved. * JFLAP is open source software. Please see the LICENSE for terms. * */ package automata.graph; import java.util.*; import automata.*; import automata.fsa.*; /** * This is an object that checks if two deterministic finite state automatons * are equal, that is, you could rearrange the states in one and (except for * state names) have exactly the same automaton looking back at you from the * screen. This does not compare two DFAs to see if they accept the same * language! * * @author Thomas Finley */ public class DFAEqualityChecker { /** * "Hypothesize" that two states are equal in the graph isomorphism for this * automaton. This function tests to see if that assumption is justifiable. * * @param state1 * the state in the first automaton * @param state2 * the state in the second automaton * @param matching * the matchings of states in the first automaton to states in * the second automaton */ private boolean hypothesize(State state1, State state2, Map matching) { { // Does state one already have a counterpart? State counterpart = (State) matching.get(state1); // If it does, is it the same? if (counterpart != null) return counterpart == state2; // We haven't visited this node yet. // Does "finality" match up? if (state1.getAutomaton().isFinalState(state1) ^ state2.getAutomaton().isFinalState(state2)) return false; } Map labelToTrans1 = new HashMap(), labelToTrans2 = new HashMap(); Transition[] t1 = state1.getAutomaton().getTransitionsFromState(state1); Transition[] t2 = state2.getAutomaton().getTransitionsFromState(state2); // If they're not even the same length... if (t1.length != t2.length) return false; for (int i = 0; i < t1.length; i++) { labelToTrans1.put(((FSATransition) t1[i]).getLabel(), t1[i]); labelToTrans2.put(((FSATransition) t2[i]).getLabel(), t2[i]); } // Now, for each transition from state1, we can find the // corresponding transition in state2, if it exists. for (int i = 0; i < t1.length; i++) { String label = ((FSATransition) t1[i]).getLabel(); Transition counterpart = (Transition) labelToTrans2.get(label); // Does the same transition exist in the other automaton? if (counterpart == null) return false; matching.put(state1, state2); boolean equal = hypothesize(t1[i].getToState(), counterpart .getToState(), matching); if (!equal) { matching.remove(state1); return false; } } return true; } /** * Compares two DFAs for equality. The precondition is that these objects be * instances of FiniteStateAutomaton, both are * deterministic, and both have an initial state. Results are undefined * otherwise. * * @param one * the first dfa * @param two * the second dfa * @return true if the two DFAs are equal, false * if they are not */ public boolean equals(FiniteStateAutomaton one, FiniteStateAutomaton two) { // Make sure they have the same number of states. if (one.getStates().length != two.getStates().length) return false; return hypothesize(one.getInitialState(), two.getInitialState(), new HashMap()); } }