/*******************************************************************************
* Copyright (C) 2010-2012 Dominik Jain.
*
* This file is part of ProbCog.
*
* ProbCog is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* ProbCog is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with ProbCog. If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/
package probcog.hmm.latent;
import java.util.HashMap;
import java.util.Map;
import probcog.hmm.IObservationModel;
/**
* @author Dominik Jain
*/
public class DwellTimeForwardCalculator<O> implements IObservationModel<O>
{
protected IDwellTimeHMM<O> hmm;
protected Map<State,Belief> bel;
protected int step = 0;
public class Belief {
public State s;
double belief;
public IObservationModel<O> obsModel;
/**
* constructs an initial belief
* @param label
* @param observation
*/
public Belief(int label, O observation) {
s = new State(label, 0);
obsModel = hmm.getObservationModel(label);
belief = hmm.getPi(label);
belief *= obsModel.getObservationProbability(observation);
}
private Belief() {}
public Belief proceed(int label, O observation) {
Belief p2 = new Belief();
if(label == -1) { // staying in same segment
p2.s = new State(s.label, s.dwellTime+1);
p2.obsModel = this.obsModel;
}
else { // switching to another segment
p2.s = new State(label, 0);
p2.obsModel = hmm.getObservationModel(label);
}
// update probabilities
double pTrans = this.s.getTransitionProbability(hmm, label);
double pObs = p2.obsModel.getObservationProbability(observation);
p2.belief = this.belief * pTrans * pObs;
return p2;
}
}
/**
* Computes the most likely state sequence matching an observation
* sequence given an HMM.
*
* @param hmm A Hidden Markov Model;
* @param oseq An observations sequence.
*/
public DwellTimeForwardCalculator(IDwellTimeHMM<O> hmm) {
this.hmm = hmm;
}
public double step(O o) {
double Z = 0.0;
int numStates = hmm.getNumStates();
if(step == 0) {
bel = new HashMap<State,Belief>();
for(int i = 0; i < numStates; i++) {
Belief b = new Belief(i, o);
if(b.belief != 0.0) {
bel.put(b.s, b);
Z += b.belief;
}
}
}
else {
HashMap<State,Belief> bel2 = new HashMap<State,Belief>();
for(Belief b1 : bel.values()) {
for(int i = -1; i < numStates; i++) {
Belief b2 = b1.proceed(i, o);
if(b2.belief != 0.0) {
Belief entry = bel2.get(b2.s);
if(entry != null)
entry.belief += b2.belief;
else
bel2.put(b2.s, b2);
Z += b2.belief;
}
}
}
bel = bel2;
}
// normalize beliefs
for(Belief b : bel.values())
b.belief /= Z;
++step;
return Z;
}
@Override
public double getObservationProbability(O observation) {
return step(observation);
}
}