State[] oldToNewStateMap = new State[fst.getNumStates()];
State[] newToOldStateMap = new State[fst.getNumStates()];
int numStates = fst.getNumStates();
for (int i = 0; i < numStates; i++) {
State s = fst.getState(i);
// Add non-epsilon arcs
State newState = new State(s.getFinalWeight());
res.addState(newState);
oldToNewStateMap[s.getId()] = newState;
newToOldStateMap[newState.getId()] = s;
if (newState.getId() == fst.getStart().getId()) {
res.setStart(newState);
}
}
for (int i = 0; i < numStates; i++) {
State s = fst.getState(i);
// Add non-epsilon arcs
State newState = oldToNewStateMap[s.getId()];
int numArcs = s.getNumArcs();
for (int j = 0; j < numArcs; j++) {
Arc a = s.getArc(j);
if ((a.getIlabel() != 0) || (a.getOlabel() != 0)) {
newState.addArc(new Arc(a.getIlabel(), a.getOlabel(), a
.getWeight(), oldToNewStateMap[a.getNextState()
.getId()]));
}
}
// Compute e-Closure
if (cl[s.getId()] == null) {
calcClosure(fst, s, cl, semiring);
}
}
// augment fst with arcs generated from epsilon moves.
numStates = res.getNumStates();
for (int i = 0; i < numStates; i++) {
State s = res.getState(i);
State oldState = newToOldStateMap[s.getId()];
if (cl[oldState.getId()] != null) {
for (State pathFinalState : cl[oldState.getId()].keySet()) {
State s1 = pathFinalState;
if (s1.getFinalWeight() != semiring.zero()) {
s.setFinalWeight(semiring.plus(s.getFinalWeight(),
semiring.times(getPathWeight(oldState, s1, cl),
s1.getFinalWeight())));
}
int numArcs = s1.getNumArcs();
for (int j = 0; j < numArcs; j++) {
Arc a = s1.getArc(j);
if ((a.getIlabel() != 0) || (a.getOlabel() != 0)) {
Arc newArc = new Arc(a.getIlabel(), a.getOlabel(),
semiring.times(a.getWeight(),
getPathWeight(oldState, s1, cl)),
oldToNewStateMap[a.getNextState().getId()]);