/*
 *  This program 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; version 3 of the License.
 *
 *  This program 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 this program; if not, a copy is available at
 *  http://www.r-project.org/Licenses/
 */
package jdistlib;

import jdistlib.rng.RandomEngine;

import static java.lang.Math.sqrt;
import static jdistlib.matrix.QMatrixUtils.*;

/**
 * Wishart distribution
 * By: Roby Joehanes
 */
public class Wishart {

	/**
	 * 

Sample Wishart distribution with n degree of freedom and LL' scale parameter. * Wishart distribution is multivariate generalization of Gamma distribution. * Remember that Gamma distribution is a generalization of both Chi-square and * exponential distribution. * *

I use L instead of the usual V to denote the scale parameter. Note that V = LL'. * Compute L using Cholesky decomposition. L is a lower triangular matrix. * *

The algorithm described here is due to:
* Smith, W. B. and Hocking, R. R.; Algorithm AS 53: Wishart Variate Generator, Applied Statistician, v.21(341--345), 1972 * http://www.jstor.org/stable/2346290 * *

See also: * Gentle, J. E., Random Number Generation and Monte Carlo Methods, 2nd ed., Springer-Verlag, 2003, pp. 199 * *

Note: If you want to generate an inverse-wishart distribution, simply generate * a matrix from Wishart distribution and invert it. * * @param n degree of freedom * @param L square matrix of d x d, lower triangular Cholesky factor of sigma matrix * @param rand Randomizer * @return square matrix of d x d */ public static final double[][] random(double n, double[][] L, RandomEngine rand) { int d = L.length; assert (d == L[0].length); // Crude check for square-ness double z[][] = new double[d][d], y[] = new double[d], B[][] = new double[d][d]; for (int i = 1; i < d; i++) for (int j = 0; j < i; j++) z[i][j] = rand.nextGaussian(); for (int i = 0; i < d; i++) { double sum = y[i] = ChiSquare.random(n - i + 1, rand); for (int j = 0; j < i; j++) { double val = z[j][i]; sum += val * val; } B[i][i] = sum / n; if (i > 0) B[0][i] = B[i][0] = z[i][0] * sqrt(y[0]) / n; } for (int i = 2; i < d; i++) for (int j = 1; j < i; j++) { double sum = z[i][j] * sqrt(y[j]); for (int k = 0; k < j; k++) sum += z[i][k] * z[j][k]; B[i][j] = B[j][i] = sum / n; } return calculateXYt(calculateXY(L,B),L); } }

Ads help maintain this website.