001: /*
002: * Copyright 2004 The Apache Software Foundation.
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016: package org.apache.commons.math.distribution;
017:
018: import junit.framework.TestCase;
019: import org.apache.commons.math.TestUtils;
020:
021: /**
022: * Abstract base class for {@link ContinuousDistribution} tests.
023: * <p>
024: * To create a concrete test class for a continuous distribution implementation,
025: * implement makeDistribution() to return a distribution instance to use in
026: * tests and each of the test data generation methods below. In each case, the
027: * test points and test values arrays returned represent parallel arrays of
028: * inputs and expected values for the distribution returned by makeDistribution().
029: * <p>
030: * makeCumulativeTestPoints() -- arguments used to test cumulative probabilities
031: * makeCumulativeTestValues() -- expected cumulative probabilites
032: * makeInverseCumulativeTestPoints() -- arguments used to test inverse cdf evaluation
033: * makeInverseCumulativeTestValues() -- expected inverse cdf values
034: * <p>
035: * To implement additional test cases with different distribution instances and test data,
036: * use the setXxx methods for the instance data in test cases and call the verifyXxx methods
037: * to verify results.
038: * <p>
039: * Error tolerance can be overriden by implementing getTolerance().
040: *
041: * @version $Revision: 201916 $ $Date: 2005-06-26 15:25:41 -0700 (Sun, 26 Jun 2005) $
042: */
043: public abstract class ContinuousDistributionAbstractTest extends
044: TestCase {
045:
046: //-------------------- Private test instance data -------------------------
047: /** Distribution instance used to perform tests */
048: private ContinuousDistribution distribution;
049:
050: /** Tolerance used in comparing expected and returned values */
051: private double tolerance = 1E-4;
052:
053: /** Arguments used to test cumulative probability density calculations */
054: private double[] cumulativeTestPoints;
055:
056: /** Values used to test cumulative probability density calculations */
057: private double[] cumulativeTestValues;
058:
059: /** Arguments used to test inverse cumulative probability density calculations */
060: private double[] inverseCumulativeTestPoints;
061:
062: /** Values used to test inverse cumulative probability density calculations */
063: private double[] inverseCumulativeTestValues;
064:
065: //-------------------------------------------------------------------------
066:
067: /**
068: * Constructor for ContinuousDistributionAbstractTest.
069: * @param name
070: */
071: public ContinuousDistributionAbstractTest(String name) {
072: super (name);
073: }
074:
075: //-------------------- Abstract methods -----------------------------------
076:
077: /** Creates the default continuous distribution instance to use in tests. */
078: public abstract ContinuousDistribution makeDistribution();
079:
080: /** Creates the default cumulative probability density test input values */
081: public abstract double[] makeCumulativeTestPoints();
082:
083: /** Creates the default cumulative probability density test expected values */
084: public abstract double[] makeCumulativeTestValues();
085:
086: //---- Default implementations of inverse test data generation methods ----
087:
088: /** Creates the default inverse cumulative probability test input values */
089: public double[] makeInverseCumulativeTestPoints() {
090: return makeCumulativeTestValues();
091: }
092:
093: /** Creates the default inverse cumulative probability density test expected values */
094: public double[] makeInverseCumulativeTestValues() {
095: return makeCumulativeTestPoints();
096: }
097:
098: //-------------------- Setup / tear down ----------------------------------
099:
100: /**
101: * Setup sets all test instance data to default values
102: */
103: protected void setUp() throws Exception {
104: super .setUp();
105: distribution = makeDistribution();
106: cumulativeTestPoints = makeCumulativeTestPoints();
107: cumulativeTestValues = makeCumulativeTestValues();
108: inverseCumulativeTestPoints = makeInverseCumulativeTestPoints();
109: inverseCumulativeTestValues = makeInverseCumulativeTestValues();
110: }
111:
112: /**
113: * Cleans up test instance data
114: */
115: protected void tearDown() throws Exception {
116: super .tearDown();
117: distribution = null;
118: cumulativeTestPoints = null;
119: cumulativeTestValues = null;
120: inverseCumulativeTestPoints = null;
121: inverseCumulativeTestValues = null;
122: }
123:
124: //-------------------- Verification methods -------------------------------
125:
126: /**
127: * Verifies that cumulative probability density calculations match expected values
128: * using current test instance data
129: */
130: protected void verifyCumulativeProbabilities() throws Exception {
131: for (int i = 0; i < cumulativeTestPoints.length; i++) {
132: TestUtils
133: .assertEquals(
134: "Incorrect cumulative probability value returned for "
135: + cumulativeTestPoints[i],
136: cumulativeTestValues[i],
137: distribution
138: .cumulativeProbability(cumulativeTestPoints[i]),
139: getTolerance());
140: }
141: }
142:
143: /**
144: * Verifies that inverse cumulative probability density calculations match expected values
145: * using current test instance data
146: */
147: protected void verifyInverseCumulativeProbabilities()
148: throws Exception {
149: for (int i = 0; i < inverseCumulativeTestPoints.length; i++) {
150: TestUtils
151: .assertEquals(
152: "Incorrect inverse cumulative probability value returned for "
153: + inverseCumulativeTestPoints[i],
154: inverseCumulativeTestValues[i],
155: distribution
156: .inverseCumulativeProbability(inverseCumulativeTestPoints[i]),
157: getTolerance());
158: }
159: }
160:
161: //------------------------ Default test cases -----------------------------
162:
163: /**
164: * Verifies that cumulative probability density calculations match expected values
165: * using default test instance data
166: */
167: public void testCumulativeProbabilities() throws Exception {
168: verifyCumulativeProbabilities();
169: }
170:
171: /**
172: * Verifies that inverse cumulative probability density calculations match expected values
173: * using default test instance data
174: */
175: public void testInverseCumulativeProbabilities() throws Exception {
176: verifyInverseCumulativeProbabilities();
177: }
178:
179: /**
180: * Verifies that probability computations are consistent
181: */
182: public void testConsistency() throws Exception {
183: for (int i = 1; i < cumulativeTestPoints.length; i++) {
184:
185: // check that cdf(x, x) = 0
186: TestUtils.assertEquals(0d, distribution
187: .cumulativeProbability(cumulativeTestPoints[i],
188: cumulativeTestPoints[i]), tolerance);
189:
190: // check that P(a < X < b) = P(X < b) - P(X < a)
191: double upper = Math.max(cumulativeTestPoints[i],
192: cumulativeTestPoints[i - 1]);
193: double lower = Math.min(cumulativeTestPoints[i],
194: cumulativeTestPoints[i - 1]);
195: double diff = distribution.cumulativeProbability(upper)
196: - distribution.cumulativeProbability(lower);
197: double direct = distribution.cumulativeProbability(lower,
198: upper);
199: TestUtils.assertEquals(
200: "Inconsistent cumulative probabilities for ("
201: + lower + "," + upper + ")", diff, direct,
202: tolerance);
203: }
204: }
205:
206: /**
207: * Verifies that illegal arguments are correctly handled
208: */
209: public void testIllegalArguments() throws Exception {
210: try {
211: distribution.cumulativeProbability(1, 0);
212: fail("Expecting IllegalArgumentException for bad cumulativeProbability interval");
213: } catch (IllegalArgumentException ex) {
214: // expected
215: }
216: try {
217: distribution.inverseCumulativeProbability(-1);
218: fail("Expecting IllegalArgumentException for p = -1");
219: } catch (IllegalArgumentException ex) {
220: // expected
221: }
222: try {
223: distribution.inverseCumulativeProbability(2);
224: fail("Expecting IllegalArgumentException for p = 2");
225: } catch (IllegalArgumentException ex) {
226: // expected
227: }
228: }
229:
230: //------------------ Getters / Setters for test instance data -----------
231: /**
232: * @return Returns the cumulativeTestPoints.
233: */
234: protected double[] getCumulativeTestPoints() {
235: return cumulativeTestPoints;
236: }
237:
238: /**
239: * @param cumulativeTestPoints The cumulativeTestPoints to set.
240: */
241: protected void setCumulativeTestPoints(double[] cumulativeTestPoints) {
242: this .cumulativeTestPoints = cumulativeTestPoints;
243: }
244:
245: /**
246: * @return Returns the cumulativeTestValues.
247: */
248: protected double[] getCumulativeTestValues() {
249: return cumulativeTestValues;
250: }
251:
252: /**
253: * @param cumulativeTestValues The cumulativeTestValues to set.
254: */
255: protected void setCumulativeTestValues(double[] cumulativeTestValues) {
256: this .cumulativeTestValues = cumulativeTestValues;
257: }
258:
259: /**
260: * @return Returns the distribution.
261: */
262: protected ContinuousDistribution getDistribution() {
263: return distribution;
264: }
265:
266: /**
267: * @param distribution The distribution to set.
268: */
269: protected void setDistribution(ContinuousDistribution distribution) {
270: this .distribution = distribution;
271: }
272:
273: /**
274: * @return Returns the inverseCumulativeTestPoints.
275: */
276: protected double[] getInverseCumulativeTestPoints() {
277: return inverseCumulativeTestPoints;
278: }
279:
280: /**
281: * @param inverseCumulativeTestPoints The inverseCumulativeTestPoints to set.
282: */
283: protected void setInverseCumulativeTestPoints(
284: double[] inverseCumulativeTestPoints) {
285: this .inverseCumulativeTestPoints = inverseCumulativeTestPoints;
286: }
287:
288: /**
289: * @return Returns the inverseCumulativeTestValues.
290: */
291: protected double[] getInverseCumulativeTestValues() {
292: return inverseCumulativeTestValues;
293: }
294:
295: /**
296: * @param inverseCumulativeTestValues The inverseCumulativeTestValues to set.
297: */
298: protected void setInverseCumulativeTestValues(
299: double[] inverseCumulativeTestValues) {
300: this .inverseCumulativeTestValues = inverseCumulativeTestValues;
301: }
302:
303: /**
304: * @return Returns the tolerance.
305: */
306: protected double getTolerance() {
307: return tolerance;
308: }
309:
310: /**
311: * @param tolerance The tolerance to set.
312: */
313: protected void setTolerance(double tolerance) {
314: this.tolerance = tolerance;
315: }
316:
317: }
|