/*
 * 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.*;
import org.jgap.util.*;

/**
 * Monitors the evolution progress extensively.
 * Keeps track of the population development for each single generation during
 * the whole evolution process.
 * Monitors chromosomes as well as genes. For each chromosome the originating
 * chromosome is monitored (applies for natural selectors as well as for genetic
 * operators that transform a single chromosome, like MutationOperator).
 * For more complex genetic operators, like CrossoverOperator, all originating
 * chromosomes are monitored (in crossover there are two).
 * For genes an analogue monitoring is supported as for chromosomes.
 *
 * TO ACTIVATE MONITORING:
 * Configuration.setMonitor(new EvolutionMonitor());
 *
 * Each chromosome and gene itself has a unique ID. This ID is set by method
 * setUniqueID. A unique ID is a String value that, in best case, is unique
 * worldwide.
 *
 * A chromosome's or gene's originator is set by method setUniqueIDTemplate.
 * This method accepts an index, as there could be more than one originator
 * (see below).
 *
 * --------------------------------------------------------------------------
 *
 * To give a better view, here are the population snapshots that are taken
 * during a single evolution generation (chromosomes are given by *,+,-,.):
 *
 *     |-------|      |-------|      |-------|      |-------|      |-------|
 *     | ** *  |      | **    |      |  *    |      |  +    |      |  +    |
 *     |* *  * |  =>  |* *  * |  =>  |*    * |  =>  |*    - |  =>  |*    . |
 *     | * **  |      |   **  |      |   **  |      |   **  |      |   -*  |
 *     |-------|      |-------|      |-------|      |-------|      |-------|
 *       Update        Natural        Natural        Genetic        Genetic
 *    Chromosomes     Selector 1     Selector i     Operator 1     Operator j
 *   (Fitness calc.)
 *
 *     |-------|      |-------|      |-------|      |-------|      |-------|
 *     |  +    |      |  +    |      |  +**  |      |  +**  |      |  + *  |
 * =>  |*    . |  =>  |*    . |  =>  |*    . |  =>  |* *  . |  =>  |* *  . |
 *     |   -*  |      |   -*  |      |*  -*  |      |*  -*  |      |*  -   |
 *     |-------|      |-------|      |-------|      |-------|      |-------|
 *    Bulk Fitness      Update        Add new         Re-add        Natural
 *      Function      Chromosomes    Chromosomes      Fittest      Selector k
 *     (optional)                                   Chromosome     (Post-Sel.)
 *
 *     |-------|
 *     |  + *  |
 * =>  |* *  . |
 *     |*  -   |
 *     |-------|
 *    End of cycle
 *
 * For each single evolution cycle, these population states are kept separately.
 *
 * --------------------------------------------------------------------------
 *
 * For each chromosome the originating chromosomes are tracked. Here are examples:
 *
 * Natural Selection, e.g. WeightedRouletteSelector:
 *   Chromosome 4715 has originator Chromosome 4711 (different ID because of
 *   cloning)
 *
 * Genetic Operation, e.g. MutationOperator:
 *   Chromosome 5512 has originator Chromosome 1139
 *
 *  Genetic Operation, e.g. CrossoverOperator:
 *   Chromosome 7119 has originator Chromosomes 807 and 5703
 *   Chromosome 7120 has originator Chromosomes 807 and 5703
 *   => two resulting Chromosomes have the same originators!
 *
 * Genetic, Operation, e.g. YourOperator:
 *   There can be as many originating Chromosomes as your operator regards
 *
 * --------------------------------------------------------------------------
 *
 * For each gene the originating genes are tracked. Examples:
 *
 * Natural Selection, e.g. WeightedRouletteSelector:
 *   All Genes in Chromosome 4711 have the same originating genes as
 *   Chromosome 4711's originating Chromosome's genes.
 *   => Chromosome is selected only, not modified, thus the Genes stick to the
 *      Chromosome they belong to. Genes unique ID of template is not set.
 *
 * Genetic Operation, e.g. MutationOperator:
 *   Each mutated Gene originates from exactly one other Gene
 *
 * Genetic Operation, e.g. CrossoverOperator:
 *   Each crossed over Gene A has one originating Gene B.
 *   In turn, Gene B has one originating Gene A, as their alleles are swapped.
 *   All uncrossed Genes have the same originator as the Chromosome they
 *   belong to, thus their unique ID of template is not set.
 *
 * Genetic, Operation, e.g. YourOperator:
 *   A Gene could virtually have any number of originators.
 *
 * @author Klaus Meffert
 * @since 3.5
 */
public class EvolutionMonitor
    implements IEvolutionMonitor {
  /** String containing the CVS revision. Read out via reflection!*/
  private final static String CVS_REVISION = "$Revision: 1.3 $";

  public static final int CONTEXT_UPDATE_CHROMOSOMES1 = 0;

  public static final int CONTEXT_OFFSET_NATURAL_SELECTOR1 = 1;

  public static final int CONTEXT_OFFSET_AFTER_OPERATE = 10;

  public static final int CONTEXT_AFTER_BULK_EVALUATION = 20;

  public static final int CONTEXT_UPDATE_CHROMOSOMES2 = 22;

  public static final int CONTEXT_NEW_CHROMOSOME = 22;

  public static final int CONTEXT_READD_FITTEST = 23;

  public static final int CONTEXT_OFFSET_NATURAL_SELECTOR2 = 30;

  public static final int CONTEXT_END_OF_CYCLE = 999;

  private int m_checks;

  private PopulationHistoryIndexed m_popHist;

  private int m_selectorIndex;

  private int m_operatorIndex;

  public EvolutionMonitor() {
    init();
  }

  protected void init() {
    m_popHist = new PopulationHistoryIndexed();
  }

  /**
   * 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) {
    // Let's verify the progress since our last check.
    // -----------------------------------------------
    IChromosome best = a_pop.determineFittestChromosome();
    if (best != null) {
      // A best solution exists.
      // -----------------------
    }
    else {
      // No solution exists at all.
      // --------------------------
    }
    // Store the population
    Population popClone = (Population) a_pop.clone();
//    m_evaluator.storePopulation(CONTEXT_END_OF_CYCLE, m_checks, popClone);
    PopulationContext context = new PopulationContext(popClone);
    context.setChromosome(best);
    m_popHist.addPopulation(m_checks, CONTEXT_END_OF_CYCLE, context);
    m_checks++;
    initCounters();
    // No continouos processing as in this example there is an outer main loop.
    // ------------------------------------------------------------------------
    return false;
  }

  /**
   * Called just before the evolution starts.
   *
   * @param a_config the configuration used
   *
   * @author Klaus Meffert
   * @since 3.5
   */
  public void start(Configuration a_config) {
    initCounters();
  }

  private void initCounters() {
    m_selectorIndex = 0;
    m_operatorIndex = 0;
  }

  /**
   * 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) {
    if (a_monitorEvent == null) {
      // Should never happen.
      // --------------------
      return;
    }
    if (a_information == null) {
      return;
    }
    PopulationContext context;
    // The events are queried in the chronological order they do appear.
    // -----------------------------------------------------------------
    if (a_monitorEvent.equals(IEvolutionMonitor.MONITOR_EVENT_REMOVE_CHROMOSOME)) {
      // Initiated by Population.keepPopSizeConstant()
      Population pop = (Population) a_information[0];
      Integer chromosomeIndex = (Integer) a_information[1];
      IChromosome chrom = pop.getChromosome(chromosomeIndex);
    }
    if (a_monitorEvent.equals(IEvolutionMonitor.
                              MONITOR_EVENT_BEFORE_UPDATE_CHROMOSOMES1)) {
      // Initiated by GABreeder.evolve before calling updateChromosomes(..)
      Population pop = (Population) a_information[0];
    }
    if (a_monitorEvent.equals(IEvolutionMonitor.
                              MONITOR_EVENT_AFTER_UPDATE_CHROMOSOMES1)) {
      // Initiated by GABreeder.evolve after calling updateChromosomes(..)
      Population pop = (Population) ( (Population) a_information[0]).clone();
      // Record population as now each chromosome has a fitness value assigned.
      // ----------------------------------------------------------------------
//      m_evaluator.storePopulation(CONTEXT_UPDATE_CHROMOSOMES1, m_checks, pop);
      context = new PopulationContext(pop);
      m_popHist.addPopulation(m_checks, CONTEXT_UPDATE_CHROMOSOMES1, context);
    }
    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];
    }
    if (a_monitorEvent.equals(IEvolutionMonitor.MONITOR_EVENT_AFTER_SELECT)) {
      NaturalSelector selector = (NaturalSelector) a_information[0];
      Population pop = (Population) ( (Population) a_information[1]).clone();
      Population newPop = (Population) ( (Population) a_information[2]).clone();
      int selectionSize = (Integer) a_information[3];
      boolean a_processBeforeGeneticOperators = (Boolean) a_information[4];
      if (a_processBeforeGeneticOperators) {
        // Selection executed before genetic operators.
        // --------------------------------------------
        // Store data for each selector subsequently.
        // ------------------------------------------
        context = new PopulationContext(pop);
        context.setSelector(selector);
        m_popHist.addPopulation(m_checks, CONTEXT_OFFSET_NATURAL_SELECTOR1 +
                                m_selectorIndex * 2 + 0, context);
        context = new PopulationContext(newPop);
        context.setSelector(selector);
        m_popHist.addPopulation(m_checks, CONTEXT_OFFSET_NATURAL_SELECTOR1 +
                                m_selectorIndex * 2 + 1, context);
        m_selectorIndex++;
      }
      else {
        // Selection executed after genetic operators.
        // -------------------------------------------
        context = new PopulationContext(pop);
        context.setSelector(selector);
        // Store data for each selector subsequently.
        // ------------------------------------------
        m_popHist.addPopulation(m_checks, CONTEXT_OFFSET_NATURAL_SELECTOR2 +
                                m_selectorIndex * 2 + 0, context);
        context = new PopulationContext(newPop);
        context.setSelector(selector);
        m_popHist.addPopulation(m_checks, CONTEXT_OFFSET_NATURAL_SELECTOR2 +
                                m_selectorIndex * 2 + 1, context);
      }
    }
    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];
      // Store data for each selector subsequently.
      // ------------------------------------------
      context = new PopulationContext(pop);
      context.setOperator(operator);
      m_popHist.addPopulation(m_checks, CONTEXT_OFFSET_AFTER_OPERATE +
                              m_operatorIndex, context);
      m_operatorIndex++;
      m_selectorIndex = 0;
    }
    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) ( (Population) a_information[1]).clone();
      context = new PopulationContext(pop);
      context.setBulkFitnessFunction(bulkFitnessFunction);
      m_popHist.addPopulation(m_checks, CONTEXT_AFTER_BULK_EVALUATION, context);
    }
    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];
      context = new PopulationContext(pop);
      m_popHist.addPopulation(m_checks, CONTEXT_UPDATE_CHROMOSOMES2, context);
    }
    if (a_monitorEvent.equals(IEvolutionMonitor.
                              MONITOR_EVENT_BEFORE_ADD_CHROMOSOME)) {
      Population pop = (Population) a_information[0];
      IChromosome newChromosome = (IChromosome) ( (ICloneable) a_information[1]).clone(); 
      context = new PopulationContext(pop);
      context.setChromosome(newChromosome);
      m_popHist.addPopulation(m_checks, CONTEXT_NEW_CHROMOSOME, context);
    }
    if (a_monitorEvent.equals(IEvolutionMonitor.MONITOR_EVENT_READD_FITTEST)) {
      Population pop = (Population) a_information[0];
      IChromosome fittest = (IChromosome) ( (ICloneable) a_information[1]). clone(); 
      context = new PopulationContext(pop);
      context.setChromosome(fittest);
      m_popHist.addPopulation(m_checks, CONTEXT_READD_FITTEST, context);
    }
  }

  public PopulationHistoryIndexed getPopulations() {
    return m_popHist;
  }
}

 

Ads help maintain this website.