/**************************************************************************** Copyright (c) 2003, Landmark Graphics and others. All rights reserved. This program and accompanying materials are made available under the terms of the Common Public License - v1.0, which accompanies this distribution, and is available at http://www.eclipse.org/legal/cpl-v10.html ****************************************************************************/ package com.lgc.wsh.opt; import com.lgc.wsh.util.Almost; import com.lgc.wsh.util.Monitor; import java.util.Arrays; import java.util.logging.Logger; /** Search a single variable for a value that minimizes a function @author W.S. Harlan */ public class ScalarSolver { @SuppressWarnings("unused") private static final Logger LOG = Logger.getLogger("com.lgc.wsh.opt"); private static final double GOLD = 0.5*(Math.sqrt(5.) - 1.); // 0.618034 private static Almost s_almost = new Almost(); private Function _function = null; /** Implement a function of one variable to be minimized */ public interface Function { /** Return a single value as a function of the argument @param scalar Argument to be optimized within a known range. @return value to be minimized */ public double function(double scalar); } /** Constructor @param function Objective function to be minimized. */ public ScalarSolver(Function function) { _function = function; } /** Minimize a function of scalar and return the optimum value. @param scalarMin The minimum value allowed for the argument scalar. @param scalarMax The maximum value allowed for the argument scalar. @param okError The unknown error in scalar should be less than this fraction of the range: dscalar/(scalarMax-scalarMin) <= okError, where dscalar is the error bound on the returned value of scalar. @param okFraction The error in scalar should be less than this fraction of the minimum possible range for scalar: dscalar <= okFraction*(scalar-scalarMin), where dscalar is the error bound on the returned value of scalar. @param numberIterations The maximum number of iterations if greater than 6. The optimization performs at least 6 iterations -- the minimum necessary for a genuinely parabolic function. I recommend at least 20. @param monitor For reporting progress. Ignored if null. @return The optimum value minimizing the function. */ public double solve(double scalarMin, double scalarMax, double okError, double okFraction, int numberIterations, Monitor monitor) { if (monitor == null) monitor = Monitor.NULL_MONITOR; monitor.report(0.); int iter =0, nter = numberIterations; if (nter < 6) nter = 6; double[] xs = {0., 0.25, 0.75, 1.}; // Assume bias toward endpoints double[] fs = new double[4]; for (int i=0; i