iDynoOptimizer.MOEAFramework26.src.org.moeaframework.util.progress.ProgressHelper.java Source code

Java tutorial

Introduction

Here is the source code for iDynoOptimizer.MOEAFramework26.src.org.moeaframework.util.progress.ProgressHelper.java

Source

/* 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)
    }

}