You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by er...@apache.org on 2013/01/31 00:27:41 UTC
svn commit: r1440734 - in /commons/proper/math/trunk/src: changes/changes.xml
main/java/org/apache/commons/math3/random/UnitSphereRandomVectorGenerator.java
test/java/org/apache/commons/math3/random/UnitSphereRandomVectorGeneratorTest.java
Author: erans
Date: Wed Jan 30 23:27:41 2013
New Revision: 1440734
URL: http://svn.apache.org/viewvc?rev=1440734&view=rev
Log:
MATH-931
Efficiency improvement and unit test (thanks to Sean Owen).
Added:
commons/proper/math/trunk/src/test/java/org/apache/commons/math3/random/UnitSphereRandomVectorGeneratorTest.java (with props)
Modified:
commons/proper/math/trunk/src/changes/changes.xml
commons/proper/math/trunk/src/main/java/org/apache/commons/math3/random/UnitSphereRandomVectorGenerator.java
Modified: commons/proper/math/trunk/src/changes/changes.xml
URL: http://svn.apache.org/viewvc/commons/proper/math/trunk/src/changes/changes.xml?rev=1440734&r1=1440733&r2=1440734&view=diff
==============================================================================
--- commons/proper/math/trunk/src/changes/changes.xml (original)
+++ commons/proper/math/trunk/src/changes/changes.xml Wed Jan 30 23:27:41 2013
@@ -55,6 +55,9 @@ This is a minor release: It combines bug
Changes to existing features were made in a backwards-compatible
way such as to allow drop-in replacement of the v3.1[.1] JAR file.
">
+ <action dev="erans" type="update" issue="MATH-931" due-to="Sean Owen">
+ Greater efficiency in "UnitSphereRandomVectorGenerator".
+ </action>
<action dev="tn" type="fix" issue="MATH-930">
Improved class javadoc wrt convergence criteria and added
additional constructors to override the default epsilon and cut-off
Modified: commons/proper/math/trunk/src/main/java/org/apache/commons/math3/random/UnitSphereRandomVectorGenerator.java
URL: http://svn.apache.org/viewvc/commons/proper/math/trunk/src/main/java/org/apache/commons/math3/random/UnitSphereRandomVectorGenerator.java?rev=1440734&r1=1440733&r2=1440734&view=diff
==============================================================================
--- commons/proper/math/trunk/src/main/java/org/apache/commons/math3/random/UnitSphereRandomVectorGenerator.java (original)
+++ commons/proper/math/trunk/src/main/java/org/apache/commons/math3/random/UnitSphereRandomVectorGenerator.java Wed Jan 30 23:27:41 2013
@@ -59,18 +59,17 @@ public class UnitSphereRandomVectorGener
/** {@inheritDoc} */
public double[] nextVector() {
-
final double[] v = new double[dimension];
- double normSq;
- do {
- normSq = 0;
- for (int i = 0; i < dimension; i++) {
- final double comp = 2 * rand.nextDouble() - 1;
- v[i] = comp;
- normSq += comp * comp;
- }
- } while (normSq > 1);
+ // See http://mathworld.wolfram.com/SpherePointPicking.html for example.
+ // Pick a point by choosing a standard Gaussian for each element, and then
+ // normalizing to unit length.
+ double normSq = 0;
+ for (int i = 0; i < dimension; i++) {
+ final double comp = rand.nextGaussian();
+ v[i] = comp;
+ normSq += comp * comp;
+ }
final double f = 1 / FastMath.sqrt(normSq);
for (int i = 0; i < dimension; i++) {
@@ -78,7 +77,5 @@ public class UnitSphereRandomVectorGener
}
return v;
-
}
-
}
Added: commons/proper/math/trunk/src/test/java/org/apache/commons/math3/random/UnitSphereRandomVectorGeneratorTest.java
URL: http://svn.apache.org/viewvc/commons/proper/math/trunk/src/test/java/org/apache/commons/math3/random/UnitSphereRandomVectorGeneratorTest.java?rev=1440734&view=auto
==============================================================================
--- commons/proper/math/trunk/src/test/java/org/apache/commons/math3/random/UnitSphereRandomVectorGeneratorTest.java (added)
+++ commons/proper/math/trunk/src/test/java/org/apache/commons/math3/random/UnitSphereRandomVectorGeneratorTest.java Wed Jan 30 23:27:41 2013
@@ -0,0 +1,68 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.commons.math3.random;
+
+import org.apache.commons.math3.util.FastMath;
+import org.junit.Assert;
+import org.junit.Test;
+
+public class UnitSphereRandomVectorGeneratorTest {
+ /**
+ * Test the distribution of points from {@link UnitSphereRandomVectorGenerator#nextVector()}
+ * in two dimensions.
+ */
+ @Test
+ public void test2DDistribution() {
+
+ RandomGenerator rg = new JDKRandomGenerator();
+ rg.setSeed(17399225432l);
+ UnitSphereRandomVectorGenerator generator = new UnitSphereRandomVectorGenerator(2, rg);
+
+ // In 2D, angles with a given vector should be uniformly distributed
+ int[] angleBuckets = new int[100];
+ int steps = 1000000;
+ for (int i = 0; i < steps; ++i) {
+ final double[] v = generator.nextVector();
+ Assert.assertEquals(2, v.length);
+ Assert.assertEquals(1, length(v), 1e-10);
+ // Compute angle formed with vector (1,0)
+ // Cosine of angle is their dot product, because both are unit length
+ // Dot product here is just the first element of the vector by construction
+ final double angle = FastMath.acos(v[0]);
+ final int bucket = (int) (angleBuckets.length * (angle / FastMath.PI));
+ ++angleBuckets[bucket];
+ }
+
+ // Simplistic test for roughly even distribution
+ final int expectedBucketSize = steps / angleBuckets.length;
+ for (int bucket : angleBuckets) {
+ Assert.assertTrue("Bucket count " + bucket + " vs expected " + expectedBucketSize,
+ FastMath.abs(expectedBucketSize - bucket) < 350);
+ }
+ }
+
+ /**
+ * @return length (L2 norm) of given vector
+ */
+ private static double length(double[] vector) {
+ double total = 0;
+ for (double d : vector) {
+ total += d * d;
+ }
+ return FastMath.sqrt(total);
+ }
+}
Propchange: commons/proper/math/trunk/src/test/java/org/apache/commons/math3/random/UnitSphereRandomVectorGeneratorTest.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: commons/proper/math/trunk/src/test/java/org/apache/commons/math3/random/UnitSphereRandomVectorGeneratorTest.java
------------------------------------------------------------------------------
svn:keywords = Id Revision