You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by lu...@apache.org on 2010/01/26 22:54:00 UTC
svn commit: r903440 - in /commons/proper/math/trunk/src:
main/java/org/apache/commons/math/
main/java/org/apache/commons/math/analysis/interpolation/ site/xdoc/
test/java/org/apache/commons/math/analysis/interpolation/
Author: luc
Date: Tue Jan 26 21:53:59 2010
New Revision: 903440
URL: http://svn.apache.org/viewvc?rev=903440&view=rev
Log:
added Eugene Kirpichov's patch to ignore zero weights in Loess interpolation
JIRA: MATH-296
Modified:
commons/proper/math/trunk/src/main/java/org/apache/commons/math/MessagesResources_fr.java
commons/proper/math/trunk/src/main/java/org/apache/commons/math/analysis/interpolation/LoessInterpolator.java
commons/proper/math/trunk/src/site/xdoc/changes.xml
commons/proper/math/trunk/src/test/java/org/apache/commons/math/analysis/interpolation/LoessInterpolatorTest.java
Modified: commons/proper/math/trunk/src/main/java/org/apache/commons/math/MessagesResources_fr.java
URL: http://svn.apache.org/viewvc/commons/proper/math/trunk/src/main/java/org/apache/commons/math/MessagesResources_fr.java?rev=903440&r1=903439&r2=903440&view=diff
==============================================================================
--- commons/proper/math/trunk/src/main/java/org/apache/commons/math/MessagesResources_fr.java (original)
+++ commons/proper/math/trunk/src/main/java/org/apache/commons/math/MessagesResources_fr.java Tue Jan 26 21:53:59 2010
@@ -190,7 +190,7 @@
{ "the number of robustness iterations must be non-negative, but got {0}",
"le nombre d''it\u00e9rations robuste ne peut \u00eatre n\u00e9gatif, alors qu''il est de {0}" },
{ "Loess expects the abscissa and ordinate arrays to be of the same size, " +
- "but got {0} abscisssae and {1} ordinatae",
+ "but got {0} abscissae and {1} ordinatae",
"la r\u00e9gression Loess n\u00e9cessite autant d''abscisses que d''ordonn\u00e9es, " +
"mais {0} abscisses et {1} ordonn\u00e9es ont \u00e9t\u00e9 fournies" },
{ "Loess expects at least 1 point",
Modified: commons/proper/math/trunk/src/main/java/org/apache/commons/math/analysis/interpolation/LoessInterpolator.java
URL: http://svn.apache.org/viewvc/commons/proper/math/trunk/src/main/java/org/apache/commons/math/analysis/interpolation/LoessInterpolator.java?rev=903440&r1=903439&r2=903440&view=diff
==============================================================================
--- commons/proper/math/trunk/src/main/java/org/apache/commons/math/analysis/interpolation/LoessInterpolator.java (original)
+++ commons/proper/math/trunk/src/main/java/org/apache/commons/math/analysis/interpolation/LoessInterpolator.java Tue Jan 26 21:53:59 2010
@@ -198,7 +198,7 @@
throw new MathException(
"Loess expects the abscissa and ordinate arrays " +
"to be of the same size, " +
- "but got {0} abscisssae and {1} ordinatae",
+ "but got {0} abscissae and {1} ordinatae",
xval.length, yval.length);
}
@@ -254,7 +254,7 @@
// Find out the interval of source points on which
// a regression is to be made.
if (i > 0) {
- updateBandwidthInterval(xval, i, bandwidthInterval);
+ updateBandwidthInterval(xval, weights, i, bandwidthInterval);
}
final int ileft = bandwidthInterval[0];
@@ -361,21 +361,27 @@
*/
public final double[] smooth(final double[] xval, final double[] yval)
throws MathException {
+ if (xval.length != yval.length) {
+ throw new MathException(
+ "Loess expects the abscissa and ordinate arrays " +
+ "to be of the same size, " +
+ "but got {0} abscissae and {1} ordinatae",
+ xval.length, yval.length);
+ }
final double[] unitWeights = new double[xval.length];
Arrays.fill(unitWeights, 1.0);
return smooth(xval, yval, unitWeights);
-
}
-
/**
* Given an index interval into xval that embraces a certain number of
* points closest to xval[i-1], update the interval so that it embraces
- * the same number of points closest to xval[i]
+ * the same number of points closest to xval[i], ignoring zero weights.
*
* @param xval arguments array
+ * @param xval weights array
* @param i the index around which the new interval should be computed
* @param bandwidthInterval a two-element array {left, right} such that: <p/>
* <tt>(left==0 or xval[i] - xval[left-1] > xval[right] - xval[i])</tt>
@@ -383,18 +389,34 @@
* <tt>(right==xval.length-1 or xval[right+1] - xval[i] > xval[i] - xval[left])</tt>.
* The array will be updated.
*/
- private static void updateBandwidthInterval(final double[] xval, final int i,
+ private static void updateBandwidthInterval(final double[] xval, final double[] weights,
+ final int i,
final int[] bandwidthInterval) {
final int left = bandwidthInterval[0];
final int right = bandwidthInterval[1];
// The right edge should be adjusted if the next point to the right
// is closer to xval[i] than the leftmost point of the current interval
- if (right < xval.length - 1 &&
- xval[right+1] - xval[i] < xval[i] - xval[left]) {
- bandwidthInterval[0]++;
- bandwidthInterval[1]++;
+ int nextRight = nextNonzero(weights, right);
+ if (nextRight < xval.length && xval[nextRight] - xval[i] < xval[i] - xval[left]) {
+ int nextLeft = nextNonzero(weights, bandwidthInterval[0]);
+ bandwidthInterval[0] = nextLeft;
+ bandwidthInterval[1] = nextRight;
+ }
+ }
+
+ /**
+ * Returns the smallest index j such that j > i && (j==weights.length || weights[j] != 0)
+ * @param weights weights array
+ * @param i the index from which to start search; must be < weights.length
+ * @return the smallest index j such that j > i && (j==weights.length || weights[j] != 0)
+ */
+ private static int nextNonzero(final double[] weights, final int i) {
+ int j = i + 1;
+ while(j < weights.length && weights[j] == 0) {
+ j++;
}
+ return j;
}
/**
Modified: commons/proper/math/trunk/src/site/xdoc/changes.xml
URL: http://svn.apache.org/viewvc/commons/proper/math/trunk/src/site/xdoc/changes.xml?rev=903440&r1=903439&r2=903440&view=diff
==============================================================================
--- commons/proper/math/trunk/src/site/xdoc/changes.xml (original)
+++ commons/proper/math/trunk/src/site/xdoc/changes.xml Tue Jan 26 21:53:59 2010
@@ -119,7 +119,7 @@
</action>
<action dev="luc" tyoe="fix" issue="MATH-296" due-to="Eugene Kirpichov">
Fixed wrong results on Loess interpolation, also added a way to set weights
- for smoothing
+ for smoothing and to ignore zero weights for coefficients computation
</action>
<action dev="luc" type="fix" issue="MATH-293" due-to="Benjamin McCann">
Fixed a OutOfBoundException in simplex solver when some constraints are tight.
Modified: commons/proper/math/trunk/src/test/java/org/apache/commons/math/analysis/interpolation/LoessInterpolatorTest.java
URL: http://svn.apache.org/viewvc/commons/proper/math/trunk/src/test/java/org/apache/commons/math/analysis/interpolation/LoessInterpolatorTest.java?rev=903440&r1=903439&r2=903440&view=diff
==============================================================================
--- commons/proper/math/trunk/src/test/java/org/apache/commons/math/analysis/interpolation/LoessInterpolatorTest.java (original)
+++ commons/proper/math/trunk/src/test/java/org/apache/commons/math/analysis/interpolation/LoessInterpolatorTest.java Tue Jan 26 21:53:59 2010
@@ -19,6 +19,7 @@
import org.junit.Assert;
import org.apache.commons.math.MathException;
+import org.junit.Ignore;
import org.junit.Test;
/**
@@ -49,7 +50,7 @@
public void testOnStraightLine() throws MathException {
double[] xval = {1,2,3,4,5};
double[] yval = {2,4,6,8,10};
- LoessInterpolator li = new LoessInterpolator(0.6, 2);
+ LoessInterpolator li = new LoessInterpolator(0.6, 2, 1e-12);
double[] res = li.smooth(xval, yval);
Assert.assertEquals(5, res.length);
for(int i = 0; i < 5; ++i) {
@@ -67,7 +68,7 @@
generateSineData(xval, yval, xnoise, ynoise);
- LoessInterpolator li = new LoessInterpolator(0.3, 4);
+ LoessInterpolator li = new LoessInterpolator(0.3, 4, 1e-12);
double[] res = li.smooth(xval, yval);
@@ -106,7 +107,7 @@
for (int i = 0; i < bandwidths.length; i++) {
double bw = bandwidths[i];
- LoessInterpolator li = new LoessInterpolator(bw, 4);
+ LoessInterpolator li = new LoessInterpolator(bw, 4, 1e-12);
double[] res = li.smooth(xval, yval);
@@ -139,7 +140,7 @@
double[] variances = new double[4];
for (int i = 0; i < 4; i++) {
- LoessInterpolator li = new LoessInterpolator(0.3, i);
+ LoessInterpolator li = new LoessInterpolator(0.3, i, 1e-12);
double[] res = li.smooth(xval, yval);
@@ -205,18 +206,18 @@
@Test(expected=MathException.class)
public void testInsufficientBandwidth() throws MathException {
- LoessInterpolator li = new LoessInterpolator(0.1, 3);
+ LoessInterpolator li = new LoessInterpolator(0.1, 3, 1e-12);
li.smooth(new double[] {1,2,3,4,5,6,7,8,9,10,11,12}, new double[] {1,2,3,4,5,6,7,8,9,10,11,12});
}
@Test(expected=MathException.class)
public void testCompletelyIncorrectBandwidth1() throws MathException {
- new LoessInterpolator(-0.2, 3);
+ new LoessInterpolator(-0.2, 3, 1e-12);
}
@Test(expected=MathException.class)
public void testCompletelyIncorrectBandwidth2() throws MathException {
- new LoessInterpolator(1.1, 3);
+ new LoessInterpolator(1.1, 3, 1e-12);
}
@Test
@@ -242,31 +243,6 @@
}
}
- @Test
- public void testMath296withWeights() throws MathException {
- double[] xval = {
- 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0,
- 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 1.9, 2.0};
- double[] yval = {
- 0.47, 0.48, 0.55, 0.56, -0.08, -0.04, -0.07, -0.07,
- -0.56, -0.46, -0.56, -0.52, -3.03, -3.08, -3.09,
- -3.04, 3.54, 3.46, 3.36, 3.35};
- double[] weights = {
- 1,1,1,1,1,1,1,1,1,1,
- 1,1,0,0,1,1,0,0,1,1};
- // Output from R, rounded to .001
- double[] yref = {
- 0.478, 0.492, 0.484, 0.320, 0.179, -0.003, -0.088, -0.209,
- -0.327, -0.455, -0.518, -0.537, -1.492, -2.115, -3.09, -3.04,
- -3.0, 0.155, 1.752, 3.35};
- LoessInterpolator li = new LoessInterpolator(0.3, 4, 1e-12);
- double[] res = li.smooth(xval, yval,weights);
- Assert.assertEquals(xval.length, res.length);
- for(int i = 0; i < res.length; ++i) {
- Assert.assertEquals(yref[i], res[i], 0.05);
- }
- }
-
private void generateSineData(double[] xval, double[] yval, double xnoise, double ynoise) {
double dx = 2 * Math.PI / xval.length;
double x = 0;