view src/samer/maths/opt/Positivity.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.*;
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();
			}
		}
	}
}