gov.sandia.cognition.learning.algorithm.root.RootBracketExpander Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of cognitive-foundry Show documentation
Show all versions of cognitive-foundry Show documentation
A single jar with all the Cognitive Foundry components.
/*
* File: RootBracketExpander.java
* Authors: Kevin R. Dixon
* Company: Sandia National Laboratories
* Project: Cognitive Foundry
*
* Copyright Feb 5, 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.evaluator.Evaluator;
import gov.sandia.cognition.learning.algorithm.AbstractAnytimeBatchLearner;
import gov.sandia.cognition.learning.algorithm.minimization.line.InputOutputSlopeTriplet;
import gov.sandia.cognition.learning.algorithm.minimization.line.LineBracket;
import gov.sandia.cognition.learning.algorithm.minimization.line.interpolator.LineBracketInterpolatorGoldenSection;
/**
* The root-bracketing expansion algorithm. This function repeatedly expands
* a root bracket about an initial guess until it finds a region where it
* can be demonstrated that the function makes a zero-crossing (root). The
* algorithm can fail on functions where the function "kisses" zero, or
* has a "notch" type look.
* @author Kevin R. Dixon
* @since 3.0
*/
public class RootBracketExpander
extends AbstractAnytimeBatchLearner, LineBracket>
implements RootBracketer
{
/**
* Default scale factor on expansion, the golden ratio, {@value}
*/
public static final double SCALE_FACTOR = LineBracketInterpolatorGoldenSection.GOLDEN_RATIO;
/**
* Default max iterations, {@value}
*/
public static final int DEFAULT_MAX_ITERATIONS = 100;
/**
* Default initial guess, {@value}
*/
public static final double DEFAULT_INITIAL_GUESS = 0.0;
/**
* Bracket on the root location.
*/
private LineBracket bracket;
/**
* Initial guess of the root's location.
*/
private double initialGuess;
/**
* Creates a new instance of RootBracketExpander
*/
public RootBracketExpander()
{
super( DEFAULT_MAX_ITERATIONS );
this.setInitialGuess( DEFAULT_INITIAL_GUESS );
this.setBracket( null );
}
@Override
protected boolean initializeAlgorithm()
{
Evaluator f = this.data;
double x0 = this.getInitialGuess();
Double y0 = f.evaluate( x0 );
InputOutputSlopeTriplet initial = new InputOutputSlopeTriplet(
x0, y0, null );
double x1 = x0 + SCALE_FACTOR;
// double x1 = x0 + SCALE_FACTOR * y0;
Double y1 = f.evaluate( x1 );
InputOutputSlopeTriplet guess = new InputOutputSlopeTriplet(
x1, y1, null );
this.setBracket( new LineBracket( initial, guess, initial.clone() ) );
return true;
}
@Override
protected boolean step()
{
double x0 = this.getBracket().getLowerBound().getInput();
double y0 = this.getBracket().getLowerBound().getOutput();
double x1 = this.getBracket().getUpperBound().getInput();
double y1 = this.getBracket().getUpperBound().getOutput();
if( y0*y1 < 0.0 )
{
return false;
}
if( Math.abs(y0) < Math.abs(y1) )
{
x0 += SCALE_FACTOR * (x0-x1);
y0 = this.data.evaluate( x0 );
this.getBracket().getLowerBound().setInput( x0 );
this.getBracket().getLowerBound().setOutput( y0 );
}
else
{
x1 += SCALE_FACTOR * (x1-x0);
y1 = this.data.evaluate( x1 );
this.getBracket().getUpperBound().setInput( x1 );
this.getBracket().getUpperBound().setOutput( y1 );
}
// Keep going while the outputs are the same sign.
// Stop when they've got opposite signs, then we definitely know
// there's a root between them.
return y0*y1 > 0.0;
}
@Override
protected void cleanupAlgorithm()
{
// Make sure that a.x < b.x
InputOutputSlopeTriplet a = this.getBracket().getLowerBound();
InputOutputSlopeTriplet b = this.getBracket().getUpperBound();
if( a.getInput() > b.getInput() )
{
this.getBracket().setLowerBound( b );
this.getBracket().setUpperBound( a );
}
}
public LineBracket getResult()
{
return this.getBracket();
}
@Override
public boolean isResultValid()
{
return super.isResultValid() &&
(this.getBracket().getLowerBound().getOutput() * this.getBracket().getUpperBound().getOutput() < 0.0);
}
/**
* Getter for initialGuess.
* @return
* Initial guess of the root's location.
*/
public double getInitialGuess()
{
return this.initialGuess;
}
public void setInitialGuess(
double initialGuess )
{
this.initialGuess = initialGuess;
}
/**
* Getter for bracket.
* @return
* Bracket on the root location.
*/
public LineBracket getBracket()
{
return this.bracket;
}
/**
* Setter for bracket.
* @param bracket
* Bracket on the root location.
*/
protected void setBracket(
LineBracket bracket )
{
this.bracket = bracket;
}
}