for (int u = 0; u < observationSequence.size(); u++) {
List<Pair<Double, String>> tw = observationSequence.get(u);
double normTot = 0.0;
// for each of its tags within the search beam.
for (int v = 0; v < tw.size(); v++) {
Word currTag = seqLabs.getCoord(u, v);
List<Word> bestHist = null;
Double seqScore = null;
Double obsScore = initScores.getCoord(u, v);
if (u == 0) {
// beginning of sequence.
bestHist = getBestHist(u, v, order);
bestHist.add(currTag);
seqScore = lmScore(bestHist);
double fs = seqScore + obsScore;
normTot += Math.exp(fs);
fbScores.setCoord(u, v, fs);
} else {
// use dynamic programming-computed scores to progress.
List<Pair<Double, String>> prevTaggedWord = observationSequence.get(u - 1);
ProbIndexPair[] bestPrevScores = new ProbIndexPair[Math.min(prevTaggedWord.size(), searchBeam)];
for (int z = 0; z < Math.min(prevTaggedWord.size(), searchBeam); z++) {
bestHist = getBestHist(u - 1, z, order - 1);
bestHist.add(currTag);
seqScore = lmScore(bestHist);
double fs = fbScores.getCoord(u - 1, z) + seqScore;
fs += obsScore;
bestPrevScores[z] = new ProbIndexPair(
Double.valueOf(fs),
Integer.valueOf(z));
}
// sort descending based on score.
Arrays.sort(bestPrevScores);
// add up the prob's of all sequences leading to this node.
double fsum = 0.0;
for (int q = 0; q < bestPrevScores.length; q++) {
fsum += Math.exp(bestPrevScores[q].a);
}
normTot += fsum;
//fbScores.setCoord(u, v, bestPrevScores[0].a.doubleValue());
fbScores.setCoord(u, v, Math.log(fsum));
// add n-best backpointers.
List<Integer> bks = new ArrayList<Integer>(bestPrevScores.length);
for (int q = 0; q < bestPrevScores.length; q++) {
bks.add(bestPrevScores[q].b);
}
backPointers.setCoord(u, v, new Backpointer(bks));
}
}
// normalise.
for (int v = 0; v < tw.size(); v++) {
fbScores.setCoord(u, v, Math.log(Math.exp(fbScores.getCoord(u, v)) / normTot));
}
}
// backward loop.
int size = observationSequence.size();
if (alg == Constants.TaggingAlgorithm.FORWARDBACKWARD) {
// for each word...
for (int u = size - 1; u >= 0; u--) {
List<Pair<Double, String>> tw = observationSequence.get(u);
double normTot = 0.0;
// for each of its tags...
for (int v = 0; v < tw.size(); v++) {
List<Word> bestHist = null;
Double obsScore = initScores.getCoord(u, v);
if (u == (size - 1)) { // right-hand end of sequence.
bestHist = getBestHist(u, v, order - 1);
bestHist.add(words.intern(Word.createWord("</s>", null, null, null, null, null, null)));
double bsc = fbScores.getCoord(u, v) + obsScore;
normTot += Math.exp(bsc);
fbScores.setCoord(u, v, bsc);
} else {
// use dynamic programming-computed scores to progress backwards.
bestHist = getBestHist(u, v, order - 1);
List<Pair<Double, String>> followingTaggedWd = observationSequence.get(u + 1);
double backwardSum = 0.0;
for (int z = 0; z < followingTaggedWd.size(); z++) {
Word followingTag = words.intern(Word.createWord(followingTaggedWd.get(z).b.intern(), null, null, null, null, null, null));
if (z > 0) {
bestHist.remove(bestHist.size() - 1);
}
bestHist.add(followingTag);
backwardSum += Math.exp(lmScore(bestHist) + fbScores.getCoord(u + 1, z));