@Override public void optimize(Point initial, OptimizationController control) throws OptimizationException { if (initial.dim() != 1) { throw new IllegalArgumentException( "Only single-dimensional optimization supported, dim=" + initial.dim()); } log.info("Starting golden section search for optimization"); Point guessAC = null; Point guessBD = null; try { boolean guessedAC; Point previous = p(0); double previousValue = Double.NaN; current = previous; double currentValue = Double.NaN; /* * Initialize the points + computation. */ Point a = p(0); Point d = p(1.0); Point b = section1(a, d); Point c = section2(a, d); functionExecutor.compute(a); functionExecutor.compute(d); functionExecutor.compute(b); functionExecutor.compute(c); // Wait for points a and d, which normally are already precomputed functionExecutor.waitFor(a); functionExecutor.waitFor(d); boolean continueOptimization = true; while (continueOptimization) { /* * Get values at A & D for guessing. * These are pre-calculated except during the first step. */ double fa, fd; fa = functionExecutor.getValue(a); fd = functionExecutor.getValue(d); /* * Start calculating possible two next points. The order of evaluation * is selected based on the function values at A and D. */ guessAC = section1(a, c); guessBD = section2(b, d); if (Double.isNaN(fd) || fa < fd) { guessedAC = true; functionExecutor.compute(guessAC); functionExecutor.compute(guessBD); } else { guessedAC = false; functionExecutor.compute(guessBD); functionExecutor.compute(guessAC); } /* * Get values at B and C. */ double fb, fc; functionExecutor.waitFor(b); functionExecutor.waitFor(c); fb = functionExecutor.getValue(b); fc = functionExecutor.getValue(c); double min = MathUtil.min(fa, fb, fc, fd); if (Double.isNaN(min)) { throw new OptimizationException("Unable to compute initial function values"); } /* * Update previous and current values for step control. */ previousValue = currentValue; currentValue = min; previous = current; if (min == fa) { current = a; } else if (min == fb) { current = b; } else if (min == fc) { current = c; } else { current = d; } /* * Select next positions. These are already being calculated in the background * as guessAC and guessBD. */ if (min == fa || min == fb) { d = c; c = b; b = guessAC; functionExecutor.abort(guessBD); guessBD = null; log.debug("Selecting A-C region, a=" + a.get(0) + " c=" + c.get(0)); if (guessedAC) { guessSuccess++; } else { guessFailure++; } } else { a = b; b = c; c = guessBD; functionExecutor.abort(guessAC); guessAC = null; log.debug("Selecting B-D region, b=" + b.get(0) + " d=" + d.get(0)); if (!guessedAC) { guessSuccess++; } else { guessFailure++; } } /* * Check optimization control. */ continueOptimization = control.stepTaken(previous, previousValue, current, currentValue, c.get(0) - a.get(0)); if (Thread.interrupted()) { throw new InterruptedException(); } } } catch (InterruptedException e) { log.info("Optimization was interrupted with InterruptedException"); } if (guessAC != null) { functionExecutor.abort(guessAC); } if (guessBD != null) { functionExecutor.abort(guessBD); } log.info( "Finishing optimization at point " + getOptimumPoint() + " value " + getOptimumValue()); log.info("Optimization statistics: " + getStatistics()); }
private Point section2(Point a, Point b) { double va = a.get(0); double vb = b.get(0); return p(va + ALPHA * (vb - va)); }