samer@0: /* samer@0: * Copyright (c) 2000, Samer Abdallah, King's College London. samer@0: * All rights reserved. samer@0: * samer@0: * This software is provided AS iS and WITHOUT ANY WARRANTY; samer@0: * without even the implied warranty of MERCHANTABILITY or samer@0: * FITNESS FOR A PARTICULAR PURPOSE. samer@0: */ samer@0: samer@0: package samer.maths.opt; samer@0: import samer.maths.*; samer@0: import samer.core.*; samer@0: import samer.core.types.*; samer@0: import java.util.*; samer@0: samer@0: /** samer@0: Constraints and line minimisations for functions with gradient samer@0: discontinuity at co-ordinate zeros (hyperplanes). samer@0: The ZeroCrossingSparsity class handles this by checking for samer@0: zero crossings during the line search. If a gradient samer@0: discontinuity causes a change of sign in the gradient, samer@0: that dimension is constrained and becomes inactive (drops samer@0: out of minimisation). It can later be reactivated if samer@0: the algorithm determines that the gradient no longer samer@0: changes sign at that point. samer@0: */ samer@0: samer@0: public class ZeroCrossingSparsity extends Constraints samer@0: { samer@0: public double alphas[]; samer@0: public int crossings[]; samer@0: public int numcrossings; samer@0: public int clipped=0; samer@0: private int released, releasable; samer@0: private double XEPS=1e-6, GEPS=1e-4; samer@0: private double GTHRESH=1; samer@0: samer@0: public static Factory factory() { samer@0: return new Factory() { samer@0: public Constraints build(MinimiserBase minimiser) { samer@0: return new ZeroCrossingSparsity(minimiser); samer@0: } samer@0: }; samer@0: } samer@0: samer@0: public ZeroCrossingSparsity(MinimiserBase minimiser) samer@0: { samer@0: super(minimiser); samer@0: crossings=new int[n]; samer@0: alphas=new double[n]; samer@0: samer@0: minimiser.add(new VParameter("XEPS", new DoubleModel() { samer@0: public void set(double t) { XEPS=t; } samer@0: public double get() { return XEPS; } samer@0: } ) samer@0: ); samer@0: samer@0: minimiser.add(new VParameter("GEPS", new DoubleModel() { samer@0: public void set(double t) { GEPS=t; } samer@0: public double get() { return GEPS; } samer@0: } ) samer@0: ); samer@0: samer@0: try { samer@0: final Object jump=Shell.get("ZeroCrossingSparsity.jump"); samer@0: if (jump instanceof Double) { samer@0: GTHRESH=((Double)jump).doubleValue(); samer@0: Shell.print("Gradient jump="+GTHRESH); samer@0: } else if (jump instanceof VDouble) { samer@0: GTHRESH=((VDouble)jump).value; samer@0: ((VDouble)jump).addObserver( new Observer() { samer@0: public void update(Observable o, Object arg) { samer@0: GTHRESH=((VDouble)jump).value; samer@0: } samer@0: } ); samer@0: Shell.print("Gradient jump in VDouble="+GTHRESH); samer@0: } samer@0: } catch (Exception ex) { samer@0: Shell.print("*** no jump object found! ***"); samer@0: Shell.print(ex.toString()); samer@0: ex.printStackTrace(); samer@0: } samer@0: } samer@0: samer@0: public void setGThreshold(double gt) { GTHRESH=gt; } samer@0: samer@0: /** constrain all dimensions which are currently set samer@0: to zero. samer@0: */ samer@0: samer@0: public void initialise() samer@0: { samer@0: int p=0, q=0; samer@0: samer@0: for (int i=0; iXEPS && S.P2.x[i]-XEPS && S.P1.x[i]<-XEPS) ) { samer@0: crossings[numcrossings]=i; samer@0: alphas[numcrossings]=-S.P1.x[i]/S.h[i]; samer@0: numcrossings++; samer@0: } samer@0: } samer@0: return numcrossings>0; samer@0: } samer@0: samer@0: public void report() samer@0: { samer@0: if (numcrossings>0) { samer@0: Shell.trace("crossings: "+numcrossings); samer@0: for (int i=0; igrad) { samer@0: releasable++; samer@0: grad=Math.abs(P.g[j]); samer@0: imax=j; samer@0: } samer@0: } samer@0: samer@0: if (imax!=-1) { samer@0: activate(imax); released=imax; samer@0: return true; samer@0: } samer@0: else return false; samer@0: } samer@0: samer@0: public int getReleasedDimension() { return released; } samer@0: public int getReleasableDimensions() { return releasable; } samer@0: samer@0: public void lineSearch(Condition convergence, CubicLineSearch ls, double beta0) samer@0: { samer@0: boolean zcdone=false; samer@0: samer@0: step(beta0); samer@0: eval2(); samer@0: samer@0: while (!convergence.test()) { samer@0: samer@0: // formulate any other direction change conditions samer@0: samer@0: if (S.P2.f0) { samer@0: samer@0: // we are going to look at the alphas, and samer@0: // find the smallest one that is between samer@0: // interp and current alpha samer@0: samer@0: int best=-1; samer@0: double bestAlpha=S.alpha; samer@0: samer@0: for (int k=0; k=interp && beta