/* * File: InverseTransformSamplingTest.java * Authors: Kevin R. Dixon * Company: Sandia National Laboratories * Project: Cognitive Foundry * * Copyright February 22, 2009, Sandia Corporation. * Under the terms of Contract DE-AC04-94AL85000, there is a non-exclusive * license for use of this work by or on behalf of the U.S. Government. * Export of this program may require a license from the United States * Government. See CopyrightHistory.txt for complete details. * */ package gov.sandia.cognition.statistics.method; import gov.sandia.cognition.learning.algorithm.root.AbstractBracketedRootFinder; import gov.sandia.cognition.learning.algorithm.root.RootFinderRiddersMethod; import gov.sandia.cognition.learning.data.InputOutputPair; import gov.sandia.cognition.statistics.CumulativeDistributionFunction; import gov.sandia.cognition.statistics.distribution.BetaDistribution; import gov.sandia.cognition.statistics.distribution.StudentTDistribution; import gov.sandia.cognition.statistics.distribution.UnivariateGaussian; import java.util.ArrayList; import java.util.Random; import junit.framework.TestCase; /** * Tests of InverseTransformSampling * @author krdixon */ public class InverseTransformSamplingTest extends TestCase { /** * Random number generator */ Random RANDOM = new Random( 1 ); /** * Confidence */ final double CONFIDENCE = 0.95; /** * Creates a test * @param testName * Name of the test */ public InverseTransformSamplingTest( String testName) { super(testName); } /** * Constructors */ public void testConstructor() { System.out.println( "constructor" ); InverseTransformSampling its = new InverseTransformSampling(); assertNotNull( its ); } /** * eval.cdf * @param cdf */ public void evaluateCDF( CumulativeDistributionFunction<Double> cdf ) { System.out.println( "Evaluating CDF: " + cdf ); int numSamples = 0; ArrayList<Double> result = InverseTransformSampling.sample(cdf, RANDOM, numSamples); assertEquals( numSamples, result.size() ); numSamples = 1000; result = InverseTransformSampling.sample(cdf, RANDOM, numSamples); assertEquals( numSamples, result.size() ); StudentTConfidence ttest = new StudentTConfidence(); ConfidenceInterval c = ttest.computeConfidenceInterval(result, CONFIDENCE); System.out.println( "Mean = " + cdf.getMean() + " Interval = " + c ); assertTrue( c.withinInterval(cdf.getMean()) ); KolmogorovSmirnovConfidence.Statistic stat = KolmogorovSmirnovConfidence.evaluateNullHypothesis(result, cdf); System.out.println( "K-S test: " + stat ); assertEquals( 1.0, stat.getNullHypothesisProbability(), CONFIDENCE ); this.invertCDF(cdf); } public void invertCDF( CumulativeDistributionFunction<Double> cdf ) { System.out.println( "Inverting CDF: " + cdf ); final int numSamples = 1000; final double TOLERANCE = 1e-3; for( int i = 0; i < numSamples; i++ ) { double p = RANDOM.nextDouble(); InputOutputPair<Double,Double> root = InverseTransformSampling.inverse(cdf, p); double phat = root.getOutput(); assertEquals( phat, cdf.evaluate(root.getInput()) ); assertEquals( p, phat, TOLERANCE ); } } public void testUnitGaussian() { System.out.println( "Unit Gaussian" ); this.evaluateCDF( new UnivariateGaussian.CDF() ); } public void testSharpGaussian() { System.out.println( "Sharp Gaussian" ); this.evaluateCDF( new UnivariateGaussian.CDF( RANDOM.nextGaussian(), 1e-5 ) ); } public void testStudentT10() { System.out.println( "Student t 10" ); this.evaluateCDF(new StudentTDistribution.CDF(10.0)); } public void testStudentT2() { // This distribution has infinite variance, so this should be telling System.out.println( "Student t 2" ); this.evaluateCDF(new StudentTDistribution.CDF( 2.0 )); } /** * Test of sample method, of class InverseTransformSampling. */ public void testSample_3args() { System.out.println("sample"); CumulativeDistributionFunction<Double> cdf = new UnivariateGaussian.CDF(); int numSamples = 100; ArrayList<Double> result = InverseTransformSampling.sample(cdf, RANDOM, numSamples); assertEquals( numSamples, result.size() ); KolmogorovSmirnovConfidence.Statistic stat = KolmogorovSmirnovConfidence.evaluateNullHypothesis(result, cdf); System.out.println( "K-S Test: " + stat ); assertEquals( 1.0, stat.getNullHypothesisProbability(), CONFIDENCE ); } /** * Test of inverseRootFinder method, of class InverseTransformSampling. */ public void testInverse_CumulativeDistributionFunction_double() { System.out.println("inverse"); CumulativeDistributionFunction<Double> cdf = new StudentTDistribution.CDF( 10.0 ); try { InverseTransformSampling.inverse(cdf,-0.1); fail( "p must be [0,1]" ); } catch (Exception e) { System.out.println( "Good: " + e ); } try { InverseTransformSampling.inverse(cdf,1.0+1e-10); fail( "p must be [0,1]" ); } catch (Exception e) { System.out.println( "Good: " + e ); } } /** * inverseNewtonsMethod */ public void testInverseNewtonsMethod() { System.out.println( "inverseNewtonsMethod" ); InputOutputPair<Double,Double> result; int numSamples = 10; ArrayList<Double> ps = new ArrayList<Double>( numSamples ); ArrayList<IT_CDF> cdfs = new ArrayList<IT_CDF>( numSamples ); for( int n = 0; n < numSamples; n++ ) { cdfs.add( new IT_CDF() ); ps.add( RANDOM.nextDouble() ); } ArrayList<Double> r1 = new ArrayList<Double>( numSamples*numSamples ); ArrayList<Double> e1 = new ArrayList<Double>( numSamples*numSamples ); ArrayList<Double> r2 = new ArrayList<Double>( numSamples*numSamples ); ArrayList<Double> e2 = new ArrayList<Double>( numSamples*numSamples ); double err; final double tolerance = AbstractBracketedRootFinder.DEFAULT_TOLERANCE*1e-3; long start1 = System.currentTimeMillis(); for( int n = 0; n < numSamples; n++ ) { IT_CDF cdf = cdfs.get(n); for( int i = 0; i < numSamples; i++ ) { double p = ps.get(i); cdf.numEvals = 0; result = InverseTransformSampling.inverseRootFinder(new RootFinderRiddersMethod(), cdf, p); e1.add( Math.abs( result.getOutput()-p ) ); r1.add( (double) cdf.numEvals ); } } long stop1 = System.currentTimeMillis(); long start2 = System.currentTimeMillis(); for( int n = 0; n < numSamples; n++ ) { IT_CDF cdf = cdfs.get(n); for( int i = 0; i < numSamples; i++ ) { double p = ps.get(i); cdf.numEvals = 0; result = InverseTransformSampling.inverseNewtonsMethod(cdf, p, tolerance ); e2.add( Math.abs( result.getOutput()-p ) ); r2.add( (double) cdf.numEvals ); } } long stop2 = System.currentTimeMillis(); System.out.println( "Time Root: " + ((double) (stop1-start1))/1000.0 ); System.out.println( "Time Newton: " + ((double) (stop2-start2))/1000.0 ); GaussianConfidence t = new GaussianConfidence(); try { ConfidenceInterval cr1 = t.computeConfidenceInterval(r1, CONFIDENCE); System.out.println( "Evals Root: " + cr1 ); ConfidenceInterval cr2 = t.computeConfidenceInterval(r2, CONFIDENCE); System.out.println( "Evals Newton: " + cr2 ); } catch (Exception e) { } ConfidenceInterval ce1 = t.computeConfidenceInterval(e1, CONFIDENCE); System.out.println( "Accuracy Root: " + ce1 ); ConfidenceInterval ce2 = t.computeConfidenceInterval(e2, CONFIDENCE); System.out.println( "Accuracy Newton: " + ce2 ); } public class IT_CDF extends BetaDistribution.CDF { public int numEvals; public IT_CDF() { super( Math.abs(RANDOM.nextGaussian())+1.0, Math.abs(RANDOM.nextGaussian())+1.0 ); this.numEvals = 0; } @Override public double evaluate( double input) { this.numEvals++; return super.evaluate(input); } } }