*/
public class MultivarGaussian extends AbstractCondProbDistrib {
<<<<<<< HEAD
/**
* Creates a new MultivarGaussian distribution with the given mean vector and
* covariance matrix. The dimension is inferred from the length of the mean
* vector.
*
* @param mean
* 1-by-d mean vector
* @param covariance
* d-by-d covariance matrix
*/
public MultivarGaussian(MatrixLib mean, MatrixLib covariance) {
setDimension(mean.numRows());
fixedMean = true;
setMean(mean);
fixedCovariance = true;
setCovariance(covariance);
}
/** Sets mean and covariance and ensures that their dimensions match. */
public MultivarGaussian(List params) {
if (params.size() == 0) {
throw new IllegalArgumentException(
"Dimension of MultivarGaussian distribution must be "
+ "specified as parameter.");
}
Object ob = params.get(0);
int dims = 0;
if (ob instanceof MatrixSpec) {
dims = ((MatrixLib) ((MatrixSpec) ob).getValueIfNonRandom()).numRows();
} else {
dims = ((MatrixLib) ob).numRows();
}
setDimension(dims);
if (params.size() == 1) {
fixedMean = false;
fixedCovariance = true;
setCovariance(params.get(0));
} else if (params.size() == 2) {
fixedMean = true;
setMean(params.get(0));
fixedCovariance = true;
setCovariance(params.get(1));
} else {
throw new IllegalArgumentException(
"MultivarGaussian CPD expects at most 2 parameters, not "
+ params.size());
}
}
/**
* Ensures that x = value is a column matrix of appropriate dimension d and
* returns the density of this Gaussian distribution at x.
*/
public double getProb(List args, Object value) {
initParams(args);
if (!((value instanceof MatrixLib) && (((MatrixLib) value).numRows() == d) && (((MatrixLib) value)
.numCols() == 1)))
throw new IllegalArgumentException("The value passed to the " + d
+ "-dimensional " + "multivariate Gaussian distribution's getProb "
+ "method must be a column vector of length " + d + ", not " + value);
return getProbInternal((MatrixLib) value);
}
/**
* Given a d-dimensional column vector x, returns the density value p =
* 1/sqrt((2*pi)^d*|sigma|)*exp{-0.5(x-mean)'*inverse(sigma)*(x-mean)}
*
* @throws IllegalStateException
* if this distribution does not have fixed mean and covariance
*/
public double getProb(MatrixLib x) {
if (!fixedMean || !fixedCovariance) {
throw new IllegalStateException("Mean and covariance are not fixed.");
}
return getProbInternal(x);
}
/**
* Returns the natural log of the probability returned by getProb.
*/
public double getLogProb(MatrixLib x) {
if (!fixedMean || !fixedCovariance) {
throw new IllegalStateException("Mean and covariance are not fixed.");
}
return getLogProbInternal(x);
}
public double getLogProb(List args, Object value) {
initParams(args);
if (!((value instanceof MatrixLib) &&
(((MatrixLib) value).numRows() == d) &&
(((MatrixLib) value).numCols() == 1)))
throw new IllegalArgumentException("The value passed to the " + d
+ "-dimensional " + "multivariate Gaussian distribution's getLogProb "
+ "method must be a column vector of length " + d + ", not " + value);
return getLogProbInternal((MatrixLib) value);
}
/**
* Samples a value from this multivariate Gaussian by generating d
* independent samples from univariate Gaussians with unit variance, one for
* each dimension, and multiplying the obtained vector on the left by the
* square root of sigma (Cholesky decomposition of sigma). This method should
* only be called if this distribution was constructed with a fixed mean and
if (fixedMean) {
* covariance matrix (internal calls are ok if the private method
* initParams is called first).
*/
public Object sampleVal(List args, Type childType) {
initParams(args);
return sampleVal();
}
/**
* Samples a value from this multivariate Gaussian by generating d
* independent samples from univariate Gaussians with unit variance, one for
* each mean in the mean vector, and multiplying the obtained vector on the
* left by the square root of sigma (Cholesky decomposition of sigma). This
* method should only be called if this distribution was constructed with a
* fixed mean and covariance matrix (internal calls are ok if the private
* method initParams is called first).
*/
public MatrixLib sampleVal() {
double[][] mat = new double[d][1];
for (int i = 0; i < d; i++) {
mat[i][0] = UnivarGaussian.STANDARD.sampleVal();
}
MatrixLib temp = MatrixFactory.fromArray(mat);
return mu.plus(sqrtSigma.timesMat(temp));
}
/**
* Returns the mean of this distribution, or null if the mean is not fixed.
*/
public MatrixLib getMean() {
if (fixedMean) {
return mu;
}
return null;
}
/**
* Returns the covariance matrix of this distribution, or null if the
* covariance is not fixed.
*/
public MatrixLib getCovar() {
if (fixedCovariance) {
return sigma;
}
return null;
}
/**
* Given a d-dimensional column vector x, returns the density value p =
* 1/sqrt((2*pi)^d*|sigma|)*exp{-0.5(x-mean)'*inverse(sigma)*(x-mean)}
*/
private double getProbInternal(MatrixLib x) {
return Math.exp(-0.5
* x.minus(mu).transpose().timesMat(sigmaInverse).timesMat(x.minus(mu))
.elementAt(0, 0))
/ normConst;
}
private double getLogProbInternal(MatrixLib x) {
return ((-0.5 * x.minus(mu).transpose().timesMat(sigmaInverse)
.timesMat(x.minus(mu)).elementAt(0, 0)) - Math.log(normConst));
}
private void initParams(List args) {
if (fixedMean) {
if (args.size() > 0) {
throw new IllegalArgumentException(
"MultivarGaussian CPD with fixed mean expects no " + "arguments.");
}
} else {
if (args.size() < 1) {
throw new IllegalArgumentException(
"MultivarGaussian CPD created without a fixed mean; "
+ "requires mean as an argument.");
}
setMean(args.get(0));
if (fixedCovariance) {
if (args.size() > 1) {
throw new IllegalArgumentException(
"MultivarGaussian CPD with fixed covariance matrix "
+ "expects only one argument.");
}
} else {
if (args.size() < 2) {
throw new IllegalArgumentException(
"MultivarGaussian CPD created without a fixed "
+ "covariance matrix; requires covariance matrix "
+ "as argument.");
}
setCovariance(args.get(1));
}
}
}
private void setDimension(int dim) {
if (dim <= 0) {
throw new IllegalArgumentException(
"Dimension of MultivarGaussian distribution must be "
+ "positive, not " + dim);
}
d = dim;
dimFactor = Math.pow(2 * Math.PI, d / 2.0);
}
private void setMean(Object mean) {
if (mean instanceof MatrixSpec) {
mean = ((MatrixSpec) mean).getValueIfNonRandom();
}
if (!((mean instanceof MatrixLib) && (((MatrixLib) mean).numCols() == 1))) {
throw new IllegalArgumentException(
"The mean of a MultivarGaussian distribution must be a "
+ "column vector, not " + mean + " of " + mean.getClass());
}
mu = (MatrixLib) mean;
if (mu.numRows() != d) {
throw new IllegalArgumentException("Mean of " + d
+ "-dimensional Gaussian distribution must "
+ "be column vector of length " + d);
}
}
private void setCovariance(Object cov) {
if (cov instanceof MatrixSpec) {
cov = ((MatrixSpec) cov).getValueIfNonRandom();
}
if (!((cov instanceof MatrixLib) && (((MatrixLib) cov).numRows() == d) && (((MatrixLib) cov)
.numCols() == d))) {
throw new IllegalArgumentException("The covariance matrix of a " + d
+ "-dimensional Gaussian " + "distribution must be a " + d + "-by-"
+ d + " Matrix, " + "not " + cov + " of " + cov.getClass());
}
sigma = (MatrixLib) cov;
for (int i = 0; i < sigma.numRows(); i++) {
for (int j = 0; j < sigma.numCols(); j++) {
double ratio = sigma.elementAt(i, j) / sigma.elementAt(j, i);
if (Math.abs(ratio - 1) > 1e-6)
throw new IllegalArgumentException(
"Invalid covariance matrix (not symmetric): " + sigma);
}
}
normConst = Math.sqrt(sigma.det()) * dimFactor;
sigmaInverse = sigma.inverse();
sqrtSigma = sigma.choleskyFactor();
}
private boolean fixedMean;
private boolean fixedCovariance;
private int d;
private MatrixLib mu;
private MatrixLib sigma;
private double dimFactor;
private double normConst;
private MatrixLib sigmaInverse;
private MatrixLib sqrtSigma;
=======
/**
* Creates a new MultivarGaussian distribution with the given mean vector and
* covariance matrix. The dimension is inferred from the length of the mean
* vector.
*
* @param mean
* 1-by-d mean vector
* @param covariance
* d-by-d covariance matrix
*/
public MultivarGaussian(MatrixLib mean, MatrixLib covariance) {
setDimension(mean.rowLen());
fixedMean = true;
setMean(mean);
fixedCovariance = true;
setCovariance(covariance);
}
/** Sets mean and covariance and ensures that their dimensions match. */
public MultivarGaussian(List params) {
if (params.size() == 0) {
throw new IllegalArgumentException(
"Dimension of MultivarGaussian distribution must be "
+ "specified as parameter.");
}
Object ob = params.get(0);
int dims = 0;
if (ob instanceof MatrixSpec) {
dims = ((MatrixLib) ((MatrixSpec) ob).getValueIfNonRandom()).rowLen();
} else {
dims = ((MatrixLib) ob).rowLen();
}
setDimension(dims);
if (params.size() == 1) {
fixedMean = false;
fixedCovariance = true;
setCovariance(params.get(0));
} else if (params.size() == 2) {
fixedMean = true;
setMean(params.get(0));
fixedCovariance = true;
setCovariance(params.get(1));
} else {
throw new IllegalArgumentException(
"MultivarGaussian CPD expects at most 2 parameters, not "
+ params.size());
}
}
/**
* Ensures that x = value is a column matrix of appropriate dimension d and
* returns the density of this Gaussian distribution at x.
*/
public double getProb(List args, Object value) {
initParams(args);
if (!((value instanceof MatrixLib) && (((MatrixLib) value).rowLen() == d) && (((MatrixLib) value)
.colLen() == 1)))
throw new IllegalArgumentException("The value passed to the " + d
+ "-dimensional " + "multivariate Gaussian distribution's getProb "
+ "method must be a column vector of length " + d + ", not " + value);
return getProbInternal((MatrixLib) value);
}
/**
* Given a d-dimensional column vector x, returns the density value p =
* 1/sqrt((2*pi)^d*|sigma|)*exp{-0.5(x-mean)'*inverse(sigma)*(x-mean)}
*
* @throws IllegalStateException
* if this distribution does not have fixed mean and covariance
*/
public double getProb(MatrixLib x) {
if (!fixedMean || !fixedCovariance) {
throw new IllegalStateException("Mean and covariance are not fixed.");
}
return getProbInternal(x);
}
/**
* Returns the natural log of the probability returned by getProb.
*/
public double getLogProb(MatrixLib x) {
if (!fixedMean || !fixedCovariance) {
throw new IllegalStateException("Mean and covariance are not fixed.");
}
return getLogProbInternal(x);
}
public double getLogProb(List args, Object value) {
initParams(args);
if (!((value instanceof MatrixLib) &&
(((MatrixLib) value).rowLen() == d) &&
(((MatrixLib) value).colLen() == 1)))
throw new IllegalArgumentException("The value passed to the " + d
+ "-dimensional " + "multivariate Gaussian distribution's getLogProb "
+ "method must be a column vector of length " + d + ", not " + value);
return getLogProbInternal((MatrixLib) value);
}
/**
* Samples a value from this multivariate Gaussian by generating d
* independent samples from univariate Gaussians with unit variance, one for
* each dimension, and multiplying the obtained vector on the left by the
* square root of sigma (Cholesky decomposition of sigma). This method should
* only be called if this distribution was constructed with a fixed mean and
* covariance matrix (internal calls are ok if the private method
* initParams is called first).
*/
public Object sampleVal(List args, Type childType) {
initParams(args);
return sampleVal();
}
/**
* Samples a value from this multivariate Gaussian by generating d
* independent samples from univariate Gaussians with unit variance, one for
* each mean in the mean vector, and multiplying the obtained vector on the
* left by the square root of sigma (Cholesky decomposition of sigma). This
* method should only be called if this distribution was constructed with a
* fixed mean and covariance matrix (internal calls are ok if the private
* method initParams is called first).
*/
public MatrixLib sampleVal() {
double[][] mat = new double[d][1];
for (int i = 0; i < d; i++) {
mat[i][0] = UnivarGaussian.STANDARD.sampleVal();
}
MatrixLib temp = MatrixFactory.fromArray(mat);
return mu.plus(sqrtSigma.timesMat(temp));
}
/**
* Returns the mean of this distribution, or null if the mean is not fixed.
*/
public MatrixLib getMean() {
return mu;
}
return null;
}
/**
* Returns the covariance matrix of this distribution, or null if the
* covariance is not fixed.
*/
public MatrixLib getCovar() {
if (fixedCovariance) {
return sigma;
}
return null;
}
/**
* Given a d-dimensional column vector x, returns the density value p =
* 1/sqrt((2*pi)^d*|sigma|)*exp{-0.5(x-mean)'*inverse(sigma)*(x-mean)}
*/
private double getProbInternal(MatrixLib x) {
return Math.exp(-0.5
* x.minus(mu).transpose().timesMat(sigmaInverse).timesMat(x.minus(mu))
.elementAt(0, 0))
/ normConst;
}
private double getLogProbInternal(MatrixLib x) {
return ((-0.5 * x.minus(mu).transpose().timesMat(sigmaInverse)
.timesMat(x.minus(mu)).elementAt(0, 0)) - Math.log(normConst));
}
private void initParams(List args) {
if (fixedMean) {
if (args.size() > 0) {
throw new IllegalArgumentException(
"MultivarGaussian CPD with fixed mean expects no " + "arguments.");
}
} else {
if (args.size() < 1) {
throw new IllegalArgumentException(
"MultivarGaussian CPD created without a fixed mean; "
+ "requires mean as an argument.");
}
setMean(args.get(0));
if (fixedCovariance) {
if (args.size() > 1) {
throw new IllegalArgumentException(
"MultivarGaussian CPD with fixed covariance matrix "
+ "expects only one argument.");
}
} else {
if (args.size() < 2) {
throw new IllegalArgumentException(
"MultivarGaussian CPD created without a fixed "
+ "covariance matrix; requires covariance matrix "
+ "as argument.");
}
setCovariance(args.get(1));
}
}
}
private void setDimension(int dim) {
if (dim <= 0) {
throw new IllegalArgumentException(
"Dimension of MultivarGaussian distribution must be "
+ "positive, not " + dim);
}
d = dim;
dimFactor = Math.pow(2 * Math.PI, d / 2.0);
}
private void setMean(Object mean) {
if (mean instanceof MatrixSpec) {
mean = ((MatrixSpec) mean).getValueIfNonRandom();
}
if (!((mean instanceof MatrixLib) && (((MatrixLib) mean).colLen() == 1))) {
throw new IllegalArgumentException(
"The mean of a MultivarGaussian distribution must be a "
+ "column vector, not " + mean + " of " + mean.getClass());
}
mu = (MatrixLib) mean;
if (mu.rowLen() != d) {
throw new IllegalArgumentException("Mean of " + d
+ "-dimensional Gaussian distribution must "
+ "be column vector of length " + d);
}
}
private void setCovariance(Object cov) {
if (cov instanceof MatrixSpec) {
cov = ((MatrixSpec) cov).getValueIfNonRandom();
}
if (!((cov instanceof MatrixLib) && (((MatrixLib) cov).rowLen() == d) && (((MatrixLib) cov)
.colLen() == d))) {
throw new IllegalArgumentException("The covariance matrix of a " + d
+ "-dimensional Gaussian " + "distribution must be a " + d + "-by-"
+ d + " Matrix, " + "not " + cov + " of " + cov.getClass());
}
sigma = (MatrixLib) cov;
for (int i = 0; i < sigma.rowLen(); i++) {
for (int j = 0; j < sigma.colLen(); j++) {
double ratio = sigma.elementAt(i, j) / sigma.elementAt(j, i);
if (Math.abs(ratio - 1) > 1e-6)
throw new IllegalArgumentException(
"Invalid covariance matrix (not symmetric): " + sigma);
}
}
normConst = Math.sqrt(sigma.det()) * dimFactor;
sigmaInverse = sigma.inverse();
sqrtSigma = sigma.choleskyFactor();
}
private boolean fixedMean;
private boolean fixedCovariance;
private int d;
private MatrixLib mu;
private MatrixLib sigma;
private double dimFactor;
private double normConst;
private MatrixLib sigmaInverse;
private MatrixLib sqrtSigma;
>>>>>>> 9dff756211456d6664cf4bb0dcc71a87d366c454
} |