package iterators; import java.io.*; import main.BetterTokenizer; import java.lang.*; import main.Model; import affectors.Affector; import parameters.ParameterSet; public class SteepestDescentIterator extends ModelIterator implements Runnable { float h, origEpsilon, tolerance; public SteepestDescentIterator() {} // Have a no argument initializer so we can do new_by_name public ModelIterator copy() throws Exception { SteepestDescentIterator newIter = new SteepestDescentIterator(); newIter.init(this.network, this.model); newIter.nParsTV = this.nParsTV; newIter.parsTV = this.parsTV.copy(); newIter.theFunction = this.theFunction.copy(); newIter.h = this.h; newIter.origEpsilon = this.origEpsilon; newIter.tolerance = this.tolerance; return newIter; } public void loadParameters(BetterTokenizer tokenizer) throws Exception { super.loadParameters(tokenizer); // The grunt work is done by parent class // This is initialization stuff we need to do after figuring out how many // parameters will be varied. } // Put any parameters specific to this iterator class in here, as if clauses. protected void loadParameter(String info, BetterTokenizer tokenizer) throws Exception { if(info.equals("Tolerance")) {tokenizer.nextToken(); tolerance = (float)tokenizer.nval; } else if(info.equals("FirstEpsilon")) {tokenizer.nextToken(); origEpsilon = (float)tokenizer.nval; } else if(info.equals("GradStep")) {tokenizer.nextToken(); h = (float)tokenizer.nval; } else super.loadParameter(info, tokenizer); } /***************************************************************** // ******* This version of theFunction for diagnostic purposes only public float F(float [] thePoint) { double score,x3eight,sinx3eight,fac0,fac1,fac2,fac3; numFunctionCalls++; x3eight= 8.0 * thePoint[3]; sinx3eight = Math.sin(x3eight); sinx3eight = thePoint[3] * sinx3eight*sinx3eight; fac0 = 5.0 * (thePoint[0] - sinx3eight); score = fac0*fac0; fac1 = 5.0 * (thePoint[1] - sinx3eight); score += fac1*fac1; fac2 = Math.cos(x3eight); fac2 = 5.0 * (thePoint[2] - fac2*fac2); score += fac2*fac2; fac3 = 0.5 * Math.abs(thePoint[3]); score += fac3; return (float)score; } // ******* This version of F for diagnostic purposes only //*****************************************************************/ //ELI 3/23 Changed from run to doRun public void doRun() { // minimize F from starting point p[] // using the steepest descent method. At // the end p[] is at the best point and finalScore // is set to F(p). float new_val, new_val2; float epsilon, last_epsilon = origEpsilon; float f_at_p; int i, param; reset(); float [] pt = new float [nParsTV]; float [] gradients = new float[nParsTV]; new_val = F(p); do { f_at_p = new_val; // First find the gradient in the direction of each parameter for(param = 0; param < nParsTV; param++) { p[param] += h; gradients[param] = (F(p) - f_at_p) / h; p[param] -= h; } // Now check increasingly large moves in that direction to see how far we can go downhill epsilon = last_epsilon; moveEpsilon(p, gradients, epsilon, pt); new_val = F(pt); if(new_val < f_at_p) { epsilon += last_epsilon; moveEpsilon(p, gradients, epsilon, pt); new_val2 = F(pt); while(new_val2 < new_val && new_val - new_val2 > tolerance * new_val) { new_val = new_val2; epsilon += last_epsilon; moveEpsilon(p, gradients, epsilon, pt); new_val2 = F(pt); } if(new_val2 < new_val) // Stopped cause of tolerance, so make that move new_val = new_val2; else epsilon -= last_epsilon; } else { // Move back towards original point, cause epsilon is too large epsilon /= 2f; moveEpsilon(p, gradients, epsilon, pt); new_val2 = F(pt); while(new_val2 < new_val && new_val - new_val2 > tolerance * new_val) { new_val = new_val2; epsilon /= 2f; moveEpsilon(p, gradients, epsilon, pt); new_val2 = F(pt); } if(new_val2 < new_val) // Stopped cause of tolerance, so make that move new_val = new_val2; else epsilon *= 2f; } moveEpsilon(p, gradients, epsilon, p); // for(i = 0; i < nParsTV; i++) p[i] = p[i] - gradients[i] * epsilon; last_epsilon = epsilon; } while(f_at_p - new_val > tolerance * new_val); finalScore = new_val; // finalScore now holds the final score // Print the results... System.out.println("SteepestDescent ended with value " + f_at_p + " and params:"); for(i = 0; i < nParsTV; i++) System.out.println(parsTV.getName(i) + " = " + p[i]); super.stopRun(); } private void moveEpsilon(float [] p, float [] gradients, float epsilon, float [] pt) { // Scale the move so that we go epsilon along the steepest axis float max_grad = 0f; int i; for(i = 0; i < nParsTV; i++) { if(gradients[i] > max_grad) max_grad = gradients[i]; } for(i = 0; i < nParsTV; i++) { pt[i] = p[i] - (gradients[i] / max_grad) * epsilon; } } }