Java tutorial
/* Copyright 2009-2015 David Hadka * * This file is part of the MOEA Framework. * * The MOEA Framework is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or (at your * option) any later version. * * The MOEA Framework is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with the MOEA Framework. If not, see <http://www.gnu.org/licenses/>. */ package iDynoOptimizer.MOEAFramework26.src.org.moeaframework.util.progress; import org.apache.commons.lang3.event.EventListenerSupport; import org.apache.commons.math3.stat.descriptive.DescriptiveStatistics; import iDynoOptimizer.MOEAFramework26.src.org.moeaframework.Executor; /** * Helper for notifying {@link ProgressListener}s when the evaluation progress * of an {@link Executor} changes. This class reports the current progress, * percent complete, elapsed time, and remaining time. Be sure to first call * {@link #start(int, int)} to set the total number of seeds and NFE prior to * invoking any other method. */ public class ProgressHelper { /** * The listeners to receive progress reports. */ private final EventListenerSupport<ProgressListener> listeners; /** * Calculates the moving average processing speed for estimating remaining * time. */ private final DescriptiveStatistics statistics; /** * The executor using this progress helper. */ private final Executor executor; /** * The current seed being evaluated, starting at 1. */ private int currentSeed; /** * The total number of seeds to be evaluated. */ private int totalSeeds; /** * The current number of objective function evaluations for the current * seed. */ private int currentNFE; /** * The maximum number of objective function evaluations per seed. */ private int maxNFE; /** * The time the {@link #start(int, int)} method was invoked. */ private long startTime; /** * The last time that the {@link #updateStatistics()} method was invoked, * used for estimating the remaining time. */ private long lastTime; /** * The seed that was evaluated when {@link #updateStatistics()} was last * invoked, used for estimating the remaining time. */ private int lastSeed; /** * The NFE when {@link #updateStatistics()} was last invoked, used for * estimating the remaining time. */ private int lastNFE; /** * Constructs a new progress helper for generating progress reports for * the given executor. * * @param executor the executor that will be reporting progress */ public ProgressHelper(Executor executor) { super(); this.executor = executor; statistics = new DescriptiveStatistics(25); listeners = EventListenerSupport.create(ProgressListener.class); } /** * Adds the given listener to receive progress reports. * * @param listener the listener to receive progress reports */ public void addProgressListener(ProgressListener listener) { listeners.addListener(listener); } /** * Removes the given listener so it no longer receives progress reports. * * @param listener the listener to no longer receive progress reports */ public void removeProgressListener(ProgressListener listener) { listeners.removeListener(listener); } /** * Updates the moving average statistics used for estimating the remaining * time. The processing speed is measured by the NFE completed since this * method was last invoked. */ private void updateStatistics() { long currentTime = System.currentTimeMillis(); // calculate the change since the last call double diffTime = currentTime - lastTime; double diffSeed = currentSeed - lastSeed; double diffNFE = currentNFE - lastNFE; double percentChange = (diffSeed + (diffNFE / maxNFE)) / totalSeeds; // only update if the change was significant if ((diffTime > 0.0) && (percentChange > 0.0001)) { statistics.addValue(diffTime / percentChange); // update the last values lastTime = currentTime; lastSeed = currentSeed; lastNFE = currentNFE; } } /** * Sends a progress report to all registered listeners. Use the argument * {@code isSeedFinished} to indicate that a seed has completed and * results can be accessed from the executor. * * @param isSeedFinished {@code true} if this report is being sent as a * result of a completed seed; {@code false} otherwise */ private void sendProgressEvent(boolean isSeedFinished) { long currentTime = System.currentTimeMillis(); double remainingSeeds = totalSeeds - currentSeed; double remainingNFE = maxNFE - currentNFE; double percentRemaining = (remainingSeeds + (remainingNFE / maxNFE)) / totalSeeds; ProgressEvent event = new ProgressEvent(executor, currentSeed, totalSeeds, isSeedFinished, currentNFE, maxNFE, Math.max(1.0 - percentRemaining, 0.0), (currentTime - startTime) / 1000.0, (statistics.getMean() * percentRemaining) / 1000.0); listeners.fire().progressUpdate(event); } /** * Sets the current number of objective function evaluations. This method * will generate a progress report. * * @param currentNFE the current number of objective function evaluations */ public void setCurrentNFE(int currentNFE) { this.currentNFE = currentNFE; updateStatistics(); sendProgressEvent(false); } /** * Sets the current seed. This call will have no affect if the current * seed is unchanged. This method will generate a progress report if the * current seed changes. * <p> * <b>It is strongly recommended that {@link #nextSeed()} is used instead * of this method, as {@code nextSeed()} sets the current NFE to 0.</b> * * @param currentSeed the current seed being processed, starting at * {@code 1} */ public void setCurrentSeed(int currentSeed) { if (this.currentSeed != currentSeed) { this.currentSeed = currentSeed; updateStatistics(); sendProgressEvent(true); } } /** * Increments the current seed and sets NFE to 0. This method will * generate a progress report. This method should be invoked after every * seed completes in order to notify listeners that the seed completed. */ public void nextSeed() { currentSeed++; currentNFE = 0; updateStatistics(); sendProgressEvent(true); } /** * Prepares this progress helper for use. This method must be invoked * prior to calling all other methods. The internal state of the progress * helper is reset, allowing a single progress helper to be reused across * many sequential runs. * * @param totalSeeds the total number of seeds to be evaluated * @param maxNFE the maximum number of objective function evaluations per * seed */ public void start(int totalSeeds, int maxNFE) { this.totalSeeds = totalSeeds; this.maxNFE = maxNFE; // reset all internal parameters lastSeed = 1; lastNFE = 0; currentSeed = 1; currentNFE = 0; statistics.clear(); startTime = System.currentTimeMillis(); lastTime = startTime; } /** * Stops this progress helper. No other methods should be invoked after * calling this method. However, {@link #start(int, int)} can be called * to reset and restart this progress helper. */ public void stop() { // this currently does nothing, but may be used in the future if we // do anything to reduce the number of reports (i.e., send updates // at most once every second) } }