/* * File: RootFinderTestHarness.java * Authors: Kevin R. Dixon * Company: Sandia National Laboratories * Project: Cognitive Foundry * * Copyright Feb 6, 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.learning.algorithm.root; import gov.sandia.cognition.learning.algorithm.minimization.line.interpolator.LineBracketInterpolatorTestHarness.CosineFunction; import gov.sandia.cognition.learning.data.InputOutputPair; import gov.sandia.cognition.learning.function.scalar.AtanFunction; import gov.sandia.cognition.math.AbstractUnivariateScalarFunction; import gov.sandia.cognition.math.DifferentiableEvaluator; import gov.sandia.cognition.statistics.method.StudentTConfidence; import java.util.ArrayList; import java.util.Random; import junit.framework.TestCase; /** * JUnit tests for class RootFinderTestHarness * @author Kevin R. Dixon */ public abstract class RootFinderTestHarness extends TestCase { /** * Random number generator. */ public Random random = new Random( 1 ); /** * Entry point for JUnit tests for class RootFinderTestHarness * @param testName name of this test */ public RootFinderTestHarness( String testName) { super(testName); } public static abstract class RootFinderFunction extends AbstractUnivariateScalarFunction implements DifferentiableEvaluator<Double,Double,Double> { public int NUM_EVALUATIONS; public DifferentiableEvaluator<Double,Double,Double> f; public RootFinderFunction( DifferentiableEvaluator<Double,Double,Double> f ) { this.f = f; NUM_EVALUATIONS = 0; } public double evaluate( double input) { NUM_EVALUATIONS++; return this.f.evaluate(input); } public Double differentiate( Double input) { return this.f.differentiate(input); } } public static class AtanRootFunction extends RootFinderFunction { public AtanRootFunction() { super( new AtanFunction() ); } } public static class CosineRootFunction extends RootFinderFunction { public CosineRootFunction() { super( new CosineFunction() ); } } public static class CubicRootFunction extends RootFinderFunction { public static class CubicFunction extends AbstractUnivariateScalarFunction implements DifferentiableEvaluator<Double,Double,Double> { public double evaluate( double input ) { double x = input; return (x-1.0)*(x+2.0)*(x-3.0); } public Double differentiate( Double input) { double x = input; return 3*x*x - 4*x - 5; } } public CubicRootFunction() { super( new CubicFunction() ); } } /** * Creates a new RootFinder instance to test. * @return */ public abstract RootFinder createInstance(); public void testRootFunction( RootFinderFunction f, double toleranceMultiplier ) { String name = f.getClass().getSimpleName(); System.out.println( "Testing " + name ); int num = 100; ArrayList<Double> evals = new ArrayList<Double>(); for( int n = 0; n < num; n++ ) { RootFinder instance = this.createInstance(); instance.setInitialGuess( random.nextGaussian() ); f.NUM_EVALUATIONS = 0; InputOutputPair<Double,Double> root = instance.learn( f ); assertEquals( f.evaluate(root.getInput()), root.getOutput() ); assertEquals( 0.0, root.getOutput(), instance.getTolerance()*toleranceMultiplier ); evals.add( (double) f.NUM_EVALUATIONS ); } StudentTConfidence ttest = new StudentTConfidence(); final double confidence = 0.95; System.out.println( name + " Evals: " + ttest.computeConfidenceInterval( evals, confidence ) ); } /** * Clone */ public void testClone() { System.out.println( "Clone" ); RootFinder instance = this.createInstance(); RootFinder clone = (RootFinder) instance.clone(); assertNotSame( instance, clone ); assertEquals( instance.getInitialGuess(), clone.getInitialGuess() ); assertEquals( instance.getTolerance(), clone.getTolerance() ); } /** * Test cosine */ public void testCosine() { System.out.println( "Cosine" ); this.testRootFunction( new CosineRootFunction(), 100.0 ); } /** * Atan() */ public void testAtan() { System.out.println( "Atan" ); this.testRootFunction( new AtanRootFunction(), 1.0 ); } /** * Cubic() */ public void testCubic() { System.out.println( "Cubic" ); this.testRootFunction( new CubicRootFunction(), 1000.0 ); } /** * Test of getResult method, of class RootFinderBisection. */ public void testGetResult() { System.out.println( "getResult" ); RootFinder instance = this.createInstance(); assertNull( instance.getResult() ); AtanFunction f = new AtanFunction(); instance.learn( f ); assertNotNull( instance.getResult() ); } /** * Test of getTolerance method, of class RootFinderBisection. */ public void testGetTolerance() { System.out.println( "getTolerance" ); RootFinder instance = this.createInstance(); assertEquals( AbstractBracketedRootFinder.DEFAULT_TOLERANCE, instance.getTolerance() ); } /** * Test of setTolerance method, of class RootFinderBisection. */ public void testSetTolerance() { System.out.println( "setTolerance" ); double tolerance = random.nextDouble(); RootFinder instance = this.createInstance(); instance.setTolerance( tolerance ); assertEquals( tolerance, instance.getTolerance() ); instance.setTolerance( 0.0 ); assertEquals( 0.0, instance.getTolerance() ); try { instance.setTolerance( -tolerance ); fail( "Tolerance must be >= 0" ); } catch (Exception e) { System.out.println( "Good: " + e ); } } /** * Test of getInitialGuess method, of class RootFinderBisection. */ public void testGetInitialGuess() { System.out.println( "getInitialGuess" ); RootFinder instance = this.createInstance(); assertEquals( 0.0, instance.getInitialGuess() ); double guess = random.nextGaussian(); instance.setInitialGuess( guess ); assertEquals( guess, instance.getInitialGuess() ); } /** * Test of setInitialGuess method, of class RootFinderBisection. */ public void testSetInitialGuess() { System.out.println( "setInitialGuess" ); RootFinder instance = this.createInstance(); double guess = random.nextGaussian(); instance.setInitialGuess( guess ); assertEquals( guess, instance.getInitialGuess() ); } /** * Test of getBracketer method, of class RootFinderBisection. */ public void testGetBracketer() { System.out.println( "getBracketer" ); RootFinder instance = this.createInstance(); if( instance instanceof AbstractBracketedRootFinder ) { assertSame( AbstractBracketedRootFinder.DEFAULT_ROOT_BRACKETER, ((AbstractBracketedRootFinder) instance).getBracketer() ); } } /** * Test of setBracketer method, of class RootFinderBisection. */ public void testSetBracketer() { System.out.println( "setBracketer" ); RootFinder base = this.createInstance(); if( base instanceof AbstractBracketedRootFinder ) { AbstractBracketedRootFinder instance = (AbstractBracketedRootFinder) base; RootBracketer b = instance.getBracketer(); assertNotNull( b ); instance.setBracketer( null ); assertNull( instance.getBracketer() ); instance.setBracketer( b ); assertSame( b, instance.getBracketer() ); } } /** * Test of getRootBracket method, of class RootFinderBisection. */ public void testGetRootBracket() { System.out.println( "getRootBracket" ); RootFinder base = this.createInstance(); if( base instanceof AbstractBracketedRootFinder ) { AbstractBracketedRootFinder instance = (AbstractBracketedRootFinder) base; assertNull( instance.getRootBracket() ); AtanFunction f = new AtanFunction(); instance.learn( f ); assertNotNull( instance.getRootBracket() ); } } /** * Test of setRootBracket method, of class RootFinderBisection. */ public void testSetRootBracket() { System.out.println( "setRootBracket" ); RootFinder base = this.createInstance(); if( base instanceof AbstractBracketedRootFinder ) { AbstractBracketedRootFinder instance = (AbstractBracketedRootFinder) base; assertNull( instance.getRootBracket() ); AtanFunction f = new AtanFunction(); instance.learn( f ); assertNotNull( instance.getRootBracket() ); instance.setRootBracket( null ); assertNull( instance.getRootBracket() ); } } }