All Downloads are FREE. Search and download functionalities are using the official Maven repository.

gov.sandia.cognition.learning.algorithm.minimization.FunctionMinimizerDFP Maven / Gradle / Ivy

There is a newer version: 4.0.1
Show newest version
/*
 * File:                FunctionMinimizerDFP.java
 * Authors:             Kevin R. Dixon
 * Company:             Sandia National Laboratories
 * Project:             Cognitive Foundry
 * 
 * Copyright Jun 21, 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;

import gov.sandia.cognition.annotation.PublicationReference;
import gov.sandia.cognition.annotation.PublicationReferences;
import gov.sandia.cognition.annotation.PublicationType;
import gov.sandia.cognition.learning.algorithm.minimization.line.LineMinimizer;
import gov.sandia.cognition.math.matrix.Matrix;
import gov.sandia.cognition.math.matrix.Vector;
import gov.sandia.cognition.util.ObjectUtil;

/**
 * Implementation of the Davidon-Fletcher-Powell (DFP) formula for a
 * Quasi-Newton minimization update.  The DFP formula is generally recognized
 * as inferior to the BFGS update formula (FunctionMinimizerBFGS), and I would
 * recommend using that first.  However, there are a few problems that DFP
 * may be more efficient than BFGS, so here it is.
 *
 * @author Kevin R. Dixon
 * @since 2.1
 */
@PublicationReferences(
    references={
        @PublicationReference(
            author="R. Fletcher",
            title="Practical Methods of Optimization, Second Edition",
            type=PublicationType.Book,
            year=1987,
            pages=54,
            notes="Section 3.2, Equation 3.2.11"
        )
        ,
        @PublicationReference(
            author="Wikipedia",
            title="Davidon-Fletcher-Powell formula",
            type=PublicationType.WebPage,
            year=2008,
            url="http://en.wikipedia.org/wiki/Davidon-Fletcher-Powell_formula"
        )
    }
)
public class FunctionMinimizerDFP 
    extends FunctionMinimizerQuasiNewton
{

    /** 
     * Creates a new instance of FunctionMinimizerBFGS 
     */
    public FunctionMinimizerDFP()
    {
        this( ObjectUtil.cloneSafe( DEFAULT_LINE_MINIMIZER ) );
    }
    
    /**
     * Creates a new instance of FunctionMinimizerBFGS 
     * @param lineMinimizer
     * Work-horse algorithm that minimizes the function along a direction
     */
    public FunctionMinimizerDFP(
        LineMinimizer lineMinimizer )
    {
        this( lineMinimizer, null, DEFAULT_TOLERANCE, DEFAULT_MAX_ITERATIONS );        
    }
    /**
     * Creates a new instance of FunctionMinimizerBFGS
     * 
     * @param initialGuess Initial guess about the minimum of the method
     * @param tolerance Tolerance of the minimization algorithm, must be >= 0.0, typically ~1e-10
     * @param lineMinimizer 
     * Work-horse algorithm that minimizes the function along a direction
     * @param maxIterations Maximum number of iterations, must be >0, typically ~100
     */
    public FunctionMinimizerDFP(
        LineMinimizer lineMinimizer,
        Vector initialGuess,
        double tolerance,
        int maxIterations )
    {
        super( lineMinimizer, initialGuess, tolerance, maxIterations );
    }

    @PublicationReference(
        author="R. Fletcher",
        title="Practical Methods of Optimization, Second Edition",
        type=PublicationType.Book,
        year=1987,
        pages=54,
        notes="Section 3.2, Equation 3.2.11"
    )
    @Override
    protected boolean updateHessianInverse(
        Matrix hessianInverse,
        Vector delta,
        Vector gamma )
    {
        
        // Solving for Fletcher's "H"
        int M = hessianInverse.getNumRows();
        
        // This is formula 3.2.12 on p.55 in PMOO
        // Solving for Fletcher's "H"
        Vector Higamma = hessianInverse.times( gamma );
        double deltaTgamma = delta.dotProduct( gamma );
        double gammaTHigamma = gamma.dotProduct( Higamma );
        
        // If we're close to singular, then skip the Hessian update.
        // Some people add some clever resetting code here.
        // I'll just skip for now.
        double singularThreshold = Math.sqrt( 
            this.getTolerance() * delta.norm2Squared() * gamma.norm2Squared() );
        
        if( (singularThreshold >= Math.abs(deltaTgamma)) ||
            (singularThreshold >= Math.abs(gammaTHigamma)) )
        {
            return false;
        }
        
        for( int i = 0; i < M; i++ )
        {
            double deltai = delta.getElement( i );
            double Higammai = Higamma.getElement( i );
            
            // Since the Hessian inverse is symmetric, we can just iterate
            // through the bottom half of the matrix and mirror the values.
            for( int j = 0; j <= i; j++ )
            {
                double oldValue = hessianInverse.getElement( i, j );
                double change = deltai*delta.getElement(j) / deltaTgamma;
                change -= Higammai*Higamma.getElement(j) / gammaTHigamma;
                
                double newValue = oldValue + change;
                
                // Since the Hessian inverse is symmetric, we can just iterate
                // through the bottom half of the matrix and mirror the values.
                // But make sure we don't double update the diagonal.
                hessianInverse.setElement( i, j, newValue );
                if( i != j )
                {
                    hessianInverse.setElement( j, i, newValue );
                }
            }
            
        }

        return true;        
        
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy