Mercurial > hg > jslab
diff src/samer/maths/opt/Positivity.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/Positivity.java Tue Jan 17 17:50:20 2012 +0000 @@ -0,0 +1,179 @@ +/* + * 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.*; +import samer.core.types.*; + +/** + Cubic line search with positivity constraints + dimensions become inactive when they go to + zero and the gradient > GEPS + */ + +public class Positivity extends Constraints +{ + double XEPS=1e-6; + double GEPS=1e-4; + int [] zerod; + int released; + + public Positivity(MinimiserBase minimiser) + { + super(minimiser); + zerod=new int[n]; + + minimiser.add(new VParameter("XEPS", new DoubleModel() { + public void set(double t) { XEPS=t; } + public double get() { return XEPS; } + } ) + ); + + minimiser.add(new VParameter("GEPS", new DoubleModel() { + public void set(double t) { GEPS=t; } + public double get() { return GEPS; } + } ) + ); + } + + /** constrain all dimensions which are currently set + to zero. + */ + + public void initialise() + { + int p=0, q=0; + + for (int i=0; i<n; i++) { + if (S.P1.x[i]<=0) { inactive[p++]=i; S.P1.x[i]=0; } + else active[q++]=i; + } + m=q; + } + + /** + This finds the constrained dimension with the + largest positive gradient, and if of + that gradient is bigger than 1, then releases + that dimension so that it can take part in the + optimization + */ + + public boolean release(Datum P) + { + if (m==n) return false; + + int imax=-1; + double grad=-GEPS; // tolerance + + for (int k=0; k<(n-m); k++) { + int j=inactive[k]; + if (P.g[j]<grad) { + grad=P.g[j]; + imax=j; + } + } + + if (imax!=-1) { activate(imax); released=imax; return true; } + else return false; + } + + public int getReleasedDimension() { return released; } + + /** + Take a step but make sure none of the coordinates + becomes negative. This function returns true if + any dimensions were inactivated - implying that + we should finish the line search. The alternative + is that even the clipped step was too long and + we need to interpolate some more. + */ + + public boolean clipStep(double beta) + { + + step(beta); + + + // got to find sign swappers + int imin=-1; + double alphamin=beta; // ?? + + for (int k=0; k<m; k++) { + int i=active[k]; + if (S.P2.x[i]<=XEPS) { + double alpha=-S.P1.x[i]/S.h[i]; + if (imin==-1 || alpha<alphamin) { + imin=i; + alphamin=alpha; + } + } + } + + // if no negative values, evaluate and return + if (imin==-1) { S.eval2(); return false; } + + // atlease one dimension has become + // zero or negative. imin was the first + // what if alphamin=0? + step(alphamin); + + // now we should check for ANY unconstrained + // x[i] being less than XEPS, and set it to + // exactly zero, including, obviously x[j] + int numzerod=0; + for (int k=0; k<m; k++) { + int j=active[k]; + if (S.P2.x[j]<=XEPS) { + S.P2.x[j]=0; + zerod[numzerod++]=j; + } + } + + eval2(); + + // next, check zeroed dimensions + // for constraint eligibilty + boolean flag=false; + + for (int k=0; k<numzerod; k++) { + int j=zerod[k]; + if (S.P2.g[j]>=-GEPS) { + inactivate(j); + flag=true; + } + } + + return flag; + } + + + public void lineSearch(Condition convergence, CubicLineSearch ls, double beta0) + { + if (clipStep(beta0)) return; + + while (!convergence.test()) { + // formulate any other direction change conditions + + if (S.P2.f<S.P1.f && S.P2.s<0) { + double beta=ls.extrapolate(); + S.move(); + if (clipStep(beta)) break; + } else { + // since both P1 and P2 must satisfy positivity + // constraints, all points between them do alse, + // so no worries about interpolation + step(ls.interpolate()); + eval2(); + } + } + } +} +