001    package aima.probability.reasoning;
002    
003    import java.util.ArrayList;
004    import aima.probability.RandomVariable;
005    import aima.util.Matrix;
006    
007    /**
008     * @author Ravi Mohan
009     * 
010     */
011    
012    public class FixedLagSmoothing {
013    
014            // This implementation is almost certainly wrong (see comments below).
015            // This is faithful to the algorithm in the book but I think there are
016            // some errors in the algorithmas published. Need to clarify with Dr N.
017    
018            private HiddenMarkovModel hmm;
019    
020            private int timelag;
021    
022            private ArrayList<String> evidenceFromSmoothedStepToPresent;
023    
024            private int time;
025    
026            private RandomVariable forwardMessage;
027    
028            private Matrix B;
029    
030            public FixedLagSmoothing(HiddenMarkovModel hmm, int timelag) {
031                    this.hmm = hmm;
032                    this.timelag = timelag;
033                    this.evidenceFromSmoothedStepToPresent = new ArrayList<String>();
034                    this.time = 1;
035                    this.forwardMessage = hmm.prior();
036                    this.B = hmm.transitionModel().unitMatrix();
037            }
038    
039            public RandomVariable smooth(String perception) {
040    
041                    evidenceFromSmoothedStepToPresent.add(perception);
042                    Matrix O_t = hmm.sensorModel().asMatrix(perception);
043                    Matrix transitionMatrix = hmm.transitionModel().asMatrix();
044                    if (time > timelag) {
045    
046                            forwardMessage = hmm.forward(forwardMessage, perception); // This
047                            // seems
048                            // WRONG
049                            // I think this should be
050                            // forwardMessage = hmm.forward(forwardMessage,
051                            // evidenceFromSmoothedStepToPresent.get(0));
052                            // this the perception at t-d. the book's algorithm
053                            // uses the latest perception.
054                            evidenceFromSmoothedStepToPresent.remove(0);
055                            Matrix O_t_minus_d = hmm.sensorModel().asMatrix(
056                                            evidenceFromSmoothedStepToPresent.get(0));
057    
058                            B = O_t_minus_d.inverse().times(
059                                            transitionMatrix.inverse().times(
060                                                            B.times(transitionMatrix.times(O_t))));
061    
062                    } else {
063    
064                            B = B.times(transitionMatrix.times(O_t));
065    
066                    }
067                    time += 1;
068                    if (time > timelag) {
069    
070                            Matrix one = hmm.prior().createUnitBelief().asMatrix();
071                            Matrix forwardMatrix = forwardMessage.asMatrix();
072                            RandomVariable result = hmm.prior().duplicate();
073                            Matrix backwardMessage = (B.times(one));
074    
075                            result.updateFrom(forwardMatrix.arrayTimes(backwardMessage));
076    
077                            result.normalize();
078                            return result;
079                    } else {
080                            return null;
081                    }
082    
083            }
084    
085    }