import net.sf.openrocket.optimization.general.FunctionCache;
import net.sf.openrocket.optimization.general.FunctionOptimizer;
import net.sf.openrocket.optimization.general.OptimizationController;
+import net.sf.openrocket.optimization.general.OptimizationException;
import net.sf.openrocket.optimization.general.ParallelFunctionCache;
import net.sf.openrocket.optimization.general.Point;
import net.sf.openrocket.startup.Application;
* This is a parallel pattern search optimization algorithm. The function evaluations are performed
* using an ExecutorService. By default a ThreadPoolExecutor is used that has as many thread defined
* as the system has processors.
+ * <p>
+ * The optimization can be aborted by interrupting the current thread.
*/
public class MultidirectionalSearchOptimizer implements FunctionOptimizer, Statistics {
private static final LogHelper log = Application.getLogger();
private ParallelFunctionCache functionExecutor;
private boolean useExpansion = false;
+ private boolean useCoordinateSearch = false;
private int stepCount = 0;
private int reflectionAcceptance = 0;
@Override
- public void optimize(Point initial, OptimizationController control) {
+ public void optimize(Point initial, OptimizationController control) throws OptimizationException {
FunctionCacheComparator comparator = new FunctionCacheComparator(functionExecutor);
final List<Point> pattern = SearchPattern.square(initial.dim());
List<Point> coordinateSearch = new ArrayList<Point>(simplex.size());
Point current;
double currentValue;
- do {
+ boolean continueOptimization = true;
+ while (continueOptimization) {
log.debug("Starting optimization step with simplex " + simplex +
(simplexComputed ? "" : " (not computed)"));
* Expansion is unlikely as we're mainly dealing with bounded optimization.
*/
createReflection(simplex, reflection);
- createCoordinateSearch(current, step, coordinateSearch);
+ if (useCoordinateSearch)
+ createCoordinateSearch(current, step, coordinateSearch);
if (useExpansion)
createExpansion(simplex, expansion);
functionExecutor.compute(reflection);
- functionExecutor.compute(coordinateSearch);
+ if (useCoordinateSearch)
+ functionExecutor.compute(coordinateSearch);
if (useExpansion)
functionExecutor.compute(expansion);
// Check reflection acceptance
+ System.err.println("stepsize = " + step);
+ System.err.println("Simplex = " + simplex);
+ System.err.println("Reflection = " + reflection);
log.debug("Computing reflection");
functionExecutor.waitFor(reflection);
log.debug("Reflection was successful, aborting coordinate search, " +
(useExpansion ? "computing" : "skipping") + " expansion");
- functionExecutor.abort(coordinateSearch);
+ if (useCoordinateSearch)
+ functionExecutor.abort(coordinateSearch);
simplex.clear();
simplex.add(current);
*/
halveStep(simplex);
functionExecutor.compute(simplex);
- functionExecutor.waitFor(coordinateSearch);
- if (accept(coordinateSearch, currentValue)) {
+ if (useCoordinateSearch) {
+ functionExecutor.waitFor(coordinateSearch);
- log.debug("Coordinate search successful, reseting simplex");
- List<Point> toAbort = new LinkedList<Point>(simplex);
- simplex.clear();
- simplex.add(current);
- for (Point p : pattern) {
- simplex.add(current.add(p.mul(step)));
+ if (accept(coordinateSearch, currentValue)) {
+
+ log.debug("Coordinate search successful, reseting simplex");
+ List<Point> toAbort = new LinkedList<Point>(simplex);
+ simplex.clear();
+ simplex.add(current);
+ for (Point p : pattern) {
+ simplex.add(current.add(p.mul(step)));
+ }
+ toAbort.removeAll(simplex);
+ functionExecutor.abort(toAbort);
+ simplexComputed = false;
+ coordinateAcceptance++;
+
+ } else {
+ log.debug("Coordinate search unsuccessful, halving step.");
+ step /= 2;
+ simplexComputed = false;
+ reductionFallback++;
}
- toAbort.removeAll(simplex);
- functionExecutor.abort(toAbort);
- simplexComputed = false;
- coordinateAcceptance++;
-
} else {
- log.debug("Coordinate search unsuccessful, halving step.");
+ log.debug("Coordinate search not used, halving step.");
step /= 2;
+ simplexComputed = false;
reductionFallback++;
}
log.debug("Ending optimization step with simplex " + simplex);
+ continueOptimization = control.stepTaken(current, currentValue, simplex.get(0),
+ functionExecutor.getValue(simplex.get(0)), step);
+
if (Thread.interrupted()) {
throw new InterruptedException();
}
- } while (control.stepTaken(current, currentValue, simplex.get(0),
- functionExecutor.getValue(simplex.get(0)), step));
+ }
} catch (InterruptedException e) {
log.info("Optimization was interrupted with InterruptedException");
log.info("Finishing optimization at point " + simplex.get(0) + " value = " +
functionExecutor.getValue(simplex.get(0)));
+ log.info("Optimization statistics: " + getStatistics());
}
private void createReflection(List<Point> base, List<Point> reflection) {
Point current = base.get(0);
reflection.clear();
+
+ /* new = - (old - current) + current = 2*current - old */
for (int i = 1; i < base.size(); i++) {
- Point p = current.mul(2).sub(base.get(i));
+ Point p = base.get(i);
+ p = current.mul(2).sub(p);
reflection.add(p);
}
}
Point current = base.get(0);
for (int i = 1; i < base.size(); i++) {
Point p = base.get(i);
+
+ /* new = (old - current)*0.5 + current = old*0.5 + current*0.5 = (old + current)*0.5 */
+
p = p.add(current).mul(0.5);
base.set(i, p);
}