/** * Create a multi-start optimizer from a single-start optimizer. * * @param optimizer Single-start optimizer to wrap. * @param starts Number of starts to perform. If {@code starts == 1}, the {@code optimize} methods * will return the same solution as {@code optimizer} would. * @param generator Random generator to use for restarts. * @throws NotStrictlyPositiveException if {@code starts < 1}. */ public MultiStartUnivariateOptimizer( final UnivariateOptimizer optimizer, final int starts, final RandomGenerator generator) { super(optimizer.getConvergenceChecker()); if (starts < 1) { throw new NotStrictlyPositiveException(starts); } this.optimizer = optimizer; this.starts = starts; this.generator = generator; }
/** {@inheritDoc} */ @Override protected UnivariatePointValuePair doOptimize() { // Remove all instances of "MaxEval" and "SearchInterval" from the // array that will be passed to the internal optimizer. // The former is to enforce smaller numbers of allowed evaluations // (according to how many have been used up already), and the latter // to impose a different start value for each start. for (int i = 0; i < optimData.length; i++) { if (optimData[i] instanceof MaxEval) { optimData[i] = null; maxEvalIndex = i; continue; } if (optimData[i] instanceof SearchInterval) { optimData[i] = null; searchIntervalIndex = i; continue; } } if (maxEvalIndex == -1) { throw new MathIllegalStateException(); } if (searchIntervalIndex == -1) { throw new MathIllegalStateException(); } RuntimeException lastException = null; optima = new UnivariatePointValuePair[starts]; totalEvaluations = 0; final int maxEval = getMaxEvaluations(); final double min = getMin(); final double max = getMax(); final double startValue = getStartValue(); // Multi-start loop. for (int i = 0; i < starts; i++) { // CHECKSTYLE: stop IllegalCatch try { // Decrease number of allowed evaluations. optimData[maxEvalIndex] = new MaxEval(maxEval - totalEvaluations); // New start value. final double s = (i == 0) ? startValue : min + generator.nextDouble() * (max - min); optimData[searchIntervalIndex] = new SearchInterval(min, max, s); // Optimize. optima[i] = optimizer.optimize(optimData); } catch (RuntimeException mue) { lastException = mue; optima[i] = null; } // CHECKSTYLE: resume IllegalCatch totalEvaluations += optimizer.getEvaluations(); } sortPairs(getGoalType()); if (optima[0] == null) { throw lastException; // Cannot be null if starts >= 1. } // Return the point with the best objective function value. return optima[0]; }