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;
	}