Mercurial > hg > jslab
view src/samer/maths/opt/State.java @ 8:5e3cbbf173aa tip
Reorganise some more
author | samer |
---|---|
date | Fri, 05 Apr 2019 22:41:58 +0100 |
parents | bf79fb79ee13 |
children |
line wrap: on
line source
/* * Copyright (c) 2000, Samer Abdallah, King's College London. * All rights reserved. * * This software is provided AS iS and WITHOUT ANY WARRANTY; * without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. */ package samer.maths.opt; import samer.maths.*; import samer.core.*; public class State { public Functionx func; // function public int n; // number of dimensions public double[] h; // search direction public Datum P1, P2; // two bracket points and a new point public double alpha; // step length public double normh; // some norm of h /** x must have an accessible array */ public State( Vec x, Functionx func) { this.n = x.size(); this.func = func; P1 = new Datum(n,x.array()); P2 = new Datum(n); h = new double[n]; } public void dispose() { func.dispose(); P1.dispose(); P2.dispose(); h=null; } /** estimated step to minimum using cubic interpolation of current state */ public final double cubic() { return Util.cubici(P1.f,P1.s,P2.f,P2.s,alpha); } /** evaluate at P1 */ public final void evaluate() { func.evaluate(P1); } /** move P1 to where P2 is now */ public final void move() { P1.copy(P2); } // assert that P1.s<0 ? /** take step of length lambda from P1 in direction of h, evaluate and store in P2 */ public void step(double lambda) { for (int i=0; i<n; i++) { P2.x[i] = P1.x[i] + lambda*h[i]; } func.evaluate(P2); P2.s = Mathx.dot(P2.g,h); alpha=lambda; } /** evaluate at P2 */ public final void eval2() { func.evaluate(P2); P2.s = Mathx.dot(P2.g,h); } /** evaluate slope at P1 using gradient at P1 */ public final void setSlope() { double s1 = Mathx.dot(P1.g,h); if (Double.isNaN(s1)) throw new Error( "slope 1 is NaN"); if (s1>0) { Shell.trace(toString()); Shell.trace("bad new slope="+s1); } P1.s = s1; } /** set slope at P2, assert new slope is negative */ public final void setSlope2(double s2) { if (Double.isNaN(s2)) throw new Error( "slope 2 is NaN"); if (s2>0) { Shell.trace(" ***** BAD DIRECTION UPDATE **** "); Shell.trace(toString()); Shell.trace("-- slope = "+s2); } P2.s=s2; } public String toString() { return append(new StringBuffer()).toString(); } public double initialStep() { double step=2*Math.abs(P1.f/P1.s); if (Double.isNaN(step)) return 1; return Util.clip(0.01,step,1); } /** estimate initial step for line search after turn */ public double nextStep() { double beta; if (P2.s<=P1.s) return 1; if (P2.s>0) { // signal: 'overshoot, updhess' // expect beta between 0 and 1 if (alpha<0.9) beta=alpha; else beta=cubic(); if (Double.isNaN(beta) || Double.isInfinite(beta)) beta=1; } else { // signal: 'undershoot, updhess' double gamma=1.5*alpha; if (gamma<2) gamma=2; double delta=alpha*(P2.s-P1.s)-P2.s+(alpha>1?alpha:1); // double delta=uv-P2.s+(alpha>1?alpha:1); beta=cubic(); if (Double.isNaN(beta) || Double.isInfinite(beta) || beta<alpha) beta=2*alpha+1e-5; beta*=1.2; if (gamma<beta) beta=gamma; if (delta<beta) beta=delta; } return beta; } public StringBuffer append(StringBuffer info) { info.append(DoubleFormat.format(P1.f,4)) .append(", ") .append(DoubleFormat.format(P1.s,4)) .append("\t") .append(DoubleFormat.format(alpha,4)) .append("\t") .append(DoubleFormat.format(P2.f,4)) .append(", ") .append(DoubleFormat.format(P2.s,4)) .append(" : "); // .append(this.info); return info; } }