001: /*
002: *
003: * Copyright (c) 2004-2005 The Apache Software Foundation. All rights reserved.
004: *
005: * Licensed under the Apache License, Version 2.0 (the "License"); you may not
006: * use this file except in compliance with the License. You may obtain a copy
007: * of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
013: * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
014: * License for the specific language governing permissions and limitations
015: * under the License.
016: *
017: */
018: package org.apache.commons.math.analysis;
019:
020: import org.apache.commons.math.MathException;
021: import org.apache.commons.math.TestUtils;
022:
023: import junit.framework.Test;
024: import junit.framework.TestCase;
025: import junit.framework.TestSuite;
026:
027: /**
028: * Test the SplineInterpolator.
029: *
030: * @version $Revision: 201916 $ $Date: 2005-06-26 15:25:41 -0700 (Sun, 26 Jun 2005) $
031: */
032: public class SplineInterpolatorTest extends TestCase {
033:
034: /** error tolerance for spline interpolator value at knot points */
035: protected double knotTolerance = 1E-12;
036:
037: /** error tolerance for interpolating polynomial coefficients */
038: protected double coefficientTolerance = 1E-6;
039:
040: /** error tolerance for interpolated values -- high value is from sin test */
041: protected double interpolationTolerance = 1E-2;
042:
043: public SplineInterpolatorTest(String name) {
044: super (name);
045: }
046:
047: public static Test suite() {
048: TestSuite suite = new TestSuite(SplineInterpolatorTest.class);
049: suite.setName("UnivariateRealInterpolator Tests");
050: return suite;
051: }
052:
053: public void testInterpolateLinearDegenerateTwoSegment()
054: throws Exception {
055: double x[] = { 0.0, 0.5, 1.0 };
056: double y[] = { 0.0, 0.5, 1.0 };
057: UnivariateRealInterpolator i = new SplineInterpolator();
058: UnivariateRealFunction f = i.interpolate(x, y);
059: verifyInterpolation(f, x, y);
060: verifyConsistency((PolynomialSplineFunction) f, x);
061:
062: // Verify coefficients using analytical values
063: PolynomialFunction polynomials[] = ((PolynomialSplineFunction) f)
064: .getPolynomials();
065: double target[] = { y[0], 1d, 0d, 0d };
066: TestUtils.assertEquals(polynomials[0].getCoefficients(),
067: target, coefficientTolerance);
068: target = new double[] { y[1], 1d, 0d, 0d };
069: TestUtils.assertEquals(polynomials[1].getCoefficients(),
070: target, coefficientTolerance);
071:
072: // Check interpolation
073: assertEquals(0.0, f.value(0.0), interpolationTolerance);
074: assertEquals(0.4, f.value(0.4), interpolationTolerance);
075: assertEquals(1.0, f.value(1.0), interpolationTolerance);
076: }
077:
078: public void testInterpolateLinearDegenerateThreeSegment()
079: throws Exception {
080: double x[] = { 0.0, 0.5, 1.0, 1.5 };
081: double y[] = { 0.0, 0.5, 1.0, 1.5 };
082: UnivariateRealInterpolator i = new SplineInterpolator();
083: UnivariateRealFunction f = i.interpolate(x, y);
084: verifyInterpolation(f, x, y);
085:
086: // Verify coefficients using analytical values
087: PolynomialFunction polynomials[] = ((PolynomialSplineFunction) f)
088: .getPolynomials();
089: double target[] = { y[0], 1d, 0d, 0d };
090: TestUtils.assertEquals(polynomials[0].getCoefficients(),
091: target, coefficientTolerance);
092: target = new double[] { y[1], 1d, 0d, 0d };
093: TestUtils.assertEquals(polynomials[1].getCoefficients(),
094: target, coefficientTolerance);
095: target = new double[] { y[2], 1d, 0d, 0d };
096: TestUtils.assertEquals(polynomials[2].getCoefficients(),
097: target, coefficientTolerance);
098:
099: // Check interpolation
100: assertEquals(0, f.value(0), interpolationTolerance);
101: assertEquals(1.4, f.value(1.4), interpolationTolerance);
102: assertEquals(1.5, f.value(1.5), interpolationTolerance);
103: }
104:
105: public void testInterpolateLinear() throws Exception {
106: double x[] = { 0.0, 0.5, 1.0 };
107: double y[] = { 0.0, 0.5, 0.0 };
108: UnivariateRealInterpolator i = new SplineInterpolator();
109: UnivariateRealFunction f = i.interpolate(x, y);
110: verifyInterpolation(f, x, y);
111: verifyConsistency((PolynomialSplineFunction) f, x);
112:
113: // Verify coefficients using analytical values
114: PolynomialFunction polynomials[] = ((PolynomialSplineFunction) f)
115: .getPolynomials();
116: double target[] = { y[0], 1.5d, 0d, -2d };
117: TestUtils.assertEquals(polynomials[0].getCoefficients(),
118: target, coefficientTolerance);
119: target = new double[] { y[1], 0d, -3d, 2d };
120: TestUtils.assertEquals(polynomials[1].getCoefficients(),
121: target, coefficientTolerance);
122: }
123:
124: public void testInterpolateSin() throws Exception {
125: double x[] = { 0.0, Math.PI / 6d, Math.PI / 2d,
126: 5d * Math.PI / 6d, Math.PI, 7d * Math.PI / 6d,
127: 3d * Math.PI / 2d, 11d * Math.PI / 6d, 2.d * Math.PI };
128: double y[] = { 0d, 0.5d, 1d, 0.5d, 0d, -0.5d, -1d, -0.5d, 0d };
129: UnivariateRealInterpolator i = new SplineInterpolator();
130: UnivariateRealFunction f = i.interpolate(x, y);
131: verifyInterpolation(f, x, y);
132: verifyConsistency((PolynomialSplineFunction) f, x);
133:
134: /* Check coefficients against values computed using R (version 1.8.1, Red Hat Linux 9)
135: *
136: * To replicate in R:
137: * x[1] <- 0
138: * x[2] <- pi / 6, etc, same for y[] (could use y <- scan() for y values)
139: * g <- splinefun(x, y, "natural")
140: * splinecoef <- eval(expression(z), envir = environment(g))
141: * print(splinecoef)
142: */
143: PolynomialFunction polynomials[] = ((PolynomialSplineFunction) f)
144: .getPolynomials();
145: double target[] = { y[0], 1.002676d, 0d, -0.17415829d };
146: TestUtils.assertEquals(polynomials[0].getCoefficients(),
147: target, coefficientTolerance);
148: target = new double[] { y[1], 8.594367e-01, -2.735672e-01,
149: -0.08707914 };
150: TestUtils.assertEquals(polynomials[1].getCoefficients(),
151: target, coefficientTolerance);
152: target = new double[] { y[2], 1.471804e-17, -5.471344e-01,
153: 0.08707914 };
154: TestUtils.assertEquals(polynomials[2].getCoefficients(),
155: target, coefficientTolerance);
156: target = new double[] { y[3], -8.594367e-01, -2.735672e-01,
157: 0.17415829 };
158: TestUtils.assertEquals(polynomials[3].getCoefficients(),
159: target, coefficientTolerance);
160: target = new double[] { y[4], -1.002676, 6.548562e-17,
161: 0.17415829 };
162: TestUtils.assertEquals(polynomials[4].getCoefficients(),
163: target, coefficientTolerance);
164: target = new double[] { y[5], -8.594367e-01, 2.735672e-01,
165: 0.08707914 };
166: TestUtils.assertEquals(polynomials[5].getCoefficients(),
167: target, coefficientTolerance);
168: target = new double[] { y[6], 3.466465e-16, 5.471344e-01,
169: -0.08707914 };
170: TestUtils.assertEquals(polynomials[6].getCoefficients(),
171: target, coefficientTolerance);
172: target = new double[] { y[7], 8.594367e-01, 2.735672e-01,
173: -0.17415829 };
174: TestUtils.assertEquals(polynomials[7].getCoefficients(),
175: target, coefficientTolerance);
176:
177: //Check interpolation
178: assertEquals(Math.sqrt(2d) / 2d, f.value(Math.PI / 4d),
179: interpolationTolerance);
180: assertEquals(Math.sqrt(2d) / 2d, f.value(3d * Math.PI / 4d),
181: interpolationTolerance);
182: }
183:
184: public void testIllegalArguments() throws MathException {
185: // Data set arrays of different size.
186: UnivariateRealInterpolator i = new SplineInterpolator();
187: try {
188: double xval[] = { 0.0, 1.0 };
189: double yval[] = { 0.0, 1.0, 2.0 };
190: i.interpolate(xval, yval);
191: fail("Failed to detect data set array with different sizes.");
192: } catch (IllegalArgumentException iae) {
193: }
194: // X values not sorted.
195: try {
196: double xval[] = { 0.0, 1.0, 0.5 };
197: double yval[] = { 0.0, 1.0, 2.0 };
198: i.interpolate(xval, yval);
199: fail("Failed to detect unsorted arguments.");
200: } catch (IllegalArgumentException iae) {
201: }
202: }
203:
204: /**
205: * verifies that f(x[i]) = y[i] for i = 0..n-1 where n is common length.
206: */
207: protected void verifyInterpolation(UnivariateRealFunction f,
208: double x[], double y[]) throws Exception {
209: for (int i = 0; i < x.length; i++) {
210: assertEquals(f.value(x[i]), y[i], knotTolerance);
211: }
212: }
213:
214: /**
215: * Verifies that interpolating polynomials satisfy consistency requirement:
216: * adjacent polynomials must agree through two derivatives at knot points
217: */
218: protected void verifyConsistency(PolynomialSplineFunction f,
219: double x[]) throws Exception {
220: PolynomialFunction polynomials[] = f.getPolynomials();
221: for (int i = 1; i < x.length - 2; i++) {
222: // evaluate polynomials and derivatives at x[i + 1]
223: assertEquals(polynomials[i].value(x[i + 1] - x[i]),
224: polynomials[i + 1].value(0), 0.1);
225: assertEquals(polynomials[i].derivative().value(
226: x[i + 1] - x[i]), polynomials[i + 1].derivative()
227: .value(0), 0.5);
228: assertEquals(polynomials[i].polynomialDerivative()
229: .derivative().value(x[i + 1] - x[i]),
230: polynomials[i + 1].polynomialDerivative()
231: .derivative().value(0), 0.5);
232: }
233: }
234:
235: }
|