public static <L> Fst<L> determinize(Fst<L> nondet) {

		Fst<L> det = new Fst<L>();

		ArrayDeque<Collection<State>> stack = new ArrayDeque<>();
		Map<Collection<State>, State> chart = new HashMap<>();

		stack.push(nondet.initialStates);

		Multimap<L, State> transFunction = HashMultimap.create();
		while (!stack.isEmpty()) {

			Collection<State> sourceSet = stack.pop();
			State source = resolveSet(sourceSet, nondet, chart, det);

			// compute the transition function
			transFunction.clear();
			for (State nondetState : sourceSet) {
				// TODO epsilon reachable states
				for (Transition<L> t : nondetState.outgoing) {
					assert (t.label != null);
					transFunction.put(t.label, t.target);
				}
			}

			// add transitions XXX merge with calculation of transition
			// function?
			for (Entry<L, Collection<State>> e : transFunction.asMap()
					.entrySet()) {

				L label = e.getKey();
				Collection<State> targetSet = e.getValue();

				State target = resolveSet(targetSet, nondet, chart, det);
				det.addTransition(label, source, target);

				stack.push(targetSet);
			}

		}

		return det;
	}