/** * Constructs an equivalent {@link NFA} by reducing all * Lambda transitions * to other transitions (and if necessary, making the initial state an accept state). [Martin, Th. 3.17] * The input automaton is unmodified. */ public NFA removeLambdas() { NFA f = new NFA(); f.alphabet = alphabet; Map m = new HashMap(); // map from old states to new states for (State p : states) { State s = (State) p.clone(); f.states.add(s); m.put(p, s); if (accept.contains(p)) f.accept.add(s); } f.initial = m.get(initial); Set cl = new HashSet(); cl.add(initial); cl = lambdaClosure(cl); cl.retainAll(accept); if (!cl.isEmpty()) f.accept.add(f.initial); for (State p : states) // this is quite naive but closely follows the mathematical definition in [Martin, Th. 3.17] for (char c : alphabet.symbols) { Set set = deltaStar(p, Character.toString(c)); Set nset = new HashSet(); for (State q : set) nset.add(m.get(q)); f.transitions.put(new StateSymbolPair(m.get(p), c), nset); } return f; }