/* * UncminOptimizer.java * * Created on May 28, 2002, 11:21 AM */ package hep.aida.ref.optimizer.uncmin; import hep.aida.IFunction; import hep.aida.ext.IOptimizerResult; import hep.aida.ext.IVariableSettings; import hep.aida.ref.optimizer.OptimizerResult; import optimization.Uncmin_f77; import optimization.Uncmin_methods; /** * * @author turri */ public class UncminOptimizer extends hep.aida.ref.optimizer.AbstractOptimizer { int[] varIndex; /** Creates a new instance of UncminOptimizer */ public UncminOptimizer() { result = new OptimizerResult(); configuration = new UncminOptimizerConfiguration(); domainConstraint = null; } /** * Perform the optimization. * @return <code>true</code> if the optimization was * successfull, <code>false</code> otherwise. * */ public void optimize() { if ( function == null ) throw new IllegalArgumentException("Cannot optimize!! The function was not set correctely!"); String[] variableNames = function.variableNames(); varIndex = new int[variableNames.length]; if ( variableNames == null || variableNames.length == 0 ) throw new IllegalArgumentException("Cannot optimize!! There are no variables in this function!"); int dimension = 0; for ( int i = 0; i<variableNames.length; i++ ) { String varName = variableNames[i]; IVariableSettings varSet = variableSettings(varName); if ( ! varSet.isFixed() ) { varIndex[dimension] = i; dimension++; } } if ( dimension == 0 ) throw new IllegalArgumentException("There are no free variables!!"); UncminFunc uncminFunc = new UncminFunc( function, dimension, this ); String method = configuration.method(); int strategy = configuration.strategy(); // Input to the optimizer double[] xIn = new double[dimension+1]; double[] stepSize = new double[dimension+1]; double[] fscale = new double[2]; int[] methodIndex = new int[2]; int[] strategyIndex = new int[2]; int[] performChecks = new int[2]; int[] ndigit = new int[2]; int[] maxIter = new int[2]; int[] useGradient = new int[2]; int[] useHessian = new int[2]; double[] trustRegionRadius = new double[2]; double gradientTol[] = new double[2]; double stepTol[] = new double[2]; double stepMax[] = new double[2]; // Optimizer's output double[] xOut = new double[dimension+1]; double[] fOut = new double[2]; double[] gradientOut = new double[dimension+1]; double[][] hessianOut = new double[dimension+1][dimension+1]; double[] hessianDiagOut = new double[dimension+1]; int[] terminationCode = new int[2]; // What are these fields for? fscale[1] = 1; ndigit[1] = -1; trustRegionRadius[1] = -1.0; stepMax[1] = 0.0; // Set the method method.toUpperCase(); if ( method.startsWith(UncminOptimizerConfiguration.LINE_SEARCH) ) methodIndex[1] = 1; else if ( method.startsWith(UncminOptimizerConfiguration.DOUBLE_DOGLEG) ) methodIndex[1] = 2; else if ( method.startsWith(UncminOptimizerConfiguration.MORE_HEBDON) ) methodIndex[1] = 3; // Set the strategy switch ( strategy ) { case UncminOptimizerConfiguration.LOW_CALL_STRATEGY: strategyIndex[1] = 1; performChecks[1] = 0; break; case UncminOptimizerConfiguration.HIGH_CALL_STRATEGY: strategyIndex[1] = 0; performChecks[1] = 0; break; case UncminOptimizerConfiguration.LOW_CALL_STRATEGY_CHECK: strategyIndex[1] = 1; performChecks[1] = 1; break; case UncminOptimizerConfiguration.HIGH_CALL_STRATEGY_CHECK: strategyIndex[1] = 0; performChecks[1] = 1; break; } // Set maxIterations maxIter[1] = configuration.maxIterations(); // Set gradient and Hessian calculation if ( configuration.useFunctionGradient() ) useGradient[1] = 1; if ( configuration.useFunctionHessian() ) useHessian[1] = 1; // Set Tolerance double tolerance = configuration.tolerance(); gradientTol[1] = tolerance; stepTol[1] = tolerance; for ( int i = 0; i<dimension; i++ ) { String varName = variableNames[ varIndex(i) ]; IVariableSettings varSet = variableSettings(varName); xIn[i+1] = varSet.value(); stepSize[i+1] = varSet.stepSize(); } Uncmin_f77.optif9_f77(dimension,xIn,uncminFunc,stepSize,fscale, methodIndex,strategyIndex,performChecks,ndigit,maxIter,useGradient,useHessian, trustRegionRadius,gradientTol,stepMax,stepTol,xOut,fOut,gradientOut,terminationCode,hessianOut, hessianDiagOut); switch( terminationCode[1] ) { case 0: result.setOptimizationStatus( IOptimizerResult.CONVERGED ); break; case 1: result.setOptimizationStatus( IOptimizerResult.CONVERGED_SMALL_GRADIENT ); break; case 2: result.setOptimizationStatus( IOptimizerResult.CONVERGED_SMALL_STEP_SIZE ); break; case 3: result.setOptimizationStatus( IOptimizerResult.NOT_CONVERGED ); break; case 4: result.setOptimizationStatus( IOptimizerResult.REACHED_MAX_ITER ); break; case 5: result.setOptimizationStatus( IOptimizerResult.TOO_MANY_LARGE_STEPS ); break; } double[] pars = new double[variableNames.length]; int outCount = 0; for ( int i = 0; i<variableNames.length; i++ ) { String varName = variableNames[i]; IVariableSettings varSet = variableSettings(varName); if ( ! varSet.isFixed() ) { double val = xOut[outCount+1]; double err = Math.sqrt(2./hessianDiagOut[outCount+1]); varSet.setValue(val); varSet.setStepSize(err); outCount++; } pars[i] = varSet.value(); } result.setParameters(pars); double[][] covMatrix = new double[dimension][dimension]; for ( int i = 0; i<dimension; i++ ) { for ( int j = i; j<dimension; j++ ) { covMatrix[i][j] = Math.pow(1/(hessianOut[i+1][j+1]/2),2); covMatrix[j][i] = Math.pow(1/(hessianOut[i+1][j+1]/2),2); } } result.setCovarianceMatrix( covMatrix ); } private int varIndex( int index ) { return varIndex[index]; } private class UncminFunc implements Uncmin_methods { IFunction function; UncminOptimizer optimizer; int dimension; double[] vars; UncminFunc( IFunction function, int dimension, UncminOptimizer optimizer ) { this.dimension = dimension; this.function = function; this.optimizer = optimizer; String[] variableNames = function.variableNames(); vars = new double[variableNames.length]; for( int i = 0; i < variableNames.length; i++ ) vars[i] = optimizer.variableSettings( variableNames[i] ).value(); } public double f_to_minimize(double x[]) { for ( int i = 0; i<dimension; i++ ) vars[optimizer.varIndex(i)] = x[i+1]; return function.value(vars); } public void gradient(double x[], double g[]) { g = function.gradient( x ); } public void hessian(double x[], double h[][]) { throw new UnsupportedOperationException("Cannot calculate function's Hessian. Please report this problem"); } private int indexOf( int index ) { return varIndex[ index ]; } } }