Mercurial > hg > jslab
diff src/samer/maths/opt/PolynomialLineSearch.java @ 0:bf79fb79ee13
Initial Mercurial check in.
author | samer |
---|---|
date | Tue, 17 Jan 2012 17:50:20 +0000 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/samer/maths/opt/PolynomialLineSearch.java Tue Jan 17 17:50:20 2012 +0000 @@ -0,0 +1,74 @@ +/* + * 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.*; + +/** + Line search from <b>Numerical Recipes in C</b>, pretty + much as supplied. + + I removed the max step and slope checking and made it the + responsibility of the calling code to check these. + Also, this works with ONE-DIMENSIONAL functions: the stuff + about vectors can be handled by a <code>LineFunction</code> object. + */ + +public class PolynomialLineSearch +{ + State S; + + public PolynomialLineSearch(State s) { S=s; } + + /** + This assumes that the initial step has already been taken + @param alamin minimum step size + */ + + public void run(Condition termination) + { + double alam, alam2, f3; + double tmplam; + + // if initial step is ok... + if (termination.test()) return; + + // backtrack using quadratic interpolation + tmplam = -S.P1.s/(2*(S.P1.f-S.P2.f-S.P1.s)); + alam = S.alpha; + + for (;;) { + + // remember failed parameters + alam2=alam; f3=S.P2.f; + alam=Math.max(tmplam,0.1*alam); + + S.step(alam); + + // if step was ok... + if (termination.test()) return; + + // backtrack using cubic interpolation + double rhs1 = S.P2.f - S.P1.f - alam*S.P1.s; + double rhs2 = f3 - S.P1.f - alam2*S.P1.s; + double a = (rhs1/(alam*alam) - rhs2/(alam2*alam2)) / (alam-alam2); + double b = (-alam2*rhs1/(alam*alam)+alam*rhs2/(alam2*alam2))/(alam-alam2); + + if (a==0.0) tmplam = -S.P1.s/(2*b); + else { + double disc=b*b-2*a*S.P1.s; + if (disc<0) tmplam=alam/2; + else if (b<=0) tmplam=(-b+Math.sqrt(disc))/(3*a); + else tmplam=-S.P1.s/(b+Math.sqrt(disc)); + } + if (tmplam>alam/2) tmplam=alam/2; + } + } +}