Projects >> blog >>acd6b3f2fc22cdbd4e084c0cb9363be8414dab1c

Chunk
Conflicting content
	 */
   */
 * @author awong
 * @date November 5, 2012
 */
<<<<<<< HEAD
public interface MatrixLib {	
	/**
	 * Gives the value of an element of this matrix
	 * 
	 * @param x the row index
	 * @param y the column index
	 * @return 
	 */
	public double elementAt(int x, int y);
	
	/**
	 * Sets the value of the given element of this matrix
	 * 
	 * @param x the row index
	 * @param y the column index
	 * @param val the value to set mat[x][y] to
	 * @return null
	 */
	public void setElement(int x, int y, double val);
	
	/**
	 * Returns the contents of this matrix
	public String toString();
	
	/**
	 * Returns number of rows in this matrix
	 */
	public int numRows();
	
	/**
	 * Returns number of columns in this matrix
	 */
	public int numCols();
	
	/**
	 * Returns a row of the matrix as specified
	 * 
	 * @param i the index of the row
	 */
	public MatrixLib sliceRow(int i);
	
	/**
	 * Returns the sum of this matrix with the one provided
	 */
	public MatrixLib plus(MatrixLib otherMat);
	
	/**
	 * Returns the difference of this matrix with the one provided
	 */
	public MatrixLib minus(MatrixLib otherMat);
	
	/**
	 * Returns the scalar product of this matrix with the given value
	 */
	public MatrixLib timesScale(double scale);
	
	/**
	 * Returns the matrix product of this matrix with the one provided
	 */
	public MatrixLib timesMat(MatrixLib otherMat);
	
	/**
	 * Returns the determinant of this matrix
	 */
	public double det();
	
	/**
	 * Returns the transpose of this matrix
	 */
	public MatrixLib transpose();
	
	/**
	 * Returns the inverse of this matrix
	 */
	public MatrixLib inverse();
	
	/**
	 * Returns a lower triangular matrix representing the Cholesky
	 * decomposition of this matrix 
	 */
	public MatrixLib choleskyFactor();
=======
public interface MatrixLib {
  /**
   * Gives the value of an element of this matrix
   *
   * @param x the row index
   * @param y the column index
   * @return
   */
  public double elementAt(int x, int y);

  /**
   * Sets the value of the given element of this matrix
   *
   * @param x the row index
   * @param y the column index
   * @param val the value to set mat[x][y] to
   * @return null
   */
  public void setElement(int x, int y, double val);

  /**
   * Returns the contents of this matrix
   */
  public String toString();

  /**
   * Returns number of rows in this matrix
   */
  public int rowLen();

  /**
   * Returns number of columns in this matrix
   */
  public int colLen();

  /**
   * Returns a row of the matrix as specified
   *
   * @param i the index of the row
   */
  public MatrixLib sliceRow(int i);

  /**
   * Returns the sum of this matrix with the one provided
   */
  public MatrixLib plus(MatrixLib otherMat);

  /**
   * Returns the difference of this matrix with the one provided
   */
  public MatrixLib minus(MatrixLib otherMat);

  /**
   * Returns the scalar product of this matrix with the given value
   */
  public MatrixLib timesScale(double scale);

  /**
   * Returns the matrix product of this matrix with the one provided
  public MatrixLib timesMat(MatrixLib otherMat);

  /**
   * Returns the determinant of this matrix
   */
  public double det();

  /**
   * Returns the transpose of this matrix
   */
  public MatrixLib transpose();

  /**
   * Returns the inverse of this matrix
   */
  public MatrixLib inverse();

  /**
   * Returns a lower triangular matrix representing the Cholesky
   * decomposition of this matrix
   */
  public MatrixLib choleskyFactor();
>>>>>>> 9dff756211456d6664cf4bb0dcc71a87d366c454

  /**
   * Returns a row vector representing the column sum of the matrix.
Solution content
	/**
 * @author awong
 * @date November 5, 2012
 */
public interface MatrixLib {	
	/**
	 * Gives the value of an element of this matrix
	 * 
	 * @param x the row index
	 * @param y the column index
	 * @return 
	 */
	public double elementAt(int x, int y);
	
	/**
	 * Sets the value of the given element of this matrix
	 * 
	 * @param x the row index
	 * @param y the column index
	 * @param val the value to set mat[x][y] to
	 * @return null
	 */
	public void setElement(int x, int y, double val);
	
	/**
	 * Returns the contents of this matrix
	 */
	public String toString();
	
	/**
	 * Returns number of rows in this matrix
	 */
	public int numRows();
	
	/**
	 * Returns number of columns in this matrix
	 */
	public int numCols();
	
	/**
	 * Returns a row of the matrix as specified
	 * 
	 * @param i the index of the row
	 */
	public MatrixLib sliceRow(int i);
	
	 * Returns the sum of this matrix with the one provided
	 */
	public MatrixLib plus(MatrixLib otherMat);
	
	/**
	 * Returns the difference of this matrix with the one provided
	 */
	public MatrixLib minus(MatrixLib otherMat);
	
	/**
	 * Returns the scalar product of this matrix with the given value
	 */
	public MatrixLib timesScale(double scale);
	
	/**
	 * Returns the matrix product of this matrix with the one provided
	 */
	public MatrixLib timesMat(MatrixLib otherMat);
	
	/**
	 * Returns the determinant of this matrix
	 */
	public double det();
	
	/**
	 * Returns the transpose of this matrix
	 */
	public MatrixLib transpose();
	
	/**
	 * Returns the inverse of this matrix
	 */
	public MatrixLib inverse();
	
	/**
	 * Returns a lower triangular matrix representing the Cholesky
	 * decomposition of this matrix 
	 */
	public MatrixLib choleskyFactor();

  /**
   * Returns a row vector representing the column sum of the matrix.
File
MatrixLib.java
Developer's decision
Version 1
Kind of conflict
Comment
Interface signature
Method interface
Chunk
Conflicting content
 */
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
}
Solution content
 */
public class MultivarGaussian extends AbstractCondProbDistrib {

	/**
	 * 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 "
	private MatrixLib sigma;
					+ "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
	 * 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 double dimFactor;
	private double normConst;
	private MatrixLib sigmaInverse;
	private MatrixLib sqrtSigma;
}
File
MultivarGaussian.java
Developer's decision
Version 1
Kind of conflict
Attribute
Comment
Method declaration