// semiring not provided
return null;
}
// initialize the queue and new fst
Semiring semiring = fst.getSemiring();
Fst res = new Fst(semiring);
res.setIsyms(fst.getIsyms());
res.setOsyms(fst.getOsyms());
// stores the queue (item in index 0 is next)
Queue<ArrayList<Pair<State, Float>>> queue = new LinkedList<ArrayList<Pair<State, Float>>>();
HashMap<String, State> stateMapper = new HashMap<String, State>();
State s = new State(semiring.zero());
String stateString = "(" + fst.getStart() + "," + semiring.one() + ")";
queue.add(new ArrayList<Pair<State, Float>>());
queue.peek().add(new Pair<State, Float>(fst.getStart(), semiring.one()));
res.addState(s);
stateMapper.put(stateString, s);
res.setStart(s);
while (!queue.isEmpty()) {
ArrayList<Pair<State, Float>> p = queue.remove();
State pnew = getStateLabel(p, stateMapper);
queue.remove(0);
ArrayList<Integer> labels = getUniqueLabels(fst, p);
for (int label : labels) {
Float wnew = semiring.zero();
// calc w'
for (Pair<State, Float> ps : p) {
State old = ps.getLeft();
Float u = ps.getRight();
int numArcs = old.getNumArcs();
for (int j = 0; j < numArcs; j++) {
Arc arc = old.getArc(j);
if (label == arc.getIlabel()) {
wnew = semiring.plus(wnew,
semiring.times(u, arc.getWeight()));
}
}
}
// calc new states
// keep residual weights to variable forQueue
ArrayList<Pair<State, Float>> forQueue = new ArrayList<Pair<State, Float>>();
for (Pair<State, Float> ps : p) {
State old = ps.getLeft();
Float u = ps.getRight();
Float wnewRevert = semiring.divide(semiring.one(), wnew);
int numArcs = old.getNumArcs();
for (int j = 0; j < numArcs; j++) {
Arc arc = old.getArc(j);
if (label == arc.getIlabel()) {
State oldstate = arc.getNextState();
Pair<State, Float> pair = getPair(forQueue,
oldstate, semiring.zero());
pair.setRight(semiring.plus(
pair.getRight(),
semiring.times(wnewRevert,
semiring.times(u, arc.getWeight()))));
}
}
}
// build new state's id and new elements for queue
String qnewid = "";
for (Pair<State, Float> ps : forQueue) {
State old = ps.getLeft();
Float unew = ps.getRight();
if (!qnewid.equals("")) {
qnewid = qnewid + ",";
}
qnewid = qnewid + "(" + old + "," + unew + ")";
}
if (stateMapper.get(qnewid) == null) {
State qnew = new State(semiring.zero());
res.addState(qnew);
stateMapper.put(qnewid, qnew);
// update new state's weight
Float fw = qnew.getFinalWeight();
for (Pair<State, Float> ps : forQueue) {
fw = semiring.plus(fw, semiring.times(ps.getLeft()
.getFinalWeight(), ps.getRight()));
}
qnew.setFinalWeight(fw);
queue.add(forQueue);