/*******************************************************************************
*   Copyright 2013 Analog Devices, Inc.
*
*   Licensed under the Apache License, Version 2.0 (the "License");
*   you may not use this file except in compliance with the License.
*   You may obtain a copy of the License at
*
*       http://www.apache.org/licenses/LICENSE-2.0
*
*   Unless required by applicable law or agreed to in writing, software
*   distributed under the License is distributed on an "AS IS" BASIS,
*   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*   See the License for the specific language governing permissions and
*   limitations under the License.
********************************************************************************/

package com.analog.lyric.dimple.factorfunctions;

import static com.analog.lyric.math.Utilities.*;

import com.analog.lyric.dimple.exceptions.DimpleException;
import com.analog.lyric.dimple.factorfunctions.core.FactorFunction;
import com.analog.lyric.dimple.model.values.Value;


/**
 * Parameterized discrete transition factor, which corresponds to p(y | x, A),
 * where A is a matrix of transition probabilities that are
 * parameterized as normalized probabilities.
 * The transition matrix is organized such that each column is represented as
 * a single RealJoint variable that corresponds to
 * the output distribution for each input state. That is, the transition
 * matrix multiplies on the left.  The domain of x and y do not need to be
 * the same.
 * <p>
 * Representing A as described, the conjugate prior for A is such that
 * each column vector of the A matrix is distributed according to
 * a Dirichlet distribution.
 * Depending on the solver, it may or may not be necessary to use a
 * conjugate prior (for the Gibbs solver, for example, it is not).
 * <p>
 * The variables in the argument list are ordered as follows:
 * <ol>
 * <li>y: Discrete output variable
 * <li>x: Discrete input variable
 * <li>A: Matrix of transition matrix values (1D vector of RealJoint variables)
 * </ol>
 */
public class DiscreteTransition extends FactorFunction
{
	private final static int NUM_DATA_ARGUMENTS = 2;
	
	@Override
	public final double evalEnergy(Value[] arguments)
	{
    	if (arguments.length < NUM_DATA_ARGUMENTS + 1)
    		throw new DimpleException("Insufficient number of arguments.");
		
    	final int y = arguments[0].getIndexOrInt(); 	// First argument is y (output variable)
    	final int x = arguments[1].getIndexOrInt(); 	// Second argument is x (input variable)

    	// Choose column of A indexed by input variable x
    	final double[] Acol = arguments[x + NUM_DATA_ARGUMENTS].getDoubleArray();

    	return weightToEnergy(Acol[y]);
	}
}
