int l = pp.getE().getWords().length;
float[] anorms = new float[J];
alphas.resize(J + 1, getNumStates());
betas.resize(J + 1, getNumStates());
alphas.set(0, 0, 1.0f); anorms[0]=1.0f;
Alignment m1a = null;
if (m1_post != null)
m1a = m1_post.alignPosteriorThreshold(THRESH);
for (int j = 1; j < J; j++) {
//System.out.println("J="+j);
for (int s = 0; s < numStates; s++) {
float alpha = 0.0f;
float m1boost = 1.0f;
float m1penalty = 0.0f;
boolean use_m1 = false;
if (m1a != null && m1a.isFAligned(j-1)) {
float m1post = 0.0f;
use_m1 = true;
for (int i=0; i<l; i++)
if (m1a.aligned(j-1, i))
m1post = m1_post.getAlignmentPointPosterior(j-1, i+1);
//System.out.println(m1post);
m1boost = (float)(Math.sqrt(m1post));
m1penalty = 1.0f - m1boost;
}
for (int s_prev = 0; s_prev < numStates; s_prev++) {
float trans = getTransitionProb(s_prev, s);
if (use_m1) {
if (s <= l && s > 0 && m1a.aligned(j-1, s-1))
trans = m1boost;
else
trans *= m1penalty;
}
alpha += alphas.get(j - 1, s_prev) * trans;
}
alpha *= getEmissionProb(j, s);
//System.out.println(" ep:" + hmm.getEmissionProb(s, j));
alphas.set(j, s, alpha);
}
//anorms[j] = 1.0f;
try {
anorms[j] = alphas.normalizeColumn(j);
} catch (ZeroProbabilityException ex) {
this.notifyUnalignablePair(pp, ex.getMessage());
return 0.0f;
}
}
for (int s=1; s<numStates; s++)
betas.set(J-1, s, 1.0f);
for (int j=J-2; j>=1; j--) {
//System.out.println("J="+j);
for (int s = 0; s < numStates; s++) {
float beta = 0.0f;
float m1boost = 1.0f;
float m1penalty = 0.0f;
boolean use_m1 = false;
if (m1a != null && m1a.isFAligned(j-1)) {
float m1post = 0.0f;
use_m1 = true;
for (int i=0; i<l; i++)
if (m1a.aligned(j-1, i))
m1post = m1_post.getAlignmentPointPosterior(j-1, i+1);
m1boost = (float)(Math.sqrt(m1post));
m1penalty = 1.0f - m1boost;
}
for (int s_next = 0; s_next < numStates; s_next++) {
//System.out.println(" s_next="+s_next + " b(j+1,s_next)="+ betas.get(j+1, s_next) + " * " +
// hmm.getTransitionProb(s, s_next) + " * " + hmm.getEmissionProb(s_next, j));
float trans = getTransitionProb(s, s_next);
if (use_m1) {
if (s <= l && s > 0 && m1a.aligned(j-1, s-1))
trans = m1boost;
else
trans *= m1penalty;
}
beta += betas.get(j+1, s_next) *
trans *
getEmissionProb(j+1, s_next);
}
beta /= anorms[j];
//System.out.println(" s="+s+ " b:"+beta);
betas.set(j, s, beta);
}
}
// PARTIAL COUNTS FOR EMMISSIONS (WORD TRANSLATION)
float totalProb[] = new float[J];
for (int j=1; j<J; j++) {
float tp = 0.0f;
for (int s = 0; s < numStates; s++) {
tp += betas.get(j, s) * alphas.get(j, s);
}
// System.out.println("total prob(" + j + ")=" + tp);
totalProb[j] = tp;
for (int s = 0; s < numStates; s++) {
// j=1 s=14
int iplus1 = e_coords.get(j, s);
if (iplus1 == -1) continue;
float pc = betas.get(j, s) * alphas.get(j, s) / tp;
if (pg != null) {
int e = 0;
if (s <= l)
e = s;
if (s != 0) {
float p = pg.getAlignmentPointPosterior(j-1, e) + pc;
pg.setAlignmentPointPosterior(j-1, e, p);
}
} else {
try {
addTranslationCount(iplus1, j-1, pc);
} catch (Exception e) {
throw new RuntimeException("J=" + J + ", numStates=" + numStates +": Failed to add (" +iplus1+","+(j-1)+") += " + pc + " s=" + s + " pp=" + pp + "\n E:\n"+ e_coords);
}
}
//System.out.println("ec="+ec+" pc="+pc);
}
}
// PARTIAL COUNTS FOR TRANSITIONS
if (pg == null) {
for (int j=1; j<J-1; j++) {
for (int s_prev=0; s_prev < numStates; s_prev++) {
for (int s=0; s < numStates; s++) {
int tc = transition_coords.get(s_prev, s);
if (tc == -1) continue;
float m1boost = 1.0f;
float m1penalty = 0.0f;
boolean use_m1 = false;
if (m1a != null && m1a.isFAligned(j-1)) {
float m1post = 0.0f;
use_m1 = true;
for (int i=0; i<l; i++)
if (m1a.aligned(j-1, i))
m1post = m1_post.getAlignmentPointPosterior(j-1, i+1);
m1boost = (float)(Math.sqrt(m1post));
m1penalty = 1.0f - m1boost;
}
float trans = getTransitionProb(s_prev, s);
if (use_m1) {
if (s <= l && s > 0 && m1a.aligned(j-1, s-1))
trans = m1boost;
else
trans *= m1penalty;
}
// SKIPPING: REMOVE!!!