optimization updates
[debian/openrocket] / src / net / sf / openrocket / optimization / general / multidim / MultidirectionalSearchOptimizer.java
index 80a194b853340a4d8b252b4664a0656500e10e85..d50618a32e2779c226323e4f465aaa81c422e012 100644 (file)
@@ -9,6 +9,7 @@ import net.sf.openrocket.logging.LogHelper;
 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;
@@ -20,6 +21,8 @@ import net.sf.openrocket.util.Statistics;
  * 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();
@@ -29,6 +32,7 @@ public class MultidirectionalSearchOptimizer implements FunctionOptimizer, Stati
        private ParallelFunctionCache functionExecutor;
        
        private boolean useExpansion = false;
+       private boolean useCoordinateSearch = false;
        
        private int stepCount = 0;
        private int reflectionAcceptance = 0;
@@ -48,7 +52,7 @@ public class MultidirectionalSearchOptimizer implements FunctionOptimizer, Stati
        
 
        @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());
@@ -72,7 +76,8 @@ public class MultidirectionalSearchOptimizer implements FunctionOptimizer, Stati
                        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)"));
@@ -94,16 +99,21 @@ public class MultidirectionalSearchOptimizer implements FunctionOptimizer, Stati
                                 * 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);
                                
@@ -112,7 +122,8 @@ public class MultidirectionalSearchOptimizer implements FunctionOptimizer, Stati
                                        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);
@@ -159,25 +170,34 @@ public class MultidirectionalSearchOptimizer implements FunctionOptimizer, Stati
                                         */
                                        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++;
                                        }
                                        
@@ -185,12 +205,14 @@ public class MultidirectionalSearchOptimizer implements FunctionOptimizer, Stati
                                
                                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");
@@ -198,6 +220,7 @@ public class MultidirectionalSearchOptimizer implements FunctionOptimizer, Stati
                
                log.info("Finishing optimization at point " + simplex.get(0) + " value = " +
                                functionExecutor.getValue(simplex.get(0)));
+               log.info("Optimization statistics: " + getStatistics());
        }
        
        
@@ -205,8 +228,11 @@ public class MultidirectionalSearchOptimizer implements FunctionOptimizer, Stati
        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);
                }
        }
@@ -224,6 +250,9 @@ public class MultidirectionalSearchOptimizer implements FunctionOptimizer, Stati
                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);
                }