/**
* Constructs an equivalent {@link NFA} by reducing all
* 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;
}