/*
 * This file is part of JGAP.
 *
 * JGAP offers a dual license model containing the LGPL as well as the MPL.
 *
 * For licensing information please see the file license.txt included with JGAP
 * or have a look at the top of class org.jgap.Chromosome which representatively
 * includes the JGAP license policy applicable for any file delivered with JGAP.
 */
package org.jgap.audit;

import java.util.*;

import org.jgap.*;
import org.jgap.eval.*;

/**
 * Monitors the evolution and stops it if evolution does not make a progress
 * as desired.
 * For usage of this monitor class, see class examples.audit.EvolutionMonitorExample.
 *
 * @author Klaus Meffert
 * @since 3.4.4
 */
public class FitnessImprovementMonitor
    implements IEvolutionMonitor {
  /** String containing the CVS revision. Read out via reflection!*/
  private final static String CVS_REVISION = "$Revision: 1.4 $";

  private int m_initialWaitSeconds;

  private int m_checkIntervalSeconds;

  private double m_improvedFitnessExpected;

  private long m_startMillis;

  private long m_lastCheckMillis;

  private double m_bestFitnessPreviously;

  private int m_checks;

  /**
   * Constructor.
   *
   * @param a_initialWaitSeconds number of seconds to wait until first check
   * @param a_checkIntervalSeconds number of seconds to wait after the previous
   * check (except for the first check, where a_initialWaitSeconds is taken)
   * @param a_improvedFitnessExpected number of fitness units the current best
   * solution evolved is better than the best solution from the previously check
   *
   * @author Klaus Meffert
   * @since 3.4.4
   */
  public FitnessImprovementMonitor(int a_initialWaitSeconds,
                                   int a_checkIntervalSeconds,
                                   double a_improvedFitnessExpected) {
    m_initialWaitSeconds = a_initialWaitSeconds;
    m_checkIntervalSeconds = a_checkIntervalSeconds;
    m_improvedFitnessExpected = a_improvedFitnessExpected;
    m_bestFitnessPreviously = FitnessFunction.NO_FITNESS_VALUE;
  }

  /**
   * Called after another evolution cycle has been executed.
   *
   * @param a_pop the currently evolved population
   * @param a_messages the monitor can append messages to indicate why it asks
   * evolution to stop
   * @return true: continue with the evolution; false: stop evolution
   *
   * @author Klaus Meffert
   * @since 3.4.4
   */
  public boolean nextCycle(Population a_pop, List a_messages) {
    long currentMillis = System.currentTimeMillis();
    boolean doCheck = false;
    if (m_checks == 0) {
      if (currentMillis - m_startMillis >= m_initialWaitSeconds * 1000) {
        doCheck = true;
      }
    }
    else {
      if (currentMillis - m_lastCheckMillis >= m_checkIntervalSeconds * 1000) {
        doCheck = true;
      }
    }
    if (doCheck) {
      // Let's verify the progress since our last check.
      // -----------------------------------------------
      IChromosome best = a_pop.determineFittestChromosome();
      if (best != null) {
        // A best solution exists.
        // -----------------------
        if (Math.abs(m_bestFitnessPreviously - FitnessFunction.NO_FITNESS_VALUE) <
            FitnessFunction.DELTA) {
          // There was no previous best solution.
          // ------------------------------------
          m_bestFitnessPreviously = best.getFitnessValue();
        }
        else {
          // Is the current best solution better than the previous one?
          // ----------------------------------------------------------
          if (Math.abs(best.getFitnessValue() - m_bestFitnessPreviously) <
              m_improvedFitnessExpected) {
            // Bad luck, not enough progress.
            // ------------------------------
            a_messages.add("Not enough progress was made after initial delay");
            return false;
          }
          else {
            m_bestFitnessPreviously = best.getFitnessValue();
          }
        }
      }
      else {
        if (m_checks > 0) {
          // No result evolved during two check cycles.
          // ------------------------------------------
          a_messages.add(
              "No solution at all was evolved during two check cycles.");
          return false;
        }
      }
      m_lastCheckMillis = System.currentTimeMillis();
      m_checks++;
    }
    // No check needed yet.
    // --------------------
    return true;
  }

  /**
   * Called just before the evolution starts.
   *
   * @param a_config the configuration used
   *
   * @author Klaus Meffert
   * @since 3.4.4
   */
  public void start(Configuration a_config) {
    m_startMillis = System.currentTimeMillis();
  }

  /**
   * Called whenever it's worth monitoring.
   *
   * @param a_monitorEvent see constants at top of class IEvolutionMonitor
   * @param a_evolutionNo the index of the evolution round (1, 2, ...)
   * @param a_information event-specific information
   *
   * @author Klaus Meffert
   * @since 3.5
   */
  public void event(String a_monitorEvent, int a_evolutionNo,
                    Object[] a_information) {
    // Just a sample implemetation here to show how to react to the specific
    // monitor events that are supported.
    // ---------------------------------------------------------------------
    if (a_monitorEvent == null) {
      // Should never happen.
      // --------------------
      return;
    }
    if (a_information == null) {
      return;
    }
    // The events are queried in the chronological order they do appear.
    // -----------------------------------------------------------------
    if (a_monitorEvent.equals(IEvolutionMonitor.MONITOR_EVENT_REMOVE_CHROMOSOME)) {
      Population pop = (Population) a_information[0];
      Integer chromosomeIndex = (Integer) a_information[1];
    }
    if (a_monitorEvent.equals(IEvolutionMonitor.
                              MONITOR_EVENT_BEFORE_UPDATE_CHROMOSOMES1)) {
      Population pop = (Population) a_information[0];
    }
    if (a_monitorEvent.equals(IEvolutionMonitor.
                              MONITOR_EVENT_AFTER_UPDATE_CHROMOSOMES1)) {
      Population pop = (Population) a_information[0];
    }
    if (a_monitorEvent.equals(IEvolutionMonitor.MONITOR_EVENT_BEFORE_SELECT)) {
      NaturalSelector selector = (NaturalSelector) a_information[0];
      Population pop = (Population) a_information[1];
      int selectionSize = (Integer) a_information[2];
      boolean a_processBeforeGeneticOperators = (Boolean) a_information[3];
      /*
       * a_processBeforeGeneticOperators = true:
       *    called after MONITOR_EVENT_AFTER_UPDATE_CHROMOSOMES1
       * a_processBeforeGeneticOperators = false:
       *    called after MONITOR_EVENT_AFTER_UPDATE_CHROMOSOMES2
       */
    }
    if (a_monitorEvent.equals(IEvolutionMonitor.MONITOR_EVENT_AFTER_SELECT)) {
      NaturalSelector selector = (NaturalSelector) a_information[0];
      Population pop = (Population) a_information[1];
      Population newPop = (Population) a_information[2];
      int selectionSize = (Integer) a_information[3];
      boolean a_processBeforeGeneticOperators = (Boolean) a_information[4];
      /*
       * a_processBeforeGeneticOperators = true:
       *    called after MONITOR_EVENT_AFTER_UPDATE_CHROMOSOMES1
       * a_processBeforeGeneticOperators = false:
       *    called after MONITOR_EVENT_AFTER_UPDATE_CHROMOSOMES2
       */
    }
    if (a_monitorEvent.equals(IEvolutionMonitor.MONITOR_EVENT_BEFORE_OPERATE)) {
      GeneticOperator operator = (GeneticOperator) a_information[0];
      Population pop = (Population) a_information[1];
      List chromosomes = (List) a_information[2];
    }
    if (a_monitorEvent.equals(IEvolutionMonitor.MONITOR_EVENT_AFTER_OPERATE)) {
      GeneticOperator operator = (GeneticOperator) a_information[0];
      Population pop = (Population) a_information[1];
      List chromosomes = (List) a_information[2];
    }
    if (a_monitorEvent.equals(IEvolutionMonitor.MONITOR_EVENT_BEFORE_BULK_EVAL)) {
      BulkFitnessFunction bulkFitnessFunction = (BulkFitnessFunction)
          a_information[0];
      Population pop = (Population) a_information[1];
    }
    if (a_monitorEvent.equals(IEvolutionMonitor.MONITOR_EVENT_AFTER_BULK_EVAL)) {
      BulkFitnessFunction bulkFitnessFunction = (BulkFitnessFunction)
          a_information[0];
      Population pop = (Population) a_information[1];
    }
    if (a_monitorEvent.equals(IEvolutionMonitor.
                              MONITOR_EVENT_BEFORE_UPDATE_CHROMOSOMES2)) {
      Population pop = (Population) a_information[0];
    }
    if (a_monitorEvent.equals(IEvolutionMonitor.
                              MONITOR_EVENT_AFTER_UPDATE_CHROMOSOMES2)) {
      Population pop = (Population) a_information[0];
    }
    if (a_monitorEvent.equals(IEvolutionMonitor.
                              MONITOR_EVENT_BEFORE_ADD_CHROMOSOME)) {
      Population pop = (Population) a_information[0];
      IChromosome newChromosome = (IChromosome) a_information[1];
    }
    if (a_monitorEvent.equals(IEvolutionMonitor.MONITOR_EVENT_READD_FITTEST)) {
      Population pop = (Population) a_information[0];
      IChromosome fittest = (IChromosome) a_information[1];
    }
  }

  /**
   * @return null as no data is gathered by this monitor
   *
   * @author Klaus Meffert
   * @since 3.5
   */
  public PopulationHistoryIndexed getPopulations() {
    return null;
  }
}

 

Ads help maintain this website.