
/*
 * Copyright 1999-2002 Carnegie Mellon University.  
 * Portions Copyright 2002 Sun Microsystems, Inc.  
 * Portions Copyright 2002 Mitsubishi Electronic Research Laboratories.
 * All Rights Reserved.  Use is subject to license terms.
 * 
 * See the file "license.terms" for information on usage and
 * redistribution of this file, and for a DISCLAIMER OF ALL 
 * WARRANTIES.
 *
 */

package edu.cmu.sphinx.knowledge.acoustic;
import edu.cmu.sphinx.util.Utilities;
import java.io.Serializable;


import java.util.List;
import java.util.ArrayList;
/**
 * Represents a hidden-markov-model. An HMM consists of a unit
 * (context dependent or independent), a transition matrix from state
 * to state, and a sequence of senones associated with each state.
 * This representation of an HMM is a specialized left-to-right markov
 * model. No backward transitions are allowed.  
 *
 * TODO: Perhaps we should switch over to using HMMState and
 * HMMStateArcs internally to store Senones and the transition matrix.
 *
 */
public class HMM implements Serializable {
    private Unit unit;
    private SenoneSequence senoneSequence;
    private float[][] transitionMatrix;
    private HMMPosition position;
    private static int objectCount;
    private HMMState[] hmmStates;


    /**
     * Constructs an HMM
     *
     * @param unit	the unit for this HMM
     * @param senoneSequence 	the sequence of senones for this HMM
     * @param transitionMatrix  the state transition matrix
     * @param position		the position associated with this HMM
     */
    public HMM(Unit unit, SenoneSequence senoneSequence,
	    float[][] transitionMatrix, HMMPosition position) {
	this.unit = unit;
	this.senoneSequence = senoneSequence;
	this.transitionMatrix = transitionMatrix;
	this.position = position;
	Utilities.objectTracker("HMM", objectCount++);

	hmmStates = new HMMState[transitionMatrix.length];
	for (int i = 0; i < hmmStates.length; i++) {
	    hmmStates[i] = new HMMState(this, i);
	}
    }

    /**
     * Gets the  unit associated with this HMM
     *
     * @return the unit associated with this HMM
     */
    public Unit getUnit() {
	return unit;
    }


    /**
     * Retrieves the hmm state 
     *
     * @param which the state of interest
     */
    public HMMState getState(int which) {
	return hmmStates[which];
    }


    /**
     * Returns the order of the HMM
     *
     * @return the order of the HMM
     */
    // [[[NOTE: this method is probably not explicitly needed since
    // getSenoneSequence.getSenones().length will provide the same
    // value, but this is certainly more convenient and easier to
    // understand
    public int getOrder() {
	return getSenoneSequence().getSenones().length;
    }


    /**
     * Returns the SenoneSequence associated with this HMM
     *
     * @return the sequence of senones associated with this HMM. The
     * length of the sequence is N, where N is the order of the HMM.
     * Note that senone sequences may be shared among HMMs.
     */
    // [[ NOTE: the senone sequence may in fact be a sequence of
    // composite senones
    public SenoneSequence getSenoneSequence() {
	return senoneSequence;
    }


    /**
     * Determines if this HMM is a composite HMM
     *
     * @return true if this is a composite hmm
     */
    public boolean isComposite() {
	Senone[] senones = getSenoneSequence().getSenones();
	for (int i = 0; i < senones.length; i++) {
	    if (senones[i] instanceof CompositeSenone) {
		return true;
	    }
	}
	return false;
    }


    /**
     * Returns the transition matrix that determines the state
     * transition probabilities for the matrix. Each entry in the
     * transition matrix defines the probability of transitioning from
     * one state to the next. For example, the probablility of 
     * transitioning from
     * state 1 to state 2 can be determined byh accessesing transition
     * matrix element[1][2].
     *
     * @return the transition matrix of size NxN where N is the order
     * of the HMM
     */
    public float[][] getTransitionMatrix() {
	return transitionMatrix;
    }


    /**
     * Retrieves the position of this HMM. Possible
     *
     * @return the position for this HMM
     */
    public HMMPosition getPosition() {
	return position;
    }


    /**
     * Determines if this HMM represents a filler unit. A filler unit
     * is speech that is not meaningful such as a cough, 'um' , 'er', 
     * or silence.
     *
     * @return true if the HMM  represents a filler unit
     */
    public boolean isFiller() {
	return unit.isFiller();
    }

    /**
     * Determines if this HMM corresponds to a context dependent unit
     *
     * @return true if the HMM is context dependent
     */
    public boolean isContextDependent() {
	return unit.isContextDependent();
    }

    /**
     * Gets the initial states (with probabilities) for this HMM
     *
     * @return the set of arcs that transition to the initial states
     * for this HMM
     */
    public HMMState getInitialState() {
	return getState(0);
    }

    /**
     * Returns the string representation of this object
     * 
     * @return the string representation
     */
    public String toString() {
	String name = isComposite() ? "HMM@" : "HMM";
	return name + "(" + unit +"):" + position;
    }
}


@@ -4098,32 +4098,434 @@
 Matrix;%0A    %7D%0A%0A%0A
+    /**%0A     * Returns the transition probability between two states.%0A     *%0A     * @param stateFrom the index of the state this transition goes from%0A     * @param stateTo the index of the state this transition goes to%0A     *%0A     * @return the transition probability%0A     */%0A    public float getTransitionProbability(int stateFrom, int stateTo) %7B%0A%09return transitionMatrix%5BstateFrom%5D%5BstateTo%5D;%0A    %7D%0A%0A%0A
     /**%0A     * R

Added a method to return the transition probability given indices of states in the HMM.