/*
* File: LineBracketInterpolatorTestHarness.java
* Authors: Kevin R. Dixon
* Company: Sandia National Laboratories
* Project: Cognitive Foundry
*
* Copyright Jun 27, 2008, 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.minimization.line.interpolator;
import gov.sandia.cognition.evaluator.Evaluator;
import gov.sandia.cognition.learning.algorithm.minimization.line.InputOutputSlopeTriplet;
import gov.sandia.cognition.learning.algorithm.minimization.line.LineBracket;
import gov.sandia.cognition.math.AbstractDifferentiableUnivariateScalarFunction;
import java.util.Random;
import junit.framework.TestCase;
/**
* JUnit tests for class LineBracketInterpolator
* @param <EvaluatorType> Type of Evaluator to consider
* @author Kevin R. Dixon
*/
public abstract class LineBracketInterpolatorTestHarness<EvaluatorType extends Evaluator<Double,Double>>
extends TestCase
{
/**
* Entry point for JUnit tests for class LineBracketInterpolatorTestHarness
* @param testName name of this test
*/
public LineBracketInterpolatorTestHarness(
String testName)
{
super(testName);
}
public Random random = new Random( 0 );
/**
* Returns a new instance of the LineBracketInterpolator
* @return
*/
abstract public LineBracketInterpolator<EvaluatorType> createInstance();
public static class CosineFunction
extends AbstractDifferentiableUnivariateScalarFunction
{
@Override
public CosineFunction clone()
{
return new CosineFunction();
}
public double evaluate(
double input )
{
return Math.cos( input );
}
public double differentiate(
double input )
{
return -Math.sin( input );
}
}
public void testTolerance()
{
LineBracketInterpolator<EvaluatorType> instance = this.createInstance();
assertTrue( instance.getTolerance() > 0.0 );
}
@SuppressWarnings("unchecked")
public void testCosine()
{
System.out.println( "Test Consine" );
CosineFunction f = new CosineFunction();
final int num = 100;
final double range = 10.0;
for( int n = 0; n < num; n++ )
{
LineBracketInterpolator<EvaluatorType> instance = this.createInstance();
LineBracket bracket = new LineBracket();
double minx = range * (2.0*random.nextDouble()-1.0);
double maxx = range * (2.0*random.nextDouble()-1.0);
if( minx > maxx )
{
double temp = minx;
minx = maxx;
maxx = temp;
}
double x0 = range * (2.0*random.nextDouble()-1.0);
bracket.setLowerBound( new InputOutputSlopeTriplet(
x0, f.evaluate( x0 ), f.differentiate( x0 ) ) );
// Nobody can interpolate using a single point
assertFalse( instance.hasSufficientPoints( bracket ) );
try
{
instance.findMinimum( bracket, minx, maxx, (EvaluatorType) f );
fail( "Cannot interpolate with a single point" );
}
catch (Exception e)
{
//System.out.println( "Good: " + e );
}
double x1 = range * (2.0*random.nextDouble()-1.0);
bracket.setUpperBound( new InputOutputSlopeTriplet(
x1, f.evaluate( x1 ), f.differentiate( x1 ) ) );
if( instance.hasSufficientPoints( bracket ) )
{
@SuppressWarnings("unchecked")
double r2 = instance.findMinimum( bracket, minx, maxx, (EvaluatorType) f );
assertTrue( minx <= r2 );
assertTrue( r2 <= maxx );
}
double x2 = range * (2.0*random.nextDouble()-1.0);
bracket.setOtherPoint( new InputOutputSlopeTriplet(
x2, f.evaluate( x2 ), f.differentiate( x2 ) ) );
// We have to be able to interpolate with three points
assertTrue( instance.hasSufficientPoints( bracket ) );
@SuppressWarnings("unchecked")
double r3 = instance.findMinimum( bracket, minx, maxx, (EvaluatorType) f );
assertTrue( minx <= r3 );
assertTrue( r3 <= maxx );
// Let's make sure we barf when all points are the same
bracket.setUpperBound( bracket.getLowerBound() );
bracket.setOtherPoint( bracket.getLowerBound() );
try
{
instance.findMinimum( bracket, minx, maxx, (EvaluatorType) f );
fail( "Bracket points are collinear" );
}
catch (Exception e)
{
//System.out.println( "Good: " + e );
}
}
}
}