You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mahout.apache.org by td...@apache.org on 2012/11/15 09:19:35 UTC

svn commit: r1409687 - /mahout/trunk/math/src/main/java/org/apache/mahout/math/random/MultiNormal.java

Author: tdunning
Date: Thu Nov 15 08:19:35 2012
New Revision: 1409687

URL: http://svn.apache.org/viewvc?rev=1409687&view=rev
Log:
Improved names for arguments of Multi-normal.  No functional changes.

Modified:
    mahout/trunk/math/src/main/java/org/apache/mahout/math/random/MultiNormal.java

Modified: mahout/trunk/math/src/main/java/org/apache/mahout/math/random/MultiNormal.java
URL: http://svn.apache.org/viewvc/mahout/trunk/math/src/main/java/org/apache/mahout/math/random/MultiNormal.java?rev=1409687&r1=1409686&r2=1409687&view=diff
==============================================================================
--- mahout/trunk/math/src/main/java/org/apache/mahout/math/random/MultiNormal.java (original)
+++ mahout/trunk/math/src/main/java/org/apache/mahout/math/random/MultiNormal.java Thu Nov 15 08:19:35 2012
@@ -28,62 +28,91 @@ import java.util.Random;
 
 /**
  * Samples from a multi-variate normal distribution.
+ * <p/>
+ * This is done by sampling from several independent unit normal distributions to get a vector u.
+ * The sample value that is returned is then A u + m where A is derived from the covariance matrix
+ * and m is the mean of the result.
+ * <p/>
+ * If \Sigma is the desired covariance matrix, then you can use any value of A such that A' A =
+ * \Sigma.  The Cholesky decomposition can be used to compute A if \Sigma is positive definite.
+ * Slightly more expensive is to use the SVD U S V' = \Sigma and then set A = U \sqrt{S}.
+ *
+ * Useful special cases occur when \Sigma is diagonal so that A = \sqrt(\Sigma) or where \Sigma = r I.
+ *
+ * Another special case is where m = 0.
  */
 public class MultiNormal implements Sampler<Vector> {
-    private final Random gen;
-    private final int dimension;
-    private final Matrix mean;
-    private final Vector offset;
-
-    public MultiNormal(Vector diagonal) {
-        this(new DiagonalMatrix(diagonal), null);
-    }
-
-    public MultiNormal(Vector diagonal, Vector offset) {
-        this(new DiagonalMatrix(diagonal), offset);
-    }
-
-    public MultiNormal(Matrix a, Vector offset) {
-        this(a, offset, a.columnSize());
-    }
-
-    public MultiNormal(int dimension) {
-        this(null, null, dimension);
-    }
-
-    public MultiNormal(double radius, Vector mean) {
-        this(new DiagonalMatrix(radius, mean.size()), mean);
-    }
-
-    private MultiNormal(Matrix mean, Vector offset, int dimension) {
-        gen = RandomUtils.getRandom();
-        this.dimension = dimension;
-        this.mean = mean;
-        this.offset = offset;
-    }
-
-    @Override
-    public Vector sample() {
-        Vector v = new DenseVector(dimension).assign(
-                new DoubleFunction() {
-                    @Override
-                    public double apply(double ignored) {
-                        return gen.nextGaussian();
-                    }
-                }
-        );
-        if (offset != null) {
-            return mean.times(v).plus(offset);
-        } else {
-            if (mean != null) {
-                return mean.times(v);
-            } else {
-                return v;
-            }
+  private final Random gen;
+  private final int dimension;
+  private final Matrix scale;
+  private final Vector mean;
+
+  /**
+   * Constructs a sampler with diagonal scale matrix.
+   * @param diagonal The diagonal elements of the scale matrix.
+   */
+  public MultiNormal(Vector diagonal) {
+    this(new DiagonalMatrix(diagonal), null);
+  }
+
+  /**
+   * Constructs a sampler with diagonal scale matrix and (potentially)
+   * non-zero mean.
+   * @param diagonal The scale matrix's principal diagonal.
+   * @param mean The desired mean.  Set to null if zero mean is desired.
+   */
+  public MultiNormal(Vector diagonal, Vector mean) {
+    this(new DiagonalMatrix(diagonal), mean);
+  }
+
+  /**
+   * Constructs a sampler with non-trivial scale matrix and mean.
+   */
+  public MultiNormal(Matrix a, Vector mean) {
+    this(a, mean, a.columnSize());
+  }
+
+  public MultiNormal(int dimension) {
+    this(null, null, dimension);
+  }
+
+  public MultiNormal(double radius, Vector mean) {
+    this(new DiagonalMatrix(radius, mean.size()), mean);
+  }
+
+  private MultiNormal(Matrix scale, Vector mean, int dimension) {
+    gen = RandomUtils.getRandom();
+    this.dimension = dimension;
+    this.scale = scale;
+    this.mean = mean;
+  }
+
+  @Override
+  public Vector sample() {
+    Vector v = new DenseVector(dimension).assign(
+      new DoubleFunction() {
+        @Override
+        public double apply(double ignored) {
+          return gen.nextGaussian();
         }
-    }
-
-    public Vector getMean() {
-        return offset;
-    }
+      }
+    );
+    if (mean != null) {
+      if (scale != null) {
+        return scale.times(v).plus(mean);
+      } else {
+        return v.plus(mean);
+      }
+    } else {
+      if (scale != null) {
+        return scale.times(v);
+      } else {
+        return v;
+      }
+    }
+  }
+
+  public Vector getScale() {
+    return mean;
+  }
 }